Remove bond operations
This commit is contained in:
parent
9b3220f13a
commit
d12d9cdb0c
14 changed files with 0 additions and 744 deletions
|
|
@ -18,7 +18,6 @@ add_library( graphene_chain
|
|||
proposal_evaluator.cpp
|
||||
short_order_evaluator.cpp
|
||||
limit_order_evaluator.cpp
|
||||
bond_evaluator.cpp
|
||||
vesting_balance_evaluator.cpp
|
||||
withdraw_permission_evaluator.cpp
|
||||
worker_evaluator.cpp
|
||||
|
|
|
|||
|
|
@ -1,218 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/bond_evaluator.hpp>
|
||||
#include <graphene/chain/bond_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
object_id_type bond_create_offer_evaluator::do_evaluate( const bond_create_offer_operation& op )
|
||||
{
|
||||
const auto& d = db();
|
||||
|
||||
const auto& creator_account = op.creator( d );
|
||||
const auto& base_asset = op.collateral_rate.base.asset_id( d );
|
||||
const auto& quote_asset = op.collateral_rate.quote.asset_id( d );
|
||||
|
||||
// TODO: Check asset authorizations and withdrawals
|
||||
|
||||
const auto& amount_asset = (op.amount.asset_id == op.collateral_rate.base.asset_id) ? base_asset : quote_asset;
|
||||
|
||||
FC_ASSERT( !base_asset.is_transfer_restricted() && !quote_asset.is_transfer_restricted() );
|
||||
|
||||
if( base_asset.options.whitelist_markets.size() )
|
||||
FC_ASSERT( base_asset.options.whitelist_markets.find( quote_asset.id ) != base_asset.options.whitelist_markets.end() );
|
||||
if( base_asset.options.blacklist_markets.size() )
|
||||
FC_ASSERT( base_asset.options.blacklist_markets.find( quote_asset.id ) == base_asset.options.blacklist_markets.end() );
|
||||
|
||||
FC_ASSERT( d.get_balance( creator_account, amount_asset ) >= op.amount );
|
||||
|
||||
return object_id_type();
|
||||
}
|
||||
|
||||
object_id_type bond_create_offer_evaluator::do_apply( const bond_create_offer_operation& op )
|
||||
{
|
||||
db().adjust_balance( op.creator, -op.amount );
|
||||
db().adjust_core_in_orders( op.creator(db()), op.amount );
|
||||
|
||||
const auto& offer = db().create<bond_offer_object>( [&]( bond_offer_object& obj )
|
||||
{
|
||||
obj.offered_by_account = op.creator;
|
||||
obj.offer_to_borrow = op.offer_to_borrow;
|
||||
obj.amount = op.amount;
|
||||
obj.min_match = op.min_match;
|
||||
obj.collateral_rate = op.collateral_rate;
|
||||
obj.min_loan_period_sec = op.min_loan_period_sec;
|
||||
obj.loan_period_sec = op.loan_period_sec;
|
||||
obj.interest_apr = op.interest_apr;
|
||||
} );
|
||||
|
||||
return offer.id;
|
||||
}
|
||||
|
||||
|
||||
object_id_type bond_cancel_offer_evaluator::do_evaluate( const bond_cancel_offer_operation& op )
|
||||
{
|
||||
_offer = &op.offer_id(db());
|
||||
FC_ASSERT( op.creator == _offer->offered_by_account );
|
||||
FC_ASSERT( _offer->amount == op.refund );
|
||||
return object_id_type();
|
||||
}
|
||||
|
||||
object_id_type bond_cancel_offer_evaluator::do_apply( const bond_cancel_offer_operation& op )
|
||||
{
|
||||
assert( _offer != nullptr );
|
||||
db().adjust_balance( op.creator, op.refund );
|
||||
db().adjust_core_in_orders( op.creator(db()), -op.refund );
|
||||
db().remove( *_offer );
|
||||
return object_id_type();
|
||||
}
|
||||
|
||||
object_id_type bond_accept_offer_evaluator::do_evaluate( const bond_accept_offer_operation& op )
|
||||
{ try {
|
||||
_offer = &op.offer_id(db());
|
||||
|
||||
if( _offer->offer_to_borrow )
|
||||
FC_ASSERT( op.amount_borrowed.amount >= _offer->min_match );
|
||||
else
|
||||
FC_ASSERT( op.amount_collateral.amount >= _offer->min_match );
|
||||
|
||||
FC_ASSERT( (op.amount_borrowed / op.amount_collateral == _offer->collateral_rate) ||
|
||||
(op.amount_collateral / op.amount_borrowed == _offer->collateral_rate) );
|
||||
|
||||
return object_id_type();
|
||||
} FC_CAPTURE_AND_RETHROW((op)) }
|
||||
|
||||
object_id_type bond_accept_offer_evaluator::do_apply( const bond_accept_offer_operation& op )
|
||||
{ try {
|
||||
|
||||
if( op.claimer == op.lender )
|
||||
{
|
||||
db().adjust_balance( op.lender, -op.amount_borrowed );
|
||||
}
|
||||
else // claimer == borrower
|
||||
{
|
||||
db().adjust_balance( op.borrower, -op.amount_collateral );
|
||||
db().adjust_core_in_orders( op.borrower(db()), op.amount_collateral );
|
||||
}
|
||||
db().adjust_balance( op.borrower, op.amount_borrowed );
|
||||
|
||||
const auto& bond = db().create<bond_object>( [&]( bond_object& obj )
|
||||
{
|
||||
obj.borrowed = op.amount_borrowed;
|
||||
obj.collateral = op.amount_collateral;
|
||||
obj.borrower = op.borrower;
|
||||
obj.lender = op.lender;
|
||||
|
||||
auto head_time = db().get_dynamic_global_properties().time;
|
||||
obj.interest_apr = _offer->interest_apr;
|
||||
obj.start_date = head_time;
|
||||
obj.due_date = head_time + fc::seconds( _offer->loan_period_sec );
|
||||
obj.earliest_payoff_date = head_time + fc::seconds( _offer->min_loan_period_sec );
|
||||
} );
|
||||
|
||||
if( _offer->offer_to_borrow && op.amount_borrowed < _offer->amount )
|
||||
{
|
||||
db().modify( *_offer, [&]( bond_offer_object& offer ){
|
||||
offer.amount -= op.amount_borrowed;
|
||||
});
|
||||
}
|
||||
else if( !_offer->offer_to_borrow && op.amount_collateral < _offer->amount )
|
||||
{
|
||||
db().modify( *_offer, [&]( bond_offer_object& offer ){
|
||||
offer.amount -= op.amount_collateral;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
db().remove( *_offer );
|
||||
}
|
||||
return bond.id;
|
||||
} FC_CAPTURE_AND_RETHROW((op)) }
|
||||
|
||||
|
||||
|
||||
object_id_type bond_claim_collateral_evaluator::do_evaluate( const bond_claim_collateral_operation& op )
|
||||
{
|
||||
_bond = &op.bond_id(db());
|
||||
auto head_time = db().get_dynamic_global_properties().time;
|
||||
FC_ASSERT( head_time > _bond->earliest_payoff_date );
|
||||
|
||||
|
||||
FC_ASSERT( op.collateral_claimed <= _bond->collateral );
|
||||
if( _bond->borrower == op.claimer )
|
||||
{
|
||||
auto elapsed_time = head_time - _bond->start_date;
|
||||
auto elapsed_days = 1 + elapsed_time.to_seconds() / (60*60*24);
|
||||
|
||||
fc::uint128 tmp = _bond->borrowed.amount.value;
|
||||
tmp *= elapsed_days;
|
||||
tmp *= _bond->interest_apr;
|
||||
tmp /= (365 * GRAPHENE_100_PERCENT);
|
||||
FC_ASSERT( tmp < GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
_interest_due = asset(tmp.to_uint64(), _bond->borrowed.asset_id);
|
||||
|
||||
FC_ASSERT( _interest_due + _bond->borrowed <= op.payoff_amount );
|
||||
|
||||
auto total_debt = _interest_due + _bond->borrowed;
|
||||
|
||||
fc::uint128 max_claim = _bond->collateral.amount.value;
|
||||
max_claim *= op.payoff_amount.amount.value;
|
||||
max_claim /= total_debt.amount.value;
|
||||
|
||||
FC_ASSERT( op.collateral_claimed.amount.value == max_claim.to_uint64() );
|
||||
}
|
||||
else
|
||||
{
|
||||
FC_ASSERT( _bond->lender == op.claimer );
|
||||
FC_ASSERT( head_time > _bond->due_date );
|
||||
FC_ASSERT( _bond->collateral == op.collateral_claimed );
|
||||
FC_ASSERT( op.payoff_amount == asset(0,_bond->borrowed.asset_id ) );
|
||||
}
|
||||
return object_id_type();
|
||||
}
|
||||
|
||||
object_id_type bond_claim_collateral_evaluator::do_apply( const bond_claim_collateral_operation& op )
|
||||
{
|
||||
assert( _bond != nullptr );
|
||||
|
||||
const account_object& claimer = op.claimer(db());
|
||||
|
||||
db().adjust_core_in_orders( _bond->borrower(db()), -op.collateral_claimed );
|
||||
|
||||
if( op.payoff_amount.amount > 0 )
|
||||
{
|
||||
db().adjust_balance( claimer, -op.payoff_amount );
|
||||
db().adjust_balance( op.lender, op.payoff_amount );
|
||||
}
|
||||
db().adjust_balance( claimer, op.collateral_claimed );
|
||||
|
||||
if( op.collateral_claimed == _bond->collateral )
|
||||
db().remove(*_bond);
|
||||
else
|
||||
db().modify( *_bond, [&]( bond_object& bond ){
|
||||
bond.borrowed -= op.payoff_amount + _interest_due;
|
||||
bond.collateral -= op.collateral_claimed;
|
||||
bond.start_date = db().get_dynamic_global_properties().time;
|
||||
});
|
||||
|
||||
return object_id_type();
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -21,7 +21,6 @@
|
|||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/block_summary_object.hpp>
|
||||
#include <graphene/chain/bond_object.hpp>
|
||||
#include <graphene/chain/delegate_object.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/key_object.hpp>
|
||||
|
|
@ -37,7 +36,6 @@
|
|||
|
||||
#include <graphene/chain/account_evaluator.hpp>
|
||||
#include <graphene/chain/asset_evaluator.hpp>
|
||||
#include <graphene/chain/bond_evaluator.hpp>
|
||||
#include <graphene/chain/custom_evaluator.hpp>
|
||||
#include <graphene/chain/delegate_evaluator.hpp>
|
||||
#include <graphene/chain/global_parameters_evaluator.hpp>
|
||||
|
|
@ -89,10 +87,6 @@ void database::initialize_evaluators()
|
|||
register_evaluator<global_parameters_update_evaluator>();
|
||||
register_evaluator<witness_create_evaluator>();
|
||||
register_evaluator<witness_withdraw_pay_evaluator>();
|
||||
register_evaluator<bond_create_offer_evaluator>();
|
||||
register_evaluator<bond_cancel_offer_evaluator>();
|
||||
register_evaluator<bond_accept_offer_evaluator>();
|
||||
register_evaluator<bond_claim_collateral_evaluator>();
|
||||
register_evaluator<vesting_balance_create_evaluator>();
|
||||
register_evaluator<vesting_balance_withdraw_evaluator>();
|
||||
register_evaluator<withdraw_permission_create_evaluator>();
|
||||
|
|
@ -118,8 +112,6 @@ void database::initialize_indexes()
|
|||
add_index< primary_index<call_order_index > >();
|
||||
add_index< primary_index<proposal_index > >();
|
||||
add_index< primary_index<withdraw_permission_index > >();
|
||||
add_index< primary_index<bond_index > >();
|
||||
add_index< primary_index<bond_offer_index > >();
|
||||
add_index< primary_index<simple_index<vesting_balance_object> > >();
|
||||
add_index< primary_index<worker_index> >();
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/bond_object.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
#include <graphene/chain/short_order_object.hpp>
|
||||
|
||||
|
|
@ -33,7 +32,6 @@ namespace graphene { namespace chain {
|
|||
calculate the USD->CORE price and convert all USD balances to CORE at that price and subtract CORE from total
|
||||
- any fees accumulated by the issuer in the bitasset are forfeit / not redeemed
|
||||
- cancel all open orders with bitasset in it
|
||||
- any bonds with the bitasset as collateral get converted to CORE as collateral
|
||||
- any bitassets that use this bitasset as collateral are immediately settled at their feed price
|
||||
- convert all balances in bitasset to CORE and subtract from total
|
||||
- any prediction markets with usd as the backing get converted to CORE as the backing
|
||||
|
|
@ -111,38 +109,6 @@ void database::globally_settle_asset( const asset_object& mia, const price& sett
|
|||
// settle all balances
|
||||
asset total_mia_settled = mia.amount(0);
|
||||
|
||||
// convert collateral held in bonds
|
||||
const auto& bond_idx = get_index_type<bond_index>().indices().get<by_collateral>();
|
||||
auto bond_itr = bond_idx.find( bitasset.id );
|
||||
while( bond_itr != bond_idx.end() )
|
||||
{
|
||||
if( bond_itr->collateral.asset_id == bitasset.id )
|
||||
{
|
||||
auto settled_amount = bond_itr->collateral * settlement_price;
|
||||
total_mia_settled += bond_itr->collateral;
|
||||
collateral_gathered -= settled_amount;
|
||||
modify( *bond_itr, [&]( bond_object& obj ) {
|
||||
obj.collateral = settled_amount;
|
||||
});
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
// cancel all bond offers holding the bitasset and refund the offer
|
||||
const auto& bond_offer_idx = get_index_type<bond_offer_index>().indices().get<by_asset>();
|
||||
auto bond_offer_itr = bond_offer_idx.find( bitasset.id );
|
||||
while( bond_offer_itr != bond_offer_idx.end() )
|
||||
{
|
||||
if( bond_offer_itr->amount.asset_id == bitasset.id )
|
||||
{
|
||||
adjust_balance( bond_offer_itr->offered_by_account, bond_offer_itr->amount );
|
||||
auto old_itr = bond_offer_itr;
|
||||
bond_offer_itr++;
|
||||
remove( *old_itr );
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
const auto& index = get_index_type<account_balance_index>().indices().get<by_asset>();
|
||||
auto range = index.equal_range(mia.get_id());
|
||||
for( auto itr = range.first; itr != range.second; ++itr )
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class bond_create_offer_evaluator : public evaluator<bond_create_offer_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef bond_create_offer_operation operation_type;
|
||||
|
||||
object_id_type do_evaluate( const bond_create_offer_operation& op );
|
||||
object_id_type do_apply( const bond_create_offer_operation& op );
|
||||
};
|
||||
|
||||
class bond_cancel_offer_evaluator : public evaluator<bond_cancel_offer_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef bond_cancel_offer_operation operation_type;
|
||||
|
||||
object_id_type do_evaluate( const bond_cancel_offer_operation& op );
|
||||
object_id_type do_apply( const bond_cancel_offer_operation& op );
|
||||
|
||||
const bond_offer_object* _offer = nullptr;
|
||||
};
|
||||
|
||||
class bond_accept_offer_evaluator : public evaluator<bond_accept_offer_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef bond_accept_offer_operation operation_type;
|
||||
|
||||
object_id_type do_evaluate( const bond_accept_offer_operation& op );
|
||||
object_id_type do_apply( const bond_accept_offer_operation& op );
|
||||
|
||||
const bond_offer_object* _offer = nullptr;
|
||||
asset _fill_amount;
|
||||
};
|
||||
|
||||
class bond_claim_collateral_evaluator : public evaluator<bond_claim_collateral_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef bond_claim_collateral_operation operation_type;
|
||||
|
||||
object_id_type do_evaluate( const bond_claim_collateral_operation& op );
|
||||
object_id_type do_apply( const bond_claim_collateral_operation& op );
|
||||
|
||||
const bond_object* _bond = nullptr;
|
||||
asset _interest_due;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#pragma once
|
||||
#include <graphene/chain/authority.hpp>
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @ingroup object
|
||||
*/
|
||||
class bond_object : public graphene::db::abstract_object<bond_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = bond_object_type;
|
||||
|
||||
asset_id_type collateral_type()const { return collateral.asset_id; }
|
||||
|
||||
account_id_type borrower;
|
||||
account_id_type lender;
|
||||
asset borrowed;
|
||||
/** if collateral is the core asset, then voting rights belong to the borrower
|
||||
* because the borrower is owner of the collateral until they default
|
||||
*/
|
||||
asset collateral;
|
||||
uint16_t interest_apr = 0;
|
||||
time_point_sec start_date;
|
||||
/** after this date the lender can collect the collateral at will or let it float */
|
||||
time_point_sec due_date;
|
||||
/** the loan cannot be paid off before this date */
|
||||
time_point_sec earliest_payoff_date;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup object
|
||||
*/
|
||||
class bond_offer_object : public graphene::db::abstract_object<bond_offer_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = bond_offer_object_type;
|
||||
|
||||
asset_id_type asset_type()const { return amount.asset_id; }
|
||||
|
||||
account_id_type offered_by_account;
|
||||
bool offer_to_borrow = false; // Offer to borrow if true, and offer to lend otherwise
|
||||
asset amount;
|
||||
share_type min_match; ///< asset type same as ammount.asset_id
|
||||
price collateral_rate;
|
||||
uint32_t min_loan_period_sec = 0;
|
||||
uint32_t loan_period_sec = 0;
|
||||
uint16_t interest_apr = 0;
|
||||
};
|
||||
|
||||
struct by_borrower;
|
||||
struct by_lender;
|
||||
struct by_offerer;
|
||||
struct by_collateral; /// needed for blackswan resolution
|
||||
struct by_asset; /// needed for blackswan resolution
|
||||
|
||||
typedef multi_index_container<
|
||||
bond_object,
|
||||
indexed_by<
|
||||
hashed_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||
ordered_non_unique< tag<by_borrower>, member<bond_object, account_id_type, &bond_object::borrower> >,
|
||||
ordered_non_unique< tag<by_lender>, member<bond_object, account_id_type, &bond_object::lender> >,
|
||||
hashed_non_unique< tag<by_collateral>, const_mem_fun<bond_object, asset_id_type, &bond_object::collateral_type> >
|
||||
>
|
||||
> bond_object_multi_index_type;
|
||||
|
||||
typedef generic_index<bond_object, bond_object_multi_index_type> bond_index;
|
||||
|
||||
/**
|
||||
* Todo: consider adding index of tuple<collateral_type,loan_asset_type,interest_rate>
|
||||
* Todo: consider adding index of tuple<collateral_type,loan_asset_type,period>
|
||||
*/
|
||||
typedef multi_index_container<
|
||||
bond_offer_object,
|
||||
indexed_by<
|
||||
hashed_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||
ordered_non_unique< tag<by_offerer>, member<bond_offer_object, account_id_type, &bond_offer_object::offered_by_account> >,
|
||||
hashed_non_unique< tag<by_asset>, const_mem_fun<bond_offer_object, asset_id_type, &bond_offer_object::asset_type> >
|
||||
>
|
||||
> bond_offer_object_multi_index_type;
|
||||
|
||||
typedef generic_index<bond_offer_object, bond_offer_object_multi_index_type> bond_offer_index;
|
||||
|
||||
}} // graphene::chain
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::bond_object, (graphene::db::object),
|
||||
(borrower)(lender)(borrowed)(collateral)(interest_apr)(start_date)(due_date)(earliest_payoff_date) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::bond_offer_object, (graphene::db::object), (offered_by_account)(offer_to_borrow)(amount)(min_match)(collateral_rate)(min_loan_period_sec)(loan_period_sec)(interest_apr) )
|
||||
|
|
@ -1248,123 +1248,6 @@ namespace graphene { namespace chain {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*
|
||||
* Bond offers are objects that exist on the blockchain and can be
|
||||
* filled in full or in part by someone using the accept_bond_offer
|
||||
* operation. When the offer is accepted a new bond_object is
|
||||
* created that defines the terms of the loan.
|
||||
*
|
||||
* @return bond_offer_id
|
||||
*/
|
||||
struct bond_create_offer_operation
|
||||
{
|
||||
asset fee;
|
||||
account_id_type creator;
|
||||
bool offer_to_borrow = false; ///< Offer to borrow if true, and offer to lend otherwise
|
||||
asset amount; ///< Amount to lend or secure depending on above
|
||||
share_type min_match; ///< asset id same as amount.asset_id and sets the minimum match that will be accepted
|
||||
price collateral_rate; ///< To derive amount of collateral or principle based on above
|
||||
/** after this time the lender can let the loan float or collect the collateral at will */
|
||||
uint32_t min_loan_period_sec = 0; ///< the earliest the loan may be paid off
|
||||
uint32_t loan_period_sec = 0;
|
||||
uint16_t interest_apr = 0; ///< MAX_INTEREST_APR == 100% and is max value
|
||||
|
||||
account_id_type fee_payer()const { return creator; }
|
||||
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const;
|
||||
void validate()const;
|
||||
share_type calculate_fee( const fee_schedule_type& k )const;
|
||||
void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const
|
||||
{
|
||||
acc.adjust( fee_payer(), -fee );
|
||||
acc.adjust( creator, -amount );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
* Subtracts refund from bond_offer.amount and frees bond_offer if refund == bond_offer.amount
|
||||
*/
|
||||
struct bond_cancel_offer_operation
|
||||
{
|
||||
asset fee;
|
||||
account_id_type creator;
|
||||
bond_offer_id_type offer_id;
|
||||
asset refund;
|
||||
|
||||
account_id_type fee_payer()const { return creator; }
|
||||
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const;
|
||||
void validate()const;
|
||||
share_type calculate_fee( const fee_schedule_type& k )const;
|
||||
void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const
|
||||
{
|
||||
acc.adjust( fee_payer(), -fee );
|
||||
acc.adjust( creator, refund );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
* @return new bond_id
|
||||
*/
|
||||
struct bond_accept_offer_operation
|
||||
{
|
||||
asset fee;
|
||||
account_id_type claimer;
|
||||
account_id_type lender;
|
||||
account_id_type borrower; ///< included in case of offer to borrow, because borrower will receive funds
|
||||
bond_offer_id_type offer_id;
|
||||
asset amount_borrowed; ///< should equal amount_collateral * offer_id->collateral_rate
|
||||
asset amount_collateral; ///< should equal amount_borrowed * offer_id->collateral_rate
|
||||
|
||||
account_id_type fee_payer()const { return claimer; }
|
||||
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const;
|
||||
void validate()const;
|
||||
share_type calculate_fee( const fee_schedule_type& k )const;
|
||||
void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const
|
||||
{
|
||||
acc.adjust( fee_payer(), -fee );
|
||||
if( claimer == lender )
|
||||
acc.adjust( claimer, -amount_borrowed );
|
||||
else // claimer == borrower
|
||||
acc.adjust( claimer, -amount_collateral );
|
||||
acc.adjust( borrower, amount_borrowed );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
* After the loan period the lender can claim
|
||||
* the collateral, prior to the loan period expiring
|
||||
* the borrower can claim it by paying off the loan
|
||||
*/
|
||||
struct bond_claim_collateral_operation
|
||||
{
|
||||
asset fee;
|
||||
account_id_type claimer; ///< must be bond_id->lender or bond_id->borrower
|
||||
account_id_type lender; ///< must be bond_id->lender
|
||||
bond_id_type bond_id;
|
||||
asset payoff_amount;
|
||||
|
||||
/** the borrower can claim a percentage of the collateral propotional to the
|
||||
* percentage of the debt+interest that was paid off
|
||||
*/
|
||||
asset collateral_claimed;
|
||||
|
||||
account_id_type fee_payer()const { return claimer; }
|
||||
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const;
|
||||
void validate()const;
|
||||
share_type calculate_fee( const fee_schedule_type& k )const;
|
||||
void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const
|
||||
{
|
||||
acc.adjust( fee_payer(), -fee );
|
||||
acc.adjust( claimer, -payoff_amount );
|
||||
acc.adjust( claimer, collateral_claimed );
|
||||
acc.adjust( lender, payoff_amount );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a vesting balance.
|
||||
* @ingroup operations
|
||||
|
|
@ -1544,10 +1427,6 @@ namespace graphene { namespace chain {
|
|||
global_parameters_update_operation,
|
||||
vesting_balance_create_operation,
|
||||
vesting_balance_withdraw_operation,
|
||||
bond_create_offer_operation,
|
||||
bond_cancel_offer_operation,
|
||||
bond_accept_offer_operation,
|
||||
bond_claim_collateral_operation,
|
||||
worker_create_operation,
|
||||
custom_operation
|
||||
> operation;
|
||||
|
|
@ -1776,11 +1655,6 @@ FC_REFLECT( graphene::chain::withdraw_permission_claim_operation, (fee)(withdraw
|
|||
FC_REFLECT( graphene::chain::withdraw_permission_delete_operation, (fee)(withdraw_from_account)(authorized_account)
|
||||
(withdrawal_permission) )
|
||||
|
||||
FC_REFLECT( graphene::chain::bond_create_offer_operation, (fee)(creator)(offer_to_borrow)(amount)(min_match)(collateral_rate)(min_loan_period_sec)(loan_period_sec)(interest_apr) )
|
||||
FC_REFLECT( graphene::chain::bond_cancel_offer_operation, (fee)(creator)(offer_id)(refund) )
|
||||
FC_REFLECT( graphene::chain::bond_accept_offer_operation, (fee)(claimer)(lender)(borrower)(offer_id)(amount_borrowed)(amount_collateral) )
|
||||
FC_REFLECT( graphene::chain::bond_claim_collateral_operation, (fee)(claimer)(lender)(bond_id)(payoff_amount)(collateral_claimed) )
|
||||
|
||||
FC_REFLECT( graphene::chain::vesting_balance_create_operation, (fee)(creator)(owner)(amount)(vesting_seconds) )
|
||||
FC_REFLECT( graphene::chain::vesting_balance_withdraw_operation, (fee)(vesting_balance)(owner)(amount) )
|
||||
|
||||
|
|
|
|||
|
|
@ -114,8 +114,6 @@ namespace graphene { namespace chain {
|
|||
proposal_object_type,
|
||||
operation_history_object_type,
|
||||
withdraw_permission_object_type,
|
||||
bond_offer_object_type,
|
||||
bond_object_type,
|
||||
vesting_balance_object_type,
|
||||
worker_object_type,
|
||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||
|
|
@ -160,8 +158,6 @@ namespace graphene { namespace chain {
|
|||
class proposal_object;
|
||||
class operation_history_object;
|
||||
class withdraw_permission_object;
|
||||
class bond_object;
|
||||
class bond_offer_object;
|
||||
class vesting_balance_object;
|
||||
class witness_schedule_object;
|
||||
class worker_object;
|
||||
|
|
@ -179,8 +175,6 @@ namespace graphene { namespace chain {
|
|||
typedef object_id< protocol_ids, proposal_object_type, proposal_object> proposal_id_type;
|
||||
typedef object_id< protocol_ids, operation_history_object_type, operation_history_object> operation_history_id_type;
|
||||
typedef object_id< protocol_ids, withdraw_permission_object_type,withdraw_permission_object> withdraw_permission_id_type;
|
||||
typedef object_id< protocol_ids, bond_offer_object_type, bond_offer_object> bond_offer_id_type;
|
||||
typedef object_id< protocol_ids, bond_object_type, bond_object> bond_id_type;
|
||||
typedef object_id< protocol_ids, vesting_balance_object_type, vesting_balance_object> vesting_balance_id_type;
|
||||
typedef object_id< protocol_ids, worker_object_type, worker_object> worker_id_type;
|
||||
|
||||
|
|
@ -379,10 +373,6 @@ namespace graphene { namespace chain {
|
|||
uint32_t membership_annual_fee; ///< the annual cost of a membership subscription
|
||||
uint32_t membership_lifetime_fee; ///< the cost to upgrade to a lifetime member
|
||||
uint32_t withdraw_permission_update_fee; ///< the cost to create/update a withdraw permission
|
||||
uint32_t create_bond_offer_fee;
|
||||
uint32_t cancel_bond_offer_fee;
|
||||
uint32_t accept_bond_offer_fee;
|
||||
uint32_t claim_bond_collateral_fee;
|
||||
uint32_t vesting_balance_create_fee;
|
||||
uint32_t vesting_balance_withdraw_fee;
|
||||
uint32_t global_settle_fee;
|
||||
|
|
@ -503,8 +493,6 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
|
|||
(proposal_object_type)
|
||||
(operation_history_object_type)
|
||||
(withdraw_permission_object_type)
|
||||
(bond_offer_object_type)
|
||||
(bond_object_type)
|
||||
(vesting_balance_object_type)
|
||||
(worker_object_type)
|
||||
(OBJECT_TYPE_COUNT)
|
||||
|
|
@ -559,10 +547,6 @@ FC_REFLECT( graphene::chain::fee_schedule_type,
|
|||
(membership_annual_fee)
|
||||
(membership_lifetime_fee)
|
||||
(withdraw_permission_update_fee)
|
||||
(create_bond_offer_fee)
|
||||
(cancel_bond_offer_fee)
|
||||
(accept_bond_offer_fee)
|
||||
(claim_bond_collateral_fee)
|
||||
(vesting_balance_create_fee)
|
||||
(vesting_balance_withdraw_fee)
|
||||
(global_settle_fee)
|
||||
|
|
@ -609,8 +593,6 @@ FC_REFLECT_TYPENAME( graphene::chain::custom_id_type )
|
|||
FC_REFLECT_TYPENAME( graphene::chain::proposal_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::operation_history_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::withdraw_permission_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::bond_offer_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::bond_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::vesting_balance_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::worker_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::relative_key_id_type )
|
||||
|
|
|
|||
|
|
@ -804,77 +804,6 @@ share_type custom_operation::calculate_fee( const fee_schedule_type& k )const
|
|||
return (data.size() * k.data_fee)/1024;
|
||||
}
|
||||
|
||||
void bond_create_offer_operation::get_required_auth( flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>& )const
|
||||
{
|
||||
active_auth_set.insert( creator );
|
||||
}
|
||||
|
||||
void bond_create_offer_operation::validate()const
|
||||
{ try {
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount.amount > 0 );
|
||||
collateral_rate.validate();
|
||||
FC_ASSERT( (amount * collateral_rate).amount > 0 );
|
||||
FC_ASSERT( min_loan_period_sec > 0 );
|
||||
FC_ASSERT( loan_period_sec >= min_loan_period_sec );
|
||||
FC_ASSERT( interest_apr <= GRAPHENE_MAX_INTEREST_APR );
|
||||
} FC_CAPTURE_AND_RETHROW((*this)) }
|
||||
|
||||
share_type bond_create_offer_operation::calculate_fee( const fee_schedule_type& schedule )const
|
||||
{
|
||||
return schedule.create_bond_offer_fee;
|
||||
}
|
||||
|
||||
|
||||
void bond_cancel_offer_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const
|
||||
{
|
||||
active_auth_set.insert( creator );
|
||||
}
|
||||
void bond_cancel_offer_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount > 0 );
|
||||
FC_ASSERT( refund.amount > 0 );
|
||||
}
|
||||
share_type bond_cancel_offer_operation::calculate_fee( const fee_schedule_type& k )const
|
||||
{
|
||||
return k.cancel_bond_offer_fee;
|
||||
}
|
||||
|
||||
void bond_accept_offer_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const
|
||||
{
|
||||
active_auth_set.insert( claimer );
|
||||
}
|
||||
|
||||
void bond_accept_offer_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount > 0 );
|
||||
(amount_collateral / amount_borrowed).validate();
|
||||
FC_ASSERT( claimer == borrower || claimer == lender );
|
||||
FC_ASSERT( borrower != lender );
|
||||
}
|
||||
|
||||
share_type bond_accept_offer_operation::calculate_fee( const fee_schedule_type& k )const
|
||||
{
|
||||
return k.accept_bond_offer_fee;
|
||||
}
|
||||
void bond_claim_collateral_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const
|
||||
{
|
||||
active_auth_set.insert( claimer );
|
||||
}
|
||||
|
||||
void bond_claim_collateral_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount > 0 );
|
||||
FC_ASSERT(payoff_amount.amount >= 0 );
|
||||
FC_ASSERT(collateral_claimed.amount >= 0 );
|
||||
FC_ASSERT( payoff_amount.asset_id != collateral_claimed.asset_id );
|
||||
}
|
||||
|
||||
share_type bond_claim_collateral_operation::calculate_fee( const fee_schedule_type& k )const
|
||||
{
|
||||
return k.claim_bond_collateral_fee;
|
||||
}
|
||||
|
||||
void worker_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
|
||||
{
|
||||
active_auth_set.insert(owner);
|
||||
|
|
|
|||
|
|
@ -232,18 +232,6 @@ struct operation_get_impacted_accounts
|
|||
_impacted.insert( account_id_type() );
|
||||
}
|
||||
|
||||
void operator()( const bond_create_offer_operation& o )const { }
|
||||
void operator()( const bond_cancel_offer_operation& o )const { }
|
||||
void operator()( const bond_accept_offer_operation& o )const {
|
||||
_impacted.insert( o.borrower );
|
||||
_impacted.insert( o.lender );
|
||||
}
|
||||
void operator()( const bond_claim_collateral_operation& o )const
|
||||
{
|
||||
_impacted.insert( o.lender );
|
||||
_impacted.insert( o.claimer );
|
||||
}
|
||||
|
||||
void operator()( const vesting_balance_create_operation& o )const
|
||||
{
|
||||
_impacted.insert( o.creator );
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/operation_history_object.hpp>
|
||||
#include <graphene/chain/withdraw_permission_object.hpp>
|
||||
#include <graphene/chain/bond_object.hpp>
|
||||
|
||||
using namespace fc;
|
||||
using namespace graphene::chain;
|
||||
|
|
@ -87,10 +86,6 @@ object* create_object( const variant& v )
|
|||
return create_object_of_type< operation_history_object >( v );
|
||||
case withdraw_permission_object_type:
|
||||
return create_object_of_type< withdraw_permission_object >( v );
|
||||
case bond_offer_object_type:
|
||||
return create_object_of_type< bond_offer_object >( v );
|
||||
case bond_object_type:
|
||||
return create_object_of_type< bond_object >( v );
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/bond_object.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
#include <graphene/chain/withdraw_permission_object.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/bond_object.hpp>
|
||||
#include <graphene/chain/delegate_object.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
#include <graphene/chain/short_order_object.hpp>
|
||||
|
|
@ -151,12 +150,6 @@ void database_fixture::verify_asset_supplies( )const
|
|||
{
|
||||
total_balances[asset_id_type()] += witness_obj.accumulated_income;
|
||||
}
|
||||
for( const bond_offer_object& bond_offer : db.get_index_type<bond_offer_index>().indices() )
|
||||
{
|
||||
total_balances[ bond_offer.amount.asset_id ] += bond_offer.amount.amount;
|
||||
if( bond_offer.amount.asset_id == asset_id_type() )
|
||||
core_in_orders += bond_offer.amount.amount;
|
||||
}
|
||||
for( const vesting_balance_object& vbo : db.get_index_type< simple_index<vesting_balance_object> >() )
|
||||
total_balances[ vbo.balance.asset_id ] += vbo.balance.amount;
|
||||
|
||||
|
|
|
|||
|
|
@ -2080,7 +2080,6 @@ BOOST_AUTO_TEST_CASE( margin_call_black_swan )
|
|||
* 2) Short Orders for BitAsset backed by BitUSD
|
||||
* 3) Call Orders for BitAsset backed by BitUSD
|
||||
* 4) Issuer Fees
|
||||
* 5) Bond Market Collateral
|
||||
*
|
||||
* This test should fail until the black swan handling code can
|
||||
* perform a recursive blackswan for any other BitAssets that use
|
||||
|
|
@ -2138,69 +2137,6 @@ BOOST_AUTO_TEST_CASE( unimp_transfer_cashback_test )
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( bond_create_offer_test )
|
||||
{ try {
|
||||
bond_create_offer_operation op;
|
||||
op.fee = asset( 0, 0 );
|
||||
op.creator = account_id_type();
|
||||
op.amount = asset( 1, 0 );
|
||||
op.collateral_rate = price( asset( 1, 0 ), asset( 1, 1 ) );
|
||||
op.min_loan_period_sec = 1;
|
||||
op.loan_period_sec = 1;
|
||||
|
||||
// Fee must be non-negative
|
||||
REQUIRE_OP_VALIDATION_SUCCESS( op, fee, asset( 1, 0 ) );
|
||||
REQUIRE_OP_VALIDATION_SUCCESS( op, fee, asset( 0, 0 ) );
|
||||
REQUIRE_OP_VALIDATION_FAILURE( op, fee, asset( -1, 0 ) );
|
||||
|
||||
// Amount must be positive
|
||||
REQUIRE_OP_VALIDATION_SUCCESS( op, amount, asset( 1, 0 ) );
|
||||
REQUIRE_OP_VALIDATION_FAILURE( op, amount, asset( 0, 0 ) );
|
||||
REQUIRE_OP_VALIDATION_FAILURE( op, amount, asset( -1, 0 ) );
|
||||
|
||||
// Collateral rate must be valid
|
||||
REQUIRE_OP_VALIDATION_SUCCESS( op, collateral_rate, price( asset( 1, 0 ), asset( 1, 1 ) ) );
|
||||
REQUIRE_OP_VALIDATION_FAILURE( op, collateral_rate, price( asset( 0, 0 ), asset( 1, 1 ) ) );
|
||||
REQUIRE_OP_VALIDATION_FAILURE( op, collateral_rate, price( asset( 1, 0 ), asset( 0, 1 ) ) );
|
||||
REQUIRE_OP_VALIDATION_FAILURE( op, collateral_rate, price( asset( 1, 0 ), asset( 1, 0 ) ) );
|
||||
|
||||
// Min loan period must be at least 1 sec
|
||||
REQUIRE_OP_VALIDATION_SUCCESS( op, min_loan_period_sec, 1 );
|
||||
REQUIRE_OP_VALIDATION_FAILURE( op, min_loan_period_sec, 0 );
|
||||
|
||||
// Loan period must be greater than min load period
|
||||
REQUIRE_OP_VALIDATION_SUCCESS( op, loan_period_sec, op.min_loan_period_sec + 1 );
|
||||
REQUIRE_OP_VALIDATION_FAILURE( op, loan_period_sec, 0 );
|
||||
|
||||
// Interest APR cannot be greater than max
|
||||
REQUIRE_OP_VALIDATION_FAILURE( op, interest_apr, GRAPHENE_MAX_INTEREST_APR + 1 );
|
||||
REQUIRE_OP_VALIDATION_SUCCESS( op, interest_apr, GRAPHENE_MAX_INTEREST_APR );
|
||||
REQUIRE_OP_VALIDATION_SUCCESS( op, interest_apr, 0 );
|
||||
|
||||
// Setup world state we will need to test actual evaluation
|
||||
INVOKE( create_uia );
|
||||
const auto& test_asset = get_asset( "TEST" );
|
||||
const auto& nathan_account = create_account( "nathan" );
|
||||
transfer( account_id_type()( db ), nathan_account, asset( 1, 0 ) );
|
||||
|
||||
op.creator = nathan_account.get_id();
|
||||
op.collateral_rate.quote.asset_id = test_asset.get_id();
|
||||
trx.operations.emplace_back( op );
|
||||
|
||||
// Insufficient funds in creator account
|
||||
REQUIRE_THROW_WITH_VALUE( op, creator, account_id_type( 1 ) );
|
||||
|
||||
// Insufficient principle
|
||||
REQUIRE_THROW_WITH_VALUE( op, amount, asset( 2, 0 ) );
|
||||
|
||||
// Insufficient collateral
|
||||
op.offer_to_borrow = true;
|
||||
REQUIRE_THROW_WITH_VALUE( op, amount, asset( 1, test_asset.get_id() ) );
|
||||
|
||||
// This op should be fully valid
|
||||
REQUIRE_OP_EVALUATION_SUCCESS( op, offer_to_borrow, false );
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_AUTO_TEST_CASE( vesting_balance_create_test )
|
||||
{ try {
|
||||
INVOKE( create_uia );
|
||||
|
|
|
|||
Loading…
Reference in a new issue