diff --git a/libraries/chain/db_bet.cpp b/libraries/chain/db_bet.cpp index 776640d9..39999b38 100644 --- a/libraries/chain/db_bet.cpp +++ b/libraries/chain/db_bet.cpp @@ -92,6 +92,8 @@ void database::resolve_betting_market_group(const betting_market_group_object& b // walking through bettors' positions and collecting winings and fees respecting asset_id for (const auto& bettor_positions_pair: bettor_positions_map) { + uint16_t rake_fee_percentage = get_global_properties().parameters.betting_rake_fee_percentage; + std::map net_profits; std::map payout_amounts; std::map fees_collected; account_id_type bettor_id = bettor_positions_pair.first; @@ -118,11 +120,17 @@ void database::resolve_betting_market_group(const betting_market_group_object& b payout_amounts[betting_market.asset_id] += position->pay_if_payout_condition; payout_amounts[betting_market.asset_id] += position->pay_if_not_canceled; fees_collected[betting_market.asset_id] += position->fees_collected; + net_profits[betting_market.asset_id] += position->pay_if_payout_condition; + net_profits[betting_market.asset_id] += position->pay_if_not_canceled; + net_profits[betting_market.asset_id] -= position->pay_if_canceled; break; case betting_market_resolution_type::not_win: payout_amounts[betting_market.asset_id] += position->pay_if_not_payout_condition; payout_amounts[betting_market.asset_id] += position->pay_if_not_canceled; fees_collected[betting_market.asset_id] += position->fees_collected; + net_profits[betting_market.asset_id] += position->pay_if_not_payout_condition; + net_profits[betting_market.asset_id] += position->pay_if_not_canceled; + net_profits[betting_market.asset_id] -= position->pay_if_canceled; break; case betting_market_resolution_type::cancel: payout_amounts[betting_market.asset_id] += position->pay_if_canceled; @@ -138,15 +146,44 @@ void database::resolve_betting_market_group(const betting_market_group_object& b std::vector fees; for (const auto& payout_amount_pair: payout_amounts) { - asset payout = asset(payout_amount_pair.second, payout_amount_pair.first); + // pay the fees to the correct (dividend-distribution) account if net profit + asset_id_type asset_id = payout_amount_pair.first; + const asset_object & asset_obj = asset_id(*this); + optional dividend_id = asset_obj.dividend_data_id; + account_id_type rake_account_id; + if (dividend_id.valid()) + { + const asset_dividend_data_id_type& asset_dividend_data_id_= *dividend_id; + const asset_dividend_data_object& dividend_obj = asset_dividend_data_id_(*this); + rake_account_id = dividend_obj.dividend_distribution_account; + } + asset fee = fees_collected[asset_id]; + share_type net_profit = net_profits[asset_id]; + share_type payout_amount = payout_amount_pair.second; + share_type rake_amount = 0; + if (dividend_id.valid()) + { + if (net_profit.value > 0) + { + rake_amount = (fc::uint128_t(net_profit.value) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100).to_uint64(); + if (rake_amount.value) + { + // adjusting balance of dividend_distribution_account + asset rake(rake_amount, asset_id); + adjust_balance(rake_account_id, rake); + } + } + adjust_balance(rake_account_id, fee); + } + else + { + adjust_balance(account_id_type(), fee); + } + // pay winning - rake + asset payout = asset(payout_amount - rake_amount, asset_id); adjust_balance(bettor_id, payout); + winnings.push_back(payout); - } - for (const auto& fee_collected_pair: fees_collected) - { - // TODO : pay the fees to the correct (dividend-distribution) account - asset fee = asset(fee_collected_pair.second, fee_collected_pair.first); - adjust_balance(account_id_type(), fee); fees.push_back(fee); } push_applied_operation(betting_market_group_resolved_operation(bettor_id, diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index a6beca42..53c2c1a6 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -381,7 +381,7 @@ void database::init_genesis(const genesis_state_type& genesis_state) a.membership_expiration_date = time_point_sec::maximum(); a.network_fee_percentage = 0; a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT; - }).get_id() == TOURNAMENT_RAKE_FEE_ACCOUNT_ID); + }).get_id() == GRAPHENE_RAKE_FEE_ACCOUNT_ID); // Create more special accounts while( true ) @@ -415,7 +415,7 @@ void database::init_genesis(const genesis_state_type& genesis_state) a.options.minimum_fee_percentage = 10*GRAPHENE_1_PERCENT; a.options.next_payout_time = genesis_state.initial_timestamp + fc::hours(1); a.options.payout_interval = 7*24*60*60; - a.dividend_distribution_account = TOURNAMENT_RAKE_FEE_ACCOUNT_ID; + a.dividend_distribution_account = GRAPHENE_RAKE_FEE_ACCOUNT_ID; }); const asset_object& core_asset = @@ -447,7 +447,7 @@ void database::init_genesis(const genesis_state_type& genesis_state) a.options.minimum_fee_percentage = 10*GRAPHENE_1_PERCENT; a.options.next_payout_time = genesis_state.initial_timestamp + fc::hours(1); a.options.payout_interval = 7*24*60*60; - a.dividend_distribution_account = TOURNAMENT_RAKE_FEE_ACCOUNT_ID; + a.dividend_distribution_account = GRAPHENE_RAKE_FEE_ACCOUNT_ID; }); const asset_object& default_asset = @@ -458,7 +458,7 @@ void database::init_genesis(const genesis_state_type& genesis_state) a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS; a.options.flags = 0; a.options.issuer_permissions = 79; - a.issuer = TOURNAMENT_RAKE_FEE_ACCOUNT_ID; + a.issuer = GRAPHENE_RAKE_FEE_ACCOUNT_ID; a.options.core_exchange_rate.base.amount = 1; a.options.core_exchange_rate.base.asset_id = asset_id_type(0); a.options.core_exchange_rate.quote.amount = 1; diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 4cc147ac..e70c2214 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -165,13 +165,15 @@ /// Represents the canonical account for specifying you will vote directly (as opposed to a proxy) #define GRAPHENE_PROXY_TO_SELF_ACCOUNT (graphene::chain::account_id_type(5)) /// -#define TOURNAMENT_RAKE_FEE_ACCOUNT_ID (graphene::chain::account_id_type(6)) +#define GRAPHENE_RAKE_FEE_ACCOUNT_ID (graphene::chain::account_id_type(6)) /// Sentinel value used in the scheduler. #define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0)) ///@} #define GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET (asset_id_type(743)) +#define GRAPHENE_DEFAULT_RAKE_FEE_PERCENTAGE (3*GRAPHENE_1_PERCENT) + /** * Betting-related constants. * diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index 5252f982..b355271f 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -69,7 +69,7 @@ namespace graphene { namespace chain { uint16_t accounts_per_fee_scale = GRAPHENE_DEFAULT_ACCOUNTS_PER_FEE_SCALE; ///< number of accounts between fee scalings uint8_t account_fee_scale_bitshifts = GRAPHENE_DEFAULT_ACCOUNT_FEE_SCALE_BITSHIFTS; ///< number of times to left bitshift account registration fee at each scaling uint8_t max_authority_depth = GRAPHENE_MAX_SIG_CHECK_DEPTH; - + uint16_t betting_rake_fee_percentage = GRAPHENE_DEFAULT_RAKE_FEE_PERCENTAGE; ///< part of prize paid into the dividend account for the core token holders bet_multiplier_type min_bet_multiplier = GRAPHENE_DEFAULT_MIN_BET_MULTIPLIER; bet_multiplier_type max_bet_multiplier = GRAPHENE_DEFAULT_MAX_BET_MULTIPLIER; flat_map permitted_betting_odds_increments = GRAPHENE_DEFAULT_PERMITTED_BETTING_ODDS_INCREMENTS; @@ -113,6 +113,7 @@ FC_REFLECT( graphene::chain::chain_parameters, (max_authority_depth) (min_bet_multiplier) (max_bet_multiplier) + (betting_rake_fee_percentage) (permitted_betting_odds_increments) (extensions) ) diff --git a/tests/betting/betting_tests.cpp b/tests/betting/betting_tests.cpp index c8d56b6c..999c824e 100644 --- a/tests/betting/betting_tests.cpp +++ b/tests/betting/betting_tests.cpp @@ -118,7 +118,11 @@ BOOST_AUTO_TEST_CASE( peerplays_sport_create_test ) {{capitals_win_market.id, betting_market_resolution_type::win}, {blackhawks_win_market.id, betting_market_resolution_type::cancel}}); - BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000); + + uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage; + uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; + BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value)); + BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000 - rake_value); BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000); } FC_LOG_AND_RETHROW() @@ -294,10 +298,16 @@ BOOST_AUTO_TEST_CASE( win ) GET_ACTOR(alice); GET_ACTOR(bob); + uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage; + uint32_t rake_value; + //rake_value = (-100 + 1100 - 1100) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; // alice starts with 10000, pays 100 (bet) + 2 (fee), wins 1100, then pays 1100 (bet) + 22 (fee), wins 0 BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000 - 100 - 2 + 1100 - 1100 - 22 + 0); + + rake_value = (-1000 - 1100 + 2200) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; // bob starts with 10000, pays 1000 (bet) + 20 (fee), wins 0, then pays 1100 (bet) + 22 (fee), wins 2200 - BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000 - 1000 - 20 + 0 - 1100 - 22 + 2200); + BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value)); + BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000 - 1000 - 20 + 0 - 1100 - 22 + 2200 - rake_value); } FC_LOG_AND_RETHROW() } @@ -312,8 +322,13 @@ BOOST_AUTO_TEST_CASE( not_win ) GET_ACTOR(alice); GET_ACTOR(bob); + uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage; + uint32_t rake_value = (-100 - 1100 + 2200) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; // alice starts with 10000, pays 100 (bet) + 2 (fee), wins 0, then pays 1100 (bet) + 22 (fee), wins 2200 - BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000 - 100 - 2 + 0 - 1100 - 22 + 2200); + BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value)); + BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000 - 100 - 2 + 0 - 1100 - 22 + 2200 - rake_value); + + //rake_value = (-1000 + 1100 - 1100) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; // bob starts with 10000, pays 1000 (bet) + 20 (fee), wins 1100, then pays 1100 (bet) + 22 (fee), wins 0 BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000 - 1000 - 20 + 1100 - 1100 - 22 + 0); } FC_LOG_AND_RETHROW()