Skip to content

Commit e5fc5d4

Browse files
committed
Test case for #338 #343 #453 #606 #625 #649 fixes
1 parent c049b53 commit e5fc5d4

File tree

1 file changed

+251
-0
lines changed

1 file changed

+251
-0
lines changed

tests/tests/market_tests.cpp

+251
Original file line numberDiff line numberDiff line change
@@ -229,5 +229,256 @@ BOOST_AUTO_TEST_CASE(issue_338_etc)
229229

230230
} FC_LOG_AND_RETHROW() }
231231

232+
/***
233+
* Fixed bitshares-core issue #338 #343 #606 #625 #649
234+
*/
235+
BOOST_AUTO_TEST_CASE(hardfork_core_338_test)
236+
{ try {
237+
generate_blocks(HARDFORK_CORE_338_TIME); // assume all hard forks occur at same time
238+
generate_block();
239+
240+
set_expiration( db, trx );
241+
242+
ACTORS((buyer)(seller)(borrower)(borrower2)(borrower3)(feedproducer));
243+
244+
const auto& bitusd = create_bitasset("USDBIT", feedproducer_id);
245+
const auto& core = asset_id_type()(db);
246+
asset_id_type usd_id = bitusd.id;
247+
asset_id_type core_id = core.id;
248+
249+
int64_t init_balance(1000000);
250+
251+
transfer(committee_account, buyer_id, asset(init_balance));
252+
transfer(committee_account, borrower_id, asset(init_balance));
253+
transfer(committee_account, borrower2_id, asset(init_balance));
254+
transfer(committee_account, borrower3_id, asset(init_balance));
255+
update_feed_producers( bitusd, {feedproducer.id} );
256+
257+
price_feed current_feed;
258+
current_feed.maintenance_collateral_ratio = 1750;
259+
current_feed.maximum_short_squeeze_ratio = 1100;
260+
current_feed.settlement_price = bitusd.amount( 1 ) / core.amount(5);
261+
publish_feed( bitusd, feedproducer, current_feed );
262+
// start out with 300% collateral, call price is 15/1.75 CORE/USD = 60/7
263+
const call_order_object& call = *borrow( borrower, bitusd.amount(1000), asset(15000));
264+
call_order_id_type call_id = call.id;
265+
// create another position with 310% collateral, call price is 15.5/1.75 CORE/USD = 63/7
266+
const call_order_object& call2 = *borrow( borrower2, bitusd.amount(1000), asset(15500));
267+
call_order_id_type call2_id = call2.id;
268+
// create yet another position with 320% collateral, call price is 16/1.75 CORE/USD = 64/7
269+
const call_order_object& call3 = *borrow( borrower3, bitusd.amount(1000), asset(16000));
270+
call_order_id_type call3_id = call3.id;
271+
transfer(borrower, seller, bitusd.amount(1000));
272+
transfer(borrower2, seller, bitusd.amount(1000));
273+
transfer(borrower3, seller, bitusd.amount(1000));
274+
275+
BOOST_CHECK_EQUAL( 1000, call.debt.value );
276+
BOOST_CHECK_EQUAL( 15000, call.collateral.value );
277+
BOOST_CHECK_EQUAL( 1000, call2.debt.value );
278+
BOOST_CHECK_EQUAL( 15500, call2.collateral.value );
279+
BOOST_CHECK_EQUAL( 1000, call3.debt.value );
280+
BOOST_CHECK_EQUAL( 16000, call3.collateral.value );
281+
BOOST_CHECK_EQUAL( 3000, get_balance(seller, bitusd) );
282+
BOOST_CHECK_EQUAL( 0, get_balance(seller, core) );
283+
284+
// adjust price feed to get call_order into margin call territory
285+
current_feed.settlement_price = bitusd.amount( 1 ) / core.amount(10);
286+
publish_feed( bitusd, feedproducer, current_feed );
287+
// settlement price = 1/10, mssp = 1/11
288+
289+
// This sell order above MSSP will not be matched with a call
290+
limit_order_id_type sell_high = create_sell_order(seller, bitusd.amount(7), core.amount(78))->id;
291+
292+
BOOST_CHECK_EQUAL( 2993, get_balance(seller, bitusd) );
293+
BOOST_CHECK_EQUAL( 0, get_balance(seller, core) );
294+
295+
// This buy order is too low will not be matched with a sell order
296+
limit_order_id_type buy_low = create_sell_order(buyer, asset(90), bitusd.amount(10))->id;
297+
// This buy order at MSSP will be matched only if no margin call (margin call takes precedence)
298+
limit_order_id_type buy_med = create_sell_order(buyer, asset(110), bitusd.amount(10))->id;
299+
// This buy order above MSSP will be matched with a sell order (limit order with better price takes precedence)
300+
limit_order_id_type buy_high = create_sell_order(buyer, asset(111), bitusd.amount(10))->id;
301+
302+
BOOST_CHECK_EQUAL( 0, get_balance(buyer, bitusd) );
303+
BOOST_CHECK_EQUAL( init_balance - 90 - 110 - 111, get_balance(buyer, core) );
304+
305+
// This order slightly below the call price will be matched: #606 fixed
306+
BOOST_CHECK( !create_sell_order(seller, bitusd.amount(700), core.amount(5900) ) );
307+
308+
// firstly it will match with buy_high, at buy_high's price: #625 fixed
309+
BOOST_CHECK( !db.find<limit_order_object>( buy_high ) );
310+
BOOST_CHECK_EQUAL( db.find<limit_order_object>( buy_med )->for_sale.value, 110 );
311+
BOOST_CHECK_EQUAL( db.find<limit_order_object>( buy_low )->for_sale.value, 90 );
312+
313+
// buy_high pays 111 CORE, receives 10 USD goes to buyer's balance
314+
BOOST_CHECK_EQUAL( 10, get_balance(buyer, bitusd) );
315+
BOOST_CHECK_EQUAL( init_balance - 90 - 110 - 111, get_balance(buyer, core) );
316+
// sell order pays 10 USD, receives 111 CORE, remaining 690 USD for sale, still at price 7/59
317+
318+
// then it will match with call, at mssp: 1/11 = 690/7590 : #338 fixed
319+
BOOST_CHECK_EQUAL( 2293, get_balance(seller, bitusd) );
320+
BOOST_CHECK_EQUAL( 7701, get_balance(seller, core) );
321+
BOOST_CHECK_EQUAL( 310, call.debt.value );
322+
BOOST_CHECK_EQUAL( 7410, call.collateral.value );
323+
BOOST_CHECK_EQUAL( 1000, call2.debt.value );
324+
BOOST_CHECK_EQUAL( 15500, call2.collateral.value );
325+
BOOST_CHECK_EQUAL( 1000, call3.debt.value );
326+
BOOST_CHECK_EQUAL( 16000, call3.collateral.value );
327+
328+
// call's call_price will be updated after the match, to 741/31/1.75 CORE/USD = 2964/217
329+
// it's above settlement price (10/1) so won't be margin called again
330+
BOOST_CHECK( price(asset(2964),asset(217,usd_id)) == call.call_price );
331+
332+
// This would match with call before, but would match with call2 after #343 fixed
333+
BOOST_CHECK( !create_sell_order(seller, bitusd.amount(700), core.amount(6000) ) );
334+
BOOST_CHECK_EQUAL( db.find<limit_order_object>( buy_med )->for_sale.value, 110 );
335+
BOOST_CHECK_EQUAL( db.find<limit_order_object>( buy_low )->for_sale.value, 90 );
336+
337+
// fill price would be mssp: 1/11 = 700/7700 : #338 fixed
338+
BOOST_CHECK_EQUAL( 1593, get_balance(seller, bitusd) );
339+
BOOST_CHECK_EQUAL( 15401, get_balance(seller, core) );
340+
BOOST_CHECK_EQUAL( 310, call.debt.value );
341+
BOOST_CHECK_EQUAL( 7410, call.collateral.value );
342+
BOOST_CHECK_EQUAL( 300, call2.debt.value );
343+
BOOST_CHECK_EQUAL( 7800, call2.collateral.value );
344+
BOOST_CHECK_EQUAL( 1000, call3.debt.value );
345+
BOOST_CHECK_EQUAL( 16000, call3.collateral.value );
346+
// call2's call_price will be updated after the match, to 78/3/1.75 CORE/USD = 312/21
347+
BOOST_CHECK( price(asset(312),asset(21,usd_id)) == call2.call_price );
348+
// it's above settlement price (10/1) so won't be margin called
349+
350+
// at this moment, collateralization of call is 7410 / 310 = 23.9
351+
// collateralization of call2 is 7800 / 300 = 26
352+
// collateralization of call3 is 16000 / 1000 = 16
353+
354+
// force settle
355+
force_settle( seller, bitusd.amount(10) );
356+
357+
BOOST_CHECK_EQUAL( 1583, get_balance(seller, bitusd) );
358+
BOOST_CHECK_EQUAL( 15401, get_balance(seller, core) );
359+
BOOST_CHECK_EQUAL( 310, call.debt.value );
360+
BOOST_CHECK_EQUAL( 7410, call.collateral.value );
361+
BOOST_CHECK_EQUAL( 300, call2.debt.value );
362+
BOOST_CHECK_EQUAL( 7800, call2.collateral.value );
363+
BOOST_CHECK_EQUAL( 1000, call3.debt.value );
364+
BOOST_CHECK_EQUAL( 16000, call3.collateral.value );
365+
366+
// generate blocks to let the settle order execute (price feed will expire after it)
367+
generate_blocks( HARDFORK_CORE_338_TIME + fc::hours(25) );
368+
369+
// call3 get settled, at settlement price 1/10: #343 fixed
370+
BOOST_CHECK_EQUAL( 1583, get_balance(seller, bitusd) );
371+
BOOST_CHECK_EQUAL( 15501, get_balance(seller, core) );
372+
BOOST_CHECK_EQUAL( 310, call_id(db).debt.value );
373+
BOOST_CHECK_EQUAL( 7410, call_id(db).collateral.value );
374+
BOOST_CHECK_EQUAL( 300, call2_id(db).debt.value );
375+
BOOST_CHECK_EQUAL( 7800, call2_id(db).collateral.value );
376+
BOOST_CHECK_EQUAL( 990, call3_id(db).debt.value );
377+
BOOST_CHECK_EQUAL( 15900, call3_id(db).collateral.value );
378+
379+
set_expiration( db, trx );
380+
update_feed_producers( usd_id(db), {feedproducer_id} );
381+
382+
// at this moment, collateralization of call is 7410 / 310 = 23.9
383+
// collateralization of call2 is 7800 / 300 = 26
384+
// collateralization of call3 is 15900 / 990 = 16.06
385+
386+
// adjust price feed to get call3 into black swan territory, but not the other call orders
387+
current_feed.settlement_price = asset(1, usd_id) / asset(20, core_id);
388+
publish_feed( usd_id(db), feedproducer_id(db), current_feed );
389+
// settlement price = 1/20, mssp = 1/22
390+
391+
// black swan event will occur: #649 fixed
392+
BOOST_CHECK( usd_id(db).bitasset_data(db).has_settlement() );
393+
// short positions will be closed
394+
BOOST_CHECK( !db.find<call_order_object>( call_id ) );
395+
BOOST_CHECK( !db.find<call_order_object>( call2_id ) );
396+
BOOST_CHECK( !db.find<call_order_object>( call3_id ) );
397+
398+
// generate a block
399+
generate_block();
400+
401+
402+
} FC_LOG_AND_RETHROW() }
403+
404+
/***
405+
* Fixed bitshares-core issue #453
406+
*/
407+
BOOST_AUTO_TEST_CASE(hardfork_core_453_test)
408+
{ try {
409+
generate_blocks(HARDFORK_CORE_453_TIME);
410+
generate_block();
411+
412+
set_expiration( db, trx );
413+
414+
ACTORS((buyer)(seller)(borrower)(borrower2)(borrower3)(feedproducer));
415+
416+
const auto& bitusd = create_bitasset("USDBIT", feedproducer_id);
417+
const auto& core = asset_id_type()(db);
418+
asset_id_type usd_id = bitusd.id;
419+
asset_id_type core_id = core.id;
420+
421+
int64_t init_balance(1000000);
422+
423+
transfer(committee_account, buyer_id, asset(init_balance));
424+
transfer(committee_account, borrower_id, asset(init_balance));
425+
transfer(committee_account, borrower2_id, asset(init_balance));
426+
transfer(committee_account, borrower3_id, asset(init_balance));
427+
update_feed_producers( bitusd, {feedproducer.id} );
428+
429+
price_feed current_feed;
430+
current_feed.maintenance_collateral_ratio = 1750;
431+
current_feed.maximum_short_squeeze_ratio = 1100;
432+
current_feed.settlement_price = bitusd.amount( 1 ) / core.amount(5);
433+
publish_feed( bitusd, feedproducer, current_feed );
434+
// start out with 300% collateral, call price is 15/1.75 CORE/USD = 60/7
435+
const call_order_object& call = *borrow( borrower, bitusd.amount(1000), asset(15000));
436+
call_order_id_type call_id = call.id;
437+
// create another position with 310% collateral, call price is 15.5/1.75 CORE/USD = 63/7
438+
const call_order_object& call2 = *borrow( borrower2, bitusd.amount(1000), asset(15500));
439+
call_order_id_type call2_id = call2.id;
440+
// create yet another position with 320% collateral, call price is 16/1.75 CORE/USD = 64/7
441+
const call_order_object& call3 = *borrow( borrower3, bitusd.amount(1000), asset(16000));
442+
call_order_id_type call3_id = call3.id;
443+
transfer(borrower, seller, bitusd.amount(1000));
444+
transfer(borrower2, seller, bitusd.amount(1000));
445+
transfer(borrower3, seller, bitusd.amount(1000));
446+
447+
BOOST_CHECK_EQUAL( 1000, call.debt.value );
448+
BOOST_CHECK_EQUAL( 15000, call.collateral.value );
449+
BOOST_CHECK_EQUAL( 1000, call2.debt.value );
450+
BOOST_CHECK_EQUAL( 15500, call2.collateral.value );
451+
BOOST_CHECK_EQUAL( 1000, call3.debt.value );
452+
BOOST_CHECK_EQUAL( 16000, call3.collateral.value );
453+
BOOST_CHECK_EQUAL( 3000, get_balance(seller, bitusd) );
454+
BOOST_CHECK_EQUAL( 0, get_balance(seller, core) );
455+
456+
// no margin call so far
457+
458+
// This order would match call when it's margin called, it has an amount same as call's debt which will be full filled later
459+
limit_order_id_type sell_med = create_sell_order(seller_id(db), asset(1000, usd_id), asset(10000))->id; // 1/10
460+
// Another big order above sell_med, amount bigger than call2's debt
461+
limit_order_id_type sell_med2 = create_sell_order(seller_id(db), asset(1200, usd_id), asset(12120))->id; // 1/10.1
462+
// Another small order above sell_med2
463+
limit_order_id_type sell_med3 = create_sell_order(seller_id(db), asset(120, usd_id), asset(1224))->id; // 1/10.2
464+
465+
// adjust price feed to get the call orders into margin call territory
466+
current_feed.settlement_price = bitusd.amount( 1 ) / core.amount(10);
467+
publish_feed( bitusd, feedproducer, current_feed );
468+
// settlement price = 1/10, mssp = 1/11
469+
470+
// Fixed #453 multiple order matching issue occurs
471+
BOOST_CHECK( !db.find<limit_order_object>( sell_med ) ); // sell_med get filled
472+
BOOST_CHECK( !db.find<limit_order_object>( sell_med2 ) ); // sell_med2 get filled
473+
BOOST_CHECK( !db.find<limit_order_object>( sell_med3 ) ); // sell_med3 get filled
474+
BOOST_CHECK( !db.find<call_order_object>( call_id ) ); // the first call order get filled
475+
BOOST_CHECK( !db.find<call_order_object>( call2_id ) ); // the second call order get filled
476+
BOOST_CHECK( db.find<call_order_object>( call3_id ) ); // the third call order is still there
477+
478+
// generate a block
479+
generate_block();
480+
481+
482+
} FC_LOG_AND_RETHROW() }
232483

233484
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)