Skip to content

Commit 7836bcc

Browse files
authored
Merge pull request #2019 from bitshares/jmj_460
Prevent black swan in prediction markets
2 parents c2cafd1 + b4e3a85 commit 7836bcc

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

libraries/chain/db_market.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,14 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa
10031003
if( !mia.is_market_issued() ) return false;
10041004

10051005
const asset_bitasset_data_object& bitasset = ( bitasset_ptr ? *bitasset_ptr : mia.bitasset_data(*this) );
1006+
1007+
// price feeds can cause black swans in prediction markets
1008+
// The hardfork check may be able to be removed after the hardfork date
1009+
// if check_for_blackswan never triggered a black swan on a prediction market.
1010+
// NOTE: check_for_blackswan returning true does not always mean a black
1011+
// swan was triggered.
1012+
if ( maint_time >= HARDFORK_CORE_460_TIME && bitasset.is_prediction_market )
1013+
return false;
10061014

10071015
if( check_for_blackswan( mia, enable_black_swan, &bitasset ) )
10081016
return false;
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// bitshares-core issue #460 Prediction Market price feed should not cause black swan
2+
#ifndef HARDFORK_CORE_460_TIME
3+
#define HARDFORK_CORE_460_TIME (fc::time_point_sec( 1609372800 ) ) // 2020-12-31T00:00:00
4+
#endif

tests/tests/operation_tests.cpp

+62
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,68 @@ BOOST_AUTO_TEST_CASE( prediction_market_resolves_to_0 )
840840
}
841841
}
842842

843+
/***
844+
* Prediction markets should not suffer a black swan (Issue #460)
845+
*/
846+
BOOST_AUTO_TEST_CASE( prediction_market_black_swan )
847+
{
848+
try {
849+
ACTORS((judge)(dan)(nathan));
850+
851+
// progress to recent hardfork
852+
generate_blocks( HARDFORK_CORE_1270_TIME );
853+
set_expiration( db, trx );
854+
855+
const auto& pmark = create_prediction_market("PMARK", judge_id);
856+
857+
int64_t init_balance(1000000);
858+
transfer(committee_account, judge_id, asset(init_balance));
859+
transfer(committee_account, dan_id, asset(init_balance));
860+
861+
update_feed_producers( pmark, { judge_id });
862+
price_feed feed;
863+
feed.settlement_price = asset( 1, pmark.id ) / asset( 1 );
864+
publish_feed( pmark, judge, feed );
865+
866+
borrow( dan, pmark.amount(1000), asset(1000) );
867+
868+
// feed a price that will cause a black swan
869+
feed.settlement_price = asset( 1, pmark.id ) / asset( 1000 );
870+
publish_feed( pmark, judge, feed );
871+
872+
// verify a black swan happened
873+
GRAPHENE_REQUIRE_THROW(borrow( dan, pmark.amount(1000), asset(1000) ), fc::exception);
874+
trx.clear();
875+
876+
// progress past hardfork
877+
generate_blocks( HARDFORK_CORE_460_TIME + db.get_global_properties().parameters.maintenance_interval );
878+
set_expiration( db, trx );
879+
880+
// create another prediction market to test the hardfork
881+
const auto& pmark2 = create_prediction_market("PMARKII", judge_id);
882+
update_feed_producers( pmark2, { judge_id });
883+
price_feed feed2;
884+
feed2.settlement_price = asset( 1, pmark2.id ) / asset( 1 );
885+
publish_feed( pmark2, judge, feed2 );
886+
887+
borrow( dan, pmark2.amount(1000), asset(1000) );
888+
889+
// feed a price that would have caused a black swan
890+
feed2.settlement_price = asset( 1, pmark2.id ) / asset( 1000 );
891+
publish_feed( pmark2, judge, feed2 );
892+
893+
// verify a black swan did not happen
894+
borrow( dan, pmark2.amount(1000), asset(1000) );
895+
896+
generate_block(~database::skip_transaction_dupe_check);
897+
generate_blocks( db.get_dynamic_global_properties().next_maintenance_time );
898+
generate_block();
899+
} catch( const fc::exception& e) {
900+
edump((e.to_detail_string()));
901+
throw;
902+
}
903+
}
904+
843905
BOOST_AUTO_TEST_CASE( create_account_test )
844906
{
845907
try {

0 commit comments

Comments
 (0)