EOS每年增发1%的机制在系统合约中,其实说每年增发1%只是一年的总数,其实是只要在出块,EOS就在增发的路途中,下面分析一下增发的代码。

  其实增发的1%的都是分给所有区块生产者的,只要出块了或者获得投票都有奖励,代码在producer_pay.cpp文件中,只有下面两个函数。

 void system_contract::onblock( block_timestamp timestamp, account_name producer ) {
using namespace eosio; require_auth(N(eosio)); /** until activated stake crosses this threshold no new rewards are paid */
if( _gstate.total_activated_stake < min_activated_stake )
return; if( _gstate.last_pervote_bucket_fill == ) /// start the presses
_gstate.last_pervote_bucket_fill = current_time(); /**
* At startup the initial producer may not be one that is registered / elected
* and therefore there may be no producer object for them.
*/
auto prod = _producers.find(producer);
if ( prod != _producers.end() ) {
_gstate.total_unpaid_blocks++;
_producers.modify( prod, , [&](auto& p ) {
p.unpaid_blocks++;
});
} /// only update block producers once every minute, block_timestamp is in half seconds
if( timestamp.slot - _gstate.last_producer_schedule_update.slot > ) {
update_elected_producers( timestamp ); if( (timestamp.slot - _gstate.last_name_close.slot) > blocks_per_day ) {
name_bid_table bids(_self,_self);
auto idx = bids.get_index<N(highbid)>();
auto highest = idx.begin();
if( highest != idx.end() &&
highest->high_bid > &&
highest->last_bid_time < (current_time() - useconds_per_day) &&
_gstate.thresh_activated_stake_time > &&
(current_time() - _gstate.thresh_activated_stake_time) > * useconds_per_day ) {
_gstate.last_name_close = timestamp;
idx.modify( highest, , [&]( auto& b ){
b.high_bid = -b.high_bid;
});
}
}
}
}

  这个onlock函数在每次生产者出块的时候都会被调用,见证者收到区块后也会调用(相当于验证区块),每次生产者出块都会把该生产者的出块数进行统计,把所有的区块也进行统计,后面的代码不太清楚在做什么,后续再补充。

  

  

void system_contract::claimrewards( const account_name& owner ) {
require_auth(owner); const auto& prod = _producers.get( owner );
eosio_assert( prod.active(), "producer does not have an active key" ); eosio_assert( _gstate.total_activated_stake >= min_activated_stake,
"cannot claim rewards until the chain is activated (at least 15% of all tokens participate in voting)" ); auto ct = current_time(); eosio_assert( ct - prod.last_claim_time > useconds_per_day, "already claimed rewards within past day" ); const asset token_supply = token( N(eosio.token)).get_supply(symbol_type(system_token_symbol).name() );
const auto usecs_since_last_fill = ct - _gstate.last_pervote_bucket_fill; if( usecs_since_last_fill > 0 && _gstate.last_pervote_bucket_fill > 0 ) {
auto new_tokens = static_cast<int64_t>( (continuous_rate * double(token_supply.amount) * double(usecs_since_last_fill)) / double(useconds_per_year) ); auto to_producers = new_tokens / 5;
auto to_savings = new_tokens - to_producers;
auto to_per_block_pay = to_producers / 4;
auto to_per_vote_pay = to_producers - to_per_block_pay; INLINE_ACTION_SENDER(eosio::token, issue)( N(eosio.token), {{N(eosio),N(active)}},
{N(eosio), asset(new_tokens), std::string("issue tokens for producer pay and savings")} ); INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), N(eosio.saving), asset(to_savings), "unallocated inflation" } ); INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), N(eosio.bpay), asset(to_per_block_pay), "fund per-block bucket" } ); INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), N(eosio.vpay), asset(to_per_vote_pay), "fund per-vote bucket" } ); _gstate.pervote_bucket += to_per_vote_pay;
_gstate.perblock_bucket += to_per_block_pay; _gstate.last_pervote_bucket_fill = ct;
} int64_t producer_per_block_pay = 0;
if( _gstate.total_unpaid_blocks > 0 ) {
producer_per_block_pay = (_gstate.perblock_bucket * prod.unpaid_blocks) / _gstate.total_unpaid_blocks;
}
int64_t producer_per_vote_pay = 0;
if( _gstate.total_producer_vote_weight > 0 ) {
producer_per_vote_pay = int64_t((_gstate.pervote_bucket * prod.total_votes ) / _gstate.total_producer_vote_weight);
}
if( producer_per_vote_pay < min_pervote_daily_pay ) {
producer_per_vote_pay = 0;
}
_gstate.pervote_bucket -= producer_per_vote_pay;
_gstate.perblock_bucket -= producer_per_block_pay;
_gstate.total_unpaid_blocks -= prod.unpaid_blocks; _producers.modify( prod, 0, [&](auto& p) {
p.last_claim_time = ct;
p.unpaid_blocks = 0;
}); if( producer_per_block_pay > 0 ) {
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio.bpay),N(active)},
{ N(eosio.bpay), owner, asset(producer_per_block_pay), std::string("producer block pay") } );
}
if( producer_per_vote_pay > 0 ) {
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio.vpay),N(active)},
{ N(eosio.vpay), owner, asset(producer_per_vote_pay), std::string("producer vote pay") } );
}
} } //namespace eosiosy

  

  先理清一下概念:

  _gstate.pervote_bucket //所有生产者获得投票的奖励资金
  _gstate.perblock_bucket //所有出块的奖励资金
  _gstate.total_unpaid_blocks //公链上还没有领取出块奖励的所有区块数

  这里的做法是:

  1.每个生产者至少每隔一天可以领取奖励;

  2.出块的资金数目分为两部:把20%当做奖励发放给生产者;把80%放在了系统用户eosio.saving下面。

  3.资金池为总数的20%,每个生产者领取的奖励计算方式: 生产者出块数 / 所有未领取奖励的区块数  * 25% + 生产者获得的投票数 / 公链上所有的投票数  * 75%(25%和75%的比例是指奖金池的比例)

  4.因为是增发,所有eosio用户也会同步发行同等代币(总数的20%,);

  5.出块的奖励资金会临时放在系统用户eosio.bpay下, 获得的投票收益临时放在eosio.vpay用户下,但又马上转给了生产者,这样的设计暂时没有弄明白(为什么不直接转帐给生产者)。

  

最新文章

  1. Yii2.0学习笔记:第一个页面Saying Hello
  2. iOS 蓝牙开发(二)iOS 连接外设的代码实现(转)
  3. Bootstrap布局
  4. Win7+VS2013初试Thrift
  5. Python面试题汇总
  6. virt viewer Usbredir USB重定向
  7. 文件I/O操作(2)
  8. 关于split与StringTokenizer的理解
  9. Maven01——简介、安装配置、入门程序、项目构建和依赖管理
  10. linux device drivers ch02
  11. C++ 第二次实验
  12. hive函数--编码解码
  13. Java中单例实现
  14. vue-cli脚手架之build文件夹上半部
  15. word2vec详解与实战
  16. CSS3实现原腾讯视频透明边框,多重边框等(关于边框那些不为人知的事情)
  17. lua的table的删除操作
  18. 安装SQL Server 2008数据库(带完整图解)
  19. STM32学习之路之入门篇
  20. JS数组中级+高级技巧

热门文章

  1. js生成邀请码(2)
  2. HOOK技术演示
  3. CSS——position
  4. DAY13-前端之JavaScript
  5. OpenCV4Android 不需要安装OpenCVManager,就可以运行的方法
  6. 深入理解asp.net中的 __doPostBack函数
  7. Struts2框架05 result标签的类型、拦截器
  8. Redis面试考点
  9. JavaWeb_泛型(Generic)
  10. Java50道经典习题-程序25 根据输入求输出