Skip to content

Commit

Permalink
adjust chain inflation (#84)
Browse files Browse the repository at this point in the history
* adjust chain inflation

* add more tests

* burn the excess inflation token

* update
  • Loading branch information
quocle108 authored Nov 23, 2023
1 parent 4e98ad9 commit 4195977
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 6 deletions.
29 changes: 24 additions & 5 deletions contracts/eosio.system/src/producer_pay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,24 @@ namespace eosiosystem {
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() ) {
auto new_tokens = static_cast<int64_t>( (continuous_rate * double(token_supply.amount) * double(usecs_since_last_fill)) / double(useconds_per_year) );
auto current_fees = eosio::token::get_balance(token_account, fees_account, core_symbol().code() );
auto distribute_tokens = static_cast<int64_t>( (continuous_rate * double(token_supply.amount) * double(usecs_since_last_fill)) / double(useconds_per_year) );
auto fees_to_use = std::min( distribute_tokens, current_fees.amount );
auto issue_tokens = distribute_tokens - fees_to_use;
// needs to be 2/5 Savings, 2/5 Voters, 1/5 producers
auto to_per_block_pay = new_tokens / 5;
auto to_per_block_pay = distribute_tokens / 5;
auto to_voters = 2 * to_per_block_pay;
auto to_savings = new_tokens - (to_voters + to_per_block_pay);
auto to_savings = distribute_tokens - (to_voters + to_per_block_pay);

{
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" );
if( issue_tokens > 0 ){
token::issue_action issue_act{ token_account, { {get_self(), active_permission} } };
issue_act.send( get_self(), asset(issue_tokens, core_symbol()), "issue tokens for producer pay and savings" );
}
if( fees_to_use > 0 ){
token::transfer_action transfer_act{ token_account, { {fees_account, active_permission} } };
transfer_act.send( fees_account, get_self(), asset(fees_to_use, core_symbol()), "collect tokenomic fees" );
}
}
{
token::transfer_action transfer_act{ token_account, { {get_self(), active_permission} } };
Expand All @@ -99,6 +108,16 @@ namespace eosiosystem {
_gstate.perblock_bucket += to_per_block_pay;
_gstate.voters_bucket += to_voters;
_gstate.last_pervote_bucket_fill = ct;

// burn remaining tokenomic fees
auto burn_fees = std::max(int64_t(0), (current_fees.amount - fees_to_use) );
if( burn_fees > 0 ){
token::transfer_action transfer_act{ token_account, { {fees_account, active_permission} } };
transfer_act.send( fees_account, get_self(), asset(burn_fees, core_symbol()), "burn tokenomic fees" );

token::retire_action retire_act{ token_account, { {get_self(), active_permission} } };
retire_act.send( asset(burn_fees, core_symbol()), "burn tokenomic fees" );
}
}
}

Expand Down
14 changes: 13 additions & 1 deletion tests/eosio.system_tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class eosio_system_tester : public TESTER {
}
}

void remaining_setup() {
void remaining_setup(symbol core_symbol = symbol{CORE_SYM}) {
produce_blocks();

// Assumes previous setup steps were done with core token symbol set to CORE_SYM
Expand All @@ -93,6 +93,10 @@ class eosio_system_tester : public TESTER {
create_account_with_resources( "carol1111111"_n, config::system_account_name, core_sym::from_string("1.0000"), false );

BOOST_REQUIRE_EQUAL( core_sym::from_string("1000000000.0000"), get_balance("eosio") + get_balance("eosio.ramfee") + get_balance("eosio.stake") + get_balance("eosio.ram") );

// open ram for eosio.fees account
open( "eosio.fees"_n, core_symbol );
BOOST_REQUIRE_EQUAL( asset(0, core_symbol), get_balance( "eosio.fees", core_symbol ) );
}

enum class setup_level {
Expand Down Expand Up @@ -836,6 +840,14 @@ class eosio_system_tester : public TESTER {
);
}

void open( const name& owner, const symbol& symbolname, const name& manager = config::system_account_name) {
base_tester::push_action( "eosio.token"_n, "open"_n, manager, mutable_variant_object()
("owner", owner)
("symbol", symbolname )
("ram_payer", manager)
);
}

void transfer( const name& from, std::string_view to, const asset& amount, const name& manager = config::system_account_name ) {
transfer( from, name(to), amount, manager );
}
Expand Down
135 changes: 135 additions & 0 deletions tests/eosio.system_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2263,6 +2263,141 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester, * boost::unit_test::t

} FC_LOG_AND_RETHROW()


BOOST_FIXTURE_TEST_CASE(adjust_chain_inflation, eosio_system_tester, * boost::unit_test::tolerance(1e-10)) try {

const double continuous_rate = 0.04879;
const double usecs_per_year = 52 * 7 * 24 * 3600 * 1000000ll;
const double secs_per_year = 52 * 7 * 24 * 3600;
const int64_t useconds_per_day = (int64_t)24 * 3600 * 1000'000ll;

const asset large_asset = core_sym::from_string("80.0000");
create_account_with_resources( "defproducera"_n, config::system_account_name, core_sym::from_string("1.0000"), false, large_asset, large_asset );
create_account_with_resources( "defproducerb"_n, config::system_account_name, core_sym::from_string("1.0000"), false, large_asset, large_asset );
create_account_with_resources( "defproducerc"_n, config::system_account_name, core_sym::from_string("1.0000"), false, large_asset, large_asset );

create_account_with_resources( "producvotera"_n, config::system_account_name, core_sym::from_string("1.0000"), false, large_asset, large_asset );
create_account_with_resources( "producvoterb"_n, config::system_account_name, core_sym::from_string("1.0000"), false, large_asset, large_asset );

BOOST_REQUIRE_EQUAL(success(), regproducer("defproducera"_n));
produce_block(fc::hours(24));
auto prod = get_producer_info( "defproducera"_n );
BOOST_REQUIRE_EQUAL("defproducera", prod["owner"].as_string());
BOOST_REQUIRE_EQUAL(0, prod["total_votes"].as_double());

transfer( config::system_account_name, "producvotera", core_sym::from_string("400000000.0000"), config::system_account_name);
BOOST_REQUIRE_EQUAL(success(), stake("producvotera", core_sym::from_string("100000000.0000"), core_sym::from_string("100000000.0000")));
BOOST_REQUIRE_EQUAL(success(), vote( "producvotera"_n, { "defproducera"_n }));

// Reduce Inflation Rate
// Simulates a scenario where the tokenomics can adjust the inflation rate.
{
produce_blocks(50);

const auto initial_global_state = get_global_state();
const uint64_t initial_claim_time = microseconds_since_epoch_of_iso_string( initial_global_state["last_pervote_bucket_fill"] );
const int64_t initial_pervote_bucket = initial_global_state["pervote_bucket"].as<int64_t>();
const int64_t initial_perblock_bucket = initial_global_state["perblock_bucket"].as<int64_t>();
const int64_t initial_savings = get_balance("eosio.saving"_n).get_amount();

prod = get_producer_info("defproducera");
const uint32_t unpaid_blocks = prod["unpaid_blocks"].as<uint32_t>();
BOOST_REQUIRE(1 < unpaid_blocks);


const asset initial_supply = get_token_supply();
const asset initial_balance = get_balance("defproducera"_n);
transfer(config::system_account_name, "eosio.fees", core_sym::from_string("1.0000"), config::system_account_name);
const asset init_account_fees = get_balance("eosio.fees"_n);
BOOST_TEST_MESSAGE("init_account_fees: " << init_account_fees.get_amount());

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

const auto global_state = get_global_state();
const uint64_t claim_time = microseconds_since_epoch_of_iso_string( global_state["last_pervote_bucket_fill"] );
const int64_t pervote_bucket = global_state["pervote_bucket"].as<int64_t>();
const int64_t perblock_bucket = global_state["perblock_bucket"].as<int64_t>();
const int64_t savings = get_balance("eosio.saving"_n).get_amount();

prod = get_producer_info("defproducera");
const asset supply = get_token_supply();
const asset balance = get_balance("defproducera"_n);
const asset account_fees = get_balance("eosio.fees"_n);
BOOST_REQUIRE_EQUAL(0, account_fees.get_amount());

BOOST_REQUIRE_EQUAL(claim_time, microseconds_since_epoch_of_iso_string( prod["last_claim_time"] ));

auto usecs_between_fills = claim_time - initial_claim_time;
int32_t secs_between_fills = usecs_between_fills/1000000;
uint64_t distribute_tokens = (initial_supply.get_amount() * double(secs_between_fills) * continuous_rate) / secs_per_year;
BOOST_REQUIRE_EQUAL(0, initial_savings);
BOOST_REQUIRE_EQUAL(0, initial_perblock_bucket);
BOOST_REQUIRE_EQUAL(0, initial_pervote_bucket);

BOOST_REQUIRE_EQUAL(distribute_tokens - init_account_fees.get_amount(), supply.get_amount() - initial_supply.get_amount());
BOOST_REQUIRE_EQUAL(int64_t(distribute_tokens - (distribute_tokens / 5) * 3), savings - initial_savings);
BOOST_REQUIRE_EQUAL(int64_t(distribute_tokens / 5), balance.get_amount() - initial_balance.get_amount());

int64_t from_perblock_bucket = int64_t( initial_supply.get_amount() * double(secs_between_fills) * (continuous_rate / 5.) / secs_per_year ) ;
int64_t from_pervote_bucket = 0;


if (from_pervote_bucket >= 100 * 10000) {
BOOST_REQUIRE_EQUAL(from_perblock_bucket + from_pervote_bucket, balance.get_amount() - initial_balance.get_amount());
BOOST_REQUIRE_EQUAL(0, pervote_bucket);
} else {
BOOST_REQUIRE_EQUAL(from_perblock_bucket, balance.get_amount() - initial_balance.get_amount());
BOOST_REQUIRE_EQUAL(from_pervote_bucket, pervote_bucket);
}
}

// Wait 1 day
produce_block(fc::seconds(24 * 3600));

// No Inflation Rate Adjustment with Token Burn
// Evaluates the situation where the tokenomics covers inflation rate and tests the burning mechanism for remaining tokens.
{
produce_blocks(100);

const auto initial_global_state = get_global_state();
const uint64_t initial_claim_time = microseconds_since_epoch_of_iso_string( initial_global_state["last_pervote_bucket_fill"] );
const int64_t initial_pervote_bucket = initial_global_state["pervote_bucket"].as<int64_t>();
const int64_t initial_perblock_bucket = initial_global_state["perblock_bucket"].as<int64_t>();
const int64_t initial_savings = get_balance("eosio.saving"_n).get_amount();

prod = get_producer_info("defproducera");
const uint32_t unpaid_blocks = prod["unpaid_blocks"].as<uint32_t>();
BOOST_REQUIRE(1 < unpaid_blocks);

const asset initial_supply = get_token_supply();
transfer(config::system_account_name, "eosio.fees", core_sym::from_string("200000.0000"), config::system_account_name);
const asset init_account_fees = get_balance("eosio.fees"_n);

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

const auto global_state = get_global_state();
const uint64_t claim_time = microseconds_since_epoch_of_iso_string( global_state["last_pervote_bucket_fill"] );
const int64_t pervote_bucket = global_state["pervote_bucket"].as<int64_t>();
const int64_t perblock_bucket = global_state["perblock_bucket"].as<int64_t>();
const int64_t savings = get_balance("eosio.saving"_n).get_amount();

prod = get_producer_info("defproducera");
const asset supply = get_token_supply();
const asset account_fees = get_balance("eosio.fees"_n);
BOOST_REQUIRE_EQUAL(account_fees.get_amount(), 0);

BOOST_REQUIRE_EQUAL(claim_time, microseconds_since_epoch_of_iso_string( prod["last_claim_time"] ));

auto usecs_between_fills = claim_time - initial_claim_time;
int32_t secs_between_fills = usecs_between_fills/1000000;
int64_t distribute_tokens = (initial_supply.get_amount() * double(usecs_between_fills) * continuous_rate) / usecs_per_year;

BOOST_REQUIRE_EQUAL(init_account_fees.get_amount() - distribute_tokens, initial_supply.get_amount() - supply.get_amount());
BOOST_REQUIRE_EQUAL(int64_t(distribute_tokens - (distribute_tokens / 5) * 3), savings - initial_savings);

}
} FC_LOG_AND_RETHROW()

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

auto within_one = [](int64_t a, int64_t b) -> bool { return std::abs( a - b ) <= 1; };
Expand Down

0 comments on commit 4195977

Please sign in to comment.