Skip to content
This repository was archived by the owner on Aug 2, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions contracts/eosio.system/eosio.system.abi
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,27 @@
"name": "eosio_global_state",
"base": "eosio_parameters",
"fields": [
{"name":"total_ram_bytes_reserved", "type":"uint64"},
{"name":"total_ram_stake", "type":"uint64"},
{"name":"payment_per_block", "type":"uint64"}
{"name":"total_ram_bytes_reserved", "type":"uint64"},
{"name":"total_ram_stake", "type":"asset"},
{"name":"last_producer_schedule_update", "type":"time"},
{"name":"last_pervote_bucket_fill", "type":"time"},
{"name":"eos_bucket", "type":"asset"},
{"name":"savings", "type":"asset"},
{"name":"last_producer_schedule_id", "type":"checksum160"},
{"name":"total_activatied_stake", "type":"int64"}
]
},{
"name": "producer_info",
"base": "",
"fields": [
{"name":"owner", "type":"account_name"},
{"name":"total_votes", "type":"uint128"},
{"name":"packed_key", "type":"public_key"},
{"name":"per_block_payments", "type":"uint64"},
{"name":"last_claim_time", "type":"time"}
{"name":"owner", "type":"account_name"},
{"name":"total_votes", "type":"float64"},
{"name":"producer_key", "type":"public_key"},
{"name":"produced_blocks", "type":"uint32"},
{"name":"last_claim_time", "type":"time"},
{"name":"location", "type":"uint16"},
{"name":"time_became_active", "type":"time"},
{"name":"last_produced_block_time", "type":"time"}
]
},{
"name": "regproducer",
Expand Down Expand Up @@ -179,7 +187,7 @@
{"name":"owner", "type":"account_name"},
{"name":"proxy", "type":"account_name"},
{"name":"producers", "type":"account_name[]"},
{"name":"staked", "type":"uint64"},
{"name":"staked", "type":"int64"},
{"name":"last_vote_weight", "type":"float64"},
{"name":"proxied_vote_weight", "type":"float64"},
{"name":"is_proxy", "type":"bool"},
Expand Down
14 changes: 8 additions & 6 deletions contracts/eosio.system/eosio.system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,26 @@ namespace eosiosystem {
eosio::asset total_ram_stake;

block_timestamp last_producer_schedule_update = 0;
block_timestamp last_pervote_bucket_fill = 0;
time last_pervote_bucket_fill = 0;
eosio::asset eos_bucket;
eosio::asset savings;
checksum160 last_producer_schedule_id;

int64_t total_activiated_stake = 0;
int64_t total_activated_stake = 0;

// explicit serialization macro is not necessary, used here only to improve compilation time
EOSLIB_SERIALIZE_DERIVED( eosio_global_state, eosio_parameters, (total_ram_bytes_reserved)(total_ram_stake)
(last_producer_schedule_update)
(last_pervote_bucket_fill)
(eos_bucket)(savings)(last_producer_schedule_id)(total_activiated_stake) )
(eos_bucket)(savings)(last_producer_schedule_id)(total_activated_stake) )
};

struct producer_info {
account_name owner;
double total_votes = 0;
eosio::public_key producer_key; /// a packed public key object
uint32_t produced_blocks;
time last_rewards_claim = 0;
time last_claim_time = 0;
uint16_t location = 0;
block_timestamp time_became_active = 0;
block_timestamp last_produced_block_time = 0;
Expand All @@ -62,7 +62,7 @@ namespace eosiosystem {

// explicit serialization macro is not necessary, used here only to improve compilation time
EOSLIB_SERIALIZE( producer_info, (owner)(total_votes)(producer_key)
(produced_blocks)(last_rewards_claim)
(produced_blocks)(last_claim_time)(location)
(time_became_active)(last_produced_block_time) )
};

Expand Down Expand Up @@ -188,9 +188,11 @@ namespace eosiosystem {
void claimrewards( const account_name& owner );

private:
eosio::asset payment_per_block( double rate, const eosio::asset& token_supply );
eosio::asset payment_per_block( double rate, const eosio::asset& token_supply, uint32_t num_blocks );

eosio::asset payment_per_vote( const account_name& owner, double owners_votes, const eosio::asset& eos_bucket );

eosio::asset supply_growth( double rate, const eosio::asset& token_supply, time seconds );

void update_elected_producers( block_timestamp timestamp );

Expand Down
118 changes: 49 additions & 69 deletions contracts/eosio.system/producer_pay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,69 +5,48 @@
namespace eosiosystem {

const int64_t min_daily_tokens = 100;
/*
const double continuous_rate = std::log1p(0.05); // 5% annual rate
const double per_block_rate = 0.0025; // 0.25%

const double continuous_rate = 0.04879; // 5% annual rate
const double perblock_rate = 0.0025; // 0.25%
const double standby_rate = 0.0075; // 0.75%
const uint32_t blocks_per_year = 52*7*24*2*3600; // half seconds per year
const uint32_t seconds_per_year = 52*7*24*3600;
const uint32_t blocks_per_day = 2 * 24 * 3600;
const uint32_t blocks_per_hour = 2 * 3600;

eosio::asset system_contract::payment_per_block( double rate, const eosio::asset& token_supply, uint32_t num_blocks ) {
const int64_t payment = static_cast<int64_t>( (rate * double(token_supply.amount) * double(num_blocks)) / double(blocks_per_year) );
return eosio::asset( payment, token_supply.symbol );
}

eosio::asset system_contract::payment_per_block( double rate, const eosio::asset& token_supply ) {
const int64_t payment = static_cast<int64_t>( (rate * double(token_supply.amount)) / double(blocks_per_year) );
eosio::asset system_contract::supply_growth( double rate, const eosio::asset& token_supply, time seconds ) {
const int64_t payment = static_cast<int64_t>( (rate * double(token_supply.amount) * double(seconds)) / double(seconds_per_year) );
return eosio::asset( payment, token_supply.symbol );
}
*/


void system_contract::onblock( block_timestamp timestamp, account_name producer ) {
using namespace eosio;

/** until activated stake crosses this threshold no new rewards are paid */
if( _gstate.total_activiated_stake < 150'000'000'0000 )
if( _gstate.total_activated_stake < 150'000'000'0000 )
return;

if( _gstate.last_pervote_bucket_fill == 0 ) /// start the presses
_gstate.last_pervote_bucket_fill = timestamp;

_producers.modify( _producers.get(producer), 0, [&](auto& p ) {
p.produced_blocks++;
p.last_produced_block_time = timestamp;
});
auto prod = _producers.find(producer);
if ( prod != _producers.end() ) {
_producers.modify( prod, 0, [&](auto& p ) {
p.produced_blocks++;
p.last_produced_block_time = timestamp;
});
}

/// only update block producers once every minute, block_timestamp is in half seconds
if( timestamp - _gstate.last_producer_schedule_update > 120 ) {
update_elected_producers( timestamp );
}

/// only update block producers once every minute, block_timestamp is in half seconds
/*
if( timestamp % 120 != 0 )
return;

const asset token_supply = token( N(eosio.token)).get_supply(symbol_type(system_token_symbol).name() );
const asset issued = payment_per_block( continuous_rate, token_supply );
const asset producer_payment = payment_per_block( per_block_rate, token_supply );
const asset to_eos_bucket = payment_per_block( standby_rate, token_supply );
const asset to_savings = issued - (producer_payment + to_eos_bucket);

INLINE_ACTION_SENDER(eosio::token, issue)( N(eosio.token), {{N(eosio),N(active)}},
{N(eosio), issued, std::string("issue tokens per block")} );
*/

/*
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {{N(eosio),N(active)}},
{N(eosio), N(eosio), to_savings, std::string("transfer to savings per block")} );


auto parameters = _global.exists() ? _global.get() : get_default_parameters();
parameters.eos_bucket += to_eos_bucket;
parameters.savings += to_savings;
_global.set ( parameters, _self );

const auto& producer_schedule_update = parameters.last_producer_schedule_update;
if ( producer_schedule_update == 0 || producer_schedule_update < timestamp + blocks_per_hour ) {
update_elected_producers( producer_schedule_update );
}
*/
}

eosio::asset system_contract::payment_per_vote( const account_name& owner, double owners_votes, const eosio::asset& eos_bucket ) {
Expand Down Expand Up @@ -112,42 +91,43 @@ namespace eosiosystem {
}

void system_contract::claimrewards( const account_name& owner ) {
using namespace eosio;

require_auth(owner);

auto prod = _producers.find( owner );
eosio_assert( prod != _producers.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");
if( prod->last_claim_time > 0 ) {
eosio_assert(now() >= prod->last_claim_time + seconds_per_day, "already claimed rewards within a day");
}

/// calcualte the price-per-block

/*
eosio::asset rewards = prod->per_block_payments;

if ( _global.exists() ) {
auto parameters = _global.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;
_global.set( parameters, _self );
}
}
}
auto parameters = _global.get();
const asset token_supply = token( N(eosio.token)).get_supply(symbol_type(system_token_symbol).name() );
const time time_since_last_fill = now() - parameters.last_pervote_bucket_fill;

const asset to_eos_bucket = supply_growth( standby_rate, token_supply, time_since_last_fill );
const asset to_savings = supply_growth( continuous_rate - (perblock_rate + standby_rate), token_supply, time_since_last_fill );
const asset perblock_pay = payment_per_block( perblock_rate, token_supply, prod->produced_blocks );
const asset issue_amount = to_eos_bucket + to_savings + perblock_pay;

eosio_assert( rewards > asset(0, S(4,EOS)), "no rewards available to claim" );
INLINE_ACTION_SENDER(eosio::token, issue)( N(eosio.token), {{N(eosio),N(active)}},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the memo is wrong here, some of these tokens are to savings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed memo

{N(eosio), issue_amount, std::string("issue tokens for producer pay and savings")} );

const asset pervote_pay = payment_per_vote( owner, prod->total_votes, to_eos_bucket + parameters.eos_bucket );

parameters.eos_bucket += ( to_eos_bucket - pervote_pay );
parameters.last_pervote_bucket_fill = now();
parameters.savings += to_savings;
_global.set( parameters, _self );

INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), owner, perblock_pay + pervote_pay, std::string("producer claiming rewards") } );

_producers.modify( prod, 0, [&](auto& p) {
p.last_rewards_claim = now();
p.last_claim_time = now();
p.produced_blocks = 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
4 changes: 2 additions & 2 deletions contracts/eosio.system/voting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,11 @@ namespace eosiosystem {

/**
* The first time someone votes we calculate and set last_vote_weight, since they cannot unstake until
* after total_activiated_stake hits threshold, we can use last_vote_weight to determine that this is
* after total_activated_stake hits threshold, we can use last_vote_weight to determine that this is
* their first vote and should consider their stake activated.
*/
if( voter->last_vote_weight <= 0.0 ) {
_gstate.total_activiated_stake += voter->staked;
_gstate.total_activated_stake += voter->staked;
}

auto weight = int64_t(now() / (seconds_per_day * 7)) / double( 52 );
Expand Down
11 changes: 4 additions & 7 deletions unittests/eosio.system_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,17 +1169,13 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester) try {
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(), regproducer(N(alice)));

auto prod = get_producer_info( N(alice) );

BOOST_REQUIRE_EQUAL("alice", prod["owner"].as_string());
BOOST_REQUIRE_EQUAL(0, prod["total_votes"].as_uint64());
REQUIRE_EQUAL_OBJECTS(params, prod["prefs"]);


issue("bob", "2000.0000 EOS", config::system_account_name);
BOOST_REQUIRE_EQUAL( asset::from_string("2000.0000 EOS"), get_balance( "bob" ) );
Expand All @@ -1198,15 +1194,16 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester) try {
)
);

produce_blocks(10);
produce_blocks(20);
prod = get_producer_info("alice");
BOOST_REQUIRE(prod["per_block_payments"].as_uint64() > 0);
// this test fails as there isn't enough total activated stake and onblock is a noop
BOOST_REQUIRE(prod["produced_blocks"].as<uint32_t>() > 0);
BOOST_REQUIRE_EQUAL(success(), push_action(N(alice), N(claimrewards), mvo()
("owner", "alice")
)
);
prod = get_producer_info("alice");
BOOST_REQUIRE_EQUAL(0, prod["per_block_payments"].as_uint64());
BOOST_REQUIRE_EQUAL(0, prod["produced_blocks"].as<uint32_t>());

} FC_LOG_AND_RETHROW()

Expand Down