updating tests to remove references to short

This commit is contained in:
Daniel Larimer 2015-06-16 12:17:09 -04:00
parent 4cee2ca608
commit 2ae6ce9cdc
8 changed files with 39 additions and 860 deletions

2
docs

@ -1 +1 @@
Subproject commit 1b53a8eca77783d073ce7cc95991447c3f34b927
Subproject commit 71ed2984b71d57cab13cdf12074cff150edc1d3d

View file

@ -45,6 +45,7 @@ namespace graphene { namespace db {
public:
void open( const fc::path& dir, bool create = true, size_t cache_size = 0 )
{ try {
idump( (dir)(create));
FC_ASSERT( !is_open(), "Database is already open!" );
ldb::Options opts;

View file

@ -21,7 +21,7 @@
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/witness_object.hpp>
#include <graphene/chain/key_object.hpp>
#include <graphene/chain/short_order_object.hpp>
#include <graphene/chain/call_order_object.hpp>
#include <graphene/chain/limit_order_object.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/block.hpp>

View file

@ -26,7 +26,7 @@
#include <graphene/chain/asset_object.hpp>
#include <graphene/chain/delegate_object.hpp>
#include <graphene/chain/limit_order_object.hpp>
#include <graphene/chain/short_order_object.hpp>
#include <graphene/chain/call_order_object.hpp>
#include <graphene/chain/vesting_balance_object.hpp>
#include <graphene/chain/witness_object.hpp>
@ -126,12 +126,6 @@ void database_fixture::verify_asset_supplies( )const
if( for_sale.asset_id == asset_id_type() ) core_in_orders += for_sale.amount;
total_balances[for_sale.asset_id] += for_sale.amount;
}
for( const short_order_object& o : db.get_index_type<short_order_index>().indices() )
{
asset col = o.get_collateral();
if( col.asset_id == asset_id_type() ) core_in_orders += col.amount;
total_balances[col.asset_id] += col.amount;
}
for( const call_order_object& o : db.get_index_type<call_order_index>().indices() )
{
asset col = o.get_collateral();
@ -409,32 +403,6 @@ void database_fixture::issue_uia( const account_object& recipient, asset amount
return;
}
const short_order_object*database_fixture::create_short(account_id_type seller, const asset& amount_to_sell, const asset& collateral_provided, uint16_t initial_collateral_ratio, uint16_t maintenance_collateral_ratio)
{
return create_short(seller(db), amount_to_sell, collateral_provided, initial_collateral_ratio, maintenance_collateral_ratio);
}
const short_order_object* database_fixture::create_short(
const account_object& seller,
const asset& amount_to_sell,
const asset& collateral_provided,
uint16_t initial_collateral_ratio /* = 2000 */,
uint16_t maintenance_collateral_ratio /* = 1750 */
)
{
short_order_create_operation op;
op.seller = seller.id;
op.amount_to_sell = amount_to_sell;
op.collateral = collateral_provided;
op.initial_collateral_ratio = initial_collateral_ratio;
op.maintenance_collateral_ratio = maintenance_collateral_ratio;
trx.operations.push_back(std::move(op));
trx.validate();
processed_transaction ptx = db.push_transaction(trx, ~0);
trx.operations.clear();
return db.find<short_order_object>(ptx.operation_results[0].get<object_id_type>());
}
const account_object& database_fixture::create_account(
const string& name,
const key_id_type& key /* = key_id_type() */
@ -603,18 +571,6 @@ asset database_fixture::cancel_limit_order( const limit_order_object& order )
return processed.operation_results[0].get<asset>();
}
asset database_fixture::cancel_short_order( const short_order_object& order )
{
short_order_cancel_operation cancel_order;
cancel_order.fee_paying_account = order.seller;
cancel_order.order = order.id;
trx.operations.push_back(cancel_order);
for( auto& op : trx.operations ) op.visit( operation_set_fee( db.current_fee_schedule() ) );
trx.validate();
auto processed = db.push_transaction(trx, ~0);
trx.operations.clear();
return processed.operation_results[0].get<asset>();
}
void database_fixture::transfer(
account_id_type from,
@ -727,15 +683,6 @@ string database_fixture::pretty( const asset& a )const
return ss.str();
}
void database_fixture::print_short_order( const short_order_object& cur )const
{
std::cout << std::setw(10) << cur.seller(db).name << " ";
std::cout << std::setw(10) << "SHORT" << " ";
std::cout << std::setw(16) << pretty( cur.amount_for_sale() ) << " ";
std::cout << std::setw(16) << pretty( cur.amount_to_receive() ) << " ";
std::cout << std::setw(16) << (~cur.sell_price).to_real() << " ";
}
void database_fixture::print_limit_order( const limit_order_object& cur )const
{
std::cout << std::setw(10) << cur.seller(db).name << " ";
@ -783,68 +730,16 @@ void database_fixture::print_joint_market( const string& syma, const string& sym
const auto& limit_idx = db.get_index_type<limit_order_index>();
const auto& limit_price_idx = limit_idx.indices().get<by_price>();
const auto& short_idx = db.get_index_type<short_order_index>();
const auto& sell_price_idx = short_idx.indices().get<by_price>();
auto limit_itr = limit_price_idx.begin();
auto short_itr = sell_price_idx.rbegin();
while( true )
while( limit_itr != limit_price_idx.end() )
{
std::cout << std::endl;
if( limit_itr != limit_price_idx.end() )
{
if( short_itr != sell_price_idx.rend() && limit_itr->sell_price > ~short_itr->sell_price )
{
print_short_order( *short_itr );
++short_itr;
}
else // print the limit
{
print_limit_order( *limit_itr );
++limit_itr;
}
}
else if( short_itr != sell_price_idx.rend() )
{
print_short_order( *short_itr );
++short_itr;
}
else
break;
print_limit_order( *limit_itr );
++limit_itr;
}
}
void database_fixture::print_short_market( const string& syma, const string& symb )const
{
const auto& limit_idx = db.get_index_type<short_order_index>();
const auto& price_idx = limit_idx.indices().get<by_price>();
cout << std::fixed;
cout.precision(5);
cout << std::setw(10) << std::left << "NAME" << " ";
cout << std::setw(16) << std::right << "FOR SHORT" << " ";
cout << std::setw(16) << std::right << "COLLATERAL" << " ";
cout << std::setw(10) << std::right << "PRICE" << " ";
cout << std::setw(10) << std::right << "1/PRICE" << " ";
cout << std::setw(10) << std::right << "CALL PRICE" << " ";
cout << std::setw(10) << std::right << "I-Ratio" << " ";
cout << std::setw(10) << std::right << "M-Ratio" << "\n";
cout << string(100, '=') << std::endl;
auto cur = price_idx.begin();
while( cur != price_idx.end() )
{
cout << std::setw( 10 ) << std::left << cur->seller(db).name << " ";
cout << std::setw( 16 ) << std::right << pretty( cur->amount_for_sale() ) << " ";
cout << std::setw( 16 ) << std::right << pretty( cur->get_collateral() ) << " ";
cout << std::setw( 10 ) << std::right << cur->sell_price.to_real() << " ";
cout << std::setw( 10 ) << std::right << (~cur->sell_price).to_real() << " ";
cout << std::setw( 10 ) << std::right << (cur->call_price).to_real() << " ";
cout << std::setw( 10 ) << std::right << (cur->initial_collateral_ratio)/double(1000) << " ";
cout << std::setw( 10 ) << std::right << (cur->maintenance_collateral_ratio)/double(1000) << " ";
cout << "\n";
++cur;
}
}
int64_t database_fixture::get_balance( account_id_type account, asset_id_type a )const
{

View file

@ -147,20 +147,6 @@ struct database_fixture {
const asset_object& create_user_issued_asset( const string& name );
void issue_uia( const account_object& recipient, asset amount );
const short_order_object* create_short(
account_id_type seller,
const asset& amount_to_sell,
const asset& collateral_provided,
uint16_t initial_collateral_ratio = 2000,
uint16_t maintenance_collateral_ratio = 1750
);
const short_order_object* create_short(
const account_object& seller,
const asset& amount_to_sell,
const asset& collateral_provided,
uint16_t initial_collateral_ratio = 2000,
uint16_t maintenance_collateral_ratio = 1750
);
const account_object& create_account(
const string& name,
@ -197,7 +183,6 @@ struct database_fixture {
const limit_order_object* create_sell_order( account_id_type user, const asset& amount, const asset& recv );
const limit_order_object* create_sell_order( const account_object& user, const asset& amount, const asset& recv );
asset cancel_limit_order( const limit_order_object& order );
asset cancel_short_order( const short_order_object& order );
void transfer( account_id_type from, account_id_type to, const asset& amount, const asset& fee = asset() );
void transfer( const account_object& from, const account_object& to, const asset& amount, const asset& fee = asset() );
void fund_fee_pool( const account_object& from, const asset_object& asset_to_fund, const share_type amount );
@ -206,11 +191,9 @@ struct database_fixture {
void upgrade_to_lifetime_member( const account_object& account );
void print_market( const string& syma, const string& symb )const;
string pretty( const asset& a )const;
void print_short_order( const short_order_object& cur )const;
void print_limit_order( const limit_order_object& cur )const;
void print_call_orders( )const;
void print_joint_market( const string& syma, const string& symb )const;
void print_short_market( const string& syma, const string& symb )const;
int64_t get_balance( account_id_type account, asset_id_type a )const;
int64_t get_balance( const account_object& account, const asset_object& a )const;
};

View file

@ -26,7 +26,7 @@
#include <graphene/chain/key_object.hpp>
#include <graphene/chain/limit_order_object.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/short_order_object.hpp>
#include <graphene/chain/call_order_object.hpp>
#include <graphene/chain/witness_schedule_object.hpp>
#include <fc/crypto/digest.hpp>
@ -464,53 +464,6 @@ BOOST_FIXTURE_TEST_CASE( maintenance_interval, database_fixture )
}
}
/**
* Orders should specify a valid expiration time and they will ba automatically canceled if not filled by that time.
* This feature allows people to safely submit orders that have a limited lifetime, which is essential to some
* traders.
*/
BOOST_FIXTURE_TEST_CASE( short_order_expiration, database_fixture )
{ try {
//Get a sane head block time
generate_block();
auto* test = &create_bitasset("TEST");
auto* core = &asset_id_type()(db);
auto* nathan = &create_account("nathan");
auto* genesis = &account_id_type()(db);
transfer(*genesis, *nathan, core->amount(50000));
BOOST_CHECK_EQUAL( get_balance(*nathan, *core), 50000 );
short_order_create_operation op;
op.seller = nathan->id;
op.amount_to_sell = test->amount(500);
op.collateral = core->amount(500);
op.expiration = db.head_block_time() + fc::seconds(10);
trx.operations.push_back(op);
auto ptrx = db.push_transaction(trx, ~0);
BOOST_CHECK_EQUAL( get_balance(*nathan, *core), 49500 );
auto ptrx_id = ptrx.operation_results.back().get<object_id_type>();
auto short_index = db.get_index_type<short_order_index>().indices();
auto short_itr = short_index.begin();
BOOST_REQUIRE( short_itr != short_index.end() );
BOOST_REQUIRE( short_itr->id == ptrx_id );
BOOST_REQUIRE( db.find_object(short_itr->id) );
BOOST_CHECK_EQUAL( get_balance(*nathan, *core), 49500 );
auto id = short_itr->id;
generate_blocks(op.expiration);
test = &get_asset("TEST");
core = &asset_id_type()(db);
nathan = &get_account("nathan");
genesis = &account_id_type()(db);
BOOST_CHECK(db.find_object(id) == nullptr);
BOOST_CHECK_EQUAL( get_balance(*nathan, *core), 50000 );
} FC_LOG_AND_RETHROW() }
BOOST_FIXTURE_TEST_CASE( limit_order_expiration, database_fixture )
{ try {
@ -606,6 +559,8 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
BOOST_FIXTURE_TEST_CASE( force_settlement, database_fixture )
{ try {
FC_ASSERT( "TODO" );
/*
auto private_key = generate_private_key("genesis");
account_id_type nathan_id = create_account("nathan").get_id();
account_id_type shorter1_id = create_account("shorter1").get_id();
@ -726,6 +681,7 @@ BOOST_FIXTURE_TEST_CASE( force_settlement, database_fixture )
BOOST_CHECK(db.find(settle_id));
BOOST_CHECK_EQUAL(get_balance(nathan_id, asset_id_type()), 5878);
BOOST_CHECK(!db.get_index_type<call_order_index>().indices().empty());
*/
} FC_LOG_AND_RETHROW() }
BOOST_FIXTURE_TEST_CASE( pop_block_twice, database_fixture )

View file

@ -26,7 +26,7 @@
#include <graphene/chain/delegate_object.hpp>
#include <graphene/chain/key_object.hpp>
#include <graphene/chain/limit_order_object.hpp>
#include <graphene/chain/short_order_object.hpp>
#include <graphene/chain/call_order_object.hpp>
#include <graphene/chain/vesting_balance_object.hpp>
#include <graphene/chain/withdraw_permission_object.hpp>
#include <graphene/chain/witness_object.hpp>
@ -314,18 +314,12 @@ BOOST_AUTO_TEST_CASE( update_mia )
pop.publisher = account_id_type(1);
price_feed feed;
feed.call_limit = price(bit_usd.amount(5), bit_usd.amount(5));
feed.short_limit = feed.call_limit;
REQUIRE_THROW_WITH_VALUE(pop, feed, feed);
feed.call_limit = price(bit_usd.amount(5), asset(5));
feed.short_limit = ~feed.call_limit;
REQUIRE_THROW_WITH_VALUE(pop, feed, feed);
feed.short_limit = price(asset(4), bit_usd.amount(5));
REQUIRE_THROW_WITH_VALUE(pop, feed, feed);
std::swap(feed.call_limit, feed.short_limit);
pop.feed = feed;
REQUIRE_THROW_WITH_VALUE(pop, feed.max_margin_period_sec, 0);
REQUIRE_THROW_WITH_VALUE(pop, feed.required_maintenance_collateral, 0);
REQUIRE_THROW_WITH_VALUE(pop, feed.required_initial_collateral, 500);
trx.operations.back() = pop;
db.push_transaction(trx, ~0);
}
@ -349,129 +343,6 @@ BOOST_AUTO_TEST_CASE( update_mia )
}
}
BOOST_AUTO_TEST_CASE( create_short_test )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 100 ) ); // 1:1 price
BOOST_REQUIRE( first_short != nullptr );
BOOST_REQUIRE( create_short( shorter_account, bitusd.amount(100), asset( 200 ) ) ); // 1:2 price
BOOST_REQUIRE( create_short( shorter_account, bitusd.amount(100), asset( 300 ) ) ); // 1:3 price
BOOST_REQUIRE_EQUAL( get_balance(shorter_account, asset_id_type()(db) ), 10000-600 );
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
BOOST_AUTO_TEST_CASE( cancel_short_test )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 100 ) ); // 1:1 price
BOOST_REQUIRE( first_short != nullptr );
BOOST_REQUIRE( create_short( shorter_account, bitusd.amount(100), asset( 200 ) ) ); // 1:2 price
BOOST_REQUIRE( create_short( shorter_account, bitusd.amount(100), asset( 300 ) ) ); // 1:3 price
BOOST_REQUIRE_EQUAL( get_balance(shorter_account, asset_id_type()(db) ), 10000-600 );
auto refund = cancel_short_order( *first_short );
BOOST_REQUIRE_EQUAL( get_balance(shorter_account, asset_id_type()(db) ), 10000-500 );
FC_ASSERT( refund == asset(100) );
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
/**
* Assume there exists an offer to buy BITUSD
* Create a short that exactly matches that offer at a price 2:1
*/
BOOST_AUTO_TEST_CASE( match_short_now_exact )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
const account_object& buyer_account = create_account( "buyer" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
transfer( genesis_account(db), buyer_account, asset( 10000 ) );
auto buy_order = create_sell_order( buyer_account, asset(200), bitusd.amount(100) );
BOOST_REQUIRE( buy_order );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 200 ) ); // 1:1 price
BOOST_REQUIRE( first_short == nullptr );
print_call_orders();
//print_short_market("","");
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
/**
* Assume there exists an offer to buy BITUSD
* Create a short that exactly matches that offer at a price 2:1
*/
BOOST_AUTO_TEST_CASE( dont_match_short )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
const account_object& buyer_account = create_account( "buyer" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
transfer( genesis_account(db), buyer_account, asset( 10000 ) );
create_sell_order( buyer_account, asset(125), bitusd.amount(100) );
create_sell_order( buyer_account, asset(150), bitusd.amount(100) );
auto buy_order = create_sell_order( buyer_account, asset(100), bitusd.amount(100) );
//print_market("","");
BOOST_REQUIRE( buy_order );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 200 ) ); // 1:1 price
auto second_short = create_short( shorter_account, bitusd.amount(100), asset( 300 ) ); // 1:1 price
auto third_short = create_short( shorter_account, bitusd.amount(100), asset( 400 ) ); // 1:1 price
//print_short_market("","");
BOOST_REQUIRE( first_short && second_short && third_short );
//print_joint_market("","");
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
/**
* Assume there exists an offer to buy BITUSD
* Create a short that exactly matches that offer at a price 2:1
*/
BOOST_AUTO_TEST_CASE( match_all_short_with_surplus_collaterl )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
const account_object& buyer_account = create_account( "buyer" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
transfer( genesis_account(db), buyer_account, asset( 10000 ) );
//auto buy_order = create_sell_order( buyer_account, asset(200), bitusd.amount(101) );
auto buy_order = create_sell_order( buyer_account, asset(300), bitusd.amount(100) );
print_market("","");
BOOST_REQUIRE( buy_order );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 200 ) ); // 1:1 price
print_short_market("","");
BOOST_REQUIRE( !first_short );
//print_short_market("","");
print_call_orders();
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
BOOST_AUTO_TEST_CASE( create_uia )
{
@ -916,7 +787,6 @@ BOOST_AUTO_TEST_CASE( delegate_feeds )
asset_publish_feed_operation op({asset(), active_witnesses[0]});
op.asset_id = bit_usd.get_id();
op.feed.call_limit = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(30));
op.feed.short_limit = ~price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(10));
// We'll expire margins after a month
op.feed.max_margin_period_sec = fc::days(30).to_seconds();
// Accept defaults for required collateral
@ -938,38 +808,29 @@ BOOST_AUTO_TEST_CASE( delegate_feeds )
const asset_bitasset_data_object& bitasset = bit_usd.bitasset_data(db);
BOOST_CHECK(bitasset.current_feed.call_limit.to_real() == GRAPHENE_BLOCKCHAIN_PRECISION / 30.0);
BOOST_CHECK_EQUAL(bitasset.current_feed.short_limit.to_real(), 10.0 / GRAPHENE_BLOCKCHAIN_PRECISION);
BOOST_CHECK(bitasset.current_feed.max_margin_period_sec == fc::days(30).to_seconds());
BOOST_CHECK(bitasset.current_feed.required_initial_collateral == GRAPHENE_DEFAULT_INITIAL_COLLATERAL_RATIO);
BOOST_CHECK(bitasset.current_feed.required_maintenance_collateral == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
op.publisher = active_witnesses[1];
op.feed.call_limit = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(25));
op.feed.short_limit = ~price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(20));
op.feed.max_margin_period_sec = fc::days(10).to_seconds();
trx.operations.back() = op;
db.push_transaction(trx, ~0);
BOOST_CHECK_EQUAL(bitasset.current_feed.call_limit.to_real(), GRAPHENE_BLOCKCHAIN_PRECISION / 25.0);
BOOST_CHECK_EQUAL(bitasset.current_feed.short_limit.to_real(), 20.0 / GRAPHENE_BLOCKCHAIN_PRECISION);
BOOST_CHECK(bitasset.current_feed.max_margin_period_sec == fc::days(30).to_seconds());
BOOST_CHECK(bitasset.current_feed.required_initial_collateral == GRAPHENE_DEFAULT_INITIAL_COLLATERAL_RATIO);
BOOST_CHECK(bitasset.current_feed.required_maintenance_collateral == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
op.publisher = active_witnesses[2];
op.feed.call_limit = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(40));
op.feed.short_limit = ~price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(10));
op.feed.max_margin_period_sec = fc::days(100).to_seconds();
// But this delegate is an idiot.
op.feed.required_initial_collateral = 1001;
op.feed.required_maintenance_collateral = 1000;
trx.operations.back() = op;
db.push_transaction(trx, ~0);
BOOST_CHECK_EQUAL(bitasset.current_feed.call_limit.to_real(), GRAPHENE_BLOCKCHAIN_PRECISION / 30.0);
BOOST_CHECK_EQUAL(bitasset.current_feed.short_limit.to_real(), 10.0 / GRAPHENE_BLOCKCHAIN_PRECISION);
BOOST_CHECK(bitasset.current_feed.max_margin_period_sec == fc::days(30).to_seconds());
BOOST_CHECK(bitasset.current_feed.required_initial_collateral == GRAPHENE_DEFAULT_INITIAL_COLLATERAL_RATIO);
BOOST_CHECK(bitasset.current_feed.required_maintenance_collateral == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
} catch (const fc::exception& e) {
edump((e.to_detail_string()));
@ -977,241 +838,12 @@ BOOST_AUTO_TEST_CASE( delegate_feeds )
}
}
/**
* Assume there exists an offer to buy BITUSD
* Create a short that exactly matches that offer at a price 2:1
*/
BOOST_AUTO_TEST_CASE( limit_match_existing_short_exact )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
const account_object& buyer_account = create_account( "buyer" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
transfer( genesis_account(db), buyer_account, asset( 10000 ) );
create_sell_order( buyer_account, asset(125), bitusd.amount(100) );
create_sell_order( buyer_account, asset(150), bitusd.amount(100) );
auto buy_order = create_sell_order( buyer_account, asset(100), bitusd.amount(100) );
//print_market("","");
BOOST_REQUIRE( buy_order );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 200 ) ); // 1:1 price
auto second_short = create_short( shorter_account, bitusd.amount(100), asset( 300 ) ); // 1:1 price
auto third_short = create_short( shorter_account, bitusd.amount(100), asset( 400 ) ); // 1:1 price
//print_short_market("","");
BOOST_REQUIRE( first_short && second_short && third_short );
//print_joint_market("","");
auto unmatched_order = create_sell_order( buyer_account, asset(200), bitusd.amount(100) );
//print_joint_market("","");
BOOST_REQUIRE( !unmatched_order );
// now it shouldn't fill
unmatched_order = create_sell_order( buyer_account, asset(200), bitusd.amount(100) );
//print_joint_market("","");
BOOST_REQUIRE( unmatched_order );
BOOST_CHECK( unmatched_order->amount_for_sale() == asset(200) );
BOOST_CHECK( unmatched_order->amount_to_receive() == bitusd.amount(100) );
BOOST_CHECK( second_short->amount_for_sale() == bitusd.amount(100) );
BOOST_CHECK( third_short->amount_for_sale() == bitusd.amount(100) );
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
/**
* Assume there exists an offer to buy BITUSD
* Create a short that exactly matches that offer at a price 2:1
*/
BOOST_AUTO_TEST_CASE( limit_match_existing_short_partial_exact_price )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
const account_object& buyer_account = create_account( "buyer" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
transfer( genesis_account(db), buyer_account, asset( 10000 ) );
create_sell_order( buyer_account, asset(125), bitusd.amount(100) );
create_sell_order( buyer_account, asset(150), bitusd.amount(100) );
auto buy_order = create_sell_order( buyer_account, asset(100), bitusd.amount(100) );
//print_market("","");
BOOST_REQUIRE( buy_order );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 200 ) ); // 1:1 price
auto second_short = create_short( shorter_account, bitusd.amount(100), asset( 300 ) ); // 1:1 price
auto third_short = create_short( shorter_account, bitusd.amount(100), asset( 400 ) ); // 1:1 price
//print_short_market("","");
BOOST_REQUIRE( first_short && second_short && third_short );
//print_joint_market("","");
auto unmatched_order = create_sell_order( buyer_account, asset(100), bitusd.amount(50) );
//print_joint_market("","");
BOOST_REQUIRE( !unmatched_order );
BOOST_CHECK( first_short->amount_for_sale() == bitusd.amount(50) );
BOOST_CHECK( first_short->get_collateral() == asset(100) );
BOOST_CHECK( second_short->amount_for_sale() == bitusd.amount(100) );
BOOST_CHECK( third_short->amount_for_sale() == bitusd.amount(100) );
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
/**
* Assume there exists an offer to buy BITUSD
* Create a short that exactly matches that offer at a price 2:1
*/
BOOST_AUTO_TEST_CASE( limit_match_existing_short_partial_over_price )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
const account_object& buyer_account = create_account( "buyer" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
transfer( genesis_account(db), buyer_account, asset( 10000 ) );
create_sell_order( buyer_account, asset(125), bitusd.amount(100) );
create_sell_order( buyer_account, asset(150), bitusd.amount(100) );
auto buy_order = create_sell_order( buyer_account, asset(100), bitusd.amount(100) );
//print_market("","");
BOOST_REQUIRE( buy_order );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 200 ) ); // 1:1 price
auto second_short = create_short( shorter_account, bitusd.amount(100), asset( 300 ) ); // 1:1 price
auto third_short = create_short( shorter_account, bitusd.amount(100), asset( 400 ) ); // 1:1 price
BOOST_REQUIRE( first_short && second_short && third_short );
//print_joint_market("","");
auto unmatched_order = create_sell_order( buyer_account, asset(100), bitusd.amount(40) );
//print_joint_market("","");
BOOST_REQUIRE( !unmatched_order );
BOOST_CHECK( first_short->amount_for_sale() == bitusd.amount(50) );
BOOST_CHECK( first_short->get_collateral() == asset(100) );
BOOST_CHECK( second_short->amount_for_sale() == bitusd.amount(100) );
BOOST_CHECK( third_short->amount_for_sale() == bitusd.amount(100) );
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
/**
* Assume there exists an offer to buy BITUSD
* Create a short that exactly matches that offer at a price 2:1
*/
BOOST_AUTO_TEST_CASE( limit_match_multiple_existing_short_partial_over_price )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
const account_object& buyer_account = create_account( "buyer" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
transfer( genesis_account(db), buyer_account, asset( 10000 ) );
create_sell_order( buyer_account, asset(125), bitusd.amount(100) );
create_sell_order( buyer_account, asset(150), bitusd.amount(100) );
auto buy_order = create_sell_order( buyer_account, asset(100), bitusd.amount(100) );
//print_market("","");
BOOST_REQUIRE( buy_order );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 200 ) ); // 1:1 price
auto next_short = create_short( shorter_account, bitusd.amount(100), asset( 210 ) ); // 1:1 price
auto second_short = create_short( shorter_account, bitusd.amount(100), asset( 300 ) ); // 1:1 price
auto third_short = create_short( shorter_account, bitusd.amount(100), asset( 400 ) ); // 1:1 price
//print_short_market("","");
BOOST_REQUIRE( first_short && second_short && third_short );
auto unmatched_order = create_sell_order( buyer_account, asset(200+115), bitusd.amount(150) );
// print_joint_market("","");
BOOST_REQUIRE( !unmatched_order );
//wdump( (next_short->amount_for_sale().amount)(next_short->get_collateral().amount) );
BOOST_CHECK( next_short->amount_for_sale() == bitusd.amount(46) );
BOOST_CHECK( next_short->get_collateral() == asset(97) );
BOOST_CHECK( second_short->amount_for_sale() == bitusd.amount(100) );
BOOST_CHECK( third_short->amount_for_sale() == bitusd.amount(100) );
print_call_orders();
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
/**
* Assume there exists an offer to buy BITUSD
* Create a short that exactly matches that offer at a price 2:1
*/
BOOST_AUTO_TEST_CASE( limit_dont_match_existing_short_partial_over_price )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter_account = create_account( "shorter" );
const account_object& buyer_account = create_account( "buyer" );
transfer( genesis_account(db), shorter_account, asset( 10000 ) );
transfer( genesis_account(db), buyer_account, asset( 10000 ) );
create_sell_order( buyer_account, asset(125), bitusd.amount(100) );
create_sell_order( buyer_account, asset(150), bitusd.amount(100) );
auto buy_order = create_sell_order( buyer_account, asset(100), bitusd.amount(100) );
BOOST_REQUIRE( buy_order );
auto first_short = create_short( shorter_account, bitusd.amount(100), asset( 200 ) ); // 1:1 price
auto second_short = create_short( shorter_account, bitusd.amount(100), asset( 300 ) ); // 1:1 price
auto third_short = create_short( shorter_account, bitusd.amount(100), asset( 400 ) ); // 1:1 price
//print_short_market("","");
BOOST_REQUIRE( first_short && second_short && third_short );
//print_joint_market("","");
auto unmatched_order = create_sell_order( buyer_account, asset(100), bitusd.amount(60) );
BOOST_REQUIRE( unmatched_order );
BOOST_CHECK( first_short->amount_for_sale() == bitusd.amount(100) );
BOOST_CHECK( first_short->get_collateral() == asset(200) );
BOOST_CHECK( second_short->amount_for_sale() == bitusd.amount(100) );
BOOST_CHECK( third_short->amount_for_sale() == bitusd.amount(100) );
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
}
}
BOOST_AUTO_TEST_CASE( multiple_shorts_matching_multiple_bids_in_order )
{ try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const account_object& shorter1_account = create_account( "shorter1" );
const account_object& shorter2_account = create_account( "shorter2" );
const account_object& shorter3_account = create_account( "shorter3" );
const account_object& buyer_account = create_account( "buyer" );
transfer( genesis_account(db), shorter1_account, asset( 10000 ) );
transfer( genesis_account(db), shorter2_account, asset( 10000 ) );
transfer( genesis_account(db), shorter3_account, asset( 10000 ) );
transfer( genesis_account(db), buyer_account, asset( 10000 ) );
BOOST_REQUIRE( create_sell_order( buyer_account, asset(125), bitusd.amount(100) ) );
BOOST_REQUIRE( create_sell_order( buyer_account, asset(150), bitusd.amount(100) ) );
BOOST_REQUIRE( create_sell_order( buyer_account, asset(200), bitusd.amount(100) ) );
print_joint_market("","");
BOOST_REQUIRE( !create_short( shorter1_account, bitusd.amount(100), asset( 200 ) ) );
BOOST_REQUIRE( !create_short( shorter2_account, bitusd.amount(100), asset( 150 ) ) );
BOOST_REQUIRE( !create_short( shorter3_account, bitusd.amount(100), asset( 125 ) ) );
print_call_orders();
auto& index = db.get_index_type<call_order_index>().indices().get<by_account>();
BOOST_CHECK(index.find(boost::make_tuple(buyer_account.id, bitusd.id)) == index.end());
BOOST_CHECK(index.find(boost::make_tuple(shorter1_account.id, bitusd.id)) != index.end());
BOOST_CHECK(index.find(boost::make_tuple(shorter1_account.id, bitusd.id))->get_debt() == bitusd.amount(100) );
BOOST_CHECK(index.find(boost::make_tuple(shorter1_account.id, bitusd.id))->call_price == price(asset(300), bitusd.amount(100)) );
BOOST_CHECK(index.find(boost::make_tuple(shorter2_account.id, bitusd.id)) != index.end());
BOOST_CHECK(index.find(boost::make_tuple(shorter2_account.id, bitusd.id))->get_debt() == bitusd.amount(100) );
BOOST_CHECK(index.find(boost::make_tuple(shorter3_account.id, bitusd.id)) != index.end());
BOOST_CHECK(index.find(boost::make_tuple(shorter3_account.id, bitusd.id))->get_debt() == bitusd.amount(100) );
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
} }
BOOST_AUTO_TEST_CASE( full_cover_test )
{
try {
INVOKE(multiple_shorts_matching_multiple_bids_in_order);
FC_ASSERT( "Reimplement with new borrowing semantics" );
/*
const asset_object& bit_usd = get_asset("BITUSD");
const asset_object& core = asset_id_type()(db);
const account_object& debt_holder = get_account("shorter1");
@ -1239,6 +871,7 @@ BOOST_AUTO_TEST_CASE( full_cover_test )
BOOST_CHECK_EQUAL(get_balance(debt_holder, bit_usd), 0);
BOOST_CHECK(index.find(boost::make_tuple(debt_holder.id, bit_usd.id)) == index.end());
*/
} catch( fc::exception& e) {
edump((e.to_detail_string()));
throw;
@ -1248,7 +881,7 @@ BOOST_AUTO_TEST_CASE( full_cover_test )
BOOST_AUTO_TEST_CASE( partial_cover_test )
{
try {
INVOKE(multiple_shorts_matching_multiple_bids_in_order);
FC_ASSERT( "Reimplement with new borrowing semantics" );
const asset_object& bit_usd = get_asset("BITUSD");
const asset_object& core = asset_id_type()(db);
const account_object& debt_holder = get_account("shorter1");
@ -1319,251 +952,6 @@ BOOST_AUTO_TEST_CASE( partial_cover_test )
}
}
BOOST_AUTO_TEST_CASE( limit_order_matching_mix_of_shorts_and_limits )
{ try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
const account_object& shorter1 = create_account( "shorter1" );
const account_object& shorter2 = create_account( "shorter2" );
const account_object& shorter3 = create_account( "shorter3" );
const account_object& buyer1 = create_account( "buyer1" );
const account_object& buyer2 = create_account( "buyer2" );
const account_object& buyer3 = create_account( "buyer3" );
transfer( genesis_account(db), shorter1, core.amount( 10000 ) );
transfer( genesis_account(db), shorter2, core.amount( 10000 ) );
transfer( genesis_account(db), shorter3, core.amount( 10000 ) );
transfer( genesis_account(db), buyer1, core.amount( 10000 ) );
transfer( genesis_account(db), buyer2, core.amount( 10000 ) );
transfer( genesis_account(db), buyer3, core.amount( 10000 ) );
// create some BitUSD
BOOST_REQUIRE( create_sell_order( buyer1, core.amount(1000), bitusd.amount(1000) ) );
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), core.amount(1000) ) );
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
// create a mixture of BitUSD sells and shorts
BOOST_REQUIRE( create_short( shorter1, bitusd.amount(100), core.amount(125) ) );
BOOST_REQUIRE( create_sell_order( buyer1, bitusd.amount(100), core.amount(150) ) );
BOOST_REQUIRE( create_short( shorter2, bitusd.amount(100), core.amount(200) ) );
BOOST_REQUIRE( create_sell_order( buyer1, bitusd.amount(100), core.amount(225) ) );
BOOST_REQUIRE( create_short( shorter3, bitusd.amount(100), core.amount(250) ) );
print_joint_market("",""); // may have bugs
// buy up everything but the highest order
auto unfilled_order = create_sell_order( buyer2, core.amount(700), bitusd.amount(311) );
if( unfilled_order ) wdump((*unfilled_order));
print_joint_market("","");
if( unfilled_order ) wdump((*unfilled_order));
BOOST_REQUIRE( !unfilled_order );
BOOST_REQUIRE_EQUAL( get_balance(buyer2, bitusd), 396 );
print_joint_market("","");
print_call_orders();
}catch ( const fc::exception& e )
{
elog( "${e}", ("e", e.to_detail_string() ) );
throw;
} }
BOOST_AUTO_TEST_CASE( big_short )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
const account_object& shorter1 = create_account( "shorter1" );
const account_object& buyer1 = create_account( "buyer1" );
const account_object& buyer2 = create_account( "buyer2" );
const account_object& buyer3 = create_account( "buyer3" );
transfer( genesis_account(db), shorter1, asset( 10000 ) );
transfer( genesis_account(db), buyer1, asset( 10000 ) );
transfer( genesis_account(db), buyer2, asset( 10000 ) );
transfer( genesis_account(db), buyer3, asset( 10000 ) );
create_sell_order(buyer1, core.amount(500), bitusd.amount(500));
create_sell_order(buyer2, core.amount(500), bitusd.amount(600));
auto unmatched_buy3 = create_sell_order(buyer3, core.amount(500), bitusd.amount(700));
auto unmatched = create_short(shorter1, bitusd.amount(1300), core.amount(800));
if( unmatched ) wdump((*unmatched));
BOOST_CHECK( !unmatched );
BOOST_CHECK( unmatched_buy3 );
BOOST_CHECK_EQUAL( unmatched_buy3->amount_for_sale().amount.value, 358);
// The extra 1 is rounding leftovers; it has to go somewhere.
BOOST_CHECK_EQUAL( unmatched_buy3->amount_to_receive().amount.value, 501);
// All three buyers offered 500 CORE for varying numbers of dollars.
BOOST_CHECK_EQUAL(get_balance(buyer1, core), 9500);
BOOST_CHECK_EQUAL(get_balance(buyer2, core), 9500);
BOOST_CHECK_EQUAL(get_balance(buyer3, core), 9500);
// Sans the 1% market fee, buyer1 got 500 USD, buyer2 got 600 USD
BOOST_CHECK_EQUAL(get_balance(buyer1, bitusd), 495);
BOOST_CHECK_EQUAL(get_balance(buyer2, bitusd), 594);
// Buyer3 wanted 700 USD, but the shorter only had 1300-500-600=200 left, so buyer3 got 200.
BOOST_CHECK_EQUAL(get_balance(buyer3, bitusd), 198);
// Shorter1 never had any USD, so he shouldn't have any now. He paid 800 CORE, so he should have 9200 left.
BOOST_CHECK_EQUAL(get_balance(shorter1, bitusd), 0);
BOOST_CHECK_EQUAL(get_balance(shorter1, core), 9200);
const auto& call_index = db.get_index_type<call_order_index>().indices().get<by_account>();
const auto call_itr = call_index.find(boost::make_tuple(shorter1.id, bitusd.id));
BOOST_CHECK(call_itr != call_index.end());
const call_order_object& call_object = *call_itr;
BOOST_CHECK(call_object.borrower == shorter1.id);
// 800 from shorter1, 500 from buyer1 and buyer2 each, 500/700*200 from buyer3 totals 1942
BOOST_CHECK_EQUAL(call_object.collateral.value, 1942);
// Shorter1 sold 1300 USD. Make sure that's recorded accurately.
BOOST_CHECK_EQUAL(call_object.debt.value, 1300);
// 13 USD was paid in market fees.
BOOST_CHECK_EQUAL(bitusd.dynamic_asset_data_id(db).accumulated_fees.value, 13);
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( big_short2 )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
const account_object& shorter1 = create_account( "shorter1" );
const account_object& buyer1 = create_account( "buyer1" );
const account_object& buyer2 = create_account( "buyer2" );
const account_object& buyer3 = create_account( "buyer3" );
transfer( genesis_account(db), shorter1, asset( 10000 ) );
transfer( genesis_account(db), buyer1, asset( 10000 ) );
transfer( genesis_account(db), buyer2, asset( 10000 ) );
transfer( genesis_account(db), buyer3, asset( 10000 ) );
create_sell_order(buyer1, core.amount(500), bitusd.amount(500));
create_sell_order(buyer2, core.amount(500), bitusd.amount(600));
auto unmatched_buy3 = create_sell_order(buyer3, core.amount(500), bitusd.amount(700));
//We want to perfectly match the first two orders, so that's 1100 USD at 500/600 = 916
auto unmatched = create_short(shorter1, bitusd.amount(1100), core.amount(916));
if( unmatched ) wdump((*unmatched));
BOOST_CHECK( !unmatched );
BOOST_CHECK( unmatched_buy3 );
BOOST_CHECK_EQUAL( unmatched_buy3->amount_for_sale().amount.value, 500);
// The extra 1 is rounding leftovers; it has to go somewhere.
BOOST_CHECK_EQUAL( unmatched_buy3->amount_to_receive().amount.value, 700);
// All three buyers offered 500 CORE for varying numbers of dollars.
BOOST_CHECK_EQUAL(get_balance(buyer1, core), 9500);
BOOST_CHECK_EQUAL(get_balance(buyer2, core), 9500);
BOOST_CHECK_EQUAL(get_balance(buyer3, core), 9500);
// Sans the 1% market fee, buyer1 got 500 USD, buyer2 got 600 USD
BOOST_CHECK_EQUAL(get_balance(buyer1, bitusd), 495);
BOOST_CHECK_EQUAL(get_balance(buyer2, bitusd), 594);
// Buyer3's order wasn't matched. He should have no USD.
BOOST_CHECK_EQUAL(get_balance(buyer3, bitusd), 0);
// Shorter1 never had any USD, so he shouldn't have any now. He paid 916 CORE, so he should have 9084 left.
BOOST_CHECK_EQUAL(get_balance(shorter1, bitusd), 0);
BOOST_CHECK_EQUAL(get_balance(shorter1, core), 9084);
const auto& call_index = db.get_index_type<call_order_index>().indices().get<by_account>();
const auto call_itr = call_index.find(boost::make_tuple(shorter1.id, bitusd.id));
BOOST_CHECK(call_itr != call_index.end());
const call_order_object& call_object = *call_itr;
BOOST_CHECK(call_object.borrower == shorter1.id);
// 916 from shorter1, 500 from buyer1 and buyer2 each adds to 1916
BOOST_CHECK_EQUAL(call_object.collateral.value, 1916);
// Shorter1 sold 1100 USD. Make sure that's recorded accurately.
BOOST_CHECK_EQUAL(call_object.debt.value, 1100);
// 11 USD was paid in market fees.
BOOST_CHECK_EQUAL(bitusd.dynamic_asset_data_id(db).accumulated_fees.value, 11);
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( big_short3 )
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
const account_object& shorter1 = create_account( "shorter1" );
const account_object& buyer1 = create_account( "buyer1" );
const account_object& buyer2 = create_account( "buyer2" );
const account_object& buyer3 = create_account( "buyer3" );
transfer( genesis_account(db), shorter1, asset( 10000 ) );
transfer( genesis_account(db), buyer1, asset( 10000 ) );
transfer( genesis_account(db), buyer2, asset( 10000 ) );
transfer( genesis_account(db), buyer3, asset( 10000 ) );
create_short(shorter1, bitusd.amount(1300), core.amount(800));
print_joint_market("","");
create_sell_order(buyer1, core.amount(500), bitusd.amount(500));
create_sell_order(buyer2, core.amount(500), bitusd.amount(600));
auto unmatched_buy3 = create_sell_order(buyer3, core.amount(500), bitusd.amount(700));
print_joint_market("","");
BOOST_CHECK( unmatched_buy3 );
BOOST_CHECK_EQUAL( unmatched_buy3->amount_for_sale().amount.value, 500);
BOOST_CHECK_EQUAL( unmatched_buy3->amount_to_receive().amount.value, 700);
BOOST_CHECK_EQUAL(get_balance(buyer1, core), 9500);
BOOST_CHECK_EQUAL(get_balance(buyer2, core), 9500);
BOOST_CHECK_EQUAL(get_balance(buyer3, core), 9500);
BOOST_CHECK_EQUAL(get_balance(buyer1, bitusd), 804);
BOOST_CHECK_EQUAL(get_balance(buyer2, bitusd), 484);
BOOST_CHECK_EQUAL(get_balance(buyer3, bitusd), 0);
BOOST_CHECK_EQUAL(get_balance(shorter1, bitusd), 0);
BOOST_CHECK_EQUAL(get_balance(shorter1, core), 9200);
const auto& call_index = db.get_index_type<call_order_index>().indices().get<by_account>();
const auto call_itr = call_index.find(boost::make_tuple(shorter1.id, bitusd.id));
BOOST_CHECK(call_itr != call_index.end());
const call_order_object& call_object = *call_itr;
BOOST_CHECK(call_object.borrower == shorter1.id);
BOOST_CHECK_EQUAL(call_object.collateral.value, 1600);
BOOST_CHECK_EQUAL(call_object.debt.value, 1300);
BOOST_CHECK_EQUAL(bitusd.dynamic_asset_data_id(db).accumulated_fees.value, 12);
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
/**
* Originally, this test exposed a bug in vote tallying causing the total number of votes to exceed the number of
* voting shares. This bug was resolved in commit 489b0dafe981c3b96b17f23cfc9ddc348173c529
*/
BOOST_AUTO_TEST_CASE(break_vote_count)
{
try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
const account_object& shorter1 = create_account( "shorter1" );
const account_object& buyer1 = create_account( "buyer1" );
transfer( genesis_account(db), shorter1, asset( 100000000 ) );
transfer( genesis_account(db), buyer1, asset( 100000000 ) );
create_short(shorter1, bitusd.amount(1300), core.amount(800));
create_sell_order(buyer1, core.amount(500), bitusd.amount(500));
BOOST_CHECK_EQUAL(get_balance(buyer1, core), 99999500);
BOOST_CHECK_EQUAL(get_balance(buyer1, bitusd), 804);
BOOST_CHECK_EQUAL(get_balance(shorter1, bitusd), 0);
BOOST_CHECK_EQUAL(get_balance(shorter1, core), 99999200);
create_sell_order(shorter1, core.amount(90000000), bitusd.amount(1));
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
/**
* Create an order such that when the trade executes at the
@ -1600,6 +988,8 @@ BOOST_AUTO_TEST_CASE( trade_amount_equals_zero )
BOOST_AUTO_TEST_CASE( margin_call_limit_test )
{ try {
FC_ASSERT( "TODO - Reimplement with new short semantics" );
/*
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
@ -1663,6 +1053,7 @@ BOOST_AUTO_TEST_CASE( margin_call_limit_test )
BOOST_CHECK_THROW(db.get_object(below_id), fc::exception);
BOOST_CHECK(call.get_debt() == bitusd.amount(210));
BOOST_CHECK(call.get_collateral() == core.amount(803));
*/
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
throw;
@ -1671,6 +1062,8 @@ BOOST_AUTO_TEST_CASE( margin_call_limit_test )
BOOST_AUTO_TEST_CASE( margin_call_limit_test_protected )
{ try {
FC_ASSERT( "TODO - Reimplement with new short semantics" );
/*
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
@ -1698,6 +1091,7 @@ BOOST_AUTO_TEST_CASE( margin_call_limit_test_protected )
auto unmatched = create_sell_order( buyer1, bitusd.amount(990), core.amount(1500) );
if( unmatched ) edump((*unmatched));
BOOST_REQUIRE( unmatched );
*/
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
@ -1707,6 +1101,8 @@ BOOST_AUTO_TEST_CASE( margin_call_limit_test_protected )
BOOST_AUTO_TEST_CASE( dont_margin_call_limit_test )
{ try {
FC_ASSERT( "TODO - Reimplement with new short semantics" );
/*
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
@ -1733,6 +1129,7 @@ BOOST_AUTO_TEST_CASE( dont_margin_call_limit_test )
auto unmatched = create_sell_order( buyer1, bitusd.amount(990), core.amount(1100) );
if( unmatched ) edump((*unmatched));
BOOST_REQUIRE( unmatched );
*/
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
@ -1742,6 +1139,8 @@ BOOST_AUTO_TEST_CASE( dont_margin_call_limit_test )
BOOST_AUTO_TEST_CASE( margin_call_short_test )
{ try {
FC_ASSERT( "TODO - Reimplement with new short semantics" );
/*
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
@ -1769,6 +1168,7 @@ BOOST_AUTO_TEST_CASE( margin_call_short_test )
auto unmatched = create_short( buyer1, bitusd.amount(990), core.amount(1500) );
if( unmatched ) edump((*unmatched));
BOOST_REQUIRE( !unmatched );
*/
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
@ -1778,6 +1178,8 @@ BOOST_AUTO_TEST_CASE( margin_call_short_test )
BOOST_AUTO_TEST_CASE( margin_call_short_test_limit_protected )
{ try {
FC_ASSERT( "TODO - Reimplement with new short semantics" );
/*
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
@ -1805,6 +1207,7 @@ BOOST_AUTO_TEST_CASE( margin_call_short_test_limit_protected )
auto unmatched = create_short( buyer1, bitusd.amount(990), core.amount(1500) );
if( unmatched ) edump((*unmatched));
BOOST_REQUIRE( unmatched );
*/
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
@ -2032,66 +1435,12 @@ BOOST_AUTO_TEST_CASE( unimp_bulk_discount_test )
*/
BOOST_AUTO_TEST_CASE( margin_call_black_swan )
{ try {
const asset_object& bitusd = create_bitasset( "BITUSD" );
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
usd.current_feed.call_limit = core.amount(30) / bitusd.amount(1);
});
const account_object& shorter1 = create_account( "shorter1" );
const account_object& shorter2 = create_account( "shorter2" );
const account_object& buyer1 = create_account( "buyer1" );
const account_object& buyer2 = create_account( "buyer2" );
transfer( genesis_account(db), shorter1, asset( 10000 ) );
transfer( genesis_account(db), shorter2, asset( 10000 ) );
transfer( genesis_account(db), buyer1, asset( 10000 ) );
transfer( genesis_account(db), buyer2, asset( 10000 ) );
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
verify_asset_supplies();
ilog( "=================================== START===================================\n\n");
// this should cause the highest bid to below the margin call threshold
// which means it should be filled by the cover, except the cover does not
// have enough collateral and thus a black swan event should occur.
auto unmatched = create_sell_order( buyer1, bitusd.amount(990), core.amount(5000) );
if( unmatched ) edump((*unmatched));
/** black swans should cause all of the bitusd to be converted into backing
* asset at the price of the least collateralized call position at the time. This
* means that this sell order would be removed.
*/
BOOST_REQUIRE( !unmatched );
FC_ASSERT( "TODO - Reimplement with new short semantics" );
} catch( const fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
/**
* This test sets up a far more complex blackswan scenerio where the
* BitUSD exists in the following places:
*
* 0) Limit Orders for the BitAsset
* 1) Limit Orders for UIA Assets
* 2) Short Orders for BitAsset backed by BitUSD
* 3) Call Orders for BitAsset backed by BitUSD
* 4) Issuer Fees
*
* This test should fail until the black swan handling code can
* perform a recursive blackswan for any other BitAssets that use
* BitUSD as collateral.
*/
BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES( unimp_advanced_black_swan, 1 )
BOOST_AUTO_TEST_CASE( unimp_advanced_black_swan )
{
BOOST_FAIL( "not implemented" );
}
/**
* Assume the referrer gets 99% of transaction fee

View file

@ -25,7 +25,7 @@
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/witness_object.hpp>
#include <graphene/chain/delegate_object.hpp>
#include <graphene/chain/short_order_object.hpp>
#include <graphene/chain/call_order_object.hpp>
#include <graphene/chain/vesting_balance_object.hpp>
#include <graphene/chain/withdraw_permission_object.hpp>
@ -337,7 +337,6 @@ BOOST_AUTO_TEST_CASE( mia_feeds )
asset_publish_feed_operation op({asset(), vikram_id});
op.asset_id = bit_usd_id;
op.feed.call_limit = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(30));
op.feed.short_limit = ~price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(10));
// We'll expire margins after a month
op.feed.max_margin_period_sec = fc::days(30).to_seconds();
// Accept defaults for required collateral
@ -346,37 +345,28 @@ BOOST_AUTO_TEST_CASE( mia_feeds )
const asset_bitasset_data_object& bitasset = bit_usd.bitasset_data(db);
BOOST_CHECK(bitasset.current_feed.call_limit.to_real() == GRAPHENE_BLOCKCHAIN_PRECISION / 30.0);
BOOST_CHECK_EQUAL(bitasset.current_feed.short_limit.to_real(), 10.0 / GRAPHENE_BLOCKCHAIN_PRECISION);
BOOST_CHECK(bitasset.current_feed.max_margin_period_sec == fc::days(30).to_seconds());
BOOST_CHECK(bitasset.current_feed.required_initial_collateral == GRAPHENE_DEFAULT_INITIAL_COLLATERAL_RATIO);
BOOST_CHECK(bitasset.current_feed.required_maintenance_collateral == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
op.publisher = ben_id;
op.feed.call_limit = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(25));
op.feed.short_limit = ~price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(20));
op.feed.max_margin_period_sec = fc::days(10).to_seconds();
trx.operations.back() = op;
db.push_transaction(trx, ~0);
BOOST_CHECK_EQUAL(bitasset.current_feed.call_limit.to_real(), GRAPHENE_BLOCKCHAIN_PRECISION / 25.0);
BOOST_CHECK_EQUAL(bitasset.current_feed.short_limit.to_real(), 20.0 / GRAPHENE_BLOCKCHAIN_PRECISION);
BOOST_CHECK(bitasset.current_feed.max_margin_period_sec == fc::days(30).to_seconds());
BOOST_CHECK(bitasset.current_feed.required_initial_collateral == GRAPHENE_DEFAULT_INITIAL_COLLATERAL_RATIO);
BOOST_CHECK(bitasset.current_feed.required_maintenance_collateral == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
op.publisher = dan_id;
op.feed.call_limit = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(40));
op.feed.short_limit = ~price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(10));
op.feed.max_margin_period_sec = fc::days(100).to_seconds();
op.feed.required_initial_collateral = 1001;
op.feed.required_maintenance_collateral = 1000;
trx.operations.back() = op;
db.push_transaction(trx, ~0);
BOOST_CHECK_EQUAL(bitasset.current_feed.call_limit.to_real(), GRAPHENE_BLOCKCHAIN_PRECISION / 30.0);
BOOST_CHECK_EQUAL(bitasset.current_feed.short_limit.to_real(), 10.0 / GRAPHENE_BLOCKCHAIN_PRECISION);
BOOST_CHECK(bitasset.current_feed.max_margin_period_sec == fc::days(30).to_seconds());
BOOST_CHECK(bitasset.current_feed.required_initial_collateral == GRAPHENE_DEFAULT_INITIAL_COLLATERAL_RATIO);
BOOST_CHECK(bitasset.current_feed.required_maintenance_collateral == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
op.publisher = nathan_id;
@ -451,6 +441,8 @@ BOOST_AUTO_TEST_CASE( witness_create )
BOOST_AUTO_TEST_CASE( global_settle_test )
{ try {
ACTORS((nathan)(ben)(valentine)(dan));
FC_ASSERT( !"TODO - Reimplement this" );
/*
asset_id_type bit_usd_id = create_bitasset("BITUSD", nathan_id, 100, global_settle | charge_market_fee).get_id();
transfer(genesis_account, ben_id, asset(10000));
transfer(genesis_account, valentine_id, asset(10000));
@ -489,6 +481,7 @@ BOOST_AUTO_TEST_CASE( global_settle_test )
BOOST_CHECK_EQUAL(get_balance(ben_id, asset_id_type()), 10091);
BOOST_CHECK_EQUAL(get_balance(dan_id, bit_usd_id), 0);
BOOST_CHECK_EQUAL(get_balance(dan_id, asset_id_type()), 9850);
*/
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE( worker_create_test )
@ -680,6 +673,8 @@ BOOST_AUTO_TEST_CASE( refund_worker_test )
BOOST_AUTO_TEST_CASE( force_settlement_unavailable )
{ try {
FC_ASSERT( !"TODO - Reimplement this" );
/*
auto private_key = generate_private_key("genesis");
account_id_type nathan_id = create_account("nathan").get_id();
account_id_type shorter1_id = create_account("shorter1").get_id();
@ -735,7 +730,6 @@ BOOST_AUTO_TEST_CASE( force_settlement_unavailable )
price_feed feed;
feed.settlement_price = price(asset(1),asset(1, bit_usd));
feed.call_limit = price::min(0, bit_usd);
feed.short_limit = price::min(bit_usd, 0);
pop.feed = feed;
trx.operations.push_back(pop);
}
@ -793,6 +787,7 @@ BOOST_AUTO_TEST_CASE( force_settlement_unavailable )
BOOST_CHECK(db.get_index_type<force_settlement_index>().indices().empty());
BOOST_CHECK_EQUAL(get_balance(nathan_id, bit_usd), bit_usd(db).dynamic_data(db).current_supply.value);
}
*/
} FC_LOG_AND_RETHROW() }
// TODO: Write linear VBO tests