Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
producer_pay.cpp
Go to the documentation of this file.
3
4namespace sysiosystem {
5
6 using sysio::current_time_point;
8 using sysio::token;
9
10 void system_contract::onblock( ignore<block_header> ) {
11 using namespace sysio;
12
13 require_auth(get_self());
14
15 // Deserialize needed fields from block header.
16 block_timestamp timestamp;
17 name producer;
18 uint16_t confirmed;
19 checksum256 previous_block_id;
20
21 _ds >> timestamp >> producer >> confirmed >> previous_block_id;
22 (void)confirmed; // Only to suppress warning since confirmed is not used.
23
24 // Add latest block information to blockinfo table.
25 add_to_blockinfo_table(previous_block_id, timestamp);
26
27 // _gstate2.last_block_num is not used anywhere in the system contract code anymore.
28 // Although this field is deprecated, we will continue updating it for now until the last_block_num field
29 // is eventually completely removed, at which point this line can be removed.
30 _gstate2.last_block_num = timestamp;
31
34 return;
35
36 if( _gstate.last_pervote_bucket_fill == time_point() )
37 _gstate.last_pervote_bucket_fill = current_time_point();
38
39
44 auto prod = _producers.find( producer.value );
45 if ( prod != _producers.end() ) {
46 _gstate.total_unpaid_blocks++;
47 _producers.modify( prod, same_payer, [&](auto& p ) {
48 p.unpaid_blocks++;
49 });
50 }
51
53 if( timestamp.slot - _gstate.last_producer_schedule_update.slot > 120 ) {
54 update_elected_producers( timestamp );
55
56 if( (timestamp.slot - _gstate.last_name_close.slot) > blocks_per_day ) {
57 name_bid_table bids(get_self(), get_self().value);
58 auto idx = bids.get_index<"highbid"_n>();
59 auto highest = idx.lower_bound( std::numeric_limits<uint64_t>::max()/2 );
60 if( highest != idx.end() &&
61 highest->high_bid > 0 &&
62 (current_time_point() - highest->last_bid_time) > microseconds(useconds_per_day) &&
64 (current_time_point() - _gstate.thresh_activated_stake_time) > microseconds(14 * useconds_per_day)
65 ) {
66 _gstate.last_name_close = timestamp;
67 channel_namebid_to_rex( highest->high_bid );
68 idx.modify( highest, same_payer, [&]( auto& b ){
69 b.high_bid = -b.high_bid;
70 });
71 }
72 }
73 }
74 }
75
76 void system_contract::claimrewards( const name& owner ) {
77 require_auth( owner );
78
79 const auto& prod = _producers.get( owner.value );
80 check( prod.active(), "producer does not have an active key" );
81
82 check( _gstate.thresh_activated_stake_time != time_point(),
83 "cannot claim rewards until the chain is activated (at least 15% of all tokens participate in voting)" );
84
85 const auto ct = current_time_point();
86
87 check( ct - prod.last_claim_time > microseconds(useconds_per_day), "already claimed rewards within past day" );
88
89 const asset token_supply = token::get_supply(token_account, core_symbol().code() );
90 const auto usecs_since_last_fill = (ct - _gstate.last_pervote_bucket_fill).count();
91
92 if( usecs_since_last_fill > 0 && _gstate.last_pervote_bucket_fill > time_point() ) {
93 double additional_inflation = (_gstate4.continuous_rate * double(token_supply.amount) * double(usecs_since_last_fill)) / double(useconds_per_year);
94 check( additional_inflation <= double(std::numeric_limits<int64_t>::max() - ((1ll << 10) - 1)),
95 "overflow in calculating new tokens to be issued; inflation rate is too high" );
96 int64_t new_tokens = (additional_inflation < 0.0) ? 0 : static_cast<int64_t>(additional_inflation);
97
98 int64_t to_producers = (new_tokens * uint128_t(pay_factor_precision)) / _gstate4.inflation_pay_factor;
99 int64_t to_savings = new_tokens - to_producers;
100 int64_t to_per_block_pay = (to_producers * uint128_t(pay_factor_precision)) / _gstate4.votepay_factor;
101 int64_t to_per_vote_pay = to_producers - to_per_block_pay;
102
103 if( new_tokens > 0 ) {
104 {
105 token::issue_action issue_act{ token_account, { {get_self(), active_permission} } };
106 issue_act.send( get_self(), asset(new_tokens, core_symbol()), "issue tokens for producer pay and savings" );
107 }
108 {
109 token::transfer_action transfer_act{ token_account, { {get_self(), active_permission} } };
110 if( to_savings > 0 ) {
111 transfer_act.send( get_self(), saving_account, asset(to_savings, core_symbol()), "unallocated inflation" );
112 }
113 if( to_per_block_pay > 0 ) {
114 transfer_act.send( get_self(), bpay_account, asset(to_per_block_pay, core_symbol()), "fund per-block bucket" );
115 }
116 if( to_per_vote_pay > 0 ) {
117 transfer_act.send( get_self(), vpay_account, asset(to_per_vote_pay, core_symbol()), "fund per-vote bucket" );
118 }
119 }
120 }
121
122 _gstate.pervote_bucket += to_per_vote_pay;
123 _gstate.perblock_bucket += to_per_block_pay;
124 _gstate.last_pervote_bucket_fill = ct;
125 }
126
127 auto prod2 = _producers2.find( owner.value );
128
131 const auto last_claim_plus_3days = prod.last_claim_time + microseconds(3 * useconds_per_day);
132
133 bool crossed_threshold = (last_claim_plus_3days <= ct);
134 bool updated_after_threshold = true;
135 if ( prod2 != _producers2.end() ) {
136 updated_after_threshold = (last_claim_plus_3days <= prod2->last_votepay_share_update);
137 } else {
138 prod2 = _producers2.emplace( owner, [&]( producer_info2& info ) {
139 info.owner = owner;
140 info.last_votepay_share_update = ct;
141 });
142 }
143
144 // Note: updated_after_threshold implies cross_threshold (except if claiming rewards when the producers2 table row did not exist).
145 // The exception leads to updated_after_threshold to be treated as true regardless of whether the threshold was crossed.
146 // This is okay because in this case the producer will not get paid anything either way.
147 // In fact it is desired behavior because the producers votes need to be counted in the global total_producer_votepay_share for the first time.
148
149 int64_t producer_per_block_pay = 0;
150 if( _gstate.total_unpaid_blocks > 0 ) {
151 producer_per_block_pay = (_gstate.perblock_bucket * prod.unpaid_blocks) / _gstate.total_unpaid_blocks;
152 }
153
154 double new_votepay_share = update_producer_votepay_share( prod2,
155 ct,
156 updated_after_threshold ? 0.0 : prod.total_votes,
157 true // reset votepay_share to zero after updating
158 );
159
160 int64_t producer_per_vote_pay = 0;
161 if( _gstate2.revision > 0 ) {
162 double total_votepay_share = update_total_votepay_share( ct );
163 if( total_votepay_share > 0 && !crossed_threshold ) {
164 producer_per_vote_pay = int64_t((new_votepay_share * _gstate.pervote_bucket) / total_votepay_share);
165 if( producer_per_vote_pay > _gstate.pervote_bucket )
166 producer_per_vote_pay = _gstate.pervote_bucket;
167 }
168 } else {
169 if( _gstate.total_producer_vote_weight > 0 ) {
170 producer_per_vote_pay = int64_t((_gstate.pervote_bucket * prod.total_votes) / _gstate.total_producer_vote_weight);
171 }
172 }
173
174 if( producer_per_vote_pay < min_pervote_daily_pay ) {
175 producer_per_vote_pay = 0;
176 }
177
178 _gstate.pervote_bucket -= producer_per_vote_pay;
179 _gstate.perblock_bucket -= producer_per_block_pay;
180 _gstate.total_unpaid_blocks -= prod.unpaid_blocks;
181
182 update_total_votepay_share( ct, -new_votepay_share, (updated_after_threshold ? prod.total_votes : 0.0) );
183
184 _producers.modify( prod, same_payer, [&](auto& p) {
185 p.last_claim_time = ct;
186 p.unpaid_blocks = 0;
187 });
188
189 if ( producer_per_block_pay > 0 ) {
191 transfer_act.send( bpay_account, owner, asset(producer_per_block_pay, core_symbol()), "producer block pay" );
192 }
193 if ( producer_per_vote_pay > 0 ) {
195 transfer_act.send( vpay_account, owner, asset(producer_per_vote_pay, core_symbol()), "producer vote pay" );
196 }
197 }
198
199} //namespace sysiosystem
const mie::Vuint & p
Definition bn.cpp:27
sysio::action_wrapper<"issue"_n, &token::issue > issue_action
sysio::action_wrapper<"transfer"_n, &token::transfer > transfer_action
static asset get_supply(const name &token_contract_account, const symbol_code &sym_code)
static constexpr sysio::name token_account
static constexpr sysio::name active_permission
static constexpr sysio::name vpay_account
void onblock(ignore< block_header > header)
static constexpr sysio::name saving_account
void claimrewards(const name &owner)
static constexpr sysio::name bpay_account
int * count
__uint128_t uint128_t
Definition config.hpp:8
sysio::multi_index< "namebids"_n, name_bid, indexed_by<"highbid"_n, const_mem_fun< name_bid, uint64_t, &name_bid::by_high_bid > > > name_bid_table
#define value
Definition pkcs11.h:157
unsigned short uint16_t
Definition stdint.h:125
signed __int64 int64_t
Definition stdint.h:135
Immutable except for fc::from_variant.
Definition name.hpp:43
uint8_t revision
used to track version updates in the future.
block_timestamp last_producer_schedule_update
block_timestamp last_name_close
the sum of all producer votes