EOS合约解析----EOS Token合约

一、EOS token合约

此合约允许创建许多不同的token,这些token全部在同一合同上运行,但可能由不同的用户管理。

1.1 创建账户

$ cleos create account eosio eosio.token 

1.2 部署合约

$ cleos set contract eosio.token build/contracts/eosio.token -p eosio.token@active
Reading WAST...
Assembling WASM...
Publishing contract...
executed transaction: 52

1.3 创建token

(1)创建过程

/**
*共有函数,即为action
*/
void token::create( account_name issuer,
                    asset        maximum_supply )
{
    //首先经过认证授权 cleos push action 须有-p参数
    require_auth( _self );

    //sym:最大资产的token,symbol represents a token and contains precision and name: "4,EOS"
    auto sym = maximum_supply.symbol;
    eosio_assert( sym.is_valid(), "invalid symbol name" );
    eosio_assert( maximum_supply.is_valid(), "invalid supply");
    eosio_assert( maximum_supply.amount > 0, "max-supply must be positive");

    /*创建多索引表stats in eosio.token.hpp:typedef eosio::multi_index<N(stat), currency_stats> stats;
    *建立一个 stats 类型的数据表,用来与数据库交互(存储当前代币状态信息) 
    */
    stats statstable( _self, sym.name() );
    //在表中搜索相同名称的代币
    auto existing = statstable.find( sym.name() );
    //校验,是否已经存在相同名称的代币
    eosio_assert( existing == statstable.end(), "token with symbol already exists" );

    //使用 emplace 方法,[在数据表中增加一项](https://developers.eos.io/eosio-cpp/reference#emplace)
    statstable.emplace( _self, [&]( auto& s ) {
       s.supply.symbol = maximum_supply.symbol;
       s.max_supply    = maximum_supply;
       s.issuer        = issuer;
    });
}

(2)调用方法

$ cleos push action eosio.token create '[ "eosio", "1000000000.0000 SYS"]' \
         -p eosio.token@active

1.4 发行token

(1)发行过程

void token::issue( account_name to, asset quantity, string memo )
{
    //获取代币(token)
    auto sym = quantity.symbol;
    eosio_assert( sym.is_valid(), "invalid symbol name" );
    eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" );

    //获取代币token名称
    auto sym_name = sym.name();
    //建立一个 milti_index 数据表,用来与数据库交互
    stats statstable( _self, sym_name );
    //在数据表中搜索代币 currency_stats 结构体,返回迭代器 exsting
    auto existing = statstable.find( sym_name );
    eosio_assert( existing != statstable.end(), "token with symbol does not exist, create token before issue" );
    //取出地址内的数据赋值给st(引用 alias)
    const auto& st = *existing;

    //需要经过授权
    require_auth( st.issuer );
    eosio_assert( quantity.is_valid(), "invalid quantity" );
    eosio_assert( quantity.amount > 0, "must issue positive quantity" );

    eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );
    eosio_assert( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply");

    statstable.modify( st, 0, [&]( auto& s ) {
       s.supply += quantity;
    });

    //给发布者增加资产
    add_balance( st.issuer, quantity, st.issuer );

    //判断代币接受方是否是发币者
    if( to != st.issuer ) {
       SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} );
    }
}
/**
*issue中调用的私有函数add_balance
*/
void token::add_balance( account_name owner, asset value, account_name ram_payer )
{
   //创建数据表
   accounts to_acnts( _self, owner );
   auto to = to_acnts.find( value.symbol.name() );
   //没有则插入
   if( to == to_acnts.end() ) {
      to_acnts.emplace( ram_payer, [&]( auto& a ){
        a.balance = value;
      });
   } else {
      //找到增加余额
      to_acnts.modify( to, 0, [&]( auto& a ) {
        a.balance += value;
      });
   }
}

(2)调用发行

$ cleos push action eosio.token issue '[ "user", "100.0000 SYS", "memo" ]' \
        -p eosio@active
executed transaction: 822a607a9196112831ecc2dc14ffb1722634f1749f3ac18b73ffacd41160b019  268 bytes  1000 cycles
#   eosio.token <= eosio.token::issue           {"to":"user","quantity":"100.0000 SYS","memo":"memo"}
>> issue
#   eosio.token <= eosio.token::transfer        {"from":"eosio","to":"user","quantity":"100.0000 SYS","memo":"memo"}
>> transfer
#         eosio <= eosio.token::transfer        {"from":"eosio","to":"user","quantity":"100.0000 SYS","memo":"memo"}
#          user <= eosio.token::transfer        {"from":"eosio","to":"user","quantity":"100.0000 SYS","memo":"memo"}

1.5 交易token

(1)交易过程

/**
*公有函数,action可以调用
*/
void token::transfer( account_name from,
                      account_name to,
                      asset        quantity,
                      string       memo )
{
    eosio_assert( from != to, "cannot transfer to self" );
    //授权
    require_auth( from );
    eosio_assert( is_account( to ), "to account does not exist");
    auto sym = quantity.symbol.name();
    //监理数据表,与数据库相连
    stats statstable( _self, sym );
    const auto& st = statstable.get( sym );

    //获取响应
    require_recipient( from );
    require_recipient( to );

    eosio_assert( quantity.is_valid(), "invalid quantity" );
    eosio_assert( quantity.amount > 0, "must transfer positive quantity" );
    eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );
    eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" );


    sub_balance( from, quantity );
    add_balance( to, quantity, from );
}
/**
*私有函数:减少余额
*/
void token::sub_balance( account_name owner, asset value ) {
   accounts from_acnts( _self, owner );
   //没有找到或余额大于总数,报错
   const auto& from = from_acnts.get( value.symbol.name(), "no balance object found" );
   eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" );

   //余额等于总数,删除这个账户;余额小于总数,则余额减去转账数
   if( from.balance.amount == value.amount ) {
      from_acnts.erase( from );
   } else {
      from_acnts.modify( from, owner, [&]( auto& a ) {
          a.balance -= value;
      });
   }
}

(2)调用交易

$ cleos push action eosio.token transfer \
        '[ "user", "tester", "25.0000 SYS", "m" ]' -p user@active
executed transaction: 06d0a99652c11637230d08a207520bf38066b8817ef7cafaab2f0344aafd7018  268 bytes  1000 cycles
#   eosio.token <= eosio.token::transfer        {"from":"user","to":"tester","quantity":"25.0000 SYS","memo":"m"}
>> transfer
#          user <= eosio.token::transfer        {"from":"user","to":"tester","quantity":"25.0000 SYS","memo":"m"}
#        tester <= eosio.token::transfer        {"from":"user","to":"tester","quantity":"25.0000 SYS","memo":"m"}

猜你喜欢

转载自blog.csdn.net/http188188/article/details/81556676