对于用户的某个发行的代币记录,只保留一条,所以只有第一次记录时才消耗。
那我们看下到底谁来花费这比费用。
看代码,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
});
}
}