Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Token upgrade: update producer pay when max supply is reached #66

Merged
merged 5 commits into from
May 1, 2024
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
16 changes: 13 additions & 3 deletions contracts/eosio.system/src/producer_pay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ namespace eosiosystem {
void system_contract::claimrewards( const name& owner ) {
require_auth( owner );

const auto& prod = _producers.get( owner.value );
const auto& prod = _producers.get( owner.value, "producer not registered" );
check( prod.active(), "producer does not have an active key" );

check( _gstate.thresh_activated_stake_time != time_point(),
Expand All @@ -87,6 +87,8 @@ namespace eosiosystem {
check( ct - prod.last_claim_time > microseconds(useconds_per_day), "already claimed rewards within past day" );

const asset token_supply = token::get_supply(token_account, core_symbol().code() );
const asset token_max_supply = token::get_max_supply(token_account, core_symbol().code() );
const asset token_balance = token::get_balance(token_account, get_self(), core_symbol().code() );
const auto usecs_since_last_fill = (ct - _gstate.last_pervote_bucket_fill).count();

if( usecs_since_last_fill > 0 && _gstate.last_pervote_bucket_fill > time_point() ) {
Expand All @@ -101,9 +103,17 @@ namespace eosiosystem {
int64_t to_per_vote_pay = to_producers - to_per_block_pay;

if( new_tokens > 0 ) {
// issue new tokens or use existing eosio token balance
{
token::issue_action issue_act{ token_account, { {get_self(), active_permission} } };
issue_act.send( get_self(), asset(new_tokens, core_symbol()), "issue tokens for producer pay and savings" );
// issue new tokens if circulating supply does not exceed max supply
if ( token_supply.amount + new_tokens <= token_max_supply.amount ) {
token::issue_action issue_act{ token_account, { {get_self(), active_permission} } };
issue_act.send( get_self(), asset(new_tokens, core_symbol()), "issue tokens for producer pay and savings" );

// use existing eosio token balance if circulating supply exceeds max supply
} else {
check( token_balance.amount >= new_tokens, "insufficient system token balance for claiming rewards");
}
}
{
token::transfer_action transfer_act{ token_account, { {get_self(), active_permission} } };
Expand Down
47 changes: 37 additions & 10 deletions tests/eosio.system_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1612,7 +1612,7 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester, * boost::unit_test::t

// defproducerb tries to claim rewards but he's not on the list
{
BOOST_REQUIRE_EQUAL(wasm_assert_msg("unable to find key"),
BOOST_REQUIRE_EQUAL(wasm_assert_msg("producer not registered"),
push_action("defproducerb"_n, "claimrewards"_n, mvo()("owner", "defproducerb")));
}

Expand All @@ -1638,6 +1638,27 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester, * boost::unit_test::t
BOOST_REQUIRE(500 * 10000 > int64_t(double(initial_supply.get_amount()) * double(0.05)) - (supply.get_amount() - initial_supply.get_amount()));
BOOST_REQUIRE(500 * 10000 > int64_t(double(initial_supply.get_amount()) * double(0.04)) - (savings - initial_savings));
}

// test claimrewards when max supply is reached
{
produce_block(fc::hours(24));

const asset before_supply = get_token_supply();
const asset before_system_balance = get_balance(config::system_account_name);
const asset before_producer_balance = get_balance("defproducera"_n);

setmaxsupply( before_supply );
BOOST_REQUIRE_EQUAL(success(), push_action("defproducera"_n, "claimrewards"_n, mvo()("owner", "defproducera")));

const asset after_supply = get_token_supply();
const asset after_system_balance = get_balance(config::system_account_name);
const asset after_producer_balance = get_balance("defproducera"_n);

BOOST_REQUIRE_EQUAL(after_supply.get_amount() - before_supply.get_amount(), 0);
BOOST_REQUIRE_EQUAL(after_system_balance.get_amount() - before_system_balance.get_amount(), -1407793756);
BOOST_REQUIRE_EQUAL(after_producer_balance.get_amount() - before_producer_balance.get_amount(), 281558751);
}

} FC_LOG_AND_RETHROW()

BOOST_FIXTURE_TEST_CASE(change_inflation, eosio_system_tester) try {
Expand Down Expand Up @@ -1738,7 +1759,8 @@ BOOST_FIXTURE_TEST_CASE(change_inflation, eosio_system_tester) try {
BOOST_AUTO_TEST_CASE(extreme_inflation) try {
eosio_system_tester t(eosio_system_tester::setup_level::minimal);
symbol core_symbol{CORE_SYM};
t.create_currency( "eosio.token"_n, config::system_account_name, asset((1ll << 62) - 1, core_symbol) );
const asset max_supply = asset((1ll << 62) - 1, core_symbol);
t.create_currency( "eosio.token"_n, config::system_account_name, max_supply );
t.issue( asset(10000000000000, core_symbol) );
t.deploy_contract();
t.produce_block();
Expand All @@ -1752,25 +1774,30 @@ BOOST_AUTO_TEST_CASE(extreme_inflation) try {

BOOST_REQUIRE_EQUAL(t.success(), t.push_action("defproducera"_n, "claimrewards"_n, mvo()("owner", "defproducera")));
t.produce_block();
asset current_supply;
{
vector<char> data = t.get_row_by_account( "eosio.token"_n, name(core_symbol.to_symbol_code().value), "stat"_n, account_name(core_symbol.to_symbol_code().value) );
current_supply = t.token_abi_ser.binary_to_variant("currency_stats", data, abi_serializer::create_yield_function(eosio_system_tester::abi_serializer_max_time))["supply"].template as<asset>();
}
t.issue( asset((1ll << 62) - 1, core_symbol) - current_supply );
const asset current_supply = t.get_token_supply();
t.issue( max_supply - current_supply );

// empty system balance
// claimrewards operates by either `issue` new tokens or using the existing system balance
const asset system_balance = t.get_balance(config::system_account_name);
t.transfer( config::system_account_name, "eosio.null"_n, system_balance, config::system_account_name);
BOOST_REQUIRE_EQUAL(t.get_balance(config::system_account_name).get_amount(), 0);
BOOST_REQUIRE_EQUAL(t.get_token_supply().get_amount() - max_supply.get_amount(), 0);

// set maximum inflation
BOOST_REQUIRE_EQUAL(t.success(), t.setinflation(std::numeric_limits<int64_t>::max(), 50000, 40000));
t.produce_block();

t.produce_block(fc::hours(10*24));
BOOST_REQUIRE_EQUAL(t.wasm_assert_msg("quantity exceeds available supply"), t.push_action("defproducera"_n, "claimrewards"_n, mvo()("owner", "defproducera")));
BOOST_REQUIRE_EQUAL(t.wasm_assert_msg("insufficient system token balance for claiming rewards"), t.push_action("defproducera"_n, "claimrewards"_n, mvo()("owner", "defproducera")));

t.produce_block(fc::hours(11*24));
BOOST_REQUIRE_EQUAL(t.wasm_assert_msg("magnitude of asset amount must be less than 2^62"), t.push_action("defproducera"_n, "claimrewards"_n, mvo()("owner", "defproducera")));

t.produce_block(fc::hours(24));
BOOST_REQUIRE_EQUAL(t.wasm_assert_msg("overflow in calculating new tokens to be issued; inflation rate is too high"), t.push_action("defproducera"_n, "claimrewards"_n, mvo()("owner", "defproducera")));
BOOST_REQUIRE_EQUAL(t.success(), t.setinflation(500, 50000, 40000));
BOOST_REQUIRE_EQUAL(t.wasm_assert_msg("quantity exceeds available supply"), t.push_action("defproducera"_n, "claimrewards"_n, mvo()("owner", "defproducera")));
BOOST_REQUIRE_EQUAL(t.wasm_assert_msg("insufficient system token balance for claiming rewards"), t.push_action("defproducera"_n, "claimrewards"_n, mvo()("owner", "defproducera")));
} FC_LOG_AND_RETHROW()

BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::unit_test::tolerance(1e-10)) try {
Expand Down
Loading