【EOS踩坑记】
1、每个account只能更新自己的contract,即使两个account的秘钥相同,也不允许。
如下,使用alice的权限来更新james的contract。会返回 Missing required authority错误。
cleos set contract james /home/ubuntu/contracts/hello/jameshello -p alice@active
应该改为:
cleos set contract james /home/ubuntu/contracts/hello/jameshello -p james@active
2、contract class 名可以与 account 名不一致。如,以下调用是OK的。
cleos set contract james /home/ubuntu/contracts/hello/xhello -p james@active
3、一个account只能有一个contract。
例如,hello 账户有一个hi函数,set contract,此时abi 为:
此时,有一个xhello contract,内含一个 hi2 函数,将xhello合约提交。
cleos set contract hello /home/ubuntu/contracts/hello/xhello -p hello@active
则 hello 账户的 abi 会变为:
可以看见,原有的hi action不见了。
4、contract class 名、目录名、文件名必须一致。
1)如下,文件名为hello,目录名为xhello,两者不一致。
cleos set contract james /home/ubuntu/contracts/hello/xhello -p james@active
执行后,会返回找不到文件错误。
2)如下,contract class名为 jameshello,而目录名为hello。
cleos set contract james /home/ubuntu/contracts/hello/hello -p james@active
虽然可以成功发布合约,但合约的abi是空的,也就是实际等于没有发布成功。
5、任意account都有权调用他人的contract。如,下面用bob的权限调用james的hi action,是合法的,不论两者的公钥是否相同。
cleos push action james hi '["bob"]' -p bob@active
6、require_auth(name n)
Verifies that @ref name exists in the set of provided auths on a action. Fails if not found.
检测name是否在通过-p提供的名单里。
可以用于限制每个account在调用action时,只能修改自身相关信息。例如:
[[eosio::action]] void hi( name user ) { require_auth(user); print("Hello, ", user); }
7、contract 类中的 get_self()方法、_self。
1)_self 是 contract 类的一个 protected member,其类型为 name,可以知道,它存的是一个账号。
2)_self的赋值来源于 receiver,所以_self就是receiver。
3)get_self() 返回的就是 _self,也就是receiver,也就是一个account。
8、symbol_code
symbol_code 是一个 class.
只含有一个 uint64_t value 成员变量。
symbol_code 将长度为7以内(包括7)的字符串 encode 为 uint64_t value。(注意 uint64_t可以存储8个byte)
9、symbol
symbol 是一个class
只包括一个成员变量
通过构造函数可以看到 symbol可以存储8个Byte,上文的symbol_code使用了7个Byte,所以symbol可以将symbol_code存储在自身,并且额外加了一个precision字段。
symbol_code 指的是 TOKEN Name,如DICE、EOS。
precision 指的是一个TOKEN的精度,比如 100000000.0000,上限是1亿,precision是4。
10、asset
下面的命令可以调用 eosio.token 的action,创建一个新的TOKEN.
cleos push action eosio.token create '[ "eosio", "1000000000.0000 SYS"]' -p eosio.token@active
而 asset 代表的就是 "1000000000.0000 SYS"。
asset 是一个class。他只有2个成员变量,amount对应上述命令的 1000000000.0000, 而symbol则代码SYS,以及精度4。
11、multi_index
multi_index 是一个class,意为可以包含多个索引的table。eosio.cdt源码中有一个完整的示例:
* #include <eosiolib/eosio.hpp> * using namespace eosio; * class mycontract: contract { * struct record { * uint64_t primary; * uint64_t secondary_1; * uint128_t secondary_2; * uint256_t secondary_3; * double secondary_4; * long double secondary_5; * uint64_t primary_key() const { return primary; } * uint64_t get_secondary_1() const { return secondary_1; } * uint128_t get_secondary_2() const { return secondary_2; } * uint256_t get_secondary_3() const { return secondary_3; } * double get_secondary_4() const { return secondary_4; } * long double get_secondary_5() const { return secondary_5; } * }; * public: * mycontract(name receiver, name code, datastream<const char*> ds):contract(receiver, code, ds){} * void myaction() { * auto code = _self; * auto scope = _self; * multi_index<"mytable"_n, record, * indexed_by< "bysecondary1"_n, const_mem_fun<record, uint64_t, &record::get_secondary_1> >, * indexed_by< "bysecondary2"_n, const_mem_fun<record, uint128_t, &record::get_secondary_2> >, * indexed_by< "bysecondary3"_n, const_mem_fun<record, uint256_t, &record::get_secondary_3> >, * indexed_by< "bysecondary4"_n, const_mem_fun<record, double, &record::get_secondary_4> >, * indexed_by< "bysecondary5"_n, const_mem_fun<record, long double, &record::get_secondary_5> > * > table( code, scope); * } * } * EOSIO_DISPATCH( mycontract, (myaction) )