BitShares-Core  5.0.0
BitShares blockchain implementation and command-line interface software
db_market.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
26 
29 #include <graphene/chain/hardfork.hpp>
32 
33 #include <fc/uint128.hpp>
34 
35 namespace graphene { namespace chain {
36 
37 namespace detail {
38 
39  share_type calculate_percent(const share_type& value, uint16_t percent)
40  {
41  fc::uint128_t a(value.value);
42  a *= percent;
44  FC_ASSERT( a <= GRAPHENE_MAX_SHARE_SUPPLY, "overflow when calculating percent" );
45  return static_cast<int64_t>(a);
46  }
47 
48 } //detail
49 
57 void database::globally_settle_asset( const asset_object& mia, const price& settlement_price )
58 {
59  auto maint_time = get_dynamic_global_properties().next_maintenance_time;
60  bool before_core_hardfork_1669 = ( maint_time <= HARDFORK_CORE_1669_TIME ); // whether to use call_price
61 
62  if( before_core_hardfork_1669 )
63  {
64  globally_settle_asset_impl( mia, settlement_price,
65  get_index_type<call_order_index>().indices().get<by_price>() );
66  }
67  else
68  {
69  globally_settle_asset_impl( mia, settlement_price,
70  get_index_type<call_order_index>().indices().get<by_collateral>() );
71  }
72 }
73 
74 template<typename IndexType>
75 void database::globally_settle_asset_impl( const asset_object& mia,
76  const price& settlement_price,
77  const IndexType& call_index )
78 { try {
79  const asset_bitasset_data_object& bitasset = mia.bitasset_data(*this);
80  FC_ASSERT( !bitasset.has_settlement(), "black swan already occurred, it should not happen again" );
81 
82  const asset_object& backing_asset = bitasset.options.short_backing_asset(*this);
83  asset collateral_gathered = backing_asset.amount(0);
84 
85  const asset_dynamic_data_object& mia_dyn = mia.dynamic_asset_data_id(*this);
86  auto original_mia_supply = mia_dyn.current_supply;
87 
88  auto maint_time = get_dynamic_global_properties().next_maintenance_time;
89  bool before_core_hardfork_342 = ( maint_time <= HARDFORK_CORE_342_TIME ); // better rounding
90 
91  // cancel all call orders and accumulate it into collateral_gathered
92  auto call_itr = call_index.lower_bound( price::min( bitasset.options.short_backing_asset, mia.id ) );
93  auto call_end = call_index.upper_bound( price::max( bitasset.options.short_backing_asset, mia.id ) );
94 
95  asset pays;
96  while( call_itr != call_end )
97  {
98  const call_order_object& order = *call_itr;
99  ++call_itr;
100 
101  if( before_core_hardfork_342 )
102  pays = order.get_debt() * settlement_price; // round down, in favor of call order
103  else
104  pays = order.get_debt().multiply_and_round_up( settlement_price ); // round up in favor of global-settle fund
105 
106  if( pays > order.get_collateral() )
107  pays = order.get_collateral();
108 
109  collateral_gathered += pays;
110 
111  FC_ASSERT( fill_call_order( order, pays, order.get_debt(), settlement_price, true ) ); // call order is maker
112  }
113 
114  modify( bitasset, [&mia,original_mia_supply,&collateral_gathered]( asset_bitasset_data_object& obj ){
115  obj.settlement_price = mia.amount(original_mia_supply) / collateral_gathered;
116  obj.settlement_fund = collateral_gathered.amount;
117  });
118 
123  modify( mia_dyn, [original_mia_supply]( asset_dynamic_data_object& obj ){
124  obj.current_supply = original_mia_supply;
125  });
126 
127 } FC_CAPTURE_AND_RETHROW( (mia)(settlement_price) ) }
128 
130 { try {
131  FC_ASSERT( bitasset.is_market_issued() );
132  const asset_bitasset_data_object& bad = bitasset.bitasset_data(*this);
133  FC_ASSERT( bad.has_settlement() );
134  const asset_dynamic_data_object& bdd = bitasset.dynamic_asset_data_id(*this);
135  FC_ASSERT( !bad.is_prediction_market );
136  FC_ASSERT( !bad.current_feed.settlement_price.is_null() );
137 
138  if( bdd.current_supply > 0 )
139  {
140  // Create + execute a "bid" with 0 additional collateral
141  const collateral_bid_object& pseudo_bid = create<collateral_bid_object>([&](collateral_bid_object& bid) {
142  bid.bidder = bitasset.issuer;
143  bid.inv_swan_price = asset(0, bad.options.short_backing_asset)
144  / asset(bdd.current_supply, bitasset.id);
145  });
146  execute_bid( pseudo_bid, bdd.current_supply, bad.settlement_fund, bad.current_feed );
147  } else
148  FC_ASSERT( bad.settlement_fund == 0 );
149 
150  _cancel_bids_and_revive_mpa( bitasset, bad );
151 } FC_CAPTURE_AND_RETHROW( (bitasset) ) }
152 
153 void database::_cancel_bids_and_revive_mpa( const asset_object& bitasset, const asset_bitasset_data_object& bad )
154 { try {
155  FC_ASSERT( bitasset.is_market_issued() );
156  FC_ASSERT( bad.has_settlement() );
158 
159  // cancel remaining bids
160  const auto& bid_idx = get_index_type< collateral_bid_index >().indices().get<by_price>();
161  auto itr = bid_idx.lower_bound( boost::make_tuple( bitasset.id,
162  price::max( bad.options.short_backing_asset, bitasset.id ),
163  collateral_bid_id_type() ) );
164  while( itr != bid_idx.end() && itr->inv_swan_price.quote.asset_id == bitasset.id )
165  {
166  const collateral_bid_object& bid = *itr;
167  ++itr;
168  cancel_bid( bid );
169  }
170 
171  // revive
172  modify( bad, [&]( asset_bitasset_data_object& obj ){
173  obj.settlement_price = price();
174  obj.settlement_fund = 0;
175  });
176 } FC_CAPTURE_AND_RETHROW( (bitasset) ) }
177 
178 void database::cancel_bid(const collateral_bid_object& bid, bool create_virtual_op)
179 {
180  adjust_balance(bid.bidder, bid.inv_swan_price.base);
181 
182  if( create_virtual_op )
183  {
185  vop.bidder = bid.bidder;
188  push_applied_operation( vop );
189  }
190  remove(bid);
191 }
192 
193 void database::execute_bid( const collateral_bid_object& bid, share_type debt_covered, share_type collateral_from_fund,
194  const price_feed& current_feed )
195 {
196  const call_order_object& call_obj = create<call_order_object>( [&](call_order_object& call ){
197  call.borrower = bid.bidder;
198  call.collateral = bid.inv_swan_price.base.amount + collateral_from_fund;
199  call.debt = debt_covered;
200  // don't calculate call_price after core-1270 hard fork
201  if( get_dynamic_global_properties().next_maintenance_time > HARDFORK_CORE_1270_TIME )
202  // bid.inv_swan_price is in collateral / debt
203  call.call_price = price( asset( 1, bid.inv_swan_price.base.asset_id ),
204  asset( 1, bid.inv_swan_price.quote.asset_id ) );
205  else
206  call.call_price = price::call_price( asset(debt_covered, bid.inv_swan_price.quote.asset_id),
207  asset(call.collateral, bid.inv_swan_price.base.asset_id),
208  current_feed.maintenance_collateral_ratio );
209  });
210 
211  // Note: CORE asset in collateral_bid_object is not counted in account_stats.total_core_in_orders
212  if( bid.inv_swan_price.base.asset_id == asset_id_type() )
213  modify( get_account_stats_by_owner(bid.bidder), [&](account_statistics_object& stats) {
214  stats.total_core_in_orders += call_obj.collateral;
215  });
216 
217  push_applied_operation( execute_bid_operation( bid.bidder, asset( call_obj.collateral, bid.inv_swan_price.base.asset_id ),
218  asset( debt_covered, bid.inv_swan_price.quote.asset_id ) ) );
219 
220  remove(bid);
221 }
222 
223 void database::cancel_settle_order(const force_settlement_object& order, bool create_virtual_op)
224 {
225  adjust_balance(order.owner, order.balance);
226 
227  if( create_virtual_op )
228  {
230  vop.settlement = order.id;
231  vop.account = order.owner;
232  vop.amount = order.balance;
233  push_applied_operation( vop );
234  }
235  remove(order);
236 }
237 
238 void database::cancel_limit_order( const limit_order_object& order, bool create_virtual_op, bool skip_cancel_fee )
239 {
240  // if need to create a virtual op, try deduct a cancellation fee here.
241  // there are two scenarios when order is cancelled and need to create a virtual op:
242  // 1. due to expiration: always deduct a fee if there is any fee deferred
243  // 2. due to cull_small: deduct a fee after hard fork 604, but not before (will set skip_cancel_fee)
244  const account_statistics_object* seller_acc_stats = nullptr;
245  const asset_dynamic_data_object* fee_asset_dyn_data = nullptr;
247  share_type deferred_fee = order.deferred_fee;
248  asset deferred_paid_fee = order.deferred_paid_fee;
249  if( create_virtual_op )
250  {
251  vop.order = order.id;
252  vop.fee_paying_account = order.seller;
253  // only deduct fee if not skipping fee, and there is any fee deferred
254  if( !skip_cancel_fee && deferred_fee > 0 )
255  {
256  asset core_cancel_fee = current_fee_schedule().calculate_fee( vop );
257  // cap the fee
258  if( core_cancel_fee.amount > deferred_fee )
259  core_cancel_fee.amount = deferred_fee;
260  // if there is any CORE fee to deduct, redirect it to referral program
261  if( core_cancel_fee.amount > 0 )
262  {
263  seller_acc_stats = &order.seller( *this ).statistics( *this );
264  modify( *seller_acc_stats, [&]( account_statistics_object& obj ) {
265  obj.pay_fee( core_cancel_fee.amount, get_global_properties().parameters.cashback_vesting_threshold );
266  } );
267  deferred_fee -= core_cancel_fee.amount;
268  // handle originally paid fee if any:
269  // to_deduct = round_up( paid_fee * core_cancel_fee / deferred_core_fee_before_deduct )
270  if( deferred_paid_fee.amount == 0 )
271  {
272  vop.fee = core_cancel_fee;
273  }
274  else
275  {
276  fc::uint128_t fee128( deferred_paid_fee.amount.value );
277  fee128 *= core_cancel_fee.amount.value;
278  // to round up
279  fee128 += order.deferred_fee.value;
280  fee128 -= 1;
281  fee128 /= order.deferred_fee.value;
282  share_type cancel_fee_amount = static_cast<int64_t>(fee128);
283  // cancel_fee should be positive, pay it to asset's accumulated_fees
284  fee_asset_dyn_data = &deferred_paid_fee.asset_id(*this).dynamic_asset_data_id(*this);
285  modify( *fee_asset_dyn_data, [&](asset_dynamic_data_object& addo) {
286  addo.accumulated_fees += cancel_fee_amount;
287  });
288  // cancel_fee should be no more than deferred_paid_fee
289  deferred_paid_fee.amount -= cancel_fee_amount;
290  vop.fee = asset( cancel_fee_amount, deferred_paid_fee.asset_id );
291  }
292  }
293  }
294  }
295 
296  // refund funds in order
297  auto refunded = order.amount_for_sale();
298  if( refunded.asset_id == asset_id_type() )
299  {
300  if( seller_acc_stats == nullptr )
301  seller_acc_stats = &order.seller( *this ).statistics( *this );
302  modify( *seller_acc_stats, [&]( account_statistics_object& obj ) {
303  obj.total_core_in_orders -= refunded.amount;
304  });
305  }
306  adjust_balance(order.seller, refunded);
307 
308  // refund fee
309  // could be virtual op or real op here
310  if( order.deferred_paid_fee.amount == 0 )
311  {
312  // be here, order.create_time <= HARDFORK_CORE_604_TIME, or fee paid in CORE, or no fee to refund.
313  // if order was created before hard fork 604 then cancelled no matter before or after hard fork 604,
314  // see it as fee paid in CORE, deferred_fee should be refunded to order owner but not fee pool
315  adjust_balance( order.seller, deferred_fee );
316  }
317  else // need to refund fee in originally paid asset
318  {
319  adjust_balance(order.seller, deferred_paid_fee);
320  // be here, must have: fee_asset != CORE
321  if( fee_asset_dyn_data == nullptr )
322  fee_asset_dyn_data = &deferred_paid_fee.asset_id(*this).dynamic_asset_data_id(*this);
323  modify( *fee_asset_dyn_data, [&](asset_dynamic_data_object& addo) {
324  addo.fee_pool += deferred_fee;
325  });
326  }
327 
328  if( create_virtual_op )
329  push_applied_operation( vop );
330 
331  remove(order);
332 }
333 
335 {
346  if( order.amount_to_receive().amount == 0 )
347  {
348  if( order.deferred_fee > 0 && db.head_block_time() <= HARDFORK_CORE_604_TIME )
349  {
350  db.cancel_limit_order( order, true, true );
351  }
352  else
353  db.cancel_limit_order( order );
354  return true;
355  }
356  return false;
357 }
358 
359 bool database::apply_order_before_hardfork_625(const limit_order_object& new_order_object, bool allow_black_swan)
360 {
361  auto order_id = new_order_object.id;
362  const asset_object& sell_asset = get(new_order_object.amount_for_sale().asset_id);
363  const asset_object& receive_asset = get(new_order_object.amount_to_receive().asset_id);
364 
365  // Possible optimization: We only need to check calls if both are true:
366  // - The new order is at the front of the book
367  // - The new order is below the call limit price
368  bool called_some = check_call_orders(sell_asset, allow_black_swan, true); // the first time when checking, call order is maker
369  called_some |= check_call_orders(receive_asset, allow_black_swan, true); // the other side, same as above
370  if( called_some && !find_object(order_id) ) // then we were filled by call order
371  return true;
372 
373  const auto& limit_price_idx = get_index_type<limit_order_index>().indices().get<by_price>();
374 
375  // TODO: it should be possible to simply check the NEXT/PREV iterator after new_order_object to
376  // determine whether or not this order has "changed the book" in a way that requires us to
377  // check orders. For now I just lookup the lower bound and check for equality... this is log(n) vs
378  // constant time check. Potential optimization.
379 
380  auto max_price = ~new_order_object.sell_price;
381  auto limit_itr = limit_price_idx.lower_bound(max_price.max());
382  auto limit_end = limit_price_idx.upper_bound(max_price);
383 
384  bool finished = false;
385  while( !finished && limit_itr != limit_end )
386  {
387  auto old_limit_itr = limit_itr;
388  ++limit_itr;
389  // match returns 2 when only the old order was fully filled. In this case, we keep matching; otherwise, we stop.
390  finished = (match(new_order_object, *old_limit_itr, old_limit_itr->sell_price) != 2);
391  }
392 
393  //Possible optimization: only check calls if the new order completely filled some old order
394  //Do I need to check both assets?
395  check_call_orders(sell_asset, allow_black_swan); // after the new limit order filled some orders on the book,
396  // if a call order matches another order, the call order is taker
397  check_call_orders(receive_asset, allow_black_swan); // the other side, same as above
398 
399  const limit_order_object* updated_order_object = find< limit_order_object >( order_id );
400  if( updated_order_object == nullptr )
401  return true;
402  if( head_block_time() <= HARDFORK_555_TIME )
403  return false;
404  // before #555 we would have done maybe_cull_small_order() logic as a result of fill_order() being called by match() above
405  // however after #555 we need to get rid of small orders -- #555 hardfork defers logic that was done too eagerly before, and
406  // this is the point it's deferred to.
407  return maybe_cull_small_order( *this, *updated_order_object );
408 }
409 
410 /***
411  * @brief apply a new limit_order_object to the market, matching with existing limit orders or
412  * margin call orders where possible, leaving remainder on the book if not fully matched.
413  * @detail Called from limit_order_create_evaluator::do_apply() in market_evaluator.cpp in
414  * response to a limit_order_create operation. If we're not at the front of the book, we
415  * return false early and do nothing else, since there's nothing we can match. If we are at
416  * the front of the book, then we first look for matching limit orders that are more
417  * favorable than the margin call price, then we search through active margin calls, then
418  * finaly the remaining limit orders, until we either fully consume the order or can no
419  * longer match and must leave the remainder on the book.
420  * @return Returns true if limit order is completely consumed by matching, else false if it
421  * remains on the book.
422  * @param new_order_object the new limit order (read only ref, though the corresponding db
423  * object is modified as we match and deleted if filled completely)
424  * @param allow_black_swan ignored, defaulted to true (is used in the _before_hardfork_625
425  * variant of this function, but not this variant)
426  */
427 bool database::apply_order(const limit_order_object& new_order_object, bool allow_black_swan)
428 {
429  auto order_id = new_order_object.id;
430  asset_id_type sell_asset_id = new_order_object.sell_asset_id();
431  asset_id_type recv_asset_id = new_order_object.receive_asset_id();
432 
433  // We only need to check if the new order will match with others if it is at the front of the book
434  const auto& limit_price_idx = get_index_type<limit_order_index>().indices().get<by_price>();
435  auto limit_itr = limit_price_idx.lower_bound( boost::make_tuple( new_order_object.sell_price, order_id ) );
436  if( limit_itr != limit_price_idx.begin() )
437  {
438  --limit_itr;
439  if( limit_itr->sell_asset_id() == sell_asset_id && limit_itr->receive_asset_id() == recv_asset_id )
440  return false;
441  }
442 
443  // this is the opposite side (on the book)
444  auto max_price = ~new_order_object.sell_price;
445  limit_itr = limit_price_idx.lower_bound( max_price.max() );
446  auto limit_end = limit_price_idx.upper_bound( max_price );
447 
448  // Order matching should be in favor of the taker.
449  // When a new limit order is created, e.g. an ask, need to check if it will match the highest bid.
450  // We were checking call orders first. However, due to MSSR (maximum_short_squeeze_ratio),
451  // effective price of call orders may be worse than limit orders, so we should also check limit orders here.
452 
453  // Question: will a new limit order trigger a black swan event?
454  //
455  // 1. as of writing, it's possible due to the call-order-and-limit-order overlapping issue:
456  // https://github.com/bitshares/bitshares-core/issues/606 .
457  // when it happens, a call order can be very big but don't match with the opposite,
458  // even when price feed is too far away, further than swan price,
459  // if the new limit order is in the same direction with the call orders, it can eat up all the opposite,
460  // then the call order will lose support and trigger a black swan event.
461  // 2. after issue 606 is fixed, there will be no limit order on the opposite side "supporting" the call order,
462  // so a new order in the same direction with the call order won't trigger a black swan event.
463  // 3. calling is one direction. if the new limit order is on the opposite direction,
464  // no matter if matches with the call, it won't trigger a black swan event.
465  // (if a match at MSSP caused a black swan event, it means the call order is already undercollateralized,
466  // which should trigger a black swan event earlier.)
467  //
468  // Since it won't trigger a black swan, no need to check here.
469 
470  // currently we don't do cross-market (triangle) matching.
471  // the limit order will only match with a call order if meet all of these:
472  // 1. it's buying collateral, which means sell_asset is the MIA, receive_asset is the backing asset.
473  // 2. sell_asset is not a prediction market
474  // 3. sell_asset is not globally settled
475  // 4. sell_asset has a valid price feed
476  // 5. the call order's collateral ratio is below or equals to MCR
477  // 6. the limit order provided a good price
478 
479  auto maint_time = get_dynamic_global_properties().next_maintenance_time;
480  bool before_core_hardfork_1270 = ( maint_time <= HARDFORK_CORE_1270_TIME ); // call price caching issue
481 
482  bool to_check_call_orders = false;
483  const asset_object& sell_asset = sell_asset_id( *this );
484  const asset_bitasset_data_object* sell_abd = nullptr;
485  price call_match_price; // Price at which margin calls sit on the books. Prior to BSIP-74 this price is
486  // same as the MSSP. After, it is the MCOP, which may deviate from MSSP due to MCFR.
487  price call_pays_price; // Price margin call actually relinquishes collateral at. Equals the MSSP and it may
488  // differ from call_match_price if there is a Margin Call Fee.
489  if( sell_asset.is_market_issued() )
490  {
491  sell_abd = &sell_asset.bitasset_data( *this );
492  if( sell_abd->options.short_backing_asset == recv_asset_id
493  && !sell_abd->is_prediction_market
494  && !sell_abd->has_settlement()
495  && !sell_abd->current_feed.settlement_price.is_null() )
496  {
497  if( before_core_hardfork_1270 ) {
498  call_match_price = ~sell_abd->current_feed.max_short_squeeze_price_before_hf_1270();
499  call_pays_price = call_match_price;
500  } else {
501  call_match_price = ~sell_abd->current_feed.
502  margin_call_order_price(sell_abd->options.extensions.value.margin_call_fee_ratio);
503  call_pays_price = ~sell_abd->current_feed.max_short_squeeze_price();
504  }
505  if( ~new_order_object.sell_price <= call_match_price ) // If new limit order price is good enough to
506  to_check_call_orders = true; // match a call, then check if there are calls.
507  }
508  }
509 
510  bool finished = false; // whether the new order is gone
511  if( to_check_call_orders )
512  {
513  // check limit orders first, match the ones with better price in comparison to call orders
514  while( !finished && limit_itr != limit_end && limit_itr->sell_price > call_match_price )
515  {
516  auto old_limit_itr = limit_itr;
517  ++limit_itr;
518  // match returns 2 when only the old order was fully filled. In this case, we keep matching; otherwise, we stop.
519  finished = ( match( new_order_object, *old_limit_itr, old_limit_itr->sell_price ) != 2 );
520  }
521 
522  if( !finished && !before_core_hardfork_1270 ) // TODO refactor or cleanup duplicate code after core-1270 hard fork
523  {
524  // check if there are margin calls
525  const auto& call_collateral_idx = get_index_type<call_order_index>().indices().get<by_collateral>();
526  auto call_min = price::min( recv_asset_id, sell_asset_id );
527  while( !finished )
528  {
529  // hard fork core-343 and core-625 took place at same time,
530  // always check call order with least collateral ratio
531  auto call_itr = call_collateral_idx.lower_bound( call_min );
532  if( call_itr == call_collateral_idx.end()
533  || call_itr->debt_type() != sell_asset_id
534  // feed protected https://github.com/cryptonomex/graphene/issues/436
535  || call_itr->collateralization() > sell_abd->current_maintenance_collateralization )
536  break;
537  // hard fork core-338 and core-625 took place at same time, not checking HARDFORK_CORE_338_TIME here.
538  int match_result = match( new_order_object, *call_itr, call_match_price,
539  sell_abd->current_feed.settlement_price,
542  call_pays_price);
543  // match returns 1 or 3 when the new order was fully filled. In this case, we stop matching; otherwise keep matching.
544  // since match can return 0 due to BSIP38 (hard fork core-834), we no longer only check if the result is 2.
545  if( match_result == 1 || match_result == 3 )
546  finished = true;
547  }
548  }
549  else if( !finished ) // and before core-1270 hard fork
550  {
551  // check if there are margin calls
552  const auto& call_price_idx = get_index_type<call_order_index>().indices().get<by_price>();
553  auto call_min = price::min( recv_asset_id, sell_asset_id );
554  while( !finished )
555  {
556  // assume hard fork core-343 and core-625 will take place at same time, always check call order with least call_price
557  auto call_itr = call_price_idx.lower_bound( call_min );
558  if( call_itr == call_price_idx.end()
559  || call_itr->debt_type() != sell_asset_id
560  // feed protected https://github.com/cryptonomex/graphene/issues/436
561  || call_itr->call_price > ~sell_abd->current_feed.settlement_price )
562  break;
563  // assume hard fork core-338 and core-625 will take place at same time, not checking HARDFORK_CORE_338_TIME here.
564  int match_result = match( new_order_object, *call_itr, call_match_price,
565  sell_abd->current_feed.settlement_price,
567  optional<price>() );
568  // match returns 1 or 3 when the new order was fully filled. In this case, we stop matching; otherwise keep matching.
569  // since match can return 0 due to BSIP38 (hard fork core-834), we no longer only check if the result is 2.
570  if( match_result == 1 || match_result == 3 )
571  finished = true;
572  }
573  }
574  }
575 
576  // still need to check limit orders
577  while( !finished && limit_itr != limit_end )
578  {
579  auto old_limit_itr = limit_itr;
580  ++limit_itr;
581  // match returns 2 when only the old order was fully filled. In this case, we keep matching; otherwise, we stop.
582  finished = ( match( new_order_object, *old_limit_itr, old_limit_itr->sell_price ) != 2 );
583  }
584 
585  const limit_order_object* updated_order_object = find< limit_order_object >( order_id );
586  if( updated_order_object == nullptr )
587  return true;
588 
589  // before #555 we would have done maybe_cull_small_order() logic as a result of fill_order() being called by match() above
590  // however after #555 we need to get rid of small orders -- #555 hardfork defers logic that was done too eagerly before, and
591  // this is the point it's deferred to.
592  return maybe_cull_small_order( *this, *updated_order_object );
593 }
594 
605 int database::match( const limit_order_object& usd, const limit_order_object& core, const price& match_price )
606 {
609  FC_ASSERT( usd.for_sale > 0 && core.for_sale > 0 );
610 
611  auto usd_for_sale = usd.amount_for_sale();
612  auto core_for_sale = core.amount_for_sale();
613 
614  asset usd_pays, usd_receives, core_pays, core_receives;
615 
616  auto maint_time = get_dynamic_global_properties().next_maintenance_time;
617  bool before_core_hardfork_342 = ( maint_time <= HARDFORK_CORE_342_TIME ); // better rounding
618 
619  bool cull_taker = false;
620  if( usd_for_sale <= core_for_sale * match_price ) // rounding down here should be fine
621  {
622  usd_receives = usd_for_sale * match_price; // round down, in favor of bigger order
623 
624  // Be here, it's possible that taker is paying something for nothing due to partially filled in last loop.
625  // In this case, we see it as filled and cancel it later
626  if( usd_receives.amount == 0 && maint_time > HARDFORK_CORE_184_TIME )
627  return 1;
628 
629  if( before_core_hardfork_342 )
630  core_receives = usd_for_sale;
631  else
632  {
633  // The remaining amount in order `usd` would be too small,
634  // so we should cull the order in fill_limit_order() below.
635  // The order would receive 0 even at `match_price`, so it would receive 0 at its own price,
636  // so calling maybe_cull_small() will always cull it.
637  core_receives = usd_receives.multiply_and_round_up( match_price );
638  cull_taker = true;
639  }
640  }
641  else
642  {
643  //This line once read: assert( core_for_sale < usd_for_sale * match_price );
644  //This assert is not always true -- see trade_amount_equals_zero in operation_tests.cpp
645  //Although usd_for_sale is greater than core_for_sale * match_price, core_for_sale == usd_for_sale * match_price
646  //Removing the assert seems to be safe -- apparently no asset is created or destroyed.
647 
648  // The maker won't be paying something for nothing, since if it would, it would have been cancelled already.
649  core_receives = core_for_sale * match_price; // round down, in favor of bigger order
650  if( before_core_hardfork_342 )
651  usd_receives = core_for_sale;
652  else
653  // The remaining amount in order `core` would be too small,
654  // so the order will be culled in fill_limit_order() below
655  usd_receives = core_receives.multiply_and_round_up( match_price );
656  }
657 
658  core_pays = usd_receives;
659  usd_pays = core_receives;
660 
661  if( before_core_hardfork_342 )
662  FC_ASSERT( usd_pays == usd.amount_for_sale() ||
663  core_pays == core.amount_for_sale() );
664 
665  int result = 0;
666  result |= fill_limit_order( usd, usd_pays, usd_receives, cull_taker, match_price, false ); // the first param is taker
667  result |= fill_limit_order( core, core_pays, core_receives, true, match_price, true ) << 1; // the second param is maker
668  FC_ASSERT( result != 0 );
669  return result;
670 }
671 
672 int database::match( const limit_order_object& bid, const call_order_object& ask, const price& match_price,
673  const price& feed_price, const uint16_t maintenance_collateral_ratio,
674  const optional<price>& maintenance_collateralization,
675  const price& call_pays_price )
676 {
677  FC_ASSERT( bid.sell_asset_id() == ask.debt_type() );
678  FC_ASSERT( bid.receive_asset_id() == ask.collateral_type() );
679  FC_ASSERT( bid.for_sale > 0 && ask.debt > 0 && ask.collateral > 0 );
680 
681  bool cull_taker = false;
682 
683  asset usd_for_sale = bid.amount_for_sale();
684  asset usd_to_buy = asset( ask.get_max_debt_to_cover( call_pays_price, feed_price,
685  maintenance_collateral_ratio, maintenance_collateralization ), ask.debt_type() );
686 
687  asset call_pays, call_receives, order_pays, order_receives;
688  if( usd_to_buy > usd_for_sale )
689  { // fill limit order
690  order_receives = usd_for_sale * match_price; // round down here, in favor of call order
691  call_pays = usd_for_sale * call_pays_price; // (same as match_price until BSIP-74)
692 
693  // Be here, it's possible that taker is paying something for nothing due to partially filled in last loop.
694  // In this case, we see it as filled and cancel it later
695  if( order_receives.amount == 0 )
696  return 1;
697 
698  // The remaining amount in the limit order would be too small,
699  // so we should cull the order in fill_limit_order() below.
700  // The order would receive 0 even at `match_price`, so it would receive 0 at its own price,
701  // so calling maybe_cull_small() will always cull it.
702  call_receives = order_receives.multiply_and_round_up( match_price );
703  cull_taker = true;
704  }
705  else
706  { // fill call order
707  call_receives = usd_to_buy;
708  order_receives = usd_to_buy.multiply_and_round_up( match_price ); // round up here, in favor of limit order
709  call_pays = usd_to_buy.multiply_and_round_up( call_pays_price );
710  }
711  order_pays = call_receives;
712 
713  // Compute margin call fee (BSIP74). Difference between what the call order pays and the limit order
714  // receives is the margin call fee that is paid by the call order owner to the asset issuer.
715  // Margin call fee should equal = X*MCFR/settle_price, to within rounding error.
716  FC_ASSERT(call_pays >= order_receives);
717  const asset margin_call_fee = call_pays - order_receives;
718 
719  int result = 0;
720  result |= fill_limit_order( bid, order_pays, order_receives, cull_taker, match_price, false ); // taker
721  result |= fill_call_order( ask, call_pays, call_receives, match_price, true, margin_call_fee ) << 1; // maker
722  // result can be 0 when call order has target_collateral_ratio option set.
723 
724  return result;
725 }
726 
727 
729  const force_settlement_object& settle,
730  const price& match_price,
731  asset max_settlement,
732  const price& fill_price )
733 { try {
734  FC_ASSERT(call.get_debt().asset_id == settle.balance.asset_id );
735  FC_ASSERT(call.debt > 0 && call.collateral > 0 && settle.balance.amount > 0);
736 
737  auto maint_time = get_dynamic_global_properties().next_maintenance_time;
738  bool before_core_hardfork_342 = ( maint_time <= HARDFORK_CORE_342_TIME ); // better rounding
739 
740  auto settle_for_sale = std::min(settle.balance, max_settlement);
741  auto call_debt = call.get_debt();
742 
743  asset call_receives = std::min(settle_for_sale, call_debt);
744  asset call_pays = call_receives * match_price; // round down here, in favor of call order, for first check
745  // TODO possible optimization: check need to round up or down first
746 
747  // Be here, the call order may be paying nothing.
748  bool cull_settle_order = false; // whether need to cancel dust settle order
749  if( call_pays.amount == 0 )
750  {
751  if( maint_time > HARDFORK_CORE_184_TIME )
752  {
753  if( call_receives == call_debt ) // the call order is smaller than or equal to the settle order
754  {
755  call_pays.amount = 1;
756  }
757  else
758  {
759  if( call_receives == settle.balance ) // the settle order is smaller
760  {
761  cancel_settle_order( settle );
762  }
763  // else do nothing: neither order will be completely filled, perhaps due to max_settlement too small
764 
765  return asset( 0, settle.balance.asset_id );
766  }
767  }
768 
769  }
770  else // the call order is not paying nothing, but still possible it's paying more than minimum required due to rounding
771  {
772  if( !before_core_hardfork_342 )
773  {
774  if( call_receives == call_debt ) // the call order is smaller than or equal to the settle order
775  {
776  call_pays = call_receives.multiply_and_round_up( match_price ); // round up here, in favor of settle order
777  // be here, we should have: call_pays <= call_collateral
778  }
779  else
780  {
781  // be here, call_pays has been rounded down
782 
783  // be here, we should have: call_pays <= call_collateral
784 
785  if( call_receives == settle.balance ) // the settle order will be completely filled, assuming we need to cull it
786  cull_settle_order = true;
787  // else do nothing, since we can't cull the settle order
788 
789  call_receives = call_pays.multiply_and_round_up( match_price ); // round up here to mitigate rounding issue (core-342).
790  // It is important to understand here that the newly
791  // rounded up call_receives won't be greater than the
792  // old call_receives.
793 
794  if( call_receives == settle.balance ) // the settle order will be completely filled, no need to cull
795  cull_settle_order = false;
796  // else do nothing, since we still need to cull the settle order or still can't cull the settle order
797  }
798  }
799  }
800 
801  asset settle_pays = call_receives;
802  asset settle_receives = call_pays;
803 
811  if( before_core_hardfork_342 )
812  {
813  auto call_collateral = call.get_collateral();
814  GRAPHENE_ASSERT( call_pays < call_collateral, black_swan_exception, "" );
815 
816  assert( settle_pays == settle_for_sale || call_receives == call.get_debt() );
817  }
818  // else do nothing, since black swan event won't happen, and the assertion is no longer true
819 
820  fill_call_order( call, call_pays, call_receives, fill_price, true ); // call order is maker
821  fill_settle_order( settle, settle_pays, settle_receives, fill_price, false ); // force settlement order is taker
822 
823  if( cull_settle_order )
824  cancel_settle_order( settle );
825 
826  return call_receives;
827 } FC_CAPTURE_AND_RETHROW( (call)(settle)(match_price)(max_settlement) ) }
828 
829 bool database::fill_limit_order( const limit_order_object& order, const asset& pays, const asset& receives, bool cull_if_small,
830  const price& fill_price, const bool is_maker)
831 { try {
832  cull_if_small |= (head_block_time() < HARDFORK_555_TIME);
833 
834  FC_ASSERT( order.amount_for_sale().asset_id == pays.asset_id );
835  FC_ASSERT( pays.asset_id != receives.asset_id );
836 
837  const account_object& seller = order.seller(*this);
838 
839  const auto issuer_fees = pay_market_fees(&seller, receives.asset_id(*this), receives, is_maker);
840 
841  pay_order( seller, receives - issuer_fees, pays );
842 
843  assert( pays.asset_id != receives.asset_id );
844  push_applied_operation( fill_order_operation( order.id, order.seller, pays, receives, issuer_fees, fill_price, is_maker ) );
845 
846  // BSIP85: Maker order creation fee discount, https://github.com/bitshares/bsips/blob/master/bsip-0085.md
847  // if the order creation fee was paid in BTS,
848  // return round_down(deferred_fee * maker_fee_discount_percent) to the owner,
849  // then process the remaining deferred fee as before;
850  // if the order creation fee was paid in another asset,
851  // return round_down(deferred_paid_fee * maker_fee_discount_percent) to the owner,
852  // return round_down(deferred_fee * maker_fee_discount_percent) to the fee pool of the asset,
853  // then process the remaining deferred fee and deferred paid fee as before.
854  const uint16_t maker_discount_percent = get_global_properties().parameters.get_maker_fee_discount_percent();
855 
856  // Save local copies for calculation
857  share_type deferred_fee = order.deferred_fee;
858  share_type deferred_paid_fee = order.deferred_paid_fee.amount;
859 
860  // conditional because cheap integer comparison may allow us to avoid two expensive modify() and object lookups
861  if( order.deferred_paid_fee.amount > 0 ) // implies head_block_time() > HARDFORK_CORE_604_TIME
862  {
863  share_type fee_pool_refund = 0;
864  if( is_maker && maker_discount_percent > 0 )
865  {
866  share_type refund = detail::calculate_percent( deferred_paid_fee, maker_discount_percent );
867  // Note: it's possible that the deferred_paid_fee is very small,
868  // which can result in a zero refund due to rounding issue,
869  // in this case, no refund to the fee pool
870  if( refund > 0 )
871  {
872  FC_ASSERT( refund <= deferred_paid_fee, "Internal error" );
873  adjust_balance( order.seller, asset(refund, order.deferred_paid_fee.asset_id) );
874  deferred_paid_fee -= refund;
875 
876  // deferred_fee might be positive too
877  FC_ASSERT( deferred_fee > 0, "Internal error" );
878  fee_pool_refund = detail::calculate_percent( deferred_fee, maker_discount_percent );
879  FC_ASSERT( fee_pool_refund <= deferred_fee, "Internal error" );
880  deferred_fee -= fee_pool_refund;
881  }
882  }
883 
884  const auto& fee_asset_dyn_data = order.deferred_paid_fee.asset_id(*this).dynamic_asset_data_id(*this);
885  modify( fee_asset_dyn_data, [deferred_paid_fee,fee_pool_refund](asset_dynamic_data_object& addo) {
886  addo.accumulated_fees += deferred_paid_fee;
887  addo.fee_pool += fee_pool_refund;
888  });
889  }
890 
891  if( order.deferred_fee > 0 )
892  {
893  if( order.deferred_paid_fee.amount <= 0 // paid in CORE, or before HF 604
894  && is_maker && maker_discount_percent > 0 )
895  {
896  share_type refund = detail::calculate_percent( deferred_fee, maker_discount_percent );
897  if( refund > 0 )
898  {
899  FC_ASSERT( refund <= deferred_fee, "Internal error" );
900  adjust_balance( order.seller, asset(refund, asset_id_type()) );
901  deferred_fee -= refund;
902  }
903  }
904  // else do nothing here, because we have already processed it above, or no need to process
905 
906  if( deferred_fee > 0 )
907  {
908  modify( seller.statistics(*this), [deferred_fee,this]( account_statistics_object& statistics )
909  {
910  statistics.pay_fee( deferred_fee, get_global_properties().parameters.cashback_vesting_threshold );
911  } );
912  }
913  }
914 
915  if( pays == order.amount_for_sale() )
916  {
917  remove( order );
918  return true;
919  }
920  else
921  {
922  modify( order, [&pays]( limit_order_object& b ) {
923  b.for_sale -= pays.amount;
924  b.deferred_fee = 0;
926  });
927  if( cull_if_small )
928  return maybe_cull_small_order( *this, order );
929  return false;
930  }
931 } FC_CAPTURE_AND_RETHROW( (order)(pays)(receives) ) }
932 
933 /***
934  * @brief fill a call order in the specified amounts
935  * @param order the call order
936  * @param pays What the call order will give to the other party (collateral)
937  * @param receives what the call order will receive from the other party (debt)
938  * @param fill_price the price at which the call order will execute
939  * @param is_maker TRUE if the call order is the maker, FALSE if it is the taker
940  * @param margin_call_fee Margin call fees paid in collateral asset
941  * @returns TRUE if the call order was completely filled
942  */
943 bool database::fill_call_order( const call_order_object& order, const asset& pays, const asset& receives,
944  const price& fill_price, const bool is_maker, const asset& margin_call_fee )
945 { try {
946  FC_ASSERT( order.debt_type() == receives.asset_id );
947  FC_ASSERT( order.collateral_type() == pays.asset_id );
948  FC_ASSERT( order.collateral >= pays.amount );
949 
950  // TODO pass in mia and bitasset_data for better performance
951  const asset_object& mia = receives.asset_id(*this);
952  FC_ASSERT( mia.is_market_issued() );
953  const asset_bitasset_data_object& bitasset = mia.bitasset_data(*this);
954 
955  optional<asset> collateral_freed;
956  // adjust the order
957  modify( order, [&]( call_order_object& o ) {
958  o.debt -= receives.amount;
959  o.collateral -= pays.amount;
960  if( o.debt == 0 ) // is the whole debt paid?
961  {
962  collateral_freed = o.get_collateral();
963  o.collateral = 0;
964  }
965  else // the debt was not completely paid
966  {
967  auto maint_time = get_dynamic_global_properties().next_maintenance_time;
968  // update call_price after core-343 hard fork,
969  // but don't update call_price after core-1270 hard fork
970  if( maint_time <= HARDFORK_CORE_1270_TIME && maint_time > HARDFORK_CORE_343_TIME )
971  {
972  o.call_price = price::call_price( o.get_debt(), o.get_collateral(),
973  bitasset.current_feed.maintenance_collateral_ratio );
974  }
975  }
976  });
977 
978  // update current supply
979  const asset_dynamic_data_object& mia_ddo = mia.dynamic_asset_data_id(*this);
980  modify( mia_ddo, [&receives]( asset_dynamic_data_object& ao ){
981  ao.current_supply -= receives.amount;
982  });
983 
984  // If the whole debt is paid, adjust borrower's collateral balance
985  if( collateral_freed.valid() )
986  adjust_balance( order.borrower, *collateral_freed );
987 
988  // Update account statistics. We know that order.collateral_type() == pays.asset_id
989  if( pays.asset_id == asset_id_type() )
990  {
991  modify( get_account_stats_by_owner(order.borrower), [&collateral_freed,&pays]( account_statistics_object& b ){
992  b.total_core_in_orders -= pays.amount;
993  if( collateral_freed.valid() )
994  b.total_core_in_orders -= collateral_freed->amount;
995  });
996  }
997 
998  // BSIP74: Accumulate the collateral-denominated fee
999  if (margin_call_fee.amount.value != 0)
1000  mia.accumulate_fee(*this, margin_call_fee);
1001 
1002  // virtual operation for account history
1003  push_applied_operation( fill_order_operation( order.id, order.borrower, pays, receives,
1004  margin_call_fee, fill_price, is_maker ) );
1005 
1006  // Call order completely filled, remove it
1007  if( collateral_freed.valid() )
1008  remove( order );
1009 
1010  return collateral_freed.valid();
1011 } FC_CAPTURE_AND_RETHROW( (order)(pays)(receives) ) }
1012 
1013 /***
1014  * @brief fullfill a settle order in the specified amounts
1015  *
1016  * @details Called from database::match(), this coordinates exchange of debt asset X held in the
1017  * settle order for collateral asset Y held in a call order, and routes fees. Note that we
1018  * don't touch the call order directly, as match() handles this via a separate call to
1019  * fill_call_order(). We are told exactly how much X and Y to exchange, based on details of
1020  * order matching determined higher up the call chain. Thus it is possible that the settle
1021  * order is not completely satisfied at the conclusion of this function.
1022  *
1023  * @param settle the force_settlement object
1024  * @param pays the quantity of market-issued debt asset X which the settler will yield in this
1025  * round (may be less than the full amount indicated in settle object)
1026  * @param receives the quantity of collateral asset Y which the settler will receive in
1027  * exchange for X
1028  * @param fill_price the price at which the settle order will execute (not used - passed through
1029  * to virtual operation)
1030  * @param is_maker TRUE if the settle order is the maker, FALSE if it is the taker (passed
1031  * through to virtual operation)
1032  * @returns TRUE if the settle order was completely filled, FALSE if only partially filled
1033  */
1034 bool database::fill_settle_order( const force_settlement_object& settle, const asset& pays, const asset& receives,
1035  const price& fill_price, const bool is_maker )
1036 { try {
1037  bool filled = false;
1038 
1039  const account_object* settle_owner_ptr = nullptr;
1040  // The owner of the settle order pays market fees to the issuer of the collateral asset.
1041  // After HF core-1780, these fees are shared to the referral program, which is flagged to
1042  // pay_market_fees by setting settle_owner_ptr non-null.
1043  //
1044  // TODO Check whether the HF check can be removed after the HF.
1045  // Note: even if logically it can be removed, perhaps the removal will lead to a small performance
1046  // loss. Needs testing.
1047  if( head_block_time() >= HARDFORK_CORE_1780_TIME )
1048  settle_owner_ptr = &settle.owner(*this);
1049  // Compute and pay the market fees:
1050  asset market_fees = pay_market_fees( settle_owner_ptr, get(receives.asset_id), receives, is_maker );
1051 
1052  // Issuer of the settled smartcoin asset lays claim to a force-settlement fee (BSIP87), but
1053  // note that fee is denominated in collateral asset, not the debt asset. Asset object of
1054  // debt asset is passed to the pay function so it knows where to put the fee. Note that
1055  // amount of collateral asset upon which fee is assessed is reduced by market_fees already
1056  // paid to prevent the total fee exceeding total collateral.
1057  asset force_settle_fees = pay_force_settle_fees( get(pays.asset_id), receives - market_fees );
1058 
1059  auto total_collateral_denominated_fees = market_fees + force_settle_fees;
1060 
1061  // If we don't consume entire settle order:
1062  if( pays < settle.balance )
1063  {
1064  modify(settle, [&pays](force_settlement_object& s) {
1065  s.balance -= pays;
1066  });
1067  } else {
1068  filled = true;
1069  }
1070  // Give released collateral not already taken as fees to settle order owner:
1071  adjust_balance(settle.owner, receives - total_collateral_denominated_fees);
1072 
1073  assert( pays.asset_id != receives.asset_id );
1074  push_applied_operation( fill_order_operation( settle.id, settle.owner, pays, receives,
1075  total_collateral_denominated_fees, fill_price, is_maker ) );
1076 
1077  if (filled)
1078  remove(settle);
1079 
1080  return filled;
1081 
1082 } FC_CAPTURE_AND_RETHROW( (settle)(pays)(receives) ) }
1083 
1100 bool database::check_call_orders( const asset_object& mia, bool enable_black_swan, bool for_new_limit_order,
1101  const asset_bitasset_data_object* bitasset_ptr )
1102 { try {
1103  const auto& dyn_prop = get_dynamic_global_properties();
1104  auto maint_time = dyn_prop.next_maintenance_time;
1105  if( for_new_limit_order )
1106  FC_ASSERT( maint_time <= HARDFORK_CORE_625_TIME ); // `for_new_limit_order` is only true before HF 338 / 625
1107 
1108  if( !mia.is_market_issued() ) return false;
1109 
1110  const asset_bitasset_data_object& bitasset = ( bitasset_ptr ? *bitasset_ptr : mia.bitasset_data(*this) );
1111 
1112  // price feeds can cause black swans in prediction markets
1113  // The hardfork check may be able to be removed after the hardfork date
1114  // if check_for_blackswan never triggered a black swan on a prediction market.
1115  // NOTE: check_for_blackswan returning true does not always mean a black
1116  // swan was triggered.
1117  if ( maint_time >= HARDFORK_CORE_460_TIME && bitasset.is_prediction_market )
1118  return false;
1119 
1120  if( check_for_blackswan( mia, enable_black_swan, &bitasset ) )
1121  return false;
1122 
1123  if( bitasset.is_prediction_market ) return false;
1124  if( bitasset.current_feed.settlement_price.is_null() ) return false;
1125 
1126  const limit_order_index& limit_index = get_index_type<limit_order_index>();
1127  const auto& limit_price_index = limit_index.indices().get<by_price>();
1128 
1129  bool before_core_hardfork_1270 = ( maint_time <= HARDFORK_CORE_1270_TIME ); // call price caching issue
1130 
1131  // Looking for limit orders selling the most USD for the least CORE.
1132  auto max_price = price::max( mia.id, bitasset.options.short_backing_asset );
1133  // Stop when limit orders are selling too little USD for too much CORE.
1134  // Note that since BSIP74, margin calls offer somewhat less CORE per USD
1135  // if the issuer claims a Margin Call Fee.
1136  auto min_price = ( before_core_hardfork_1270 ?
1139  bitasset.options.extensions.value.margin_call_fee_ratio )
1140  );
1141 
1142  // NOTE limit_price_index is sorted from greatest to least
1143  auto limit_itr = limit_price_index.lower_bound( max_price );
1144  auto limit_end = limit_price_index.upper_bound( min_price );
1145 
1146  if( limit_itr == limit_end )
1147  return false;
1148 
1149  const call_order_index& call_index = get_index_type<call_order_index>();
1150  const auto& call_price_index = call_index.indices().get<by_price>();
1151  const auto& call_collateral_index = call_index.indices().get<by_collateral>();
1152 
1153  auto call_min = price::min( bitasset.options.short_backing_asset, mia.id );
1154  auto call_max = price::max( bitasset.options.short_backing_asset, mia.id );
1155 
1156  auto call_price_itr = call_price_index.begin();
1157  auto call_price_end = call_price_itr;
1158  auto call_collateral_itr = call_collateral_index.begin();
1159  auto call_collateral_end = call_collateral_itr;
1160 
1161  if( before_core_hardfork_1270 )
1162  {
1163  call_price_itr = call_price_index.lower_bound( call_min );
1164  call_price_end = call_price_index.upper_bound( call_max );
1165  }
1166  else
1167  {
1168  call_collateral_itr = call_collateral_index.lower_bound( call_min );
1169  call_collateral_end = call_collateral_index.upper_bound( call_max );
1170  }
1171 
1172  bool filled_limit = false;
1173  bool margin_called = false; // toggles true once/if we actually execute a margin call
1174 
1175  auto head_time = head_block_time();
1176  auto head_num = head_block_num();
1177 
1178  bool before_hardfork_615 = ( head_time < HARDFORK_615_TIME );
1179  bool after_hardfork_436 = ( head_time > HARDFORK_436_TIME );
1180 
1181  bool before_core_hardfork_342 = ( maint_time <= HARDFORK_CORE_342_TIME ); // better rounding
1182  bool before_core_hardfork_343 = ( maint_time <= HARDFORK_CORE_343_TIME ); // update call_price after partially filled
1183  bool before_core_hardfork_453 = ( maint_time <= HARDFORK_CORE_453_TIME ); // multiple matching issue
1184  bool before_core_hardfork_606 = ( maint_time <= HARDFORK_CORE_606_TIME ); // feed always trigger call
1185  bool before_core_hardfork_834 = ( maint_time <= HARDFORK_CORE_834_TIME ); // target collateral ratio option
1186 
1187  while( !check_for_blackswan( mia, enable_black_swan, &bitasset ) // TODO perhaps improve performance by passing in iterators
1188  && limit_itr != limit_end
1189  && ( ( !before_core_hardfork_1270 && call_collateral_itr != call_collateral_end )
1190  || ( before_core_hardfork_1270 && call_price_itr != call_price_end ) ) )
1191  {
1192  bool filled_call = false;
1193 
1194  const call_order_object& call_order = ( before_core_hardfork_1270 ? *call_price_itr : *call_collateral_itr );
1195 
1196  // Feed protected (don't call if CR>MCR) https://github.com/cryptonomex/graphene/issues/436
1197  if( ( !before_core_hardfork_1270 && bitasset.current_maintenance_collateralization < call_order.collateralization() )
1198  || ( before_core_hardfork_1270
1199  && after_hardfork_436 && bitasset.current_feed.settlement_price > ~call_order.call_price ) )
1200  return margin_called;
1201 
1202  const limit_order_object& limit_order = *limit_itr;
1203 
1204  price match_price = limit_order.sell_price;
1205  // There was a check `match_price.validate();` here, which is removed now because it always passes
1206  price call_pays_price = match_price * bitasset.current_feed.margin_call_pays_ratio(
1207  bitasset.options.extensions.value.margin_call_fee_ratio);
1208  // Since BSIP74, the call "pays" a bit more collateral per debt than the match price, with the
1209  // excess being kept by the asset issuer as a margin call fee. In what follows, we use
1210  // call_pays_price for the black swan check, and for the TCR, but we still use the match_price,
1211  // of course, to determine what the limit order receives. Note margin_call_pays_ratio() returns
1212  // 1/1 if margin_call_fee_ratio is unset (i.e. before BSIP74), so hardfork check is implicit.
1213 
1214  // Old rule: margin calls can only buy high https://github.com/bitshares/bitshares-core/issues/606
1215  if( before_core_hardfork_606 && match_price > ~call_order.call_price )
1216  return margin_called;
1217 
1218  margin_called = true;
1219 
1220  // Although we checked for black swan above, we do one more check to ensure the call order can
1221  // pay the amount of collateral which we intend to take from it (including margin call fee). I
1222  // guess this is just a sanity check, as, I'm not sure how we'd get here without it being
1223  // detected in the prior swan check, aside perhaps for rounding errors. Or maybe there was some
1224  // way prior to hf_1270.
1225  auto usd_to_buy = call_order.get_debt();
1226  if( usd_to_buy * call_pays_price > call_order.get_collateral() )
1227  {
1228  elog( "black swan detected on asset ${symbol} (${id}) at block ${b}",
1229  ("id",mia.id)("symbol",mia.symbol)("b",head_num) );
1230  edump((enable_black_swan));
1231  FC_ASSERT( enable_black_swan );
1232  globally_settle_asset(mia, bitasset.current_feed.settlement_price );
1233  return true;
1234  }
1235 
1236  if( !before_core_hardfork_1270 )
1237  {
1238  usd_to_buy.amount = call_order.get_max_debt_to_cover( call_pays_price,
1239  bitasset.current_feed.settlement_price,
1242  }
1243  else if( !before_core_hardfork_834 )
1244  {
1245  usd_to_buy.amount = call_order.get_max_debt_to_cover( call_pays_price,
1246  bitasset.current_feed.settlement_price,
1248  }
1249 
1250  asset usd_for_sale = limit_order.amount_for_sale();
1251  asset call_pays, call_receives, limit_pays, limit_receives;
1252  if( usd_to_buy > usd_for_sale )
1253  { // fill order
1254  limit_receives = usd_for_sale * match_price; // round down, in favor of call order
1255  call_pays = usd_for_sale * call_pays_price; // (same as match_price until BSIP-74)
1256 
1257  // Be here, the limit order won't be paying something for nothing, since if it would, it would have
1258  // been cancelled elsewhere already (a maker limit order won't be paying something for nothing):
1259  // * after hard fork core-625, the limit order will be always a maker if entered this function;
1260  // * before hard fork core-625,
1261  // * when the limit order is a taker, it could be paying something for nothing only when
1262  // the call order is smaller and is too small
1263  // * when the limit order is a maker, it won't be paying something for nothing
1264 
1265  if( before_core_hardfork_342 )
1266  call_receives = usd_for_sale;
1267  else
1268  // The remaining amount in the limit order would be too small,
1269  // so we should cull the order in fill_limit_order() below.
1270  // The order would receive 0 even at `match_price`, so it would receive 0 at its own price,
1271  // so calling maybe_cull_small() will always cull it.
1272  call_receives = limit_receives.multiply_and_round_up( match_price );
1273 
1274  filled_limit = true;
1275 
1276  } else { // fill call
1277  call_receives = usd_to_buy;
1278 
1279  if( before_core_hardfork_342 )
1280  {
1281  limit_receives = usd_to_buy * match_price; // round down, in favor of call order
1282  call_pays = limit_receives;
1283  } else {
1284  limit_receives = usd_to_buy.multiply_and_round_up( match_price ); // round up, in favor of limit order
1285  call_pays = usd_to_buy.multiply_and_round_up( call_pays_price ); // BSIP74; excess is fee.
1286  // Note: TODO: Due to different rounding, couldn't this potentialy be
1287  // one satoshi more than the blackswan check above? Can this bite us?
1288  }
1289 
1290  filled_call = true; // this is safe, since BSIP38 (hard fork core-834) depends on BSIP31 (hard fork core-343)
1291 
1292  if( usd_to_buy == usd_for_sale )
1293  filled_limit = true;
1294  else if( filled_limit && maint_time <= HARDFORK_CORE_453_TIME )
1295  {
1296  //NOTE: Multiple limit match problem (see issue 453, yes this happened)
1297  if( before_hardfork_615 )
1298  _issue_453_affected_assets.insert( bitasset.asset_id );
1299  }
1300  }
1301  limit_pays = call_receives;
1302 
1303  // BSIP74: Margin call fee
1304  FC_ASSERT(call_pays >= limit_receives);
1305  const asset margin_call_fee = call_pays - limit_receives;
1306 
1307  if( filled_call && before_core_hardfork_343 )
1308  ++call_price_itr;
1309 
1310  // when for_new_limit_order is true, the call order is maker, otherwise the call order is taker
1311  fill_call_order( call_order, call_pays, call_receives, match_price, for_new_limit_order, margin_call_fee);
1312 
1313  if( !before_core_hardfork_1270 )
1314  call_collateral_itr = call_collateral_index.lower_bound( call_min );
1315  else if( !before_core_hardfork_343 )
1316  call_price_itr = call_price_index.lower_bound( call_min );
1317 
1318  auto next_limit_itr = std::next( limit_itr );
1319  // when for_new_limit_order is true, the limit order is taker, otherwise the limit order is maker
1320  bool really_filled = fill_limit_order( limit_order, limit_pays, limit_receives, true,
1321  match_price, !for_new_limit_order );
1322  if( really_filled || ( filled_limit && before_core_hardfork_453 ) )
1323  limit_itr = next_limit_itr;
1324 
1325  } // while call_itr != call_end
1326 
1327  return margin_called;
1329 
1330 void database::pay_order( const account_object& receiver, const asset& receives, const asset& pays )
1331 {
1332  const auto& balances = receiver.statistics(*this);
1333  modify( balances, [&]( account_statistics_object& b ){
1334  if( pays.asset_id == asset_id_type() )
1335  {
1336  b.total_core_in_orders -= pays.amount;
1337  }
1338  });
1339  adjust_balance(receiver.get_id(), receives);
1340 }
1341 
1342 asset database::calculate_market_fee( const asset_object& trade_asset, const asset& trade_amount,
1343  const bool& is_maker )const
1344 {
1345  assert( trade_asset.id == trade_amount.asset_id );
1346 
1347  if( !trade_asset.charges_market_fees() )
1348  return trade_asset.amount(0);
1349  // Optimization: The fee is zero if the order is a maker, and the maker fee percent is 0%
1350  if( is_maker && trade_asset.options.market_fee_percent == 0 )
1351  return trade_asset.amount(0);
1352 
1353  // Optimization: The fee is zero if the order is a taker, and the taker fee percent is 0%
1354  const optional<uint16_t>& taker_fee_percent = trade_asset.options.extensions.value.taker_fee_percent;
1355  if(!is_maker && taker_fee_percent.valid() && *taker_fee_percent == 0)
1356  return trade_asset.amount(0);
1357 
1358  uint16_t fee_percent;
1359  if (is_maker) {
1360  // Maker orders are charged the maker fee percent
1361  fee_percent = trade_asset.options.market_fee_percent;
1362  } else {
1363  // Taker orders are charged the taker fee percent if they are valid. Otherwise, the maker fee percent.
1364  fee_percent = taker_fee_percent.valid() ? *taker_fee_percent : trade_asset.options.market_fee_percent;
1365  }
1366 
1367  auto value = detail::calculate_percent(trade_amount.amount, fee_percent);
1368  asset percent_fee = trade_asset.amount(value);
1369 
1370  if( percent_fee.amount > trade_asset.options.max_market_fee )
1371  percent_fee.amount = trade_asset.options.max_market_fee;
1372 
1373  return percent_fee;
1374 }
1375 
1376 
1377 asset database::pay_market_fees(const account_object* seller, const asset_object& recv_asset, const asset& receives,
1378  const bool& is_maker, const optional<asset>& calculated_market_fees )
1379 {
1380  const auto market_fees = ( calculated_market_fees.valid() ? *calculated_market_fees
1381  : calculate_market_fee( recv_asset, receives, is_maker ) );
1382  auto issuer_fees = market_fees;
1383  FC_ASSERT( issuer_fees <= receives, "Market fee shouldn't be greater than receives");
1384  //Don't dirty undo state if not actually collecting any fees
1385  if ( issuer_fees.amount > 0 )
1386  {
1387  // Share market fees to the network
1388  const uint16_t network_percent = get_global_properties().parameters.get_market_fee_network_percent();
1389  if( network_percent > 0 )
1390  {
1391  const auto network_fees_amt = detail::calculate_percent( issuer_fees.amount, network_percent );
1392  FC_ASSERT( network_fees_amt <= issuer_fees.amount,
1393  "Fee shared to the network shouldn't be greater than total market fee" );
1394  if( network_fees_amt > 0 )
1395  {
1396  const asset network_fees = recv_asset.amount( network_fees_amt );
1397  deposit_market_fee_vesting_balance( GRAPHENE_COMMITTEE_ACCOUNT, network_fees );
1398  issuer_fees -= network_fees;
1399  }
1400  }
1401  }
1402 
1403  // Process the remaining fees
1404  if ( issuer_fees.amount > 0 )
1405  {
1406  // calculate and pay rewards
1407  asset reward = recv_asset.amount(0);
1408 
1409  auto is_rewards_allowed = [&recv_asset, seller]() {
1410  if (seller == nullptr)
1411  return false;
1413  return ( !white_list || (*white_list).empty()
1414  || ( (*white_list).find(seller->registrar) != (*white_list).end() ) );
1415  };
1416 
1417  if ( is_rewards_allowed() )
1418  {
1419  const auto reward_percent = recv_asset.options.extensions.value.reward_percent;
1420  if ( reward_percent && *reward_percent )
1421  {
1422  const auto reward_value = detail::calculate_percent(issuer_fees.amount, *reward_percent);
1423  if ( reward_value > 0 && is_authorized_asset(*this, seller->registrar(*this), recv_asset) )
1424  {
1425  reward = recv_asset.amount(reward_value);
1426  // TODO after hf_1774, remove the `if` check, keep the code in `else`
1427  if( head_block_time() < HARDFORK_1774_TIME ){
1428  FC_ASSERT( reward < issuer_fees, "Market reward should be less than issuer fees");
1429  }
1430  else{
1431  FC_ASSERT( reward <= issuer_fees, "Market reward should not be greater than issuer fees");
1432  }
1433  // cut referrer percent from reward
1434  auto registrar_reward = reward;
1435 
1436  auto registrar = seller->registrar;
1437  auto referrer = seller->referrer;
1438 
1439  // After HF core-1800, for funds going to temp-account, redirect to committee-account
1440  if( head_block_time() >= HARDFORK_CORE_1800_TIME )
1441  {
1442  if( registrar == GRAPHENE_TEMP_ACCOUNT )
1443  registrar = GRAPHENE_COMMITTEE_ACCOUNT;
1444  if( referrer == GRAPHENE_TEMP_ACCOUNT )
1445  referrer = GRAPHENE_COMMITTEE_ACCOUNT;
1446  }
1447 
1448  if( referrer != registrar )
1449  {
1450  const auto referrer_rewards_value = detail::calculate_percent( reward.amount,
1451  seller->referrer_rewards_percentage );
1452 
1453  if ( referrer_rewards_value > 0 && is_authorized_asset(*this, referrer(*this), recv_asset) )
1454  {
1455  FC_ASSERT ( referrer_rewards_value <= reward.amount.value,
1456  "Referrer reward shouldn't be greater than total reward" );
1457  const asset referrer_reward = recv_asset.amount(referrer_rewards_value);
1458  registrar_reward -= referrer_reward;
1459  deposit_market_fee_vesting_balance(referrer, referrer_reward);
1460  }
1461  }
1462  if( registrar_reward.amount > 0 )
1463  deposit_market_fee_vesting_balance(registrar, registrar_reward);
1464  }
1465  }
1466  }
1467 
1468  if( issuer_fees.amount > reward.amount )
1469  {
1470  const auto& recv_dyn_data = recv_asset.dynamic_asset_data_id(*this);
1471  modify( recv_dyn_data, [&issuer_fees, &reward]( asset_dynamic_data_object& obj ){
1472  obj.accumulated_fees += issuer_fees.amount - reward.amount;
1473  });
1474  }
1475  }
1476 
1477  return market_fees;
1478 }
1479 
1480 /***
1481  * @brief Calculate force-settlement fee and give it to issuer of the settled asset
1482  * @param collecting_asset the smart asset object which should receive the fee
1483  * @param collat_receives the amount of collateral the settler would expect to receive absent this fee
1484  * (fee is computed as a percentage of this amount)
1485  * @return asset denoting the amount of fee collected
1486  */
1487 asset database::pay_force_settle_fees(const asset_object& collecting_asset, const asset& collat_receives)
1488 {
1489  FC_ASSERT( collecting_asset.get_id() != collat_receives.asset_id );
1490 
1491  const bitasset_options& collecting_bitasset_opts = collecting_asset.bitasset_data(*this).options;
1492 
1493  if( !collecting_bitasset_opts.extensions.value.force_settle_fee_percent.valid()
1494  || *collecting_bitasset_opts.extensions.value.force_settle_fee_percent == 0 )
1495  return asset{ 0, collat_receives.asset_id };
1496 
1497  auto value = detail::calculate_percent(collat_receives.amount,
1498  *collecting_bitasset_opts.extensions.value.force_settle_fee_percent);
1499  asset settle_fee = asset{ value, collat_receives.asset_id };
1500 
1501  // Deposit fee in asset's dynamic data object:
1502  if( value > 0) {
1503  collecting_asset.accumulate_fee(*this, settle_fee);
1504  }
1505  return settle_fee;
1506 }
1507 
1508 } }
asset_id_type asset_id
The asset this object belong to.
share_type max_market_fee
Market fees calculated as market_fee_percent of the traded volume are capped to this value...
Definition: asset_ops.hpp:58
#define GRAPHENE_TEMP_ACCOUNT
Represents the canonical account with WILDCARD authority (anybody can access funds in temp account) ...
Definition: config.hpp:133
fc::optional< flat_set< account_id_type > > whitelist_market_fee_sharing
Definition: asset_ops.hpp:34
asset additional_collateral
the amount of collateral to bid for the debt
Definition: market.hpp:185
bool maybe_cull_small_order(database &db, const limit_order_object &order)
Definition: db_market.cpp:334
share_type get_max_debt_to_cover(price match_price, price feed_price, const uint16_t maintenance_collateral_ratio, const optional< price > &maintenance_collateralization=optional< price >()) const
asset_id_type receive_asset_id() const
contains properties that only apply to bitassets (market issued assets)
bool is_authorized_asset(const database &d, const account_object &acct, const asset_object &asset_obj)
This class represents an account on the object graphAccounts are the primary unit of authority on the...
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
Definition: api.cpp:56
#define elog(FORMAT,...)
Definition: logger.hpp:129
bool fill_call_order(const call_order_object &order, const asset &pays, const asset &receives, const price &fill_price, const bool is_maker, const asset &margin_fee)
Definition: db_market.cpp:943
tracks debt and call price information
account_id_type bidder
pays fee and additional collateral
Definition: market.hpp:184
void globally_settle_asset(const asset_object &bitasset, const price &settle_price)
Market Helpers
Definition: db_market.cpp:57
asset calculate_market_fee(const asset_object &trade_asset, const asset &trade_amount, const bool &is_maker) const
Calculate the market fee that is to be taken.
Definition: db_market.cpp:1342
bool apply_order(const limit_order_object &new_order_object, bool allow_black_swan=true)
Definition: db_market.cpp:427
price max_short_squeeze_price() const
Definition: asset.cpp:287
price call_price
Collateral / Debt.
ratio_type margin_call_pays_ratio(const fc::optional< uint16_t > margin_call_fee_ratio) const
Definition: asset.cpp:307
account_id_type issuer
ID of the account which issued this asset.
asset pay_market_fees(const account_object *seller, const asset_object &recv_asset, const asset &receives, const bool &is_maker, const optional< asset > &calculated_market_fees={})
Definition: db_market.cpp:1377
bool is_null() const
Definition: asset.cpp:225
#define GRAPHENE_MAX_SHARE_SUPPLY
Definition: config.hpp:38
share_type for_sale
asset id is sell_price.base.asset_id
price min() const
Definition: asset.hpp:131
bool fill_settle_order(const force_settlement_object &settle, const asset &pays, const asset &receives, const price &fill_price, const bool is_maker)
Definition: db_market.cpp:1034
share_type calculate_percent(const share_type &value, uint16_t percent)
Definition: db_market.cpp:39
asset_id_type collateral_type() const
void execute_bid(const collateral_bid_object &bid, share_type debt_covered, share_type collateral_from_fund, const price_feed &current_feed)
Definition: db_market.cpp:193
void accumulate_fee(DB &db, const asset &fee) const
void cancel_settle_order(const force_settlement_object &order, bool create_virtual_op=true)
Definition: db_market.cpp:223
share_type debt
call_price.quote.asset_id, access via get_debt
bool is_prediction_market
True if this asset implements a Prediction Market.
void cancel_bid(const collateral_bid_object &bid, bool create_virtual_op=true)
Definition: db_market.cpp:178
fc::optional< uint16_t > reward_percent
Definition: asset_ops.hpp:33
bool apply_order_before_hardfork_625(const limit_order_object &new_order_object, bool allow_black_swan=true)
Process a new limit order through the markets.
Definition: db_market.cpp:359
object_id_type id
Definition: object.hpp:69
uint16_t maintenance_collateral_ratio
Definition: asset.hpp:190
account_id_type get_id() const
The price struct stores asset prices in the BitShares system.
Definition: asset.hpp:114
#define edump(SEQ)
Definition: logger.hpp:182
#define GRAPHENE_100_PERCENT
Definition: config.hpp:102
int match(const limit_order_object &taker, const limit_order_object &maker, const price &trade_price)
Definition: db_market.cpp:605
void cancel_limit_order(const limit_order_object &order, bool create_virtual_op=true, bool skip_cancel_fee=false)
Definition: db_market.cpp:238
time_point_sec head_block_time() const
Definition: db_getter.cpp:64
asset_id_type debt_type() const
asset amount(share_type a) const
Helper function to get an asset object with the given amount in this asset&#39;s type.
#define GRAPHENE_COMMITTEE_ACCOUNT
Definition: config.hpp:125
asset_dynamic_data_id_type dynamic_asset_data_id
Current supply, fee pool, and collected fees are stored in a separate object as they change frequentl...
string symbol
Ticker symbol for this asset, i.e. "USD".
tracks bitassets scheduled for force settlement at some point in the future.
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
void pay_order(const account_object &receiver, const asset &receives, const asset &pays)
Definition: db_market.cpp:1330
price margin_call_order_price(const fc::optional< uint16_t > margin_call_fee_ratio) const
Definition: asset.cpp:295
tracks the asset information that changes frequentlyBecause the asset_object is very large it doesn&#39;t...
accounts must be whitelisted in order to hold or transact this asset
Definition: types.hpp:141
bids of collateral for debt after a black swan
price max_short_squeeze_price_before_hf_1270() const
Definition: asset.cpp:269
void pay_fee(share_type core_fee, share_type cashback_vesting_threshold)
account_id_type account
Account requesting the force settlement. This account pays the fee.
Definition: asset_ops.hpp:259
share_type accumulated_fees
fees accumulate to be paid out over time
tracks the parameters of an assetAll assets have a globally unique symbol name that controls how they...
asset_id_type sell_asset_id() const
asset pay_force_settle_fees(const asset_object &collecting_asset, const asset &collat_receives)
Definition: db_market.cpp:1487
defines market parameters for margin positions
Definition: asset.hpp:164
share_type collateral
call_price.base.asset_id, access via get_collateral
bool fill_limit_order(const limit_order_object &order, const asset &pays, const asset &receives, bool cull_if_small, const price &fill_price, const bool is_maker)
fills limit order
Definition: db_market.cpp:829
asset_id_type asset_id
Definition: asset.hpp:39
bitasset_options options
The tunable options for BitAssets are stored in this field.
account_statistics_id_type statistics
fc::optional< uint16_t > taker_fee_percent
Definition: asset_ops.hpp:36
asset_id_type get_id() const
void revive_bitasset(const asset_object &bitasset)
Definition: db_market.cpp:129
#define GRAPHENE_ASSERT(expr, exc_type, FORMAT,...)
Definition: exceptions.hpp:28
account_id_type registrar
The account that paid the fee to register this account. Receives a percentage of referral rewards...
asset amount
Amount of asset to force settle. This must be a market-issued asset.
Definition: asset_ops.hpp:261
share_type current_supply
The number of shares currently in existence.
share_type deferred_fee
fee converted to CORE
asset deferred_paid_fee
originally paid fee
additional_asset_options_t extensions
Definition: asset_ops.hpp:93
price max() const
Definition: asset.hpp:130
static price call_price(const asset &debt, const asset &collateral, uint16_t collateral_ratio)
Definition: asset.cpp:212
account_id_type referrer
The account credited as referring this account. Receives a percentage of referral rewards...
const asset_bitasset_data_object & bitasset_data(const DB &db) const
share_type settlement_fund
Amount of collateral which is available for force settlement.
The bitasset_options struct contains configurable options available only to BitAssets.
Definition: asset_ops.hpp:109
asset debt_covered
the amount of debt to take over
Definition: market.hpp:186
T value
Definition: safe.hpp:22
bool check_call_orders(const asset_object &mia, bool enable_black_swan=true, bool for_new_limit_order=false, const asset_bitasset_data_object *bitasset_ptr=nullptr)
Definition: db_market.cpp:1100
an offer to sell a amount of a asset at a specified exchange rate by a certain timeThis limit_order_o...
const index_type & indices() const
asset multiply_and_round_up(const price &p) const
Multiply and round up.
Definition: asset.cpp:78