diff --git a/libraries/chain/hardfork.d/CORE_1692.hf b/libraries/chain/hardfork.d/CORE_1692.hf new file mode 100644 index 0000000000..cbbe42c4ae --- /dev/null +++ b/libraries/chain/hardfork.d/CORE_1692.hf @@ -0,0 +1,4 @@ +// bitshares-core issue #1692 validation check of bid_collateral +#ifndef HARDFORK_CORE_1692_TIME +#define HARDFORK_CORE_1692_TIME (fc::time_point_sec( 1600000000 ) ) // Sep 2020 +#endif diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 18ebbe0180..1dd6b7bc6f 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -385,13 +385,6 @@ void_result bid_collateral_evaluator::do_evaluate(const bid_collateral_operation FC_ASSERT( !_bitasset_data->is_prediction_market, "Cannot bid on a prediction market!" ); - if( o.additional_collateral.amount > 0 ) - { - FC_ASSERT( d.get_balance(*_paying_account, _bitasset_data->options.short_backing_asset(d)) >= o.additional_collateral, - "Cannot bid ${c} collateral when payer only has ${b}", ("c", o.additional_collateral.amount) - ("b", d.get_balance(*_paying_account, o.additional_collateral.asset_id(d)).amount) ); - } - const collateral_bid_index& bids = d.get_index_type(); const auto& index = bids.indices().get(); const auto& bid = index.find( boost::make_tuple( o.debt_covered.asset_id, o.bidder ) ); @@ -400,6 +393,22 @@ void_result bid_collateral_evaluator::do_evaluate(const bid_collateral_operation else FC_ASSERT( o.debt_covered.amount > 0, "Can't find bid to cancel?!"); + if( o.additional_collateral.amount > 0 ) + { + if( _bid && d.head_block_time() >= HARDFORK_CORE_1692_TIME ) // TODO: see if HF check can be removed after HF + { + asset delta = o.additional_collateral - _bid->get_additional_collateral(); + FC_ASSERT( d.get_balance(*_paying_account, _bitasset_data->options.short_backing_asset(d)) >= delta, + "Cannot increase bid from ${oc} to ${nc} collateral when payer only has ${b}", + ("oc", _bid->get_additional_collateral().amount)("nc", o.additional_collateral.amount) + ("b", d.get_balance(*_paying_account, o.additional_collateral.asset_id(d)).amount) ); + } else + FC_ASSERT( d.get_balance( *_paying_account, + _bitasset_data->options.short_backing_asset(d) ) >= o.additional_collateral, + "Cannot bid ${c} collateral when payer only has ${b}", ("c", o.additional_collateral.amount) + ("b", d.get_balance(*_paying_account, o.additional_collateral.asset_id(d)).amount) ); + } + return void_result(); } FC_CAPTURE_AND_RETHROW( (o) ) } diff --git a/tests/tests/swan_tests.cpp b/tests/tests/swan_tests.cpp index 54f233c66a..67cfb200cf 100644 --- a/tests/tests/swan_tests.cpp +++ b/tests/tests/swan_tests.cpp @@ -406,6 +406,30 @@ BOOST_AUTO_TEST_CASE( recollateralize ) } } +/** Creates a black swan, bid, adjust bid before/after hf_1692 + */ +BOOST_AUTO_TEST_CASE( bid_issue_1692 ) +{ try { + init_standard_swan( 700 ); + + generate_blocks( HARDFORK_CORE_1692_TIME - 30 ); + + int64_t b2_balance = get_balance( borrower2(), back() ); + bid_collateral( borrower2(), back().amount(1000), swan().amount(100) ); + BOOST_CHECK_EQUAL( get_balance( borrower2(), back() ), b2_balance - 1000 ); + GRAPHENE_REQUIRE_THROW( bid_collateral( borrower2(), back().amount(b2_balance), swan().amount(200) ), + fc::assert_exception ); + GRAPHENE_REQUIRE_THROW( bid_collateral( borrower2(), back().amount(b2_balance-999), swan().amount(200) ), + fc::assert_exception ); + + generate_blocks( HARDFORK_CORE_1692_TIME + 30 ); + + bid_collateral( borrower2(), back().amount(b2_balance-999), swan().amount(200) ); + BOOST_CHECK_EQUAL( get_balance( borrower2(), back() ), 999 ); + bid_collateral( borrower2(), back().amount(b2_balance), swan().amount(200) ); + BOOST_CHECK_EQUAL( get_balance( borrower2(), back() ), 0 ); +} FC_LOG_AND_RETHROW() } + /** Creates a black swan, settles all debts, recovers price feed - asset should be revived */ BOOST_AUTO_TEST_CASE( revive_empty_recovered )