【问链-EOS公开课】第十一课 EOS 智能合约相互调用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tiandiwuya/article/details/83033845

EOS中合约之间是可以相互调用的,主要通过inline action完成合约之间的调用。

譬如在掷骰子游戏中,存在两个玩家先下注资金,然后比较骰子大小后决定胜负,赢的那一方将获得所有的下注资金。在eosio源代码eos/build/contract/dice 智能合约示例中,Alice和Bob是两个玩家,他们各自将资金账户里的3个EOS作为赌注,先抵押给Dice账户,然后在游戏决出胜负后,Dice账户就自动把赌注归还给胜方。这其中就涉及到代币的转账操作,因此很自然的可以想到,在deposit(下注抵押资金)和最后的withdraw(胜方赢取资金)这两个操作中,就可以通过调用eosio.token的transfer动作来完成。

下面是deposit 和 withdraw 的函数实现。其中均对eosio.token的action—— transfer进行了调用。

//@abi action  
      void deposit( const account_name from, const asset& quantity ) {//下注抵押资金
         
         eosio_assert( quantity.is_valid(), "invalid quantity" );
         eosio_assert( quantity.amount > 0, "must deposit positive quantity" );

         auto itr = accounts.find(from);//在账户列表中查找要转出代币的账号是否存在
         if( itr == accounts.end() ) {//不存在的话就插入账号列表
            itr = accounts.emplace(_self, [&](auto& acnt){
               acnt.owner = from;
            });
         }
         
        //对eosio.token的transfer进行合约调用,玩家开始下注资金
        //账户(from)对账户( _self)进行转账,对应于游戏中,抵押代币到
         action(
            permission_level{ from, N(active) },
            N(eosio.token), N(transfer),
            std::make_tuple(from, _self, quantity, std::string(""))
         ).send();

         accounts.modify( itr, 0, [&]( auto& acnt ) {//修改转出账号的代币余额
            acnt.eos_balance += quantity;
         });
      }


//@abi action
      void withdraw( const account_name to, const asset& quantity ) {//胜方赢取资金
         require_auth( to );

         eosio_assert( quantity.is_valid(), "invalid quantity" );
         eosio_assert( quantity.amount > 0, "must withdraw positive quantity" );

         auto itr = accounts.find( to );//在账户列表中查找要转入代币的账号是否存在
         eosio_assert(itr != accounts.end(), "unknown account");

         accounts.modify( itr, 0, [&]( auto& acnt ) {//转出代币
            eosio_assert( acnt.eos_balance >= quantity, "insufficient balance" );
            acnt.eos_balance -= quantity;
         });

         //对eosio.token的transfer进行合约调用,Dice主账号对胜利一方发送资金
         //代表在资金撤回操作中,通过调用eosio.token的transfer,账户(_self)对账户(to)进行转账,对应于游戏中,Dice主账户为胜利的一方发放所赢的赌注
         action(
            permission_level{ _self, N(active) },
            N(eosio.token), N(transfer),
            std::make_tuple(_self, to, quantity, std::string(""))
         ).send();

         if( itr->is_empty() ) {
            accounts.erase(itr);
         }
      }

cleos push action eosio.token transfer '["dice","alice","6.0000 EOS", "win"]' -p alice

然后我们会得到提示信息: 没有签名!

通过api层调用智能合约,合约调用另一个合约的接口,需要用户显式的授权,有两个特殊的权限:eosio.code和eosio.ccode。其中ccode是current code的意思,对当前合约代码有效,一旦合约升级了,就失效了。我们测试示例,使用eosio.code就可以了。
现在我们就给dice账号增加配置一个eosio.code的权限:

cleos set account permission dice active '{"threshold": 1,"keys": [{"key": "EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4","weight": 1}],"accounts": [{"permission":{"actor":"dice","permission":"eosio.code"},"weight":1}]}' owner -p charity

之后执行看到正确,然后分别查询alice和bob的账户余额。

猜你喜欢

转载自blog.csdn.net/tiandiwuya/article/details/83033845
eos