Draft: Redirect operation fee to dividend #653

Closed
hirunda wants to merge 3 commits from feature/274/redirect_transaction_fees_to_dividends into develop
3 changed files with 99 additions and 2 deletions

View file

@ -76,9 +76,16 @@ void account_statistics_object::process_fees(const account_object& a, database&
share_type lifetime_cut = cut_fee(core_fee_total, account.lifetime_referrer_fee_percentage);
share_type referral = core_fee_total - network_cut - lifetime_cut;
d.modify( d.get_core_dynamic_data(), [network_cut](asset_dynamic_data_object& addo) {
if(d.head_block_time() >= HARDFORK_FEES_AS_DIVIDENDS_TIME ) {
const asset_object& ao = d.get_core_asset();
const asset_dividend_data_object& core_asset_dividend_data_obj = (*ao.dividend_data_id)(d);
account_id_type rake_account_id = core_asset_dividend_data_obj.dividend_distribution_account;
d.adjust_balance(rake_account_id, network_cut);
} else {
d.modify( d.get_core_dynamic_data(), [network_cut](asset_dynamic_data_object& addo) {
addo.accumulated_fees += network_cut;
});
});
}
// Potential optimization: Skip some of this math and object lookups by special casing on the account type.
// For example, if the account is a lifetime member, we can skip all this and just deposit the referral to

View file

@ -0,0 +1,7 @@
#ifndef HARDFORK_FEES_AS_DIVIDENDS_TIME
#ifdef BUILD_PEERPLAYS_TESTNET
#define HARDFORK_FEES_AS_DIVIDENDS_TIME (fc::time_point_sec::from_iso_string("2022-04-20T00:00:00"))
#else
#define HARDFORK_FEES_AS_DIVIDENDS_TIME (fc::time_point_sec::from_iso_string("2022-04-20T00:00:00"))
#endif
#endif

View file

@ -1522,6 +1522,89 @@ BOOST_AUTO_TEST_CASE( no_proposal )
}
}
BOOST_AUTO_TEST_CASE( dividend_distribution_fee )
{
try {
// advance to HF
generate_blocks(HARDFORK_FEES_AS_DIVIDENDS_TIME);
generate_block();
// update default gpos global parameters to 4 days
auto now = db.head_block_time();
update_gpos_global(345600, 86400, now);
generate_block();
set_expiration(db, trx);
ACTORS((nathan)(alice)(voter1)(voter2));
const auto& core = asset_id_type()(db);
// get core asset object
const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL);
// by default core token pays dividends once per month
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 2592000); // 30 days
// update the payout interval to 1 day for speed purposes of the test
update_payout_interval(core.symbol, db.head_block_time() + fc::minutes(1), 60 * 60 * 24); // 1 day
// get the dividend distribution account
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
// transfer to voters and nathan without fee. We can't enable fee yet, since create worker is a custom
// function which doesn't take the fee in transaction so by enabling it we will end up with not sufficient fee
transfer( committee_account, voter1_id, core.amount( 2000 * GRAPHENE_BLOCKCHAIN_PRECISION ) );
transfer( committee_account, voter2_id, core.amount( 3000 * GRAPHENE_BLOCKCHAIN_PRECISION ) );
transfer( committee_account, nathan_id, core.amount( 1000000 * GRAPHENE_BLOCKCHAIN_PRECISION ) );
// create some vesting for voters
create_vesting(voter1_id, core.amount(100 * GRAPHENE_BLOCKCHAIN_PRECISION ), vesting_balance_type::gpos);
create_vesting(voter2_id, core.amount(100 * GRAPHENE_BLOCKCHAIN_PRECISION ), vesting_balance_type::gpos);
// create worker
upgrade_to_lifetime_member(nathan_id);
auto worker = create_worker(nathan_id, 50 * GRAPHENE_BLOCKCHAIN_PRECISION, fc::days(2));
generate_block();
// vote for worker
vote_for(voter1_id, worker.vote_for, voter1_private_key);
// for now on enable fees
enable_fees();
// transfering some coins to alice.
for(int i = 0; i < 50; i++) {
transfer( nathan_id, alice_id, core.amount( 100 * GRAPHENE_BLOCKCHAIN_PRECISION ) );
}
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
// on the dividend account from total fee should be only network cut which is 20% of total fee.
// note that we did 50 transactions.
// Each transaction takes for fee 20 * GRAPHENE_BLOCKCHAIN_PRECISION
int dividend_distribution_account_balance = get_balance(dividend_distribution_account, core);
BOOST_CHECK_EQUAL(dividend_distribution_account_balance, 50 * 20 * GRAPHENE_BLOCKCHAIN_PRECISION * 20 / 100);
// voters are not yet paid from dividend account, it will be on next maintenance
BOOST_CHECK_EQUAL(get_balance(voter1_id(db), core), 1900 * GRAPHENE_BLOCKCHAIN_PRECISION);
BOOST_CHECK_EQUAL(get_balance(voter2_id(db), core), 2900 * GRAPHENE_BLOCKCHAIN_PRECISION);
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
// verify that voter_1 is payed from dividend account and voter_2 is not since voter_2 didn't vote
// note that we pass two maintenance intervals, so vesting factor is not anymore 1, instead it is 0.75
int payout_to_voter1 = (dividend_distribution_account_balance / 2 ) * 0.75;
BOOST_CHECK_EQUAL(get_balance(voter1_id(db), core), 1900 * GRAPHENE_BLOCKCHAIN_PRECISION + payout_to_voter1);
BOOST_CHECK_EQUAL(get_balance(voter2_id(db), core), 2900 * GRAPHENE_BLOCKCHAIN_PRECISION);
}
catch (fc::exception &e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( database_api )
{
ACTORS((alice)(bob));