Draft: Redirect operation fee to dividend #653
3 changed files with 99 additions and 2 deletions
|
|
@ -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
|
||||
|
|
|
|||
7
libraries/chain/hardfork.d/FEES_AS_DIVIDENDS.hf
Normal file
7
libraries/chain/hardfork.d/FEES_AS_DIVIDENDS.hf
Normal 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
|
||||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Reference in a new issue