您正在查看: EOS-新手问答 分类下的文章

EOS转账时,谁来花费这笔记账的费用

对于用户的某个发行的代币记录,只保留一条,所以只有第一次记录时才消耗。
那我们看下到底谁来花费这比费用。
看代码,eosio.token合约-->transfer-->add_balance
https://github.com/EOSIO/eosio.contracts/blob/52fbd4ac7e6c38c558302c48d00469a4bed35f7c/contracts/eosio.token/src/eosio.token.cpp#L114

void token::add_balance( const name& owner, const asset& value, const name& ram_payer )
{
   accounts to_acnts( get_self(), owner.value );
   auto to = to_acnts.find( value.symbol.code().raw() );
   if( to == to_acnts.end() ) {
      to_acnts.emplace( ram_payer, [&]( auto& a ){
        a.balance = value;
      });
   } else {
      to_acnts.modify( to, same_payer, [&]( auto& a ) {
        a.balance += value;
      });
   }
}

其中的ram_payer负责花费这笔费用,那往回查
https://github.com/EOSIO/eosio.contracts/commit/6db6e867a7a6722bdec69de132a7c6fd0c3d4fd0#diff-e78b36e718262da651f3608f8963aa10
之后
此时,eosio.token 版本 1.7.0
https://github.com/EOSIO/eosio.contracts/blob/52fbd4ac7e6c38c558302c48d00469a4bed35f7c/contracts/eosio.token/src/eosio.token.cpp#L97

auto payer = has_auth( to ) ? to : from; // 如果有to的权限就是to的账户来花费,没有的话就是from
sub_balance( from, quantity );
add_balance( to, quantity, payer );

也可以单独的为某些账户开户,cleos 添加参数 --pay-ram-to-open
https://github.com/EOSIO/eos/blob/1418543149b7caf8fc69a23621e3db7f3c6d18ad/programs/cleos/main.cpp#L3075

 transfer->add_flag("--pay-ram-to-open", pay_ram, localized("Pay ram to open recipient's token balance row"));

   add_standard_transaction_options(transfer, "sender@active");
   transfer->set_callback([&] {
      if (tx_force_unique && memo.size() == 0) {
         // use the memo to add a nonce
         memo = generate_nonce_string();
         tx_force_unique = false;
      }

      auto transfer_amount = to_asset(con, amount);
      auto transfer = create_transfer(con, sender, recipient, transfer_amount, memo);
      if (!pay_ram) {
         send_actions( { transfer });
      } else {
         auto open_ = create_open(con, recipient, transfer_amount.get_symbol(), sender); // 使用sender支付内存费用,先开户,再转账
         send_actions( { open_, transfer } );
      }
   });

eosio.token合约种的open实现如下
https://github.com/EOSIO/eosio.contracts/blob/52fbd4ac7e6c38c558302c48d00469a4bed35f7c/contracts/eosio.token/src/eosio.token.cpp#L129

void token::open( const name& owner, const symbol& symbol, const name& ram_payer ) // ram_payer 为上面的 sender
{
   require_auth( ram_payer );

   check( is_account( owner ), "owner account does not exist" );

   auto sym_code_raw = symbol.code().raw();
   stats statstable( get_self(), sym_code_raw );
   const auto& st = statstable.get( sym_code_raw, "symbol does not exist" );
   check( st.supply.symbol == symbol, "symbol precision mismatch" );

   accounts acnts( get_self(), owner.value );
   auto it = acnts.find( sym_code_raw );
   if( it == acnts.end() ) {
      acnts.emplace( ram_payer, [&]( auto& a ){
        a.balance = asset{0, symbol}; // 创建0
      });
   }
}

Error 3090005: irrelevant authority included

问题描述

本想在transfer“回调”函数里处理相关业务前做多签检查,

require_auth2(合约账户, 多签权限);

由于transfer权限问题,并没有将代币发行合约对应的transfer执行权限设置{set action permission}给合约的多签权限,但由于对于每笔交易,我们都需要至少有一名签名者为网络和cpu收费,但此自定义权限并没有相应的权限,所以报此错误。

解决方法

将合约多签权限linkauth给单独账户,并在此处检查此多签账户的active权限。

require_auth2(多签账户, active权限);

参考

https://github.com/EOSIO/eos/issues/4617

transaction_trace 中的 account_ram_delta

transaction_trace具有新的可选字段account_ram_delta,如果存在,则记录支付用于存储延迟交易的特定账户的RAM使用增量:输入延迟交易将具有account_ram_delta记录该交易的第一授权者的RAM使用增加的字段。当延迟交易退出(无论哪个状态)该account_ram_delta字段将存在时记录延期交易的付款人的RAM使用减少。

参考

https://github.com/EOSIO/eos/issues/6897

EOSjs getTableRows lower and upper bound on account name

try {  
      let con_account = 'bcskillsurou';
      const encodedName = new BigNumber(Eos.modules.format.encodeName("bcskillsurou", false))
      console.log(encodedName);
      console.log(await rpc.get_table_rows(
      {
        code:con_account,
        scope:con_account,
        table:"accounttb",
        lower_bound: encodedName,
      }));

    } catch (e) {
      console.log( '\nCaught exception: ' + e);
      if (e instanceof eosjs_jsonrpc.RpcError)
        console.log( '\n\n' + JSON.stringify(e.json, null, 2));
    }

参考

https://eosio.stackexchange.com/questions/813/eosjs-gettablerows-lower-and-upper-bound-on-account-name
issue: https://github.com/EOSIO/eosjs/issues/456

checksum256 secondary index to get table rows

进一步解释了如何通过cleos传递的值。正如原帖中已经提到的,这一切都围绕着字节顺序。由于某种原因,该checksum256值以不同的endian返回到索引键类型所sha256期望的范围。

如果您checksum256在表中的行中返回以下hash():

7af12386a82b6337d6b1e4c6a1119e29bb03e6209aa03c70ed3efbb9b74a290c

它首先分为两部分(每边16个字节):

7af12386a82b6337d6b1e4c6a1119e29 bb03e6209aa03c70ed3efbb9b74a290c

然后使用第一部分作为示例,以2个字符(1个字节)块反转每个部分:

7af12386a82b6337d6b1e4c6a1119e29

7a f1 23 86 a8 2b 63 37 d6 b1 e4 c6 a1 11 9e 29

29 9e 11 a1 c6 e4 b1 d6 37 63 2b a8 86 23 f1 7a

然后连接两个反转部分以形成可以与sha256索引键类型一起使用的值:

299e11a1c6e4b1d637632ba88623f17a 0c294ab7b9fb3eed703ca09a20e603bb

最终结果:

299e11a1c6e4b1d637632ba88623f17a0c294ab7b9fb3eed703ca09a20e603bb

参考

https://eosio.stackexchange.com/questions/4116/how-to-use-checksum256-secondary-index-to-get-table-rows
https://github.com/EOSIO/eos/issues/6648
https://github.com/EOSIO/eos/pull/6591