本文具体介绍了 eosio.system 智能合约中的选举、投票、零碎设置,实用于 EOS 智能合约的高级开发者,理解如何进行选举、投票以及零碎设置。
01
概述
“eosio.system”智能合约是 eos 的系统命令合约。这个合约简直实现了 eos 全副的系统命令,包含创立账户、资源质押、超级节点投票、域名竞拍等性能,它定义了区块链外围性能所需的构造和操作。
下文将介绍 eosio.system 是如何实现选举、投票以及零碎设置的。
02
环境筹备
(一)一条正在运行且可拜访的区块链
中移链(基于 EOS)测试环境搭建:
https://mp.weixin.qq.com/s/NBNFk9Xk9FCukMVgl0tfHA
(二)确保本地钱包已关上并解锁
如何创立钱包:
https://developers.eos.io/manuals/eos/latest/cleos/how-to-gui…
(三)已实现 eosio.contracts 的构建和部署
如何构建 eosio.contracts:
https://developers.eos.io/manuals/eosio.contracts/latest/buil…
(四)已实现 token 的创立、发行和转移
如何创立、发行和转移 token:
https://developers.eos.io/manuals/eosio.contracts/latest/guid…
03
选举
(一)节点的注册、勾销
eos 的超级节点选举是围绕账户进行的。账户注册为超级节点候选账户,其余账户才能够为其投票。
注册为超级节点候选账户,须要提供公钥,此公钥用于入选超级节点后,产块时验证签名。
命令根底构造:
cleos system regproducer [OPTIONS] account producer_key [url] [location]
注册节点示例:
cleos system regproducer alice EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1
勾销节点:
cleos system unregprod alice EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1
勾销节点后,其余账号不能再为其投票,然而之前投的票会被保留,下次创立节点仍会呈现。
04
投票
(一)投票流程
1、注册节点
运行以下指令注册节点(详见前文):
cleos system regproducer alice EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1
2、抵押与勾销抵押
抵押:
抵押给本人:
cleos system delegatebw ost ost "5 SYS" "5 SYS"
抵押胜利返回值
executed transaction: 403f264c483947d3a5b2cd3508632d2993789467674ff458fac1b413d2f2b4ea 144 bytes 318 us
# eosio <= eosio::delegatebw {"from":"ost","receiver":"ost","stake_net_quantity":"51.0000 SYS","stake_cpu_quantity":"49.0000 SYS"...
# eosio.token <= eosio.token::transfer {"from":"ost","to":"eosio.stake","quantity":"100.0000 SYS","memo":"stake bandwidth"}
# ost <= eosio.token::transfer {"from":"ost","to":"eosio.stake","quantity":"100.0000 SYS","memo":"stake bandwidth"}
# eosio.stake <= eosio.token::transfer {"from":"ost","to":"eosio.stake","quantity":"100.0000 SYS","memo":"stake bandwidth"}
warning: transaction executed locally, but may not be confirmed by the network yet ]
抵押前转给 ost 1000.0000 SYS token,查看抵押后的账户:
cleos get table eosio.token ost accounts
{
"rows": [{"balance": "900.0000 SYS"}
],
"more": false,
"next_key": "","next_key_bytes":""
}
查看抵押信息:
cleos get table eosio ost delband
{
"rows": [{
"from": "ost",
"to": "ost",
"net_weight": "153.0000 SYS",
"cpu_weight": "147.0000 SYS"
}
],
"more": false,
"next_key": "","next_key_bytes":""
}
抵押给他人:
cleos system delegatebw ost imtube "5.0000 SYS" "5.0000 SYS"
查看抵押信息:
cleos get table eosio ost delband{
{
"rows": [{
"from": "ost",
"to": "imtube",
"net_weight": "5.0000 SYS",
"cpu_weight": "5.0000 SYS"
},{
"from": "ost",
"to": "ost",
"net_weight": "153.0000 SYS",
"cpu_weight": "147.0000 SYS"
}
],
"more": false,
"next_key": "","next_key_bytes":""
}
查问 ost 的 balance 为:890.0000 SYS
勾销抵押:
勾销抵押命令根底构造如下:
cleos system undelegatebw [OPTIONS] from receiver unstake_net_quantity unstake_cpu_quantity
此时再次查看 ost 的 balance,显示仍为 890.0000 SYS,没有将勾销抵押的返回,起因是勾销抵押有 3 天提早,3 天后再查看即可失去失常反馈。
cleos get table eosio.token ost accounts
{
"rows": [{"balance": "890.0000 SYS"}
],
"more": false,
"next_key": "","next_key_bytes":""
}
3、投票与勾销投票
投票前筹备:
创立节点:
cleos system regproducer ost EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1
cleos system regproducer imtube EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1
抵押:
ost→ost 5.0000 SYS,ost→imtube 5.0000 SYS
cleos get table eosio ost delband
{
"rows": [{"balance": "880.0000 SYS"}
],
"more": false,
"next_key": "","next_key_bytes":""
}
root@5dca586566d1:~# cleos get table eosio ost delband
{
"rows": [{
"from": "ost",
"to": "imtube",
"net_weight": "5.0000 SYS",
"cpu_weight": "5.0000 SYS"
},{
"from": "ost",
"to": "ost",
"net_weight": "158.0000 SYS",
"cpu_weight": "152.0000 SYS"
}
],
"more": false,
"next_key": "","next_key_bytes":""
}
imtube→imtube
cleos system delegatebw imtube imtube "2 SYS" "2 SYS"
查看 imtube 抵押信息:cleos get table eosio imtube delband
{
"rows": [{
"from": "imtube",
"to": "imtube",
"net_weight": "2.0000 SYS",
"cpu_weight": "2.0000 SYS"
}
],
"more": false,
"next_key": "","next_key_bytes":""
}
imtube→bob
cleos system delegatebw imtube bob "3 SYS" "3 SYS"
节点给其余节点投票
cleos system voteproducer prods imtube ost
投票胜利返回值:
executed transaction: e21875311a7445bb9714b83fde2442a09839c246868e80cd5eef58212f83c8d5 120 bytes 300 us
# eosio <= eosio::voteproducer {"voter":"imtube","proxy":"","producers":["ost"]}
warning: transaction executed locally, but may not be confirmed by the network yet ]
获取投票者信息:
cleos get table eosio eosio voters
{
"rows": [{
"owner": "eosio",
"proxy": "","producers": [],"staked": 800840,"last_vote_weight":"0.00000000000000000","proxied_vote_weight":"0.00000000000000000","is_proxy": 0,"flags1": 0,"reserved2": 0,"reserved3":"0 "},{"owner":"imtube","proxy":"",
"producers": ["ost"],
"staked": 100000,
"last_vote_weight": "1080641469324.71191406250000000",
"proxied_vote_weight": "0.00000000000000000",
"is_proxy": 0,
"flags1": 0,
"reserved2": 0,
"reserved3": "0"
},{
"owner": "jiscfgtizds5",
"proxy": "","producers": [],"staked": 2000000,"last_vote_weight":"0.00000000000000000","proxied_vote_weight":"0.00000000000000000","is_proxy": 0,"flags1": 0,"reserved2": 0,"reserved3":"0 "},{"owner":"ost","proxy":"",
"producers": [],
"staked": 3200000,
"last_vote_weight": "0.00000000000000000",
"proxied_vote_weight": "0.00000000000000000",
"is_proxy": 0,
"flags1": 0,
"reserved2": 0,
"reserved3": "0"
},{
"owner": "pagbbj4afmu5",
"proxy": "","producers": [],"staked": 2000000,"last_vote_weight":"0.00000000000000000","proxied_vote_weight":"0.00000000000000000","is_proxy": 0,"flags1": 0,"reserved2": 0,"reserved3":"0 "}
],
"more": false,
"next_key": "","next_key_bytes":""
}
查看 imtube 抵押信息:
cleos get table eosio imtube delband
{
"rows": [{
"from": "imtube",
"to": "bob",
"net_weight": "3.0000 SYS",
"cpu_weight": "3.0000 SYS"
},{
"from": "imtube",
"to": "imtube",
"net_weight": "2.0000 SYS",
"cpu_weight": "2.0000 SYS"
}
],
"more": false,
"next_key": "","next_key_bytes":""
}
节点给本人投票
cleos system voteproducer prods imtube imtube
投票胜利返回值:
executed transaction: 65cc7f09e0b5d0bc3e263f3b770b520838c44583be1da2f6c151d57275a0b951 120 bytes 306 us
# eosio <= eosio::voteproducer {"voter":"imtube","proxy":"","producers":["imtube"]}
warning: transaction executed locally, but may not be confirmed by the network yet ]
账号给节点投票
bob 抵押:
cleos system delegatebw bob bob "11 SYS" "11 SYS"
bob 给 ost 投票:
cleos system voteproducer prods bob ost
投票数量计算公式:votingNum=(stake_net_quantity+stake_cpu_quantity)*10000;
投票给多个节点
将 alice 设置为节点
cleos system regproducer alice EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1
cleos system voteproducer prods 为间接给超级节点投票的命令,能够指定投票账户,能够一次性投给多个超级节点候选账户,账户名须要按字母从小到大排序,最多不超过 30 个账户。
cleos system voteproducer prods [OPTIONS] voter producers...
4、投票失败
以下状况会导致投票失败:
未创立的节点;
创立后又勾销的节点;
一次投 30 个以上的节点,只有前 30 能够胜利;
多个节点投票,没有按程序;
5、节点处分
cleos system voteproducer prods [OPTIONS] voter producers...
如需发放节点处分,必须保障 per_block_payments 大于 0;
否则会导致报错
Error 3050003: eosio_assert_message assertion failure
Error Details:
assertion failure with message: cannot claim rewards until the chain is activated (at least 15% of all tokens participate in voting)
pending console output:
出块处分只向 21 个超级节点发放,其中波及到一个出块处分池的概念,因为每个节点支付时都会增发局部 EOS,所以所有未支付的出块处分都会放在出块处分池中期待节点支付。每次单个节点支付(claim)时,能支付到的出块处分数量计算公式如下:单个节点可支付的数量 = 出块处分池里的 EOS 数量 * 该 BP 未支付处分的出块数量 / 所有未支付处分的区块数量
得票率处分向超级节点和备用节点发放,同出块处分类似,所有未支付的得票率处分都会放在得票处分池中期待节点支付。每次单个节点支付(claim)时,能支付到的得票率处分数量计算公式如下:单个节点可支付的数量 = 得票率处分池里的 EOS 数量 * 该 BP 的得票权重 / 所有 BP 的总得票权重
支付(claim)条件节点支付处分需满足三个条件:超级节点和备用节点才可支付;同一节点两次 claim 间隔时间不能少于 24 小时;备用节点无出块处分,只有得票率处分且须要在 100 个 EOS 以上,否则不算备用节点,无奈支付处分。
(二)代理投票流程
1、注册节点
cleos system regproducer ost EOS6u3S5RbCxVrCE2sW7yBQLZ7fftaupqB85BLDeuV9j4eTBGCKX1
2、建设代理与勾销代理
建设代理:
cleos system regproxy imtube
代理胜利返回值:
executed transaction: 06616d46400deef7191c869cb3d96f1d35b4fec1f98adb41b32b4754e00afa77 104 bytes 243 us
# eosio <= eosio::regproxy {"proxy":"imtube","isproxy":1}
warning: transaction executed locally, but may not be confirmed by the network yet ]
勾销代理:
cleos system unregproxy imtube
勾销代理胜利返回值:
executed transaction: 07a59f11b4f076dd57bc9356c65d9621bdbd40a4d5a48077cc7e48f650925c9a 104 bytes 268 us
# eosio <= eosio::regproxy {"proxy":"imtube","isproxy":0}
warning: transaction executed locally, but may not be confirmed by the network yet ]
3、代理投票
建设代理:
cleos system regproxy alice
抵押:
cleos system delegatebw imtube imtube "11.0000 SYS" "11.0000SYS"
委托代理:
cleos system voteproducer proxy imtube alice
委托胜利返回值:
executed transaction: 667ffb20e7ec556d1760495f3f6ecfe1c315405d9ac31c2133f1523854dd8672 112 bytes 285 us
# eosio <= eosio::voteproducer {"voter":"imtube","proxy":"alice","producers":[]}
warning: transaction executed locally, but may not be confirmed by the network yet ]
代理投票:
cleos system voteproducer prods alice ost
通过代理进行投票,即先投票给代理,再由代理投票给生产者。
代理的作用就是替他人做出抉择投票,自身不须要抵押。
在投票的时候,要先抵押,投票有两种抉择,只能抉择一种,两种不能同时存在。
若抉择本人投票,则间接操作;若抉择代理投票,则将票抵押给代理,由代理抉择要投票的节点。
曾经作为代理的账号,不能再设置代理投票。
05
零碎设置
(一)setalimits 设置账号资源限度
源码:
void system_contract::setalimits(const name& account, int64_t ram, int64_t net, int64_t cpu) {require_auth( get_self() );
user_resources_table userres(get_self(), account.value );
auto ritr = userres.find(account.value);
check(ritr == userres.end(), "only supports unlimited accounts" );
auto vitr = _voters.find(account.value);
if(vitr != _voters.end() ) {bool ram_managed = has_field( vitr->flags1, voter_info::flags1_fields::ram_managed);
bool net_managed = has_field(vitr->flags1, voter_info::flags1_fields::net_managed);
bool cpu_managed = has_field(vitr->flags1, voter_info::flags1_fields::cpu_managed);
check(!(ram_managed || net_managed || cpu_managed), "cannot use setalimits on an account with managed resources" );
}
set_resource_limits(account, ram, net, cpu);
}
参数详解:
account: 要设置其资源限度的帐户的名称
ram_bytes: 账户内存总购买量(以相对字节为单位)net_weight: 账户带宽总抵押权重;账户带宽总抵押权重 / 全网总抵押权重 = 账户理论可使用率;对账户总抵押权重的批改也会反馈到全网总抵押权重上。cpu_weight: 账户 CPU 总抵押权重;与 net_weight 同理。
cpu_weight:账户 CPU 总抵押权重;与 net_weight 同理。
setalimits() 办法调用 set_resource_limits 函数用来对一个用户的 ram,net,cpu 资源最大应用进行设置,该函数次要是在 eosio.system 零碎合约中交易内存,只容许合约账户自身调用,只能为已在用户资源表中的账户进行资源限度设置。
资源介绍:
EOS 的资源能够分为两类:
一类是能够借给他人应用的资源:CPU,NET,有称为可转让资源;
另一类是只可能本人应用,无奈借出给别人的资源:RAM,又称为不可转让资源。
注:CPU 和 NET 在应用后能够复原,而 RAM 则不同,RAM 是固定资源,用完了须要从新购买。
为什么要应用 setalimits() 设置账号资源限度?
- EOS 网络中的资源总是无限的,而交易解决又是资源敏感的,因而,为防止资源滥用,保障网络的失常运行,必须对资源应用权限作出限度和治理。
- 资源应用中须要实现一些根底的数据限度,如单笔交易最大 CPU 限度 150ms、单个区块最大带宽限度 1M 等,通过写死的源码常量、或者 set 接口调用、或者每次交易时传参来确定;
(二)setacctram 设置内存限度
源码:
void setacctram(const name& account, const std::optional<int64_t>& ram_bytes);
参数详解:
account:账户
ram_bytes:内存限度
因为 RAM 资源无限,在具体实现时,须要设置 RAM 资源限度:单个账户限度、单笔交易限度和单个区块限度三局部,此处 setacctram() 办法设置单个账户限度,该办法只容许合约账户自身调用。
为什么要设置 RAM 限度?
RAM 对开发者来说十分宝贵,因为开发 DApp 须要占用 RAM 空间。此外 EOS 中没有地址的概念,用户如果想应用 EOS,必须在 EOS 上创立一个账户。创立 EOS 账户须要耗费内存,即 RAM。RAM 被用来进行一些非凡的 EOS 链上的操作,比方:生成新的账户、竞价 EOS 账户名拍卖等。数据库记录须要耗费 RAM,RAM 是一项贵重的资源。所以须要设置账户应用 ram 的大小。
(三)setram 设置提供的内存大小
源码:
void system_contract::setram(uint64_t max_ram_size) {require_auth( get_self() );
check(_gstate.max_ram_size < max_ram_size, "ram may only be increased"); /// decreasing ram might result market maker issues
check(max_ram_size < 1024ll*1024*1024*1024*1024, "ram size is unrealistic");
check(max_ram_size > _gstate.total_ram_bytes_reserved, "attempt to set max below reserved");
auto delta = int64_t(max_ram_size) - int64_t(_gstate.max_ram_size);
auto itr = _rammarket.find(ramcore_symbol.raw());
/**
* Increase the amount of ram for sale based upon the change in max ram size.
*/
_rammarket.modify(itr, same_payer, [&](auto& m) {m.base.balance.amount += delta;});
_gstate.max_ram_size = max_ram_size;
}
参数详解:
max_ram_size: 内存大小
max_ram_size 初始默认为 64G,setram() 办法实现了对 RAM 的一次性扩容,该办法只容许合约账户自身调用。
利用场景:
某个基于 EOS 开发的链,提供了收费的账户注册接口,执行调用后,账户收费为其抵押 CPU、NET 和购买 RAM。因为接口没有做严格无效的防刷解决,导致账户注册重大超过预期,导致链内系统资源节约重大,以及空投局部零碎代币占用过多。
解决办法:
通过 setram() 办法一次性扩增 RAM 容量
通过 setramrate() 办法设置为每块继续新增。
(四)setramrate 设置每个块内存增长速率
源码:
void system_contract::setramrate(uint16_t bytes_per_block) {require_auth( get_self() );
update_ram_supply();
_gstate2.new_ram_per_block = bytes_per_block;
}
参数详解:
bytes_per_block: 每个块的内存大小
setramrate() 办法实现了每个块内存增长速率的设置,该办法只容许合约账户自身调用。
留神:
以字节 / 块为单位设置 ram 的减少速率,其下限为 uint16。
每年的最高速率为 3TB,如果 update_ram_supply 没有被最新的块笼罩。
在切换速率之前,将以旧速率调配新的 ram 直到以后块。
(五)setpriv 设置特权开关
源码:
void system_contract::setpriv(const name& account, uint8_t ispriv) {require_auth( get_self() );
set_privileged(account, ispriv);
}
参数详解:
account: 账户
is_priv: 是否开启特权 (0 不开,>0 开启)
setpriv() 办法只容许合约账户自身调用,实现了特权开关的设置,调用胜利后,该账户成为特权帐户,能够跳过规范受权查看执行交易。
(六)setparams 设置零碎参数
1、setparams() 办法详解
源码:
void system_contract::setparams(const eosio::blockchain_parameters& params) {require_auth( get_self() );
(eosio::blockchain_parameters&)(_gstate) = params;
check(3 <= _gstate.max_authority_depth, "max_authority_depth should be at least 3");
set_blockchain_parameters(params);
}
参数详解:
params: 参数
setparams() 是公共函数,该函数设置了链参数 eosio::blockchain_parameter,只容许合约账户自身调用。
利用场景:
cpu 资源分配的算法是动静,全网 cpu 的利用率分忙时和闲时,当利用率超过肯定阈值,即为忙时。这个阈值将会应用 setparams() 办法批改,批改参数为 target_block_cpu_usage_pct。目前,eos 主网的值为 3000,即 cpu 利用率为 30%。
setparams() 办法批改链配置。可配置的参数如下:
{ "params":
{
"max_block_net_usage": 1048577,
"target_block_net_usage_pct": 1000,
"max_transaction_net_usage": 524288,
"base_per_transaction_net_usage": 12,
"net_usage_leeway": 500,
"context_free_discount_net_usage_num": 20,
"context_free_discount_net_usage_den": 100,
"max_block_cpu_usage": 200000,
"target_block_cpu_usage_pct": 1000,
"max_transaction_cpu_usage": 150000,
"min_transaction_cpu_usage": 100,
"max_transaction_lifetime": 3600,
"deferred_trx_expiration_window": 600,
"max_transaction_delay": 3888000,
"max_inline_action_size": 4096,
"max_inline_action_depth": 4,
"max_authority_depth": 6
}
}
2、blockchain_parameters 默认配置及参数详解
数据结构:
/* 区块链全局状态 */
struct eosio_global_state : public blockchain_parameters
{
uint64_t max_ram_size = 64 * 1024 * 1024 * 1024; // 64GB
uint64_t total_ram_bytes_reserved;
int64_t total_ram_stake;
block_timestamp last_porducer_schedule_update;
uint64_t last_pervote_bucket_fill;
int64_t pervote_bucket;
int64_t perblock_bucket;
uint32_t total_unpaid_blocks;
int64_t total_activated_stake_time;
uint64_t thresh_activated_stake_time;
uint16_t last_producer_schedule_size;
double total_producer_vote_weight;
block_timestamp last_name_close;
}
// 区块链参数
struct blockchain_parameters
{
uint64_t max_block_net_usage;
uint32_t target_block_net_usage_pct;
uint32_t max_transaction_net_usage;
uint32_t base_per_transaction_net_usage;
uint32_t net_usage_leeway;
uint32_t context_free_discount_net_usage_num;
uint32_t context_free_discount_net_usage_den;
uint32_t max_block_cpu_usage;
uint32_t target_block_cpu_usage_pct;
uint32_t max_transaction_cpu_usage;
uint32_t min_transaction_cpu_usage;
uint64_t context_free_discount_cpu_usage_num;
uint64_t context_free_discount_cpu_usage_den;
uint32_t max_transaction_lifetime;
uint32_t deferred_trx_expiration_window;
uint32_t max_transaction_delay;
uint32_t max_inline_action_size;
uint16_t max_inline_action_depth;
uint16_t max_authority_depth;
};
外围参数详解:
(七)setinflation 设置通胀率
源码:
void system_contract::setinflation(int64_t annual_rate, int64_t inflation_pay_factor, int64_t votepay_factor) {require_auth(get_self());
check(annual_rate >= 0, "annual_rate can't be negative");
if (inflation_pay_factor < pay_factor_precision) {check( false, "inflation_pay_factor must not be less than" + std::to_string(pay_factor_precision) );
}
if (votepay_factor < pay_factor_precision) {check( false, "votepay_factor must not be less than" + std::to_string(pay_factor_precision) );
}
_gstate4.continuous_rate = get_continuous_rate(annual_rate);
_gstate4.inflation_pay_factor = inflation_pay_factor;
_gstate4.votepay_factor = votepay_factor;
_global4.set(_gstate4, get_self() );
}
参数详解:
annual_rate: 年率(外围代币供给的年通货膨胀率)inflation_pay_factor: 通胀系数(用于处分区块生产者的通货膨胀分数的倒数)votepay_factor: 投票系数(区块生产者处分的分数与所产生的区块成比例的倒数)
相干数据结构:
static constexpr int64_t default_inflation_pay_factor = 50000;
static constexpr int64_t default_votepay_factor = 40000;
setinflation() 办法通过更改外围代币供给的年通货膨胀率,并依据以下构造指定新发行代币的调配形式实现了通胀率的设置:
例如,对于 5% 的年通货膨胀率 =>annual_rate=default_inflation_pay_factor5%=500,对于 1.5% 的年通货膨胀率 =>annual_rate=default_inflation_pay_factor 1.5%=150
设置通胀系数后会增发一部分代币,其中 20% 会用于处分生产者(会依据指定生产者所占总量的占比来调配处分),残余 80% 存储在 eosio.saving(用作 WPS 工作提案处分用)。
设置投票系数后残余的处分将依据收到的选票按比例调配。例如,其中有 25% 的量按生产者的产块量处分;75% 的量按生产者所播种的票数处分。
为什么要设置年通货膨胀率?
产块处分与代币增发的实现是通过年通货膨胀系数的设置的。
产块处分与代币增发:
在每个新的区块中,区块生产者会生成第一个交易,该交易就是 onblock,用于标记未付款的区块数(unpaid block)和更新账户竞标的信息。其发放处分的接口 claimrewards 由内部调用触发。EOSIO 也并非每年只增发一次,一次性增发全年所有的 EOS,而是采纳间断增发形式,即任何节点支付(claim)时都会触发零碎的增发动作,这也就意味着,增发是依据流动工夫长度不定期产生的。
增发代币数量计算公式:
增发代币数量 = 年通货膨胀系数(0.04879=4.879%)×以后代币发行总量×上一次增发代币到当初的时长 / 一年的微秒数
-END-