Skip to content

Commit

Permalink
Add tests about how ICR changes affect borrowing
Browse files Browse the repository at this point in the history
  • Loading branch information
abitmore committed Apr 24, 2020
1 parent 9963c8c commit 2131c68
Showing 1 changed file with 201 additions and 0 deletions.
201 changes: 201 additions & 0 deletions tests/tests/operation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,207 @@ BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_bsip77_when_icr
INVOKE( more_call_order_update_test_after_hardfork_583 );
}

BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_bsip77_when_icr_is_set )
{
try {

auto hf_time = HARDFORK_BSIP_77_TIME;
generate_blocks( hf_time );
generate_block();
set_expiration( db, trx );

ACTORS((dan)(sam)(alice)(bob));
const auto& bitusd = create_bitasset( "USDBIT", sam.id, 100, charge_market_fee, 2, {},
GRAPHENE_MAX_SHARE_SUPPLY, 1050 ); // ICR = 1.05
const auto& core = asset_id_type()(db);

asset_id_type usd_id = bitusd.id;

// helper function for setting ICR for an asset
auto set_icr_for_asset = [&](asset_id_type aid, optional<uint16_t> icr) {
const asset_object& ao = aid(db);
const asset_bitasset_data_object& abo = ao.bitasset_data(db);
asset_update_bitasset_operation uop;
uop.issuer = ao.issuer;
uop.asset_to_update = aid;
uop.new_options = abo.options;
uop.new_options.extensions.value.initial_collateral_ratio = icr;
trx.operations.clear();
trx.operations.push_back( uop );
trx.validate();
set_expiration( db, trx );
PUSH_TX(db, trx, ~0);
};

transfer(committee_account, dan_id, asset(10000000));
transfer(committee_account, sam_id, asset(10000000));
transfer(committee_account, alice_id, asset(10000000));
transfer(committee_account, bob_id, asset(10000000));
update_feed_producers( bitusd, {sam.id} );

price_feed current_feed; current_feed.settlement_price = bitusd.amount( 100 ) / core.amount(100);
current_feed.maintenance_collateral_ratio = 1750; // need to set this explicitly, testnet has a different default
current_feed.maximum_short_squeeze_ratio = 1100; // need to set this explicitly, testnet has a different default
publish_feed( bitusd, sam, current_feed );

FC_ASSERT( bitusd.bitasset_data(db).current_feed.settlement_price == current_feed.settlement_price );

BOOST_TEST_MESSAGE( "ICR 1.05, MCR 1.75" );
BOOST_TEST_MESSAGE( "attempting to borrow using <=1.75x collateral at 1:1 price should not be allowed" );
GRAPHENE_REQUIRE_THROW( borrow( bob, bitusd.amount(10000), core.amount(17499) ), fc::exception );
GRAPHENE_REQUIRE_THROW( borrow( bob, bitusd.amount(10000), core.amount(17500) ), fc::exception );

BOOST_TEST_MESSAGE( "alice borrow using 1.7501x collateral at 1:1 price should be allowed" );
BOOST_CHECK( borrow( alice, bitusd.amount(10000), core.amount(17501) ) != nullptr );
BOOST_REQUIRE_EQUAL( get_balance( alice, bitusd ), 10000 );
BOOST_REQUIRE_EQUAL( get_balance( alice, core ), 10000000 - 17501 );
BOOST_TEST_MESSAGE( "ICR 1.05, MCR 1.75, Alice CR 1.7501" );

// Update ICR
BOOST_TEST_MESSAGE( "Updating ICR to 1.85" );
set_icr_for_asset( usd_id, 1850 );
BOOST_TEST_MESSAGE( "ICR 1.85, MCR 1.75, Alice CR 1.7501" );

BOOST_TEST_MESSAGE( "alice adding more collateral should be allowed" );
BOOST_CHECK( borrow( alice, bitusd.amount(0), core.amount(18000-17501) ) != nullptr );
BOOST_REQUIRE_EQUAL( get_balance( alice, bitusd ), 10000 );
BOOST_REQUIRE_EQUAL( get_balance( alice, core ), 10000000 - 18000 );
BOOST_TEST_MESSAGE( "ICR 1.85, MCR 1.75, Alice CR 1.8000" );

BOOST_TEST_MESSAGE( "alice reducing collateral should not be allowed if CR<=1.85 and not margin called" );
GRAPHENE_REQUIRE_THROW( cover( alice, bitusd.amount(0), core.amount(1) ), fc::exception );

BOOST_TEST_MESSAGE( "alice borrow using 1.8502x collateral at 1:1 price should be allowed" );
BOOST_CHECK( borrow( alice, bitusd.amount(0), core.amount(18502-18000) ) != nullptr );
BOOST_REQUIRE_EQUAL( get_balance( alice, bitusd ), 10000 );
BOOST_REQUIRE_EQUAL( get_balance( alice, core ), 10000000 - 18502 );
BOOST_TEST_MESSAGE( "ICR 1.85, MCR 1.75, Alice CR 1.8502" );

BOOST_TEST_MESSAGE( "alice reducing collateral to >1.85x should be allowed" );
cover( alice, bitusd.amount(0), core.amount(1) );
BOOST_REQUIRE_EQUAL( get_balance( alice, bitusd ), 10000 );
BOOST_REQUIRE_EQUAL( get_balance( alice, core ), 10000000 - 18501 );
BOOST_TEST_MESSAGE( "ICR 1.85, MCR 1.75, Alice CR 1.8501" );

BOOST_TEST_MESSAGE( "alice reducing collateral to <=1.85x should not be allowed if not margin called" );
GRAPHENE_REQUIRE_THROW( cover( alice, bitusd.amount(0), core.amount(1) ), fc::exception );

BOOST_TEST_MESSAGE( "alice borrow using 4x collateral at 1:1 price" );
BOOST_CHECK( borrow( alice, bitusd.amount(100000-10000), core.amount(400000-18501) ) != nullptr );
BOOST_REQUIRE_EQUAL( get_balance( alice, bitusd ), 100000 );
BOOST_REQUIRE_EQUAL( get_balance( alice, core ), 10000000 - 400000 );
BOOST_TEST_MESSAGE( "ICR 1.85, MCR 1.75, Alice CR 4.0000" );

BOOST_TEST_MESSAGE( "alice place an order to sell usd at 1.05" );
const limit_order_id_type alice_sell_id = create_sell_order( alice, bitusd.amount(1000), core.amount(1050) )->id;
BOOST_REQUIRE_EQUAL( get_balance( alice, bitusd ), 100000 - 1000 );
BOOST_REQUIRE_EQUAL( get_balance( alice, core ), 10000000 - 400000 );

BOOST_TEST_MESSAGE( "bob attempting to borrow too much using 1.75x collateral at 1:1 price should not be allowed" );
GRAPHENE_REQUIRE_THROW( borrow( bob, bitusd.amount(10000), core.amount(17500) ), fc::exception );

BOOST_TEST_MESSAGE( "bob attempting to borrow less using 1.75x collateral at 1:1 price should be allowed and margin called" );
BOOST_CHECK( !borrow( bob, bitusd.amount(100), core.amount(175) ) );
BOOST_REQUIRE_EQUAL( get_balance( bob, bitusd ), 100 );
BOOST_REQUIRE_EQUAL( get_balance( bob, core ), 10000000 - 105 );
BOOST_REQUIRE_EQUAL( get_balance( alice, bitusd ), 100000 - 1000 );
BOOST_REQUIRE_EQUAL( get_balance( alice, core ), 10000000 - 400000 + 105 );

BOOST_TEST_MESSAGE( "bob attempting to borrow using 2x collateral at 1:1 price now that there is a valid order" );
const call_order_id_type bob_call_id = borrow( bob, bitusd.amount(100), asset(200))->id;
BOOST_REQUIRE_EQUAL( get_balance( bob, bitusd ), 100 + 100 );
BOOST_REQUIRE_EQUAL( get_balance( bob, core ), 10000000 - 105 - 200 );

BOOST_TEST_MESSAGE( "bob attempting to borrow too much more using 1.75x collateral at 1:1 price should not be allowed" );
GRAPHENE_REQUIRE_THROW( borrow( bob, bitusd.amount(10000-100), core.amount(17500-200) ), fc::exception );

BOOST_TEST_MESSAGE( "bob attempting to reduce collateral to 1.75x at 1:1 price should be allowed and margin called" );
BOOST_CHECK( !borrow( bob, bitusd.amount(0), core.amount(175-200) ) );
BOOST_REQUIRE_EQUAL( get_balance( bob, bitusd ), 100 + 100 );
BOOST_REQUIRE_EQUAL( get_balance( bob, core ), 10000000 - 105 - 105 );
BOOST_REQUIRE_EQUAL( get_balance( alice, bitusd ), 100000 - 1000 );
BOOST_REQUIRE_EQUAL( get_balance( alice, core ), 10000000 - 400000 + 105 + 105 );
BOOST_CHECK( !db.find<call_order_object>( bob_call_id ) );

BOOST_TEST_MESSAGE( "alice cancel sell order" );
cancel_limit_order( alice_sell_id(db) );

BOOST_TEST_MESSAGE( "dan attempting to borrow using 2x collateral at 1:1 price now that there is a valid order" );
borrow( dan, bitusd.amount(5000), asset(10000));
BOOST_REQUIRE_EQUAL( get_balance( dan, bitusd ), 5000 );
BOOST_REQUIRE_EQUAL( get_balance( dan, core ), 10000000 - 10000 );

BOOST_TEST_MESSAGE( "sam update price feed so dan's position will enter margin call territory." );
current_feed.settlement_price = bitusd.amount( 100 ) / core.amount(180);
publish_feed( bitusd, sam, current_feed );

BOOST_TEST_MESSAGE( "dan covering 2500 usd and freeing 5000 core should not be allowed..." );
GRAPHENE_REQUIRE_THROW( cover( dan, bitusd.amount(2500), core.amount(5000) ), fc::exception );

BOOST_TEST_MESSAGE( "dan covering 2500 usd and freeing 5001 core should not be allowed..." );
GRAPHENE_REQUIRE_THROW( cover( dan, bitusd.amount(2500), core.amount(5001) ), fc::exception );

BOOST_TEST_MESSAGE( "dan borrow 2500 more usd wth 5000 more core should not be allowed..." );
GRAPHENE_REQUIRE_THROW( borrow( dan, bitusd.amount(2500), core.amount(5000) ), fc::exception );

BOOST_TEST_MESSAGE( "dan borrow 2500 more usd wth 4999 more core should not be allowed..." );
GRAPHENE_REQUIRE_THROW( borrow( dan, bitusd.amount(2500), core.amount(4999) ), fc::exception );

BOOST_TEST_MESSAGE( "dan covering 2500 usd and freeing 4999 core should be allowed..." );
cover( dan, bitusd.amount(2500), asset(4999));
BOOST_REQUIRE_EQUAL( get_balance( dan, bitusd ), 2500 );
BOOST_REQUIRE_EQUAL( get_balance( dan, core ), 10000000 - 10000 + 4999 );

BOOST_TEST_MESSAGE( "dan covering 0 usd and freeing 1 core should not be allowed..." );
GRAPHENE_REQUIRE_THROW( cover( dan, bitusd.amount(0), core.amount(1) ), fc::exception );

BOOST_TEST_MESSAGE( "dan adding 1 core as collateral should be allowed..." );
borrow( dan, bitusd.amount(0), asset(1));
BOOST_REQUIRE_EQUAL( get_balance( dan, bitusd ), 2500 );
BOOST_REQUIRE_EQUAL( get_balance( dan, core ), 10000000 - 10000 + 4999 - 1 );

BOOST_TEST_MESSAGE( "dan borrow 2500 more usd wth 5002 more core should not be allowed..." );
GRAPHENE_REQUIRE_THROW( borrow( dan, bitusd.amount(2500), core.amount(5002) ), fc::exception );

BOOST_TEST_MESSAGE( "dan borrow 2500 more usd wth 5003 more core should not be allowed..." );
GRAPHENE_REQUIRE_THROW( borrow( dan, bitusd.amount(2500), asset(5003) ), fc::exception );

// CR of Alice's postion is now 4.0 / 1.8 ~= 2.2222
BOOST_TEST_MESSAGE( "ICR 1.85, MCR 1.75, Alice CR 2.222222" );

BOOST_TEST_MESSAGE( "alice adding more collateral should be allowed" );
const call_order_id_type alice_call_id = borrow( alice, bitusd.amount(0), asset(1))->id;
BOOST_CHECK_EQUAL( alice_call_id(db).collateral.value, 400000 + 1 );
BOOST_CHECK_EQUAL( alice_call_id(db).debt.value, 100000 );
BOOST_TEST_MESSAGE( "ICR 1.85, MCR 1.75, Alice CR 2.222228" );

BOOST_TEST_MESSAGE( "alice reducing collateral to >1.85x should be allowed" );
cover( alice, bitusd.amount(0), core.amount(67000) );
BOOST_CHECK_EQUAL( alice_call_id(db).collateral.value, 333001 );
BOOST_CHECK_EQUAL( alice_call_id(db).debt.value, 100000 );
BOOST_TEST_MESSAGE( "ICR 1.85, MCR 1.75, Alice CR 1.850006" );

BOOST_TEST_MESSAGE( "alice reducing collateral to <=1.85x should not be allowed if not margin called" );
GRAPHENE_REQUIRE_THROW( cover( alice, bitusd.amount(0), core.amount(1) ), fc::exception );

// Update ICR
BOOST_TEST_MESSAGE( "Updating ICR to 1.84" );
set_icr_for_asset( usd_id, 1840 );
BOOST_TEST_MESSAGE( "ICR 1.84, MCR 1.75, Alice CR 1.850006" );

BOOST_TEST_MESSAGE( "alice reducing collateral to >1.84x should be allowed" );
cover( alice, bitusd.amount(0), core.amount(1) );
BOOST_CHECK_EQUAL( alice_call_id(db).collateral.value, 333000 );
BOOST_CHECK_EQUAL( alice_call_id(db).debt.value, 100000 );

generate_block();

} catch (fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}

BOOST_AUTO_TEST_CASE( call_order_update_validation_test )
{
call_order_update_operation op;
Expand Down

0 comments on commit 2131c68

Please sign in to comment.