@@ -229,5 +229,256 @@ BOOST_AUTO_TEST_CASE(issue_338_etc)
229
229
230
230
} FC_LOG_AND_RETHROW () }
231
231
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 () }
232
483
233
484
BOOST_AUTO_TEST_SUITE_END ()
0 commit comments