Skip to content

Commit 0b2dd8e

Browse files
authored
Merge pull request #2727 from bitshares/pr-2591-fix-gs
Fix issues related to global settlement introduced in PR #2721
2 parents a6dcc1a + 338de92 commit 0b2dd8e

File tree

4 files changed

+130
-12
lines changed

4 files changed

+130
-12
lines changed

libraries/chain/asset_evaluator.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,8 @@ static optional<asset> pay_collateral_fees( database& d,
12011201
{
12021202
const auto& head_time = d.head_block_time();
12031203
bool after_core_hardfork_2591 = HARDFORK_CORE_2591_PASSED( head_time ); // Tighter peg (fill settlement at MCOP)
1204-
if( after_core_hardfork_2591 && !bitasset.current_feed.settlement_price.is_null() )
1204+
if( after_core_hardfork_2591 && !bitasset.is_prediction_market
1205+
&& !bitasset.current_feed.settlement_price.is_null() )
12051206
{
12061207
price fill_price = bitasset.get_margin_call_order_price();
12071208
try

libraries/chain/db_market.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ void database::globally_settle_asset_impl( const asset_object& mia,
319319
const limit_order_object* limit_ptr = find_settled_debt_order( bitasset.asset_id );
320320
if( limit_ptr )
321321
{
322-
collateral_gathered.amount += limit_ptr->for_sale;
322+
collateral_gathered.amount += limit_ptr->settled_collateral_amount;
323323
remove( *limit_ptr );
324324
}
325325

tests/tests/bsrm_basic_tests.cpp

+24-10
Original file line numberDiff line numberDiff line change
@@ -1364,11 +1364,21 @@ BOOST_AUTO_TEST_CASE( manual_gs_test )
13641364

13651365
using bsrm_type = bitasset_options::black_swan_response_type;
13661366

1367-
// Several passes for each BSRM type
1368-
for( uint8_t i = 0; i <= 3; ++i )
1367+
// Several passes, for each BSRM type, before and after core-2591 hf
1368+
for( uint8_t i = 0; i < 8; ++i )
13691369
{
1370-
idump( (i) );
1370+
uint8_t bsrm = i % 4;
1371+
1372+
idump( (i)(bsrm) );
1373+
1374+
if( 4 == i )
1375+
{
1376+
// Advance to core-2591 hard fork
1377+
generate_blocks(HARDFORK_CORE_2591_TIME);
1378+
generate_block();
1379+
}
13711380

1381+
set_expiration( db, trx );
13721382
ACTORS((sam)(feeder)(borrower)(borrower2));
13731383

13741384
auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION;
@@ -1387,7 +1397,7 @@ BOOST_AUTO_TEST_CASE( manual_gs_test )
13871397
acop.common_options.issuer_permissions = ASSET_ISSUER_PERMISSION_ENABLE_BITS_MASK;
13881398
acop.bitasset_opts = bitasset_options();
13891399
acop.bitasset_opts->minimum_feeds = 1;
1390-
acop.bitasset_opts->extensions.value.black_swan_response_method = i;
1400+
acop.bitasset_opts->extensions.value.black_swan_response_method = bsrm;
13911401
acop.bitasset_opts->extensions.value.margin_call_fee_ratio = 11;
13921402

13931403
trx.operations.clear();
@@ -1396,7 +1406,7 @@ BOOST_AUTO_TEST_CASE( manual_gs_test )
13961406
const asset_object& mpa = db.get<asset_object>(ptx.operation_results[0].get<object_id_type>());
13971407
asset_id_type mpa_id = mpa.get_id();
13981408

1399-
BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == static_cast<bsrm_type>(i) );
1409+
BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == static_cast<bsrm_type>(bsrm) );
14001410
BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() );
14011411
BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() );
14021412
BOOST_CHECK( !db.find_settled_debt_order(mpa_id) );
@@ -1431,7 +1441,7 @@ BOOST_AUTO_TEST_CASE( manual_gs_test )
14311441
const auto& check_result = [&]
14321442
{
14331443
BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price );
1434-
switch( static_cast<bsrm_type>(i) )
1444+
switch( static_cast<bsrm_type>(bsrm) )
14351445
{
14361446
case bsrm_type::global_settlement:
14371447
BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method()
@@ -1505,11 +1515,15 @@ BOOST_AUTO_TEST_CASE( manual_gs_test )
15051515

15061516
check_result();
15071517

1518+
// publish a new feed (collateral price rises)
1519+
f.settlement_price = price( asset(1000,mpa_id), asset(15) );
1520+
publish_feed( mpa_id, feeder_id, f, feed_icr );
1521+
15081522
// globally settle
1509-
if( bsrm_type::no_settlement == static_cast<bsrm_type>(i) )
1523+
if( bsrm_type::no_settlement == static_cast<bsrm_type>(bsrm) )
15101524
force_global_settle( mpa_id(db), price( asset(1000,mpa_id), asset(18) ) );
1511-
else if( bsrm_type::individual_settlement_to_fund == static_cast<bsrm_type>(i)
1512-
|| bsrm_type::individual_settlement_to_order == static_cast<bsrm_type>(i) )
1525+
else if( bsrm_type::individual_settlement_to_fund == static_cast<bsrm_type>(bsrm)
1526+
|| bsrm_type::individual_settlement_to_order == static_cast<bsrm_type>(bsrm) )
15131527
force_global_settle( mpa_id(db), price( asset(1000,mpa_id), asset(22) ) );
15141528

15151529
// check
@@ -1526,7 +1540,7 @@ BOOST_AUTO_TEST_CASE( manual_gs_test )
15261540
BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price );
15271541
BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price );
15281542

1529-
switch( static_cast<bsrm_type>(i) )
1543+
switch( static_cast<bsrm_type>(bsrm) )
15301544
{
15311545
case bsrm_type::global_settlement:
15321546
break;

tests/tests/settle_tests.cpp

+103
Original file line numberDiff line numberDiff line change
@@ -2088,6 +2088,109 @@ BOOST_AUTO_TEST_CASE( collateral_fee_of_instant_settlement_test )
20882088

20892089
} FC_LOG_AND_RETHROW() }
20902090

2091+
/// Tests instant settlement:
2092+
/// * After hf core-2591, for prediction markets, forced-settlements are NOT filled at margin call order price (MCOP)
2093+
BOOST_AUTO_TEST_CASE( pm_instant_settlement_price_test )
2094+
{ try {
2095+
2096+
// Advance to a recent hard fork
2097+
generate_blocks(HARDFORK_CORE_2582_TIME);
2098+
generate_block();
2099+
2100+
// multiple passes,
2101+
// i == 0 : before hf core-2591
2102+
// i == 1 : after hf core-2591
2103+
for( int i = 0; i < 2; ++ i )
2104+
{
2105+
idump( (i) );
2106+
2107+
if( 1 == i )
2108+
{
2109+
// Advance to core-2591 hard fork
2110+
generate_blocks(HARDFORK_CORE_2591_TIME);
2111+
generate_block();
2112+
}
2113+
2114+
set_expiration( db, trx );
2115+
2116+
ACTORS((judge)(alice)(feeder));
2117+
2118+
const auto& pmark = create_prediction_market("PMARK", judge_id);
2119+
const auto& core = asset_id_type()(db);
2120+
2121+
asset_id_type pm_id = pmark.get_id();
2122+
2123+
int64_t init_balance(1000000);
2124+
transfer(committee_account, judge_id, asset(init_balance));
2125+
transfer(committee_account, alice_id, asset(init_balance));
2126+
2127+
BOOST_TEST_MESSAGE( "Open position with equal collateral" );
2128+
borrow( alice, pmark.amount(1000), asset(1000) );
2129+
2130+
BOOST_CHECK_EQUAL( get_balance( alice_id, pm_id ), 1000 );
2131+
BOOST_CHECK_EQUAL( get_balance( alice_id, asset_id_type() ), init_balance - 1000 );
2132+
2133+
// add a price feed publisher and publish a feed
2134+
update_feed_producers( pm_id, { feeder_id } );
2135+
2136+
price_feed f;
2137+
f.settlement_price = price( asset(100,pm_id), asset(1) );
2138+
f.core_exchange_rate = price( asset(100,pm_id), asset(1) );
2139+
f.maintenance_collateral_ratio = 1850;
2140+
f.maximum_short_squeeze_ratio = 1250;
2141+
2142+
uint16_t feed_icr = 1900;
2143+
2144+
publish_feed( pm_id, feeder_id, f, feed_icr );
2145+
2146+
BOOST_CHECK_EQUAL( get_balance( alice_id, pm_id ), 1000 );
2147+
BOOST_CHECK_EQUAL( get_balance( alice_id, asset_id_type() ), init_balance - 1000 );
2148+
2149+
BOOST_TEST_MESSAGE( "Globally settling" );
2150+
force_global_settle( pmark, pmark.amount(1) / core.amount(1) );
2151+
2152+
BOOST_CHECK_EQUAL( get_balance( alice_id, pm_id ), 1000 );
2153+
BOOST_CHECK_EQUAL( get_balance( alice_id, asset_id_type() ), init_balance - 1000 );
2154+
2155+
// alice settles
2156+
auto result = force_settle( alice, asset(300, pm_id) );
2157+
auto op_result = result.get<extendable_operation_result>().value;
2158+
2159+
BOOST_CHECK( !op_result.new_objects.valid() ); // force settlement order not created
2160+
2161+
BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() );
2162+
BOOST_CHECK( *op_result.paid->begin() == asset( 300, pm_id ) );
2163+
BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() );
2164+
BOOST_CHECK( *op_result.received->begin() == asset( 300 ) );
2165+
BOOST_REQUIRE( op_result.fees.valid() && 1U == op_result.fees->size() );
2166+
BOOST_CHECK( *op_result.fees->begin() == asset( 0 ) );
2167+
2168+
auto check_result = [&]
2169+
{
2170+
BOOST_CHECK( !pm_id(db).bitasset_data(db).has_individual_settlement() );
2171+
BOOST_CHECK( pm_id(db).bitasset_data(db).has_settlement() );
2172+
BOOST_CHECK_EQUAL( pm_id(db).bitasset_data(db).settlement_fund.value, 700 );
2173+
2174+
BOOST_CHECK_EQUAL( pm_id(db).dynamic_data(db).accumulated_collateral_fees.value, 0 );
2175+
2176+
BOOST_CHECK_EQUAL( get_balance( alice_id, pm_id ), 700 );
2177+
BOOST_CHECK_EQUAL( get_balance( alice_id, asset_id_type() ), init_balance - 700 );
2178+
};
2179+
2180+
check_result();
2181+
2182+
BOOST_TEST_MESSAGE( "Generate a block" );
2183+
generate_block();
2184+
2185+
check_result();
2186+
2187+
// reset
2188+
db.pop_block();
2189+
2190+
} // for i
2191+
2192+
} FC_LOG_AND_RETHROW() }
2193+
20912194
/**
20922195
* Test case to reproduce https://github.com/bitshares/bitshares-core/issues/1883.
20932196
* When there is only one fill_order object in the ticker rolling buffer, it should only be rolled out once.

0 commit comments

Comments
 (0)