Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement BSIP 74: Margin Call Fee Ratio #2180

Merged
merged 8 commits into from
May 28, 2020
Merged

Implement BSIP 74: Margin Call Fee Ratio #2180

merged 8 commits into from
May 28, 2020

Conversation

MichelSantos
Copy link
Contributor

An implementation of BSIP74 for #2129

jmjatlanta and others added 6 commits May 25, 2020 09:55
Co-authored by John Jones
Co-authored by John Jones
Co-authored by John Jones

Co-authored by Michel Santos
fill_order_operation alice_fill_op = histories.front().op.get<fill_order_operation>();
BOOST_CHECK(alice_fill_op.fee == asset(0));
// Alice's fill order's fill price should equal the expected match price
BOOST_CHECK(~alice_fill_op.fill_price == expected_match_price);
Copy link
Contributor Author

@MichelSantos MichelSantos May 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abitmore What do you think should be the fill_price recorded in fill_order_operation under these different maker and taker scenarios? I'm particularly curious about the two tests where target collateral ratio (TCR) are active.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to record the match_price. It's used to generate price charts.
Actually I didn't get what your concerns were.

Comment on lines +1284 to +1287
limit_receives = usd_to_buy.multiply_and_round_up( match_price ); // round up, in favor of limit order
call_pays = usd_to_buy.multiply_and_round_up( call_pays_price ); // BSIP74; excess is fee.
// Note: TODO: Due to different rounding, couldn't this potentialy be
// one satoshi more than the blackswan check above? Can this bite us?
Copy link
Member

@christophersanborn christophersanborn May 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abitmore — Wanting to call attention to this question. It's not a new issue — old code uses multiply_and_round_up seemingly without problem — but since we do a black swan check above at line 1226 using multiply-and-round-down, is there a possibility that with the exact right price feed we could end up with call_pays being one satoshi more than the collateral in the call order? I expect this would eventually cause an exception to be thrown, perhaps preventing a feed_update_operation or other operation that can move the call order price from confirming?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the question.

As you've noticed, the blackswan check above at line 1226 is only for pre-hf-1270 (or even earlier, pre-hf-338) scenarios.

After hf-1270, the effective check is the check_black_swan() call at line 1187:

while( !check_for_blackswan( mia, enable_black_swan, &bitasset ) // TODO perhaps improve performance by passing in iterators

The code inside check_black_swan() reads:

highest = bitasset.current_feed.max_short_squeeze_price();

auto least_collateral = call_ptr->collateralization();
if( ~least_collateral >= highest )
{
wdump( (*call_ptr) );
elog( "Black Swan detected on asset ${symbol} (${id}) at block ${b}: \n"

I think it guarantees that the rounding-up here won't make the call order pay more collateral than it has.

Copy link
Member

@abitmore abitmore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. The code looks mostly good, except a few minor issues. I haven't reviewed test cases so far, will do later.

call_pays_price = call_match_price;
} else {
call_match_price = ~sell_abd->current_feed.
margin_call_order_price(sell_abd->options.extensions.value.margin_call_fee_ratio);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential performance improvement to do in the future: save the prices to the bitasset_data object when feeds or MCFR changed.

libraries/chain/db_market.cpp Outdated Show resolved Hide resolved
Comment on lines +1284 to +1287
limit_receives = usd_to_buy.multiply_and_round_up( match_price ); // round up, in favor of limit order
call_pays = usd_to_buy.multiply_and_round_up( call_pays_price ); // BSIP74; excess is fee.
// Note: TODO: Due to different rounding, couldn't this potentialy be
// one satoshi more than the blackswan check above? Can this bite us?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the question.

As you've noticed, the blackswan check above at line 1226 is only for pre-hf-1270 (or even earlier, pre-hf-338) scenarios.

After hf-1270, the effective check is the check_black_swan() call at line 1187:

while( !check_for_blackswan( mia, enable_black_swan, &bitasset ) // TODO perhaps improve performance by passing in iterators

The code inside check_black_swan() reads:

highest = bitasset.current_feed.max_short_squeeze_price();

auto least_collateral = call_ptr->collateralization();
if( ~least_collateral >= highest )
{
wdump( (*call_ptr) );
elog( "Black Swan detected on asset ${symbol} (${id}) at block ${b}: \n"

I think it guarantees that the rounding-up here won't make the call order pay more collateral than it has.

libraries/chain/db_market.cpp Outdated Show resolved Hide resolved
bool fill_call_order( const call_order_object& order, const asset& pays, const asset& receives,
const price& fill_price, const bool is_maker );
const price& fill_price, const bool is_maker, const asset& margin_fee = asset(0) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default value changes old data.

The old code stores asset(0,pays.asset_id) to the fee field of the virtual fill_order_operation, but the new code will store asset(0,asset_id_type(0)) which could have a different asset ID.

push_applied_operation( fill_order_operation( order.id, order.borrower, pays, receives,
asset(0, pays.asset_id), fill_price, is_maker ) );

push_applied_operation( fill_order_operation( order.id, order.borrower, pays, receives,
margin_call_fee, fill_price, is_maker ) );

libraries/protocol/asset_ops.cpp Outdated Show resolved Hide resolved
Copy link
Member

@abitmore abitmore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test cases are mostly fine.

IMO we need a test case for scenario:

  • asset owner reducing MCFR triggers new matching and filling of margin calls and limit orders.

tests/tests/margin_call_fee_tests.cpp Outdated Show resolved Hide resolved
tests/tests/margin_call_fee_tests.cpp Show resolved Hide resolved
fill_order_operation alice_fill_op = histories.front().op.get<fill_order_operation>();
BOOST_CHECK(alice_fill_op.fee == asset(0));
// Alice's fill order's fill price should equal the expected match price
BOOST_CHECK(~alice_fill_op.fill_price == expected_match_price);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to record the match_price. It's used to generate price charts.
Actually I didn't get what your concerns were.

tests/tests/margin_call_fee_tests.cpp Show resolved Hide resolved
@MichelSantos MichelSantos force-pushed the pr-bsip74 branch 2 times, most recently from 516cd33 to d90e835 Compare May 27, 2020 04:14
Copy link
Member

@abitmore abitmore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new test case looks good. Thanks.

tests/tests/margin_call_fee_tests.cpp Show resolved Hide resolved
tests/tests/margin_call_fee_tests.cpp Outdated Show resolved Hide resolved
tests/tests/margin_call_fee_tests.cpp Outdated Show resolved Hide resolved
Copy link
Member

@abitmore abitmore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.
Code looks good. Waiting for CI results.

@abitmore abitmore merged commit 5323174 into hardfork May 28, 2020
@MichelSantos MichelSantos deleted the pr-bsip74 branch May 28, 2020 00:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants