天天看点

EOS系列 - WASM智能合约 - 特性

构造函数

addressbook(name receiver, name code, datastream<const char*> ds):contract(receiver, code, ds) {}

#单例表(code和scope都用receiver的表)也可在初始化列表中实例化
singleton_example( name receiver, name code, datastream<const char*> ds ) :
         contract(receiver, code, ds),
         singleton_instance(receiver, receiver.value)
         {}
           

内置函数

  • 权限检测函数
    • require_auth(name)

      : 必须具有某权限, 没有就不会往下执行
    • require_auth2(user.value, "active"_n.value)

      : 指定必须某账户的某种权限
    • has_auth(name)

      : 判断是否具有某权限, 返回 true | false .

      eosio::check(eosio::has_auth(...), ...)

  • get_self

    : 获取合约名称, 合约部署者
  • get_code

    |

    get_first_receiver()

    : 部署此合约的帐户名称
  • require_recipient(name)

    : 发出通知, 将action复制到发件人
    • 调用

      require_recipient

      将一个帐户添加到 require_recipient 集合并确保这些帐户收到正在执行的action的通知
  • check( is_account( oracleClient ), "Must have a valid oracleClient" )

    : 断言
  • is_account(name)

    账号是否存在

EOSIO 名称类

  • 适用于所有 EOSIO 编码的名称(帐户、操作、表等)
  • uint64_t

    在区块链上编码为 64 位无符号整数 ( )。
  • 前 12 个字符(如果有)

    base32

    使用以下字符编码:

    .

    ,

    1-5

    ,

    a-z

  • 第 13 个字符(如果适用)

    base16

    使用以下字符编码:

    .

    ,

    1-5

    ,

    a-j

例子:

auto eosio_user = eosio::name{user};  //encodes user string to eosio::name object
auto user_str = user_name_obj.to_string(); //decodes eosio::name obj to string
auto standard_account = "standardname"_n;  //encodes literal string to eosio::name
auto non_standard_account = ".standard"_n; //encodes literal string to eosio::name
           

内联操作

内联操作在调用者操作的相同范围和权限内工作, 内联操作保证在同一个事务中执行

eosio.code

权限

eosio.code

权限是一种伪权限,用于增强安全性,并使合约能够执行内联action。

例如: 为了从

addressbook

发送内联action,请将

eosio.code

权限添加到合约帐户

addressbook

的active权限中, 否则会报错

Authorization failure with inline action sent to self

#加权限
cleos set account permission addressbook active --add-code

#删权限
cleos set account permission addressbook active --remove-code
           

内联action-本合约内

需要

eosio.code

action(
    //permission_level,		一个权限级别结构(需要将`eosio.code`权限添加到合约帐户的active权限中)
    //code,					要调用的合约,部署合约的帐户(使用eosio::name类型初始化)
    //action,				action(使用eosio::name类型初始化)
    //data					传递给action的数据,与被调用的action相关的位置元组。
).send();

action(
    permission_level{get_self(),"active"_n},
    get_self(),
    "notify"_n,
    std::make_tuple(user, name{user}.to_string() + message)
).send();
           

可通过

./cleos get actions addressbook

命令查看

内联action-外部合约

使用

action_wrapper

, 需要

eosio.code

#A合约内声明
[[eosio::action]] void count(name user, std::string type){
    //可在此限定只有哪个账户/合约才能授权该命令
	require_auth(name("addressbook")); //只有addressbook合约才能成功执行此操作
	...
}
using count_action = action_wrapper<"count"_n, &abcounter::count>;

#B合约内调用A合约
abcounter::count_action count("abcounter"_n, {get_self(), "active"_n});
count.send(user, type);
           

可通过

cleos get table abcounter abcounter counts --lower alice --limit 1

查看统计结果

创建自定义权限

介绍权限

EOS系列 - WASM智能合约 - 特性
/*The authority JSON object*/
{
  "threshold"       : 100,    /*An integer that defines cumulative signature weight required for authorization*/
  "keys"            : [],     /*An array made up of individual permissions defined with an EOS PUBLIC KEY*/
  "accounts"        : []      /*An array made up of individual permissions defined with an EOS ACCOUNT*/
}

/*Set Permission with Key*/
{
  "permission" : {
    "key"           : "EOS8X7Mp7apQWtL6T2sfSZzBcQNUqZB7tARFEm9gA9Tn9nbMdsvBB",
    "permission"    : "active"
  },
  weight            : 25      /*Set the weight of a signature from this permission*/
}

/*Set Permission with Account*/
{
  "permission" : {
    "account"       : "sandwich",
    "permission"    : "active"
  },
  weight            : 75      /*Set the weight of a signature from this permission*/
}

//例如
'{"threshold":1,"keys":[{"key":"EOS8X7Mp7apQWtL6T2sfSZzBcQNUqZB7tARFEm9gA9Tn9nbMdsvBB","weight":1}],"accounts":[{"permission":{"actor":"acc2","permission":"active"},"weight":50}]}'
           

给账户添加自定义权限

./cleos set account permission alice upsert '{"threshold":1,"keys":[{"key":"EOS63gKbqNRZjboQyfXBJPijZHNr1GtXJu5eCan3e6iSqN7yP5nFZ","weight":1}],"accounts":[]}' owner -p [email protected]
           

将操作action的权限链接到自定义的权限

将调用

upsert

操作的授权与新创建的

upsert

权限关联起来:

cleos set action permission alice addressbook upsert upsert
           

on_notify

属性

on_notify

当且仅当从指定的合约和指定的动作发送通知时,使用属性注释action可确保任何传入通知被转发到带注释的action。

callback

类回调回调函数可以采用这种方法

[[eosio::on_notify("VALID_EOSIO_ACCOUNT_NAME::VALID_EOSIO_ACTION_NAME")]]

//例如
[[eosio::on_notify("eosio.token::transfer")]]

[[eosio::on_notify("eosio.token::transfer")]]
void on_token_transfer(name from, name to, assert quantity, std::string memo) {
   // do something on eosio.token contract's transfer action from any account to the account where the contract is deployed.
}

[[eosio::on_notify("*::transfer")]]
void on_any_transfer(name from, name to, assert quantity, std::string memo) {
   // do something on any contract's transfer action from any account to the account where the contract is deployed.
}
           

测试

#转账时会触发
./cleos transfer han hodl '0.0001 SYS' 'Hodl!' -p [email protected]

#触发后查看表中数据
./cleos get table hodl han balance
           

单例表

eosio::singleton

eosio::singleton

是 code和scope都用receiver的单例表, 底层还是

eosio::multi_index

#声明
using singleton_type = eosio::singleton<"testtable"_n, testtable>;
singleton_type singleton_instance;

#在合约的构造函数初始化列表中进行初始化
singleton_example( name receiver, name code, datastream<const char*> ds ) :
         contract(receiver, code, ds),
         singleton_instance(receiver, receiver.value)  // (code, scope)
         {}

#用法
singleton_instance.get_or_create(name, def) //获取存储在单例表中的值。如果它不存在,它将使用指定的默认值创建一个新的
singleton_instance.set(value, name)			//为单例表设置新值 (name:为存储的新值支付的帐户)
singleton_instance.exists					//检查单例表是否存在
singleton_instance.get						//获取存储在单例表中的值。如果不存在则抛出异常
           

笔记

  • RAM 是 EOSIO 区块链上的持久系统资源,不属于 Staking 机制的范围。
  • 选择不使用 DPoS,则不需要系统资源
  • 智能合约
    • 可以在基于 EOSIO 的区块链上部署无法修改的智能合约
    • 表中有数据时不能修改其数据结构。如果您需要以任何方式更改表的数据结构,首先需要删除其所有行
    • EOSIO 能够按多达 16 个索引对表进行排序, 二级索引需要是数字字段
    • 可以在B合约内读取A合约内的表内容
      • producers_table ptable("eosio"_n, name("eosio").value);

  • 创建和链接自定义权限
    • 创建自定义权限时,该权限将始终在父权限下创建。
  • cleos
    • 使用

      -d -j

      指示“不广播”和“将交易作为 json 返回”的选项
      • cleos push action eosio.token issue '["alice", "100.0000 SYS", "memo"]' -p [email protected] -d -j

    • 查看token信息
      • ./cleos get currency balance eosio.token bob SYS

      • ./cleos get currency stats eosio.token SYS

继续阅读