Merge pull request #183 from peerplays-network/son_vesting
Son vesting balance implementation
This commit is contained in:
commit
412177964c
10 changed files with 172 additions and 31 deletions
|
|
@ -232,8 +232,10 @@
|
|||
#define TOURNAMENT_MAX_START_TIME_IN_FUTURE (60*60*24*7*4) // 1 month
|
||||
#define TOURNAMENT_MAX_START_DELAY (60*60*24*7) // 1 week
|
||||
#define MIN_SON_MEMBER_COUNT 15
|
||||
#define SON_VESTING_AMOUNT (50*GRAPHENE_BLOCKCHAIN_PRECISION) // 50 PPY
|
||||
#define SON_VESTING_PERIOD (60*60*24*30) // 2 days
|
||||
#define MIN_SON_PAY_DAILY_MAX (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(200))
|
||||
#define SWEEPS_DEFAULT_DISTRIBUTION_PERCENTAGE (2*GRAPHENE_1_PERCENT)
|
||||
#define SWEEPS_DEFAULT_DISTRIBUTION_ASSET (graphene::chain::asset_id_type(0))
|
||||
#define SWEEPS_VESTING_BALANCE_MULTIPLIER 100000000
|
||||
#define SWEEPS_ACCUMULATOR_ACCOUNT (graphene::chain::account_id_type(0))
|
||||
#define MIN_SON_PAY_DAILY_MAX (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(200))
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <fc/smart_ref_fwd.hpp>
|
||||
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
|
||||
namespace graphene { namespace chain { struct fee_schedule; } }
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
|
@ -41,6 +43,8 @@ namespace graphene { namespace chain {
|
|||
optional< uint16_t > sweeps_distribution_percentage;
|
||||
optional< asset_id_type > sweeps_distribution_asset;
|
||||
optional< account_id_type > sweeps_vesting_accumulator_account;
|
||||
optional < uint32_t > son_vesting_amount;
|
||||
optional < uint32_t > son_vesting_period;
|
||||
optional < uint32_t > son_pay_daily_max;
|
||||
};
|
||||
|
||||
|
|
@ -125,6 +129,11 @@ namespace graphene { namespace chain {
|
|||
inline uint16_t son_count()const {
|
||||
return extensions.value.son_count.valid() ? *extensions.value.son_count : MIN_SON_MEMBER_COUNT;
|
||||
}
|
||||
inline uint32_t son_vesting_amount()const {
|
||||
return extensions.value.son_vesting_amount.valid() ? *extensions.value.son_vesting_amount : SON_VESTING_AMOUNT; /// current period start date
|
||||
}
|
||||
inline uint32_t son_vesting_period()const {
|
||||
return extensions.value.son_vesting_period.valid() ? *extensions.value.son_vesting_period : SON_VESTING_PERIOD; /// current period start date
|
||||
inline uint16_t son_pay_daily_max()const {
|
||||
return extensions.value.son_pay_daily_max.valid() ? *extensions.value.son_pay_daily_max : MIN_SON_PAY_DAILY_MAX;
|
||||
}
|
||||
|
|
@ -142,6 +151,8 @@ FC_REFLECT( graphene::chain::parameter_extension,
|
|||
(sweeps_distribution_percentage)
|
||||
(sweeps_distribution_asset)
|
||||
(sweeps_vesting_accumulator_account)
|
||||
(son_vesting_amount)
|
||||
(son_vesting_period)
|
||||
(son_pay_daily_max)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
enum class vesting_balance_type { normal, gpos, son };
|
||||
|
||||
struct linear_vesting_policy_initializer
|
||||
{
|
||||
|
|
@ -42,9 +44,10 @@ namespace graphene { namespace chain {
|
|||
cdd_vesting_policy_initializer( uint32_t vest_sec = 0, fc::time_point_sec sc = fc::time_point_sec() ):start_claim(sc),vesting_seconds(vest_sec){}
|
||||
};
|
||||
|
||||
typedef fc::static_variant<linear_vesting_policy_initializer, cdd_vesting_policy_initializer> vesting_policy_initializer;
|
||||
|
||||
struct dormant_vesting_policy_initializer {};
|
||||
|
||||
typedef fc::static_variant<linear_vesting_policy_initializer, cdd_vesting_policy_initializer,
|
||||
dormant_vesting_policy_initializer> vesting_policy_initializer;
|
||||
|
||||
/**
|
||||
* @brief Create a vesting balance.
|
||||
|
|
@ -72,6 +75,7 @@ namespace graphene { namespace chain {
|
|||
account_id_type owner; ///< Who is able to withdraw the balance
|
||||
asset amount;
|
||||
vesting_policy_initializer policy;
|
||||
vesting_balance_type balance_type;
|
||||
|
||||
account_id_type fee_payer()const { return creator; }
|
||||
void validate()const
|
||||
|
|
@ -112,9 +116,12 @@ namespace graphene { namespace chain {
|
|||
FC_REFLECT( graphene::chain::vesting_balance_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::vesting_balance_withdraw_operation::fee_parameters_type, (fee) )
|
||||
|
||||
FC_REFLECT( graphene::chain::vesting_balance_create_operation, (fee)(creator)(owner)(amount)(policy) )
|
||||
FC_REFLECT( graphene::chain::vesting_balance_create_operation, (fee)(creator)(owner)(amount)(policy)(balance_type) )
|
||||
FC_REFLECT( graphene::chain::vesting_balance_withdraw_operation, (fee)(vesting_balance)(owner)(amount) )
|
||||
|
||||
FC_REFLECT(graphene::chain::linear_vesting_policy_initializer, (begin_timestamp)(vesting_cliff_seconds)(vesting_duration_seconds) )
|
||||
FC_REFLECT(graphene::chain::cdd_vesting_policy_initializer, (start_claim)(vesting_seconds) )
|
||||
FC_REFLECT(graphene::chain::dormant_vesting_policy_initializer, )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::vesting_policy_initializer )
|
||||
|
||||
FC_REFLECT_ENUM( graphene::chain::vesting_balance_type, (normal)(gpos)(son) )
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/asset.hpp>
|
||||
#include <graphene/chain/protocol/vesting.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
|
|
@ -118,10 +119,32 @@ namespace graphene { namespace chain {
|
|||
void on_withdraw(const vesting_policy_context& ctx);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Cant withdraw anything while balance is in this policy.
|
||||
*
|
||||
* This policy is needed to register SON users where balance may be claimable only after
|
||||
* the SON object is deleted(plus a linear policy).
|
||||
* When deleting a SON member the dormant mode will be replaced by a linear policy.
|
||||
*
|
||||
* @note New funds may not be added to a dormant vesting balance.
|
||||
*/
|
||||
struct dormant_vesting_policy
|
||||
{
|
||||
asset get_allowed_withdraw(const vesting_policy_context& ctx)const;
|
||||
bool is_deposit_allowed(const vesting_policy_context& ctx)const;
|
||||
bool is_deposit_vested_allowed(const vesting_policy_context&)const { return false; }
|
||||
bool is_withdraw_allowed(const vesting_policy_context& ctx)const;
|
||||
void on_deposit(const vesting_policy_context& ctx);
|
||||
void on_deposit_vested(const vesting_policy_context&)
|
||||
{ FC_THROW( "May not deposit vested into a linear vesting balance." ); }
|
||||
void on_withdraw(const vesting_policy_context& ctx);
|
||||
};
|
||||
|
||||
typedef fc::static_variant<
|
||||
linear_vesting_policy,
|
||||
cdd_vesting_policy
|
||||
> vesting_policy;
|
||||
cdd_vesting_policy,
|
||||
dormant_vesting_policy
|
||||
> vesting_policy;
|
||||
|
||||
/**
|
||||
* Vesting balance object is a balance that is locked by the blockchain for a period of time.
|
||||
|
|
@ -140,6 +163,9 @@ namespace graphene { namespace chain {
|
|||
/// The vesting policy stores details on when funds vest, and controls when they may be withdrawn
|
||||
vesting_policy policy;
|
||||
|
||||
/// We can have 3 types of vesting, gpos, son and the rest
|
||||
vesting_balance_type balance_type = vesting_balance_type::normal;
|
||||
|
||||
vesting_balance_object() {}
|
||||
|
||||
asset_id_type get_asset_id() const { return balance.asset_id; }
|
||||
|
|
@ -219,10 +245,13 @@ FC_REFLECT(graphene::chain::cdd_vesting_policy,
|
|||
(coin_seconds_earned_last_update)
|
||||
)
|
||||
|
||||
FC_REFLECT(graphene::chain::dormant_vesting_policy, )
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::vesting_policy )
|
||||
|
||||
FC_REFLECT_DERIVED(graphene::chain::vesting_balance_object, (graphene::db::object),
|
||||
(owner)
|
||||
(balance)
|
||||
(policy)
|
||||
(balance_type)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -10,7 +11,9 @@ void_result create_son_evaluator::do_evaluate(const son_create_operation& op)
|
|||
{ try{
|
||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK");
|
||||
FC_ASSERT(db().get(op.owner_account).is_lifetime_member(), "Only Lifetime members may register a SON.");
|
||||
return void_result();
|
||||
FC_ASSERT(op.deposit(db()).policy.which() == vesting_policy::tag<dormant_vesting_policy>::value,
|
||||
"Deposit balance must have dormant vesting policy");
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
object_id_type create_son_evaluator::do_apply(const son_create_operation& op)
|
||||
|
|
@ -69,7 +72,19 @@ void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op)
|
|||
void_result delete_son_evaluator::do_apply(const son_delete_operation& op)
|
||||
{ try {
|
||||
const auto& idx = db().get_index_type<son_index>().indices().get<by_id>();
|
||||
db().remove(*idx.find(op.son_id));
|
||||
auto son = idx.find(op.son_id);
|
||||
if(son != idx.end()) {
|
||||
vesting_balance_object deposit = son->deposit(db());
|
||||
linear_vesting_policy new_vesting_policy;
|
||||
new_vesting_policy.begin_timestamp = db().head_block_time();
|
||||
new_vesting_policy.vesting_cliff_seconds = db().get_global_properties().parameters.son_vesting_period();
|
||||
|
||||
db().modify(son->deposit(db()), [&new_vesting_policy](vesting_balance_object &vbo) {
|
||||
vbo.policy = new_vesting_policy;
|
||||
});
|
||||
|
||||
db().remove(*son);
|
||||
}
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@ void_result vesting_balance_create_evaluator::do_evaluate( const vesting_balance
|
|||
FC_ASSERT( d.get_balance( creator_account.id, op.amount.asset_id ) >= op.amount );
|
||||
FC_ASSERT( !op.amount.asset_id(d).is_transfer_restricted() );
|
||||
|
||||
if(d.head_block_time() < HARDFORK_SON_TIME) // Todo: can be removed after gpos hf time pass
|
||||
FC_ASSERT( op.balance_type == vesting_balance_type::normal);
|
||||
|
||||
if(d.head_block_time() >= HARDFORK_SON_TIME && op.balance_type == vesting_balance_type::son) // Todo: hf check can be removed after pass
|
||||
FC_ASSERT( op.amount.amount >= d.get_global_properties().parameters.son_vesting_amount() );
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
|
@ -76,6 +82,11 @@ struct init_policy_visitor
|
|||
policy.coin_seconds_earned_last_update = now;
|
||||
p = policy;
|
||||
}
|
||||
void operator()( const dormant_vesting_policy_initializer& i )const
|
||||
{
|
||||
dormant_vesting_policy policy;
|
||||
p = policy;
|
||||
}
|
||||
};
|
||||
|
||||
object_id_type vesting_balance_create_evaluator::do_apply( const vesting_balance_create_operation& op )
|
||||
|
|
@ -92,10 +103,9 @@ object_id_type vesting_balance_create_evaluator::do_apply( const vesting_balance
|
|||
// If making changes to this logic, check if those changes should also be made there as well.
|
||||
obj.owner = op.owner;
|
||||
obj.balance = op.amount;
|
||||
obj.balance_type = op.balance_type;
|
||||
op.policy.visit( init_policy_visitor( obj.policy, op.amount.amount, now ) );
|
||||
} );
|
||||
|
||||
|
||||
return vbo.id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
|
|
|||
|
|
@ -157,6 +157,33 @@ bool cdd_vesting_policy::is_withdraw_allowed(const vesting_policy_context& ctx)c
|
|||
return (ctx.amount <= get_allowed_withdraw(ctx));
|
||||
}
|
||||
|
||||
asset dormant_vesting_policy::get_allowed_withdraw( const vesting_policy_context& ctx )const
|
||||
{
|
||||
share_type allowed_withdraw = 0;
|
||||
return asset( allowed_withdraw, ctx.balance.asset_id );
|
||||
}
|
||||
|
||||
void dormant_vesting_policy::on_deposit(const vesting_policy_context& ctx)
|
||||
{
|
||||
}
|
||||
|
||||
bool dormant_vesting_policy::is_deposit_allowed(const vesting_policy_context& ctx)const
|
||||
{
|
||||
return (ctx.amount.asset_id == ctx.balance.asset_id)
|
||||
&& sum_below_max_shares(ctx.amount, ctx.balance);
|
||||
}
|
||||
|
||||
void dormant_vesting_policy::on_withdraw(const vesting_policy_context& ctx)
|
||||
{
|
||||
}
|
||||
|
||||
bool dormant_vesting_policy::is_withdraw_allowed(const vesting_policy_context& ctx)const
|
||||
{
|
||||
return (ctx.amount.asset_id == ctx.balance.asset_id)
|
||||
&& (ctx.amount <= get_allowed_withdraw(ctx));
|
||||
}
|
||||
|
||||
|
||||
#define VESTING_VISITOR(NAME, MAYBE_CONST) \
|
||||
struct NAME ## _visitor \
|
||||
{ \
|
||||
|
|
|
|||
|
|
@ -1561,7 +1561,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_create_test )
|
|||
op.amount = test_asset.amount( 100 );
|
||||
//op.vesting_seconds = 60*60*24;
|
||||
op.policy = cdd_vesting_policy_initializer{ 60*60*24 };
|
||||
//op.balance_type == vesting_balance_type::unspecified;
|
||||
op.balance_type == vesting_balance_type::normal;
|
||||
|
||||
// Fee must be non-negative
|
||||
REQUIRE_OP_VALIDATION_SUCCESS( op, fee, core.amount(1) );
|
||||
|
|
@ -1581,7 +1581,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_create_test )
|
|||
|
||||
op.creator = alice_account.get_id();
|
||||
op.owner = alice_account.get_id();
|
||||
//op.balance_type = vesting_balance_type::unspecified;
|
||||
op.balance_type = vesting_balance_type::normal;
|
||||
|
||||
account_id_type nobody = account_id_type(1234);
|
||||
|
||||
|
|
@ -1652,7 +1652,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_withdraw_test )
|
|||
create_op.owner = owner;
|
||||
create_op.amount = amount;
|
||||
create_op.policy = cdd_vesting_policy_initializer(vesting_seconds);
|
||||
//create_op.balance_type = vesting_balance_type::unspecified;
|
||||
create_op.balance_type = vesting_balance_type::normal;
|
||||
tx.operations.push_back( create_op );
|
||||
set_expiration( db, tx );
|
||||
|
||||
|
|
|
|||
|
|
@ -1316,7 +1316,7 @@ BOOST_AUTO_TEST_CASE(zero_second_vbo)
|
|||
create_op.owner = alice_id;
|
||||
create_op.amount = asset(500);
|
||||
create_op.policy = pinit;
|
||||
//create_op.balance_type = vesting_balance_type::unspecified;
|
||||
create_op.balance_type = vesting_balance_type::normal;
|
||||
|
||||
signed_transaction create_tx;
|
||||
create_tx.operations.push_back( create_op );
|
||||
|
|
@ -1400,7 +1400,7 @@ BOOST_AUTO_TEST_CASE( vbo_withdraw_different )
|
|||
create_op.owner = alice_id;
|
||||
create_op.amount = asset(100, stuff_id);
|
||||
create_op.policy = pinit;
|
||||
//create_op.balance_type = vesting_balance_type::unspecified;
|
||||
create_op.balance_type = vesting_balance_type::normal;
|
||||
|
||||
signed_transaction create_tx;
|
||||
create_tx.operations.push_back( create_op );
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/son_evaluator.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
|
||||
using namespace graphene::chain;
|
||||
using namespace graphene::chain::test;
|
||||
|
|
@ -13,9 +14,6 @@ BOOST_FIXTURE_TEST_SUITE( son_operation_tests, database_fixture )
|
|||
|
||||
BOOST_AUTO_TEST_CASE( create_son_test ) {
|
||||
generate_blocks(HARDFORK_SON_TIME);
|
||||
while (db.head_block_time() <= HARDFORK_SON_TIME) {
|
||||
generate_block();
|
||||
}
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
|
|
@ -24,8 +22,8 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
|
|||
upgrade_to_lifetime_member(alice);
|
||||
upgrade_to_lifetime_member(bob);
|
||||
|
||||
transfer( committee_account, alice_id, asset( 100000 ) );
|
||||
transfer( committee_account, bob_id, asset( 100000 ) );
|
||||
transfer( committee_account, alice_id, asset( 1000*GRAPHENE_BLOCKCHAIN_PRECISION ) );
|
||||
transfer( committee_account, bob_id, asset( 1000*GRAPHENE_BLOCKCHAIN_PRECISION ) );
|
||||
|
||||
set_expiration(db, trx);
|
||||
std::string test_url = "https://create_son_test";
|
||||
|
|
@ -36,31 +34,51 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
|
|||
vesting_balance_create_operation op;
|
||||
op.creator = alice_id;
|
||||
op.owner = alice_id;
|
||||
op.amount = asset(10);
|
||||
//op.balance_type = vesting_balance_type::unspecified;
|
||||
op.amount = asset(10*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
op.balance_type = vesting_balance_type::son;
|
||||
op.policy = dormant_vesting_policy_initializer {};
|
||||
trx.operations.push_back(op);
|
||||
|
||||
// amount in the son balance need to be at least 50
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx ), fc::exception );
|
||||
|
||||
op.amount = asset(50*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
trx.clear();
|
||||
|
||||
trx.operations.push_back(op);
|
||||
set_expiration(db, trx);
|
||||
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
deposit = ptx.operation_results[0].get<object_id_type>();
|
||||
|
||||
auto deposit_vesting = db.get<vesting_balance_object>(ptx.operation_results[0].get<object_id_type>());
|
||||
|
||||
BOOST_CHECK_EQUAL(deposit(db).balance.amount.value, 50*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
auto now = db.head_block_time();
|
||||
BOOST_CHECK_EQUAL(deposit(db).is_withdraw_allowed(now, asset(50*GRAPHENE_BLOCKCHAIN_PRECISION)), false); // cant withdraw
|
||||
}
|
||||
// create payment vesting
|
||||
vesting_balance_id_type payment;
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
// create payment normal vesting
|
||||
vesting_balance_id_type payment ;
|
||||
{
|
||||
vesting_balance_create_operation op;
|
||||
op.creator = alice_id;
|
||||
op.owner = alice_id;
|
||||
op.amount = asset(10);
|
||||
//op.balance_type = vesting_balance_type::unspecified;
|
||||
op.amount = asset(1*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
op.balance_type = vesting_balance_type::normal;
|
||||
|
||||
op.validate();
|
||||
|
||||
trx.operations.push_back(op);
|
||||
set_expiration(db, trx);
|
||||
trx.validate();
|
||||
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
payment = ptx.operation_results[0].get<object_id_type>();
|
||||
}
|
||||
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
// alice became son
|
||||
{
|
||||
son_create_operation op;
|
||||
|
|
@ -112,10 +130,14 @@ BOOST_AUTO_TEST_CASE( update_son_test ) {
|
|||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( delete_son_test ) {
|
||||
|
||||
try {
|
||||
INVOKE(create_son_test);
|
||||
GET_ACTOR(alice);
|
||||
|
||||
auto deposit_vesting = db.get<vesting_balance_object>(vesting_balance_id_type(0));
|
||||
auto now = db.head_block_time();
|
||||
BOOST_CHECK_EQUAL(deposit_vesting.is_withdraw_allowed(now, asset(50)), false); // cant withdraw
|
||||
|
||||
{
|
||||
son_delete_operation op;
|
||||
op.owner_account = alice_id;
|
||||
|
|
@ -129,7 +151,25 @@ BOOST_AUTO_TEST_CASE( delete_son_test ) {
|
|||
|
||||
const auto& idx = db.get_index_type<son_index>().indices().get<by_account>();
|
||||
BOOST_REQUIRE( idx.empty() );
|
||||
|
||||
deposit_vesting = db.get<vesting_balance_object>(vesting_balance_id_type(0));
|
||||
BOOST_CHECK_EQUAL(deposit_vesting.policy.get<linear_vesting_policy>().vesting_cliff_seconds,
|
||||
db.get_global_properties().parameters.son_vesting_period()); // in linear policy
|
||||
|
||||
now = db.head_block_time();
|
||||
BOOST_CHECK_EQUAL(deposit_vesting.is_withdraw_allowed(now, asset(50)), false); // but still cant withdraw
|
||||
|
||||
generate_blocks(now + fc::seconds(db.get_global_properties().parameters.son_vesting_period()));
|
||||
generate_block();
|
||||
|
||||
deposit_vesting = db.get<vesting_balance_object>(vesting_balance_id_type(0));
|
||||
now = db.head_block_time();
|
||||
BOOST_CHECK_EQUAL(deposit_vesting.is_withdraw_allowed(now, asset(50)), true); // after 2 days withdraw is allowed
|
||||
}
|
||||
catch (fc::exception &e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
} }
|
||||
|
||||
BOOST_AUTO_TEST_CASE( update_delete_not_own ) { // fee payer needs to be the son object owner
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in a new issue