提交 5ef1d2f2 编写于 作者: K Khaled Al-Hassanieh

Refactored stanby producer payment

上级 44e7d3ef
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosiolib/eosio.hpp>
#include <eosiolib/multi_index.hpp>
#include <eosiolib/privileged.hpp>
#include <eosiolib/singleton.hpp>
#include <eosiolib/asset.hpp>
#include <eosio.token/eosio.token.hpp>
namespace eosiosystem {
template<account_name SystemAccount>
class common {
public:
static constexpr account_name system_account = SystemAccount;
static constexpr uint32_t blocks_per_producer = 12;
static constexpr uint32_t seconds_per_day = 24 * 3600;
static constexpr uint32_t days_per_4years = 1461;
static eosio_global_state& get_default_parameters() {
static eosio_global_state dp;
get_blockchain_parameters(dp);
return dp;
}
};
}
......@@ -105,7 +105,7 @@ namespace eosiosystem {
typedef eosio::singleton<N(global), eosio_global_state> global_state_singleton;
static constexpr uint32_t max_inflation_rate = 5; // 5% annual inflation
// static constexpr uint32_t max_inflation_rate = 5; // 5% annual inflation
static constexpr uint32_t seconds_per_day = 24 * 3600;
static constexpr uint64_t system_token_symbol = S(4,EOS);
......@@ -187,7 +187,9 @@ namespace eosiosystem {
void claimrewards( const account_name& owner );
private:
eosio::asset payment_per_block(uint32_t percent_of_max_inflation_rate);
eosio::asset payment_per_block( double rate );
eosio::asset payment_per_vote( const account_name& owner, double owners_votes, const eosio::asset& eos_bucket );
void update_elected_producers(time cycle_time);
......
......@@ -4,8 +4,16 @@
namespace eosiosystem {
static const uint32_t num_of_payed_producers = 121;
const int64_t min_daily_tokens = 100;
const double continuous_rate = std::log1p(5);
const uint32_t blocks_per_year = 52*7*24*2*3600; // half seconds per year
const uint32_t blocks_per_hour = 2 * 3600;
eosio::asset system_contract::payment_per_block( double rate ) {
const eosio::asset token_supply = eosio::token( N(eosio.token)).get_supply(eosio::symbol_type(system_token_symbol).name() );
const int64_t payment = static_cast<int64_t>( (rate * double(token_supply.amount)) / double(blocks_per_year) );
return eosio::asset(payment, system_token_symbol);
}
void system_contract::onblock( block_timestamp timestamp, account_name producer ) {
......@@ -27,7 +35,6 @@ void system_contract::onblock( block_timestamp timestamp, account_name producer
producers_table producers_tbl( _self, _self );
// const system_token_type block_payment = parameters.payment_per_block;
const asset block_payment = parameters.payment_per_block;
auto prod = producers_tbl.find(producer);
if ( prod != producers_tbl.end() ) {
......@@ -38,68 +45,88 @@ void system_contract::onblock( block_timestamp timestamp, account_name producer
}
const uint32_t num_of_payments = timestamp - parameters.last_bucket_fill_time;
// const system_token_type to_eos_bucket = num_of_payments * parameters.payment_to_eos_bucket;
const asset to_eos_bucket = num_of_payments * parameters.payment_to_eos_bucket;
parameters.last_bucket_fill_time = timestamp;
parameters.eos_bucket += to_eos_bucket;
gs.set( parameters, _self );
}
void system_contract::claimrewards(const account_name& owner) {
eosio::asset system_contract::payment_per_vote( const account_name& owner, double owners_votes, const eosio::asset& eos_bucket ) {
eosio::asset payment(0, S(4,EOS));
if (eos_bucket < threshold) {
return payment;
}
auto idx = _producers.template get_index<N(prototalvote)>();
double total_producer_votes = 0;
double running_payment_amount = 0;
bool to_be_payed = false;
for ( auto itr = idx.begin(); itr != idx.end(); ++itr ) {
if ( !(itr->total_votes > 0) ) {
break;
}
if ( !(itr->active()) && !(itr->owner != owner) ) {
continue;
}
if ( itr->owner == owner ) {
to_be_payed = true;
}
total_producer_votes += itr->total_votes;
running_payment_amount = (itr->total_votes) * double(eos_bucket.amount) / total_producer_votes;
if ( running_payment_amount < min_daily_tokens ) {
if ( itr->owner == owner ) {
to_be_payed = false;
}
total_producer_votes -= itr->total_votes;
break;
}
}
if ( to_be_payed ) {
payment.amount = static_cast<int64_t>( (double(eos_bucket.amount) * owners_votes) / total_producer_votes );
}
return payment;
}
void system_contract::claimrewards( const account_name& owner ) {
require_auth(owner);
producers_table producers_tbl( _self, _self );
auto prod = producers_tbl.find(owner);
auto prod = producers_tbl.find( owner );
eosio_assert(prod != producers_tbl.end(), "account name is not in producer list");
if( prod->last_rewards_claim > 0 ) {
eosio_assert(now() >= prod->last_rewards_claim + seconds_per_day, "already claimed rewards within a day");
}
// system_token_type rewards = prod->per_block_payments;
eosio::asset rewards = prod->per_block_payments;
auto idx = producers_tbl.template get_index<N(prototalvote)>();
auto itr = --idx.end();
bool is_among_payed_producers = false;
uint128_t total_producer_votes = 0;
uint32_t n = 0;
while( n < num_of_payed_producers ) {
if( !is_among_payed_producers ) {
if( itr->owner == owner )
is_among_payed_producers = true;
}
if( itr->active() ) {
total_producer_votes += itr->total_votes;
++n;
}
if( itr == idx.begin() ) {
break;
}
--itr;
}
if (is_among_payed_producers && total_producer_votes > 0) {
global_state_singleton gs( _self, _self );
if( gs.exists() ) {
auto parameters = gs.get();
// auto share_of_eos_bucket = system_token_type( static_cast<uint64_t>( (prod->total_votes * parameters.eos_bucket.quantity) / total_producer_votes ) ); // This will be improved in the future when total_votes becomes a double type.
auto share_of_eos_bucket = eosio::asset( static_cast<int64_t>( (prod->total_votes * parameters.eos_bucket.amount) / total_producer_votes ) );
rewards += share_of_eos_bucket;
parameters.eos_bucket -= share_of_eos_bucket;
gs.set( parameters, _self );
global_state_singleton gs( _self, _self );
if ( gs.exists() ) {
auto parameters = gs.get();
if ( parameters.eos_bucket.amount > 0 && prod->total_votes > 0 ) {
eosio::asset standby_payment = payment_per_vote( owner, prod->total_votes, parameters.eos_bucket );
if ( standby_payment.amount > 0 ) {
rewards += standby_payment;
parameters.eos_bucket -= standby_payment;
gs.set( parameters, _self );
}
}
}
// eosio_assert( rewards > system_token_type(), "no rewards available to claim" );
eosio_assert( rewards > asset(0, S(4,EOS)), "no rewards available to claim" );
producers_tbl.modify( prod, 0, [&](auto& p) {
p.last_rewards_claim = now();
p.per_block_payments.amount = 0;
});
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), owner, rewards, std::string("producer claiming rewards") } );
}
} //namespace eosiosystem
......@@ -27,7 +27,6 @@ namespace eosiosystem {
using eosio::transaction;
static constexpr uint32_t blocks_per_year = 52*7*24*2*3600; // half seconds per year
static constexpr uint32_t blocks_per_producer = 12;
......@@ -71,15 +70,6 @@ namespace eosiosystem {
});
}
eosio::asset system_contract::payment_per_block(uint32_t percent_of_max_inflation_rate) {
const eosio::asset token_supply = eosio::token(N(eosio.token)).get_supply(eosio::symbol_type(system_token_symbol).name());
const double annual_rate = double(max_inflation_rate * percent_of_max_inflation_rate) / double(10000);
const double continuous_rate = std::log1p(annual_rate);
int64_t payment = static_cast<int64_t>((continuous_rate * double(token_supply.amount)) / double(blocks_per_year));
return eosio::asset(payment, system_token_symbol);
}
void system_contract::update_elected_producers(time cycle_time) {
auto idx = _producers.get_index<N(prototalvote)>();
......
......@@ -49,7 +49,7 @@ public:
produce_blocks();
create_account_with_resources( N(alice), N(eosio), asset::from_string("1.0000 EOS"), false );//{ N(alice), N(bob), N(carol) } );
create_account_with_resources( N(alice), N(eosio), asset::from_string("100.0000 EOS"), false );//{ N(alice), N(bob), N(carol) } );
create_account_with_resources( N(bob), N(eosio), asset::from_string("0.4500 EOS"), false );//{ N(alice), N(bob), N(carol) } );
create_account_with_resources( N(carol), N(eosio), asset::from_string("1.0000 EOS"), false );//{ N(alice), N(bob), N(carol) } );
BOOST_REQUIRE_EQUAL( asset::from_string("1000000000.0000 EOS"), get_balance( "eosio" ) );
......@@ -944,7 +944,7 @@ BOOST_FIXTURE_TEST_CASE( producer_keep_votes, eosio_system_tester ) try {
BOOST_FIXTURE_TEST_CASE( vote_for_two_producers, eosio_system_tester ) try {
//alice becomes a producer
fc::variant params = producer_parameters_example(1);
vector<char> key = fc::raw::pack( get_public_key( N(alice), "active" ) );
auto key = get_public_key( N(alice), "active" );
BOOST_REQUIRE_EQUAL( success(), push_action( N(alice), N(regproducer), mvo()
("producer", "alice")
("producer_key", get_public_key( N(alice), "active") )
......@@ -953,7 +953,7 @@ BOOST_FIXTURE_TEST_CASE( vote_for_two_producers, eosio_system_tester ) try {
);
//bob becomes a producer
params = producer_parameters_example(2);
key = fc::raw::pack( get_public_key( N(bob), "active" ) );
key = get_public_key( N(bob), "active" );
BOOST_REQUIRE_EQUAL( success(), push_action( N(bob), N(regproducer), mvo()
("producer", "bob")
("producer_key", get_public_key( N(alice), "active") )
......@@ -1166,19 +1166,13 @@ BOOST_FIXTURE_TEST_CASE( proxy_actions_affect_producers, eosio_system_tester ) t
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester) try {
issue( "alice", "100.0000 EOS", config::system_account_name);
BOOST_REQUIRE_EQUAL( asset::from_string("100.0000 EOS"), get_balance( "alice" ) );
issue( "alice", "10000.0000 EOS", config::system_account_name);
BOOST_REQUIRE_EQUAL( asset::from_string("10000.0000 EOS"), get_balance( "alice" ) );
fc::variant params = producer_parameters_example(50);
// 1 block produced
BOOST_REQUIRE_EQUAL(success(), push_action(N(alice), N(regproducer), mvo()
("producer", "alice")
("producer_key", get_public_key( N(alice), "active") )
("url", "")
)
);
BOOST_REQUIRE_EQUAL(success(), regproducer(N(alice)));
auto prod = get_producer_info( N(alice) );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册