@@ -39,24 +39,28 @@ using namespace graphene::wallet;
39
39
BOOST_FIXTURE_TEST_SUITE (market_tests, database_fixture)
40
40
41
41
/* **
42
- * Reproduce bitshares-core issue #338
42
+ * Reproduce bitshares-core issue #338 #343 #453 #606 #625 #649
43
43
*/
44
- BOOST_AUTO_TEST_CASE(issue_338 )
44
+ BOOST_AUTO_TEST_CASE(issue_338_etc )
45
45
{ try {
46
46
generate_blocks (HARDFORK_436_TIME);
47
47
generate_block ();
48
48
49
49
set_expiration ( db, trx );
50
50
51
- ACTORS ((buyer)(seller)(borrower)(feedproducer));
51
+ ACTORS ((buyer)(seller)(borrower)(borrower2)(borrower3)( feedproducer));
52
52
53
53
const auto & bitusd = create_bitasset (" USDBIT" , feedproducer_id);
54
54
const auto & core = asset_id_type ()(db);
55
+ asset_id_type usd_id = bitusd.id ;
56
+ asset_id_type core_id = core.id ;
55
57
56
58
int64_t init_balance (1000000 );
57
59
58
60
transfer (committee_account, buyer_id, asset (init_balance));
59
61
transfer (committee_account, borrower_id, asset (init_balance));
62
+ transfer (committee_account, borrower2_id, asset (init_balance));
63
+ transfer (committee_account, borrower3_id, asset (init_balance));
60
64
update_feed_producers ( bitusd, {feedproducer.id } );
61
65
62
66
price_feed current_feed;
@@ -66,6 +70,13 @@ BOOST_AUTO_TEST_CASE(issue_338)
66
70
publish_feed ( bitusd, feedproducer, current_feed );
67
71
// start out with 300% collateral, call price is 15/1.75 CORE/USD = 60/7
68
72
const call_order_object& call = *borrow ( borrower, bitusd.amount (1000 ), asset (15000 ));
73
+ call_order_id_type call_id = call.id ;
74
+ // create another position with 310% collateral, call price is 15.5/1.75 CORE/USD = 63/7
75
+ const call_order_object& call2 = *borrow ( borrower2, bitusd.amount (1000 ), asset (15500 ));
76
+ call_order_id_type call2_id = call2.id ;
77
+ // create yet another position with 320% collateral, call price is 16/1.75 CORE/USD = 64/7
78
+ const call_order_object& call3 = *borrow ( borrower3, bitusd.amount (1000 ), asset (16000 ));
79
+ call_order_id_type call3_id = call3.id ;
69
80
transfer (borrower, seller, bitusd.amount (1000 ));
70
81
71
82
BOOST_CHECK_EQUAL ( 1000 , call.debt .value );
@@ -78,48 +89,144 @@ BOOST_AUTO_TEST_CASE(issue_338)
78
89
publish_feed ( bitusd, feedproducer, current_feed );
79
90
// settlement price = 1/10, mssp = 1/11
80
91
81
- // This order slightly below the call price will not be matched
92
+ // This order slightly below the call price will not be matched #606
82
93
limit_order_id_type sell_low = create_sell_order (seller, bitusd.amount (7 ), core.amount (59 ))->id ;
83
94
// This order above the MSSP will not be matched
84
95
limit_order_id_type sell_high = create_sell_order (seller, bitusd.amount (7 ), core.amount (78 ))->id ;
85
- // This would match but is blocked by sell_low?!
96
+ // This would match but is blocked by sell_low?! #606
86
97
limit_order_id_type sell_med = create_sell_order (seller, bitusd.amount (7 ), core.amount (60 ))->id ;
87
98
88
99
cancel_limit_order ( sell_med (db) );
89
100
cancel_limit_order ( sell_high (db) );
90
101
cancel_limit_order ( sell_low (db) );
91
102
92
103
// current implementation: an incoming limit order will be filled at the
93
- // requested price
104
+ // requested price #338
94
105
BOOST_CHECK ( !create_sell_order (seller, bitusd.amount (7 ), core.amount (60 )) );
95
106
BOOST_CHECK_EQUAL ( 993 , get_balance (seller, bitusd) );
96
107
BOOST_CHECK_EQUAL ( 60 , get_balance (seller, core) );
97
108
BOOST_CHECK_EQUAL ( 993 , call.debt .value );
98
109
BOOST_CHECK_EQUAL ( 14940 , call.collateral .value );
99
110
100
- auto buy_low = create_sell_order (buyer, asset (90 ), bitusd.amount (10 ))->id ;
111
+ limit_order_id_type buy_low = create_sell_order (buyer, asset (90 ), bitusd.amount (10 ))->id ;
101
112
// margin call takes precedence
102
113
BOOST_CHECK ( !create_sell_order (seller, bitusd.amount (7 ), core.amount (60 )) );
103
114
BOOST_CHECK_EQUAL ( 986 , get_balance (seller, bitusd) );
104
115
BOOST_CHECK_EQUAL ( 120 , get_balance (seller, core) );
105
116
BOOST_CHECK_EQUAL ( 986 , call.debt .value );
106
117
BOOST_CHECK_EQUAL ( 14880 , call.collateral .value );
107
118
108
- auto buy_med = create_sell_order (buyer, asset (105 ), bitusd.amount (10 ))->id ;
119
+ limit_order_id_type buy_med = create_sell_order (buyer, asset (105 ), bitusd.amount (10 ))->id ;
109
120
// margin call takes precedence
110
121
BOOST_CHECK ( !create_sell_order (seller, bitusd.amount (7 ), core.amount (70 )) );
111
122
BOOST_CHECK_EQUAL ( 979 , get_balance (seller, bitusd) );
112
123
BOOST_CHECK_EQUAL ( 190 , get_balance (seller, core) );
113
124
BOOST_CHECK_EQUAL ( 979 , call.debt .value );
114
125
BOOST_CHECK_EQUAL ( 14810 , call.collateral .value );
115
126
116
- auto buy_high = create_sell_order (buyer, asset (115 ), bitusd.amount (10 ))->id ;
117
- // margin call still has precedence (!))
127
+ limit_order_id_type buy_high = create_sell_order (buyer, asset (115 ), bitusd.amount (10 ))->id ;
128
+ // margin call still has precedence (!) #625
118
129
BOOST_CHECK ( !create_sell_order (seller, bitusd.amount (7 ), core.amount (77 )) );
119
130
BOOST_CHECK_EQUAL ( 972 , get_balance (seller, bitusd) );
120
131
BOOST_CHECK_EQUAL ( 267 , get_balance (seller, core) );
121
132
BOOST_CHECK_EQUAL ( 972 , call.debt .value );
122
133
BOOST_CHECK_EQUAL ( 14733 , call.collateral .value );
134
+
135
+ cancel_limit_order ( buy_high (db) );
136
+ cancel_limit_order ( buy_med (db) );
137
+ cancel_limit_order ( buy_low (db) );
138
+
139
+ // call with more usd
140
+ BOOST_CHECK ( !create_sell_order (seller, bitusd.amount (700 ), core.amount (7700 )) );
141
+ BOOST_CHECK_EQUAL ( 272 , get_balance (seller, bitusd) );
142
+ BOOST_CHECK_EQUAL ( 7967 , get_balance (seller, core) );
143
+ BOOST_CHECK_EQUAL ( 272 , call.debt .value );
144
+ BOOST_CHECK_EQUAL ( 7033 , call.collateral .value );
145
+
146
+ // at this moment, collateralization of call is 7033 / 272 = 25.8
147
+ // collateralization of call2 is 15500 / 1000 = 15.5
148
+ // collateralization of call3 is 16000 / 1000 = 16
149
+
150
+ // call more, still matches with the first call order #343
151
+ BOOST_CHECK ( !create_sell_order (seller, bitusd.amount (10 ), core.amount (110 )) );
152
+ BOOST_CHECK_EQUAL ( 262 , get_balance (seller, bitusd) );
153
+ BOOST_CHECK_EQUAL ( 8077 , get_balance (seller, core) );
154
+ BOOST_CHECK_EQUAL ( 262 , call.debt .value );
155
+ BOOST_CHECK_EQUAL ( 6923 , call.collateral .value );
156
+
157
+ // at this moment, collateralization of call is 6923 / 262 = 26.4
158
+ // collateralization of call2 is 15500 / 1000 = 15.5
159
+ // collateralization of call3 is 16000 / 1000 = 16
160
+
161
+ // force settle
162
+ force_settle ( seller, bitusd.amount (10 ) );
163
+ BOOST_CHECK_EQUAL ( 252 , get_balance (seller, bitusd) );
164
+ BOOST_CHECK_EQUAL ( 8077 , get_balance (seller, core) );
165
+ BOOST_CHECK_EQUAL ( 262 , call.debt .value );
166
+ BOOST_CHECK_EQUAL ( 6923 , call.collateral .value );
167
+
168
+ // generate blocks to let the settle order execute
169
+ generate_blocks ( HARDFORK_436_TIME + fc::days (2 ) );
170
+ // call2 get settled #343
171
+ BOOST_CHECK_EQUAL ( 252 , get_balance (seller_id, usd_id) );
172
+ BOOST_CHECK_EQUAL ( 8177 , get_balance (seller_id, core_id) );
173
+ BOOST_CHECK_EQUAL ( 262 , call_id (db).debt .value );
174
+ BOOST_CHECK_EQUAL ( 6923 , call_id (db).collateral .value );
175
+ BOOST_CHECK_EQUAL ( 990 , call2_id (db).debt .value );
176
+ BOOST_CHECK_EQUAL ( 15400 , call2_id (db).collateral .value );
177
+
178
+ set_expiration ( db, trx );
179
+ update_feed_producers ( usd_id (db), {feedproducer_id} );
180
+
181
+ // at this moment, collateralization of call is 8177 / 252 = 32.4
182
+ // collateralization of call2 is 15400 / 990 = 15.5
183
+ // collateralization of call3 is 16000 / 1000 = 16
184
+
185
+ // adjust price feed to get call2 into black swan territory, but not the first call order
186
+ current_feed.settlement_price = asset (1 , usd_id) / asset (20 , core_id);
187
+ publish_feed ( usd_id (db), feedproducer_id (db), current_feed );
188
+ // settlement price = 1/20, mssp = 1/22
189
+
190
+ // black swan event doesn't occur #649
191
+ BOOST_CHECK ( !usd_id (db).bitasset_data (db).has_settlement () );
192
+
193
+ // generate a block
194
+ generate_block ();
195
+
196
+ set_expiration ( db, trx );
197
+ update_feed_producers ( usd_id (db), {feedproducer_id} );
198
+
199
+ // adjust price feed back
200
+ current_feed.settlement_price = asset (1 , usd_id) / asset (10 , core_id);
201
+ publish_feed ( usd_id (db), feedproducer_id (db), current_feed );
202
+ // settlement price = 1/10, mssp = 1/11
203
+
204
+ transfer (borrower2_id, seller_id, asset (1000 , usd_id));
205
+ transfer (borrower3_id, seller_id, asset (1000 , usd_id));
206
+
207
+ // Re-create sell_low, slightly below the call price, will not be matched, will expire soon
208
+ sell_low = create_sell_order (seller_id (db), asset (7 , usd_id), asset (59 ), db.head_block_time () )->id ;
209
+ // This would match but is blocked by sell_low, it has an amount same as call's debt which will be full filled later
210
+ sell_med = create_sell_order (seller_id (db), asset (262 , usd_id), asset (2620 ))->id ; // 1/10
211
+ // Another big order above sell_med, blocked
212
+ limit_order_id_type sell_med2 = create_sell_order (seller_id (db), asset (1200 , usd_id), asset (12120 ))->id ; // 1/10.1
213
+ // Another small order above sell_med2, blocked
214
+ limit_order_id_type sell_med3 = create_sell_order (seller_id (db), asset (120 , usd_id), asset (1224 ))->id ; // 1/10.2
215
+
216
+ // generate a block, sell_low will expire
217
+ generate_block ();
218
+ BOOST_CHECK ( db.find <limit_order_object>( sell_low ) == nullptr );
219
+
220
+ // #453 multiple order matching issue occurs
221
+ BOOST_CHECK ( db.find <limit_order_object>( sell_med ) == nullptr ); // sell_med get filled
222
+ BOOST_CHECK ( db.find <limit_order_object>( sell_med2 ) != nullptr ); // sell_med2 is still there
223
+ BOOST_CHECK ( db.find <limit_order_object>( sell_med3 ) == nullptr ); // sell_med3 get filled
224
+ BOOST_CHECK ( db.find <call_order_object>( call_id ) == nullptr ); // the first call order get filled
225
+ BOOST_CHECK ( db.find <call_order_object>( call2_id ) == nullptr ); // the second call order get filled
226
+ BOOST_CHECK ( db.find <call_order_object>( call3_id ) != nullptr ); // the third call order is still there
227
+
228
+
123
229
} FC_LOG_AND_RETHROW () }
124
230
231
+
125
232
BOOST_AUTO_TEST_SUITE_END ()
0 commit comments