diff --git a/libraries/chain/betting_market_evaluator.cpp b/libraries/chain/betting_market_evaluator.cpp index 33c21056..94f51c35 100644 --- a/libraries/chain/betting_market_evaluator.cpp +++ b/libraries/chain/betting_market_evaluator.cpp @@ -300,10 +300,6 @@ void_result bet_place_evaluator::do_evaluate(const bet_place_operation& op) FC_ASSERT(op.amount_to_bet.amount > share_type(), "Cannot place a bet with zero amount"); - // do they have enough in their account to place the bet - FC_ASSERT( d.get_balance( *fee_paying_account, *_asset ).amount >= op.amount_to_bet.amount, "insufficient balance", - ("balance", d.get_balance(*fee_paying_account, *_asset))("amount_to_bet", op.amount_to_bet.amount) ); - return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -326,12 +322,18 @@ object_id_type bet_place_evaluator::do_apply(const bet_place_operation& op) bet_id_type new_bet_id = new_bet.id; // save the bet id here, new_bet may be deleted during place_bet() - d.adjust_balance(fee_paying_account->id, -op.amount_to_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) 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 + FC_ASSERT( d.get_balance( *fee_paying_account, *_asset ).amount >= op.amount_to_bet.amount, "insufficient balance", + ("balance", d.get_balance(*fee_paying_account, *_asset))("amount_to_bet", op.amount_to_bet.amount) ); + + // pay for it + d.adjust_balance(fee_paying_account->id, -op.amount_to_bet); + return new_bet_id; } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/tests/betting/betting_tests.cpp b/tests/betting/betting_tests.cpp index 85d82fda..3815af5f 100644 --- a/tests/betting/betting_tests.cpp +++ b/tests/betting/betting_tests.cpp @@ -442,6 +442,34 @@ BOOST_AUTO_TEST_CASE(inexact_odds) FC_LOG_AND_RETHROW() } +BOOST_AUTO_TEST_CASE(bet_reversal_test) +{ + // test whether we can bet our entire balance in one direction, then reverse our bet (while having zero balance) + try + { + generate_blocks(1); + ACTORS( (alice)(bob) ); + CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0); + + transfer(account_id_type(), alice_id, asset(10000000)); + share_type alice_expected_balance = 10000000; + BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance.value); + + // back with our entire balance + place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(10000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION); + BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), 0); + + // reverse the bet + place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(20000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION); + BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), 0); + + // try to re-reverse it, but go too far + BOOST_CHECK_THROW( place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(30000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION), fc::exception); + BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), 0); + } + FC_LOG_AND_RETHROW() +} + BOOST_AUTO_TEST_CASE(persistent_objects_test) { try