From b80587e5b54a31f1200facc34f1df47f4c45be57 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Thu, 5 Nov 2015 17:12:57 -0500 Subject: [PATCH 1/3] Prevent margin call from being triggered unless feed < call #436 --- libraries/chain/db_market.cpp | 31 +++++++++---------- .../chain/include/graphene/chain/hardfork.hpp | 1 + 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 0a280a81..f45fed6d 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -416,15 +417,8 @@ bool database::check_call_orders(const asset_object& mia, bool enable_black_swan auto limit_itr = limit_price_index.lower_bound( max_price ); auto limit_end = limit_price_index.upper_bound( min_price ); - if( limit_itr == limit_end ) { - /* - if( head_block_num() > 300000 ) - ilog( "no orders below between: ${p} and: ${m}", - ("p", bitasset.current_feed.max_short_squeeze_price()) - ("m", max_price) ); - */ + if( limit_itr == limit_end ) return false; - } auto call_min = price::min( bitasset.options.short_backing_asset, mia.id ); auto call_max = price::max( bitasset.options.short_backing_asset, mia.id ); @@ -434,14 +428,6 @@ bool database::check_call_orders(const asset_object& mia, bool enable_black_swan bool filled_limit = false; bool margin_called = false; - /* - if( head_block_num() >= 11510 && head_block_num() <= 11512) { - idump(("enter loop") ); - auto tmp = call_itr; - while( tmp != call_end ) { edump( (*tmp) ); ++tmp; } - } - */ - while( !check_for_blackswan( mia, enable_black_swan ) && call_itr != call_end ) { bool filled_call = false; @@ -457,9 +443,22 @@ bool database::check_call_orders(const asset_object& mia, bool enable_black_swan match_price.validate(); + // would be margin called, but there is no matching order #436 + bool feed_protected = ( bitasset.current_feed.settlement_price > ~call_itr->call_price ); + if( feed_protected && (head_block_time() > HARDFORK_436_TIME) ) + return margin_called; + + // would be margin called, but there is no matching order if( match_price > ~call_itr->call_price ) return margin_called; + if( feed_protected ) + { + ilog( "Feed protected margin call executing (HARDFORK_436_TIME not here yet)" ); + idump( (*call_itr) ); + idump( (*limit_itr) ); + } + // idump((*call_itr)); // idump((*limit_itr)); diff --git a/libraries/chain/include/graphene/chain/hardfork.hpp b/libraries/chain/include/graphene/chain/hardfork.hpp index c5e50f03..7f5da1a8 100644 --- a/libraries/chain/include/graphene/chain/hardfork.hpp +++ b/libraries/chain/include/graphene/chain/hardfork.hpp @@ -27,3 +27,4 @@ #define HARDFORK_415_TIME (fc::time_point_sec( 1446652800 )) #define HARDFORK_416_TIME (fc::time_point_sec( 1446652800 )) #define HARDFORK_419_TIME (fc::time_point_sec( 1446652800 )) +#define HARDFORK_436_TIME (fc::time_point_sec( 2000000000 )) From 15c455dc6361a9f4259ddeafdd62f85aeaf6d6e9 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 7 Dec 2015 14:48:16 -0500 Subject: [PATCH 2/3] Make margin_call_limit_test pass after hardfork #436 --- tests/tests/operation_tests.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index b85b3161..92ab7ac4 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -192,14 +193,25 @@ BOOST_AUTO_TEST_CASE( margin_call_limit_test ) // protection threshold. BOOST_TEST_MESSAGE( "Creating a margin call that is NOT protected by the max short squeeze price" ); auto order = create_sell_order( borrower2, bitusd.amount(1000), core.amount(1400) ); - BOOST_REQUIRE( order == nullptr ); + if( db.head_block_time() <= HARDFORK_436_TIME ) + { + BOOST_REQUIRE( order == nullptr ); - BOOST_REQUIRE_EQUAL( get_balance( borrower2, core ), init_balance - 4000 + 1400 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower2, bitusd ), 0 ); + BOOST_REQUIRE_EQUAL( get_balance( borrower2, core ), init_balance - 4000 + 1400 ); + BOOST_REQUIRE_EQUAL( get_balance( borrower2, bitusd ), 0 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower, core ), init_balance - 2000 + 600 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower, bitusd ), 1000 ); + BOOST_REQUIRE_EQUAL( get_balance( borrower, core ), init_balance - 2000 + 600 ); + BOOST_REQUIRE_EQUAL( get_balance( borrower, bitusd ), 1000 ); + } + else + { + BOOST_REQUIRE( order != nullptr ); + BOOST_REQUIRE_EQUAL( get_balance( borrower, bitusd ), 1000 ); + BOOST_REQUIRE_EQUAL( get_balance( borrower2, bitusd ), 0 ); + BOOST_REQUIRE_EQUAL( get_balance( borrower , core ), init_balance - 2000 ); + BOOST_REQUIRE_EQUAL( get_balance( borrower2, core ), init_balance - 4000 ); + } BOOST_TEST_MESSAGE( "Creating a margin call that is protected by the max short squeeze price" ); borrow( borrower, bitusd.amount(1000), asset(2000) ); From 59d0ddf0f162e5bff9bbb4ca350699088c1d7d87 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 7 Dec 2015 14:58:27 -0500 Subject: [PATCH 3/3] operation_tests.cpp: Use BOOST_CHECK instead of BOOST_REQUIRE in margin_call_limit_test --- tests/tests/operation_tests.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 92ab7ac4..e7a746c0 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -184,10 +184,10 @@ BOOST_AUTO_TEST_CASE( margin_call_limit_test ) borrow( borrower, bitusd.amount(1000), asset(2000)); borrow( borrower2, bitusd.amount(1000), asset(4000) ); - BOOST_REQUIRE_EQUAL( get_balance( borrower, bitusd ), 1000 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower2, bitusd ), 1000 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower , core ), init_balance - 2000 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower2, core ), init_balance - 4000 ); + BOOST_CHECK_EQUAL( get_balance( borrower, bitusd ), 1000 ); + BOOST_CHECK_EQUAL( get_balance( borrower2, bitusd ), 1000 ); + BOOST_CHECK_EQUAL( get_balance( borrower , core ), init_balance - 2000 ); + BOOST_CHECK_EQUAL( get_balance( borrower2, core ), init_balance - 4000 ); // this should trigger margin call that is below the call limit, but above the // protection threshold. @@ -195,22 +195,22 @@ BOOST_AUTO_TEST_CASE( margin_call_limit_test ) auto order = create_sell_order( borrower2, bitusd.amount(1000), core.amount(1400) ); if( db.head_block_time() <= HARDFORK_436_TIME ) { - BOOST_REQUIRE( order == nullptr ); + BOOST_CHECK( order == nullptr ); - BOOST_REQUIRE_EQUAL( get_balance( borrower2, core ), init_balance - 4000 + 1400 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower2, bitusd ), 0 ); + BOOST_CHECK_EQUAL( get_balance( borrower2, core ), init_balance - 4000 + 1400 ); + BOOST_CHECK_EQUAL( get_balance( borrower2, bitusd ), 0 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower, core ), init_balance - 2000 + 600 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower, bitusd ), 1000 ); + BOOST_CHECK_EQUAL( get_balance( borrower, core ), init_balance - 2000 + 600 ); + BOOST_CHECK_EQUAL( get_balance( borrower, bitusd ), 1000 ); } else { - BOOST_REQUIRE( order != nullptr ); + BOOST_CHECK( order != nullptr ); - BOOST_REQUIRE_EQUAL( get_balance( borrower, bitusd ), 1000 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower2, bitusd ), 0 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower , core ), init_balance - 2000 ); - BOOST_REQUIRE_EQUAL( get_balance( borrower2, core ), init_balance - 4000 ); + BOOST_CHECK_EQUAL( get_balance( borrower, bitusd ), 1000 ); + BOOST_CHECK_EQUAL( get_balance( borrower2, bitusd ), 0 ); + BOOST_CHECK_EQUAL( get_balance( borrower , core ), init_balance - 2000 ); + BOOST_CHECK_EQUAL( get_balance( borrower2, core ), init_balance - 4000 ); } BOOST_TEST_MESSAGE( "Creating a margin call that is protected by the max short squeeze price" ); @@ -219,7 +219,7 @@ BOOST_AUTO_TEST_CASE( margin_call_limit_test ) // this should trigger margin call without protection from the price feed. order = create_sell_order( borrower2, bitusd.amount(1000), core.amount(1800) ); - BOOST_REQUIRE( order != nullptr ); + BOOST_CHECK( order != nullptr ); } catch( const fc::exception& e) { edump((e.to_detail_string())); throw;