Move new chain parameters into extensions

This commit is contained in:
Peter Conrad 2018-09-05 16:43:35 +02:00
parent 31e68d4bb1
commit b0afddaa6b
10 changed files with 133 additions and 51 deletions

View file

@ -292,15 +292,15 @@ void_result bet_place_evaluator::do_evaluate(const bet_place_operation& op)
_current_params = &d.get_global_properties().parameters;
// are their odds valid
FC_ASSERT( op.backer_multiplier >= _current_params->min_bet_multiplier &&
op.backer_multiplier <= _current_params->max_bet_multiplier,
FC_ASSERT( op.backer_multiplier >= _current_params->min_bet_multiplier() &&
op.backer_multiplier <= _current_params->max_bet_multiplier(),
"Bet odds are outside the blockchain's limits" );
if (!_current_params->permitted_betting_odds_increments.empty())
if (!_current_params->permitted_betting_odds_increments().empty())
{
bet_multiplier_type allowed_increment;
const auto iter = _current_params->permitted_betting_odds_increments.upper_bound(op.backer_multiplier);
if (iter == _current_params->permitted_betting_odds_increments.end())
allowed_increment = std::prev(_current_params->permitted_betting_odds_increments.end())->second;
const auto iter = _current_params->permitted_betting_odds_increments().upper_bound(op.backer_multiplier);
if (iter == _current_params->permitted_betting_odds_increments().end())
allowed_increment = std::prev(_current_params->permitted_betting_odds_increments().end())->second;
else
allowed_increment = iter->second;
FC_ASSERT(op.backer_multiplier % allowed_increment == 0, "Bet odds must be a multiple of ${allowed_increment}", ("allowed_increment", allowed_increment));
@ -324,15 +324,15 @@ object_id_type bet_place_evaluator::do_apply(const bet_place_operation& op)
if (_betting_market_group->bets_are_delayed()) {
// the bet will be included in the block at time `head_block_time() + block_interval`, so make the delay relative
// to the time it's included in a block
bet_obj.end_of_delay = d.head_block_time() + _current_params->block_interval + _current_params->live_betting_delay_time;
bet_obj.end_of_delay = d.head_block_time() + _current_params->block_interval + _current_params->live_betting_delay_time();
}
});
bet_id_type new_bet_id = new_bet.id; // save the bet id here, new_bet may be deleted during place_bet()
// place the bet, this may return guaranteed winnings
ddump((_betting_market_group->bets_are_delayed())(_current_params->live_betting_delay_time));
if (!_betting_market_group->bets_are_delayed() || _current_params->live_betting_delay_time <= 0)
ddump((_betting_market_group->bets_are_delayed())(_current_params->live_betting_delay_time()));
if (!_betting_market_group->bets_are_delayed() || _current_params->live_betting_delay_time() <= 0)
d.place_bet(new_bet);
// now that their guaranteed winnings have been returned, check whether they have enough in their account to place the bet

View file

@ -25,6 +25,7 @@
#include <graphene/chain/committee_member_object.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/hardfork.hpp>
#include <graphene/chain/protocol/fee_schedule.hpp>
#include <graphene/chain/protocol/vote.hpp>
#include <graphene/chain/transaction_evaluation_state.hpp>
@ -77,12 +78,28 @@ void_result committee_member_update_global_parameters_evaluator::do_evaluate(con
{ try {
FC_ASSERT(trx_state->_is_proposed_trx);
if( db().head_block_time() < HARDFORK_1000_TIME ) // TODO: remove after hf
FC_ASSERT( !o.new_parameters.extensions.value.min_bet_multiplier.valid()
&& !o.new_parameters.extensions.value.max_bet_multiplier.valid()
&& !o.new_parameters.extensions.value.betting_rake_fee_percentage.valid()
&& !o.new_parameters.extensions.value.permitted_betting_odds_increments.valid()
&& !o.new_parameters.extensions.value.live_betting_delay_time.valid(),
"Parameter extensions are not allowed yet!" );
dgpo = &db().get_global_properties();
if( o.new_parameters.extensions.value.min_bet_multiplier.valid()
&& !o.new_parameters.extensions.value.max_bet_multiplier.valid() )
FC_ASSERT( *o.new_parameters.extensions.value.min_bet_multiplier < dgpo->parameters.max_bet_multiplier() );
if( !o.new_parameters.extensions.value.min_bet_multiplier.valid()
&& o.new_parameters.extensions.value.max_bet_multiplier.valid() )
FC_ASSERT( dgpo->parameters.min_bet_multiplier() < *o.new_parameters.extensions.value.max_bet_multiplier );
return void_result();
} FC_CAPTURE_AND_RETHROW( (o) ) }
void_result committee_member_update_global_parameters_evaluator::do_apply(const committee_member_update_global_parameters_operation& o)
{ try {
db().modify(db().get_global_properties(), [&o](global_property_object& p) {
db().modify(*dgpo, [&o](global_property_object& p) {
p.pending_parameters = o.new_parameters;
});

View file

@ -179,7 +179,7 @@ void database::settle_betting_market_group(const betting_market_group_object& be
// 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;
uint16_t rake_fee_percentage = get_global_properties().parameters.betting_rake_fee_percentage();
share_type net_profits;
share_type payout_amounts;
account_id_type bettor_id = bettor_positions_pair.first;

View file

@ -1371,6 +1371,16 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
if( p.pending_parameters )
{
if( !p.pending_parameters->extensions.value.min_bet_multiplier.valid() )
p.pending_parameters->extensions.value.min_bet_multiplier = p.parameters.extensions.value.min_bet_multiplier;
if( !p.pending_parameters->extensions.value.max_bet_multiplier.valid() )
p.pending_parameters->extensions.value.max_bet_multiplier = p.parameters.extensions.value.max_bet_multiplier;
if( !p.pending_parameters->extensions.value.betting_rake_fee_percentage.valid() )
p.pending_parameters->extensions.value.betting_rake_fee_percentage = p.parameters.extensions.value.betting_rake_fee_percentage;
if( !p.pending_parameters->extensions.value.permitted_betting_odds_increments.valid() )
p.pending_parameters->extensions.value.permitted_betting_odds_increments = p.parameters.extensions.value.permitted_betting_odds_increments;
if( !p.pending_parameters->extensions.value.live_betting_delay_time.valid() )
p.pending_parameters->extensions.value.live_betting_delay_time = p.parameters.extensions.value.live_betting_delay_time;
p.parameters = std::move(*p.pending_parameters);
p.pending_parameters.reset();
}

View file

@ -50,6 +50,8 @@ namespace graphene { namespace chain {
public:
typedef committee_member_update_global_parameters_operation operation_type;
const global_property_object* dgpo;
void_result do_evaluate( const committee_member_update_global_parameters_operation& o );
void_result do_apply( const committee_member_update_global_parameters_operation& o );
};

View file

@ -23,20 +23,22 @@
*/
#pragma once
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/protocol/ext.hpp>
#include <graphene/chain/protocol/types.hpp>
#include <fc/smart_ref_fwd.hpp>
namespace graphene { namespace chain { struct fee_schedule; } }
/*
namespace fc {
template<typename Stream, typename T> inline void pack( Stream& s, const graphene::chain::fee_schedule& value );
template<typename Stream, typename T> inline void unpack( Stream& s, graphene::chain::fee_schedule& value );
} // namespace fc
*/
namespace graphene { namespace chain {
struct parameter_extension
{
optional< bet_multiplier_type > min_bet_multiplier;
optional< bet_multiplier_type > max_bet_multiplier;
optional< uint16_t > betting_rake_fee_percentage;
optional< flat_map<bet_multiplier_type, bet_multiplier_type> > permitted_betting_odds_increments;
optional< uint16_t > live_betting_delay_time;
};
typedef static_variant<> parameter_extension;
struct chain_parameters
{
/** using a smart ref breaks the circular dependency created between operations and the fee schedule */
@ -69,12 +71,6 @@ 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<bet_multiplier_type, bet_multiplier_type> permitted_betting_odds_increments = GRAPHENE_DEFAULT_PERMITTED_BETTING_ODDS_INCREMENTS;
uint16_t live_betting_delay_time = GRAPHENE_DEFAULT_LIVE_BETTING_DELAY_TIME; ///< delayed bets
//uint8_t witness_schedule_algorithm = GRAPHENE_WITNESS_SHUFFLED_ALGORITHM; ///< 0 shuffled, 1 scheduled
uint8_t witness_schedule_algorithm = GRAPHENE_WITNESS_SCHEDULED_ALGORITHM; ///< 0 shuffled, 1 scheduled
/* rps tournament parameters constraints */
uint32_t min_round_delay = TOURNAMENT_MIN_ROUND_DELAY; ///< miniaml delay between games
@ -90,14 +86,38 @@ namespace graphene { namespace chain {
uint32_t maximum_tournament_start_time_in_future = TOURNAMENT_MAX_START_TIME_IN_FUTURE;
uint32_t maximum_tournament_start_delay = TOURNAMENT_MAX_START_DELAY;
uint16_t maximum_tournament_number_of_wins = TOURNAMENT_MAX_NUMBER_OF_WINS;
extensions_type extensions;
extension<parameter_extension> extensions;
/** defined in fee_schedule.cpp */
void validate()const;
inline bet_multiplier_type min_bet_multiplier()const {
return extensions.value.min_bet_multiplier.valid() ? *extensions.value.min_bet_multiplier : GRAPHENE_DEFAULT_MIN_BET_MULTIPLIER;
}
inline bet_multiplier_type max_bet_multiplier()const {
return extensions.value.max_bet_multiplier.valid() ? *extensions.value.max_bet_multiplier : GRAPHENE_DEFAULT_MAX_BET_MULTIPLIER;
}
inline uint16_t betting_rake_fee_percentage()const {
return extensions.value.betting_rake_fee_percentage.valid() ? *extensions.value.betting_rake_fee_percentage : GRAPHENE_DEFAULT_RAKE_FEE_PERCENTAGE;
}
inline const flat_map<bet_multiplier_type, bet_multiplier_type>& permitted_betting_odds_increments()const {
static const flat_map<bet_multiplier_type, bet_multiplier_type> _default = GRAPHENE_DEFAULT_PERMITTED_BETTING_ODDS_INCREMENTS;
return extensions.value.permitted_betting_odds_increments.valid() ? *extensions.value.permitted_betting_odds_increments : _default;
}
inline uint16_t live_betting_delay_time()const {
return extensions.value.live_betting_delay_time.valid() ? *extensions.value.live_betting_delay_time : GRAPHENE_DEFAULT_LIVE_BETTING_DELAY_TIME;
}
};
} } // graphene::chain
FC_REFLECT( graphene::chain::parameter_extension,
(min_bet_multiplier)
(max_bet_multiplier)
(betting_rake_fee_percentage)
(permitted_betting_odds_increments)
(live_betting_delay_time)
)
FC_REFLECT( graphene::chain::chain_parameters,
(current_fees)
(block_interval)
@ -127,12 +147,7 @@ FC_REFLECT( graphene::chain::chain_parameters,
(accounts_per_fee_scale)
(account_fee_scale_bitshifts)
(max_authority_depth)
(min_bet_multiplier)
(max_bet_multiplier)
(betting_rake_fee_percentage)
(permitted_betting_odds_increments)
(witness_schedule_algorithm)
(live_betting_delay_time)
(min_round_delay)
(max_round_delay)
(min_time_per_commit_move)

View file

@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <graphene/chain/hardfork.hpp>
#include <graphene/chain/proposal_evaluator.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/account_object.hpp>
@ -31,9 +32,40 @@
namespace graphene { namespace chain {
struct proposal_operation_hardfork_visitor
{
typedef void result_type;
const fc::time_point_sec block_time;
proposal_operation_hardfork_visitor( const fc::time_point_sec bt ) : block_time(bt) {}
template<typename T>
void operator()(const T &v) const {}
void operator()(const graphene::chain::committee_member_update_global_parameters_operation &op) const {
if( block_time < HARDFORK_1000_TIME ) // TODO: remove after hf
FC_ASSERT( !op.new_parameters.extensions.value.min_bet_multiplier.valid()
&& !op.new_parameters.extensions.value.max_bet_multiplier.valid()
&& !op.new_parameters.extensions.value.betting_rake_fee_percentage.valid()
&& !op.new_parameters.extensions.value.permitted_betting_odds_increments.valid()
&& !op.new_parameters.extensions.value.live_betting_delay_time.valid(),
"Parameter extensions are not allowed yet!" );
}
// loop and self visit in proposals
void operator()(const proposal_create_operation &v) const {
for (const op_wrapper &op : v.proposed_ops)
op.op.visit(*this);
}
};
void_result proposal_create_evaluator::do_evaluate(const proposal_create_operation& o)
{ try {
const database& d = db();
proposal_operation_hardfork_visitor vtor( d.head_block_time() );
vtor( o );
const auto& global_parameters = d.get_global_properties().parameters;
FC_ASSERT( o.expiration_time > d.head_block_time(), "Proposal has already expired on creation." );

View file

@ -189,16 +189,22 @@ namespace graphene { namespace chain {
FC_ASSERT( maximum_proposal_lifetime - committee_proposal_review_period > block_interval,
"Committee proposal review period must be less than the maximum proposal lifetime" );
FC_ASSERT( min_bet_multiplier >= GRAPHENE_BETTING_MIN_MULTIPLIER &&
min_bet_multiplier <= GRAPHENE_BETTING_MAX_MULTIPLIER );
FC_ASSERT( max_bet_multiplier >= GRAPHENE_BETTING_MIN_MULTIPLIER &&
max_bet_multiplier <= GRAPHENE_BETTING_MAX_MULTIPLIER );
FC_ASSERT( min_bet_multiplier < max_bet_multiplier );
FC_ASSERT( rake_fee_percentage >= TOURNAMENT_MINIMAL_RAKE_FEE_PERCENTAGE,
"Rake fee percentage must not be less than ${min}", ("min",TOURNAMENT_MINIMAL_RAKE_FEE_PERCENTAGE));
FC_ASSERT( rake_fee_percentage <= TOURNAMENT_MAXIMAL_RAKE_FEE_PERCENTAGE,
"Rake fee percentage must not be greater than ${max}", ("max", TOURNAMENT_MAXIMAL_RAKE_FEE_PERCENTAGE));
if( extensions.value.min_bet_multiplier.valid() )
FC_ASSERT( *extensions.value.min_bet_multiplier >= GRAPHENE_BETTING_MIN_MULTIPLIER &&
*extensions.value.min_bet_multiplier <= GRAPHENE_BETTING_MAX_MULTIPLIER );
if( extensions.value.max_bet_multiplier.valid() )
FC_ASSERT( *extensions.value.max_bet_multiplier >= GRAPHENE_BETTING_MIN_MULTIPLIER &&
*extensions.value.max_bet_multiplier <= GRAPHENE_BETTING_MAX_MULTIPLIER );
if( extensions.value.min_bet_multiplier.valid() && extensions.value.max_bet_multiplier.valid() )
FC_ASSERT( *extensions.value.min_bet_multiplier < *extensions.value.max_bet_multiplier );
if( extensions.value.betting_rake_fee_percentage.valid() )
{
FC_ASSERT( *extensions.value.betting_rake_fee_percentage >= TOURNAMENT_MINIMAL_RAKE_FEE_PERCENTAGE,
"Rake fee percentage must not be less than ${min}", ("min",TOURNAMENT_MINIMAL_RAKE_FEE_PERCENTAGE));
FC_ASSERT( *extensions.value.betting_rake_fee_percentage <= TOURNAMENT_MAXIMAL_RAKE_FEE_PERCENTAGE,
"Rake fee percentage must not be greater than ${max}", ("max", TOURNAMENT_MAXIMAL_RAKE_FEE_PERCENTAGE));
}
}
} } // graphene::chain

View file

@ -102,13 +102,13 @@ binned_order_book bookie_api_impl::get_binned_order_book(graphene::chain::bettin
if (bet_odds_iter->back_or_lay == bet_type::back)
{
current_bin->backer_multiplier = (bet_odds_iter->backer_multiplier + bin_size - 1) / bin_size * bin_size;
current_bin->backer_multiplier = std::min<graphene::chain::bet_multiplier_type>(current_bin->backer_multiplier, current_params.max_bet_multiplier);
current_bin->backer_multiplier = std::min<graphene::chain::bet_multiplier_type>(current_bin->backer_multiplier, current_params.max_bet_multiplier());
current_bin->back_or_lay = bet_type::back;
}
else
{
current_bin->backer_multiplier = bet_odds_iter->backer_multiplier / bin_size * bin_size;
current_bin->backer_multiplier = std::max<graphene::chain::bet_multiplier_type>(current_bin->backer_multiplier, current_params.min_bet_multiplier);
current_bin->backer_multiplier = std::max<graphene::chain::bet_multiplier_type>(current_bin->backer_multiplier, current_params.min_bet_multiplier());
current_bin->back_or_lay = bet_type::lay;
}

View file

@ -454,7 +454,7 @@ BOOST_AUTO_TEST_CASE( peerplays_sport_create_test )
generate_blocks(1);
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
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 + 2000000 - rake_value);
@ -1430,7 +1430,7 @@ 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;
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), wins 1100, then pays 1100 (bet), wins 0
@ -1456,7 +1456,7 @@ 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;
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), wins 0, then pays 1100 (bet), wins 2200
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
@ -1573,7 +1573,7 @@ BOOST_AUTO_TEST_CASE(event_group_update_test)
generate_blocks(1);
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
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 + 2000000 - rake_value);
@ -1621,7 +1621,7 @@ BOOST_AUTO_TEST_CASE(event_update_test)
generate_blocks(1);
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
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 + 2000000 - rake_value);
@ -1685,7 +1685,7 @@ BOOST_AUTO_TEST_CASE(betting_market_group_update_test)
generate_blocks(1);
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
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 + 2000000 - rake_value);
@ -1722,7 +1722,7 @@ BOOST_AUTO_TEST_CASE(betting_market_update_test)
{blackhawks_win_market.id, betting_market_resolution_type::not_win}});
generate_blocks(1);
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
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 + 2000000 - rake_value);
@ -2504,7 +2504,7 @@ BOOST_FIXTURE_TEST_CASE( another_event_group_update_test, database_fixture)
{blackhawks_win_market.id, betting_market_resolution_type::not_win}});
generate_blocks(1);
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
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 + 2000000 - rake_value);
@ -2524,7 +2524,7 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_sf_test )
CREATE_TENNIS_BETTING_MARKET();
generate_blocks(1);
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage();
transfer(account_id_type(), alice_id, asset(10000000));
transfer(account_id_type(), bob_id, asset(10000000));
@ -2585,7 +2585,7 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_final_test )
ACTORS( (alice)(bob) );
CREATE_TENNIS_BETTING_MARKET();
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage();
transfer(account_id_type(), alice_id, asset(10000000));
transfer(account_id_type(), bob_id, asset(10000000));