Skip to content

Commit

Permalink
Add database::find_least_collateralized_short()
Browse files Browse the repository at this point in the history
  • Loading branch information
abitmore committed Aug 17, 2021
1 parent e998ddd commit 67dd8a1
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 36 deletions.
36 changes: 36 additions & 0 deletions libraries/chain/db_getter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

#include <graphene/chain/database.hpp>

#include <graphene/chain/hardfork.hpp>

#include <graphene/chain/asset_object.hpp>
#include <graphene/chain/chain_property_object.hpp>
#include <graphene/chain/global_property_object.hpp>
Expand Down Expand Up @@ -156,4 +158,38 @@ const limit_order_object* database::find_bad_debt_settlement_order( const asset_
return nullptr;
}

const call_order_object* database::find_least_collateralized_short( const asset_bitasset_data_object& bitasset,
bool force_by_collateral_index )const
{
bool find_by_collateral = true;
if( !force_by_collateral_index )
// core-1270 hard fork : call price caching issue
find_by_collateral = ( get_dynamic_global_properties().next_maintenance_time > HARDFORK_CORE_1270_TIME );

const call_order_object* call_ptr = nullptr; // place holder

auto call_min = price::min( bitasset.options.short_backing_asset, bitasset.asset_id );

if( !find_by_collateral ) // before core-1270 hard fork, check with call_price
{
const auto& call_price_index = get_index_type<call_order_index>().indices().get<by_price>();
auto call_itr = call_price_index.lower_bound( call_min );
if( call_itr != call_price_index.end() ) // no call order
call_ptr = &(*call_itr);
}
else // after core-1270 hard fork, check with collateralization
{
// Note: it is safe to check here even if there is no call order due to individual bad debt settlements
const auto& call_collateral_index = get_index_type<call_order_index>().indices().get<by_collateral>();
auto call_itr = call_collateral_index.lower_bound( call_min );
if( call_itr != call_collateral_index.end() ) // no call order
call_ptr = &(*call_itr);
}
if( nullptr == call_ptr )
return nullptr;
if( call_ptr->debt_type() != bitasset.asset_id ) // no call order
return nullptr;
return call_ptr;
}

} }
49 changes: 13 additions & 36 deletions libraries/chain/db_update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,28 +208,9 @@ bool database::check_for_blackswan( const asset_object& mia, bool enable_black_s
return false;
}

const call_order_object* call_ptr = nullptr; // place holder for the call order with least collateral ratio

auto call_min = price::min( bitasset.options.short_backing_asset, debt_asset_id );

if( before_core_hardfork_1270 ) // before core-1270 hard fork, check with call_price
{
const auto& call_price_index = get_index_type<call_order_index>().indices().get<by_price>();
auto call_itr = call_price_index.lower_bound( call_min );
if( call_itr == call_price_index.end() ) // no call order
return false;
call_ptr = &(*call_itr);
}
else // after core-1270 hard fork, check with collateralization
{
// Note: it is safe to check here even if there is no call order due to individual bad debt settlements
const auto& call_collateral_index = get_index_type<call_order_index>().indices().get<by_collateral>();
auto call_itr = call_collateral_index.lower_bound( call_min );
if( call_itr == call_collateral_index.end() ) // no call order
return false;
call_ptr = &(*call_itr);
}
if( call_ptr->debt_type() != debt_asset_id ) // no call order
// Find the call order with the least collateral ratio
const call_order_object* call_ptr = find_least_collateralized_short( bitasset, false );
if( nullptr == call_ptr ) // no call order
return false;

price highest = settle_price;
Expand Down Expand Up @@ -352,14 +333,12 @@ static optional<price> get_derived_current_feed_price( const database& db,
const auto bdsm = bitasset.get_bad_debt_settlement_method();
if( bdsm_type::no_settlement == bdsm )
{
// Note: it is safe to check here even if there is no call order due to individual bad debt settlements
const auto& call_collateral_index = db.get_index_type<call_order_index>().indices().get<by_collateral>();
auto call_min = price::min( bitasset.options.short_backing_asset, bitasset.asset_id );
auto call_itr = call_collateral_index.lower_bound( call_min );
if( call_itr != call_collateral_index.end() && call_itr->debt_type() == bitasset.asset_id )
// Find the call order with the least collateral ratio
const call_order_object* call_ptr = db.find_least_collateralized_short( bitasset, true );
if( nullptr != call_ptr )
{
// GS if : call_itr->collateralization() < ~( bitasset.median_feed.max_short_squeeze_price() )
auto least_collateral = call_itr->collateralization();
// GS if : call_ptr->collateralization() < ~( bitasset.median_feed.max_short_squeeze_price() )
auto least_collateral = call_ptr->collateralization();
auto lowest_callable_feed_price = (~least_collateral) / ratio_type( GRAPHENE_COLLATERAL_RATIO_DENOM,
bitasset.current_feed.maximum_short_squeeze_ratio );
result = std::max( bitasset.median_feed.settlement_price, lowest_callable_feed_price );
Expand Down Expand Up @@ -589,15 +568,13 @@ void database::clear_expired_force_settlements()
else if( settlement_price.base.asset_id != current_asset ) // only calculate once per asset
settlement_price = settlement_fill_price;

// Note: there can be no debt position due to individual settlements, processed below
auto& call_index = get_index_type<call_order_index>().indices().get<by_collateral>();
asset settled = mia_object.amount(mia.force_settled_volume);
// Match against the least collateralized short until the settlement is finished or we reach max settlements
while( settled < max_settlement_volume && find_object(order_id) )
{
auto call_itr = call_index.lower_bound( price::min( mia.options.short_backing_asset, mia.asset_id ) );
auto call_ptr = find_least_collateralized_short( mia, true );
// Note: there can be no debt position due to individual settlements
if( call_itr == call_index.end() || call_itr->debt_type() != mia.asset_id ) // no debt position
if( nullptr == call_ptr ) // no debt position
{
wlog( "No debt position found when processing force settlement ${o}", ("o",order) );
cancel_settle_order( order );
Expand All @@ -613,7 +590,7 @@ void database::clear_expired_force_settlements()
break;
}
try {
asset new_settled = match( order, *call_itr, settlement_price, mia,
asset new_settled = match( order, *call_ptr, settlement_price, mia,
max_settlement, settlement_fill_price );
if( !before_core_hardfork_184 && new_settled.amount == 0 ) // unable to fill this settle order
{
Expand All @@ -623,12 +600,12 @@ void database::clear_expired_force_settlements()
}
settled += new_settled;
// before hard fork core-342, `new_settled > 0` is always true, we'll have:
// * call order is completely filled (thus call_itr will change in next loop), or
// * call order is completely filled (thus call_ptr will change in next loop), or
// * settle order is completely filled (thus find_object(order_id) will be false so will break out), or
// * reached max_settlement_volume limit (thus new_settled == max_settlement so will break out).
//
// after hard fork core-342, if new_settled > 0, we'll have:
// * call order is completely filled (thus call_itr will change in next loop), or
// * call order is completely filled (thus call_ptr will change in next loop), or
// * settle order is completely filled (thus find_object(order_id) will be false so will break out), or
// * reached max_settlement_volume limit, but it's possible that new_settled < max_settlement,
// in this case, new_settled will be zero in next iteration of the loop, so no need to check here.
Expand Down
8 changes: 8 additions & 0 deletions libraries/chain/include/graphene/chain/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,14 @@ namespace graphene { namespace chain {
/// @param a ID of the asset
/// @return nullptr if not found, pointer to the limit order if found
const limit_order_object* find_bad_debt_settlement_order( const asset_id_type& a )const;

/// Find the call order with the least collateral ratio
/// @param bitasset The bitasset object
/// @param force_by_collateral_index Whether to forcefully search via the by_collateral index
/// @return nullptr if not found, pointer to the call order if found
const call_order_object* find_least_collateralized_short( const asset_bitasset_data_object& bitasset,
bool force_by_collateral_index )const;

//////////////////// db_init.cpp ////////////////////
///@{

Expand Down

0 comments on commit 67dd8a1

Please sign in to comment.