abstraction of dormant vesting policy
This commit is contained in:
parent
032c4c7a99
commit
76120a5b76
8 changed files with 27 additions and 86 deletions
|
|
@ -44,16 +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){}
|
||||
};
|
||||
|
||||
struct dormant_vesting_policy_initializer
|
||||
{
|
||||
/** none may be claimed if dormant is true, otherwise this is a linear policy */
|
||||
bool dormant = true;
|
||||
fc::time_point_sec begin_timestamp;
|
||||
uint32_t vesting_cliff_seconds = 0;
|
||||
uint32_t vesting_duration_seconds = 0;
|
||||
};
|
||||
struct dormant_vesting_policy_initializer {};
|
||||
|
||||
typedef fc::static_variant<linear_vesting_policy_initializer, cdd_vesting_policy_initializer, dormant_vesting_policy_initializer> 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.
|
||||
|
|
@ -127,7 +121,7 @@ FC_REFLECT( graphene::chain::vesting_balance_withdraw_operation, (fee)(vesting_b
|
|||
|
||||
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, (dormant)(begin_timestamp)(vesting_cliff_seconds)(vesting_duration_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) )
|
||||
|
|
|
|||
|
|
@ -120,28 +120,16 @@ namespace graphene { namespace chain {
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief Cant withdraw anything while dormant mode is true, linear policy after that changes.
|
||||
* @brief Cant withdraw anything while balance is in this policy.
|
||||
*
|
||||
* This vesting balance type is needed to register SON users where balance may be claimable only after
|
||||
* 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 change and the linear policy will became active.
|
||||
* 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
|
||||
{
|
||||
/// dormant mode flag indicates if we are in dormant mode or linear policy.
|
||||
bool dormant_mode = true;
|
||||
|
||||
/// This is the time at which funds begin vesting.
|
||||
fc::time_point_sec begin_timestamp;
|
||||
/// No amount may be withdrawn before this many seconds of the vesting period have elapsed.
|
||||
uint32_t vesting_cliff_seconds = 0;
|
||||
/// Duration of the vesting period, in seconds. Must be greater than 0 and greater than vesting_cliff_seconds.
|
||||
uint32_t vesting_duration_seconds = 0;
|
||||
/// The total amount of asset to vest.
|
||||
share_type begin_balance;
|
||||
|
||||
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; }
|
||||
|
|
@ -257,13 +245,7 @@ FC_REFLECT(graphene::chain::cdd_vesting_policy,
|
|||
(coin_seconds_earned_last_update)
|
||||
)
|
||||
|
||||
FC_REFLECT(graphene::chain::dormant_vesting_policy,
|
||||
(dormant_mode)
|
||||
(begin_timestamp)
|
||||
(vesting_cliff_seconds)
|
||||
(vesting_duration_seconds)
|
||||
(begin_balance)
|
||||
)
|
||||
FC_REFLECT(graphene::chain::dormant_vesting_policy, )
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::vesting_policy )
|
||||
|
||||
|
|
|
|||
|
|
@ -72,8 +72,7 @@ void_result delete_son_evaluator::do_apply(const son_delete_operation& op)
|
|||
auto son = idx.find(op.son_id);
|
||||
if(son != idx.end()) {
|
||||
vesting_balance_object deposit = son->deposit(db());
|
||||
dormant_vesting_policy new_vesting_policy;
|
||||
new_vesting_policy.dormant_mode = false;
|
||||
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();
|
||||
|
||||
|
|
|
|||
|
|
@ -85,11 +85,6 @@ struct init_policy_visitor
|
|||
void operator()( const dormant_vesting_policy_initializer& i )const
|
||||
{
|
||||
dormant_vesting_policy policy;
|
||||
policy.dormant_mode = i.dormant;
|
||||
policy.begin_timestamp = i.begin_timestamp;
|
||||
policy.vesting_cliff_seconds = i.vesting_cliff_seconds;
|
||||
policy.vesting_duration_seconds = i.vesting_duration_seconds;
|
||||
policy.begin_balance = init_balance;
|
||||
p = policy;
|
||||
}
|
||||
};
|
||||
|
|
@ -109,16 +104,7 @@ object_id_type vesting_balance_create_evaluator::do_apply( const vesting_balance
|
|||
obj.owner = op.owner;
|
||||
obj.balance = op.amount;
|
||||
obj.balance_type = op.balance_type;
|
||||
if(op.balance_type == vesting_balance_type::son)
|
||||
{
|
||||
const auto &gpo = d.get_global_properties();
|
||||
// forcing son dormant policy
|
||||
dormant_vesting_policy p;
|
||||
p.dormant_mode = true;
|
||||
obj.policy = p;
|
||||
}
|
||||
else
|
||||
op.policy.visit( init_policy_visitor( obj.policy, op.amount.amount, now ) );
|
||||
op.policy.visit( init_policy_visitor( obj.policy, op.amount.amount, now ) );
|
||||
} );
|
||||
return vbo.id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
|
|
|||
|
|
@ -160,33 +160,6 @@ bool cdd_vesting_policy::is_withdraw_allowed(const vesting_policy_context& ctx)c
|
|||
asset dormant_vesting_policy::get_allowed_withdraw( const vesting_policy_context& ctx )const
|
||||
{
|
||||
share_type allowed_withdraw = 0;
|
||||
|
||||
if( !dormant_mode && ctx.now > begin_timestamp)
|
||||
{
|
||||
const auto elapsed_seconds = (ctx.now - begin_timestamp).to_seconds();
|
||||
assert( elapsed_seconds > 0 );
|
||||
|
||||
if( elapsed_seconds >= vesting_cliff_seconds )
|
||||
{
|
||||
share_type total_vested = 0;
|
||||
if( elapsed_seconds < vesting_duration_seconds )
|
||||
{
|
||||
total_vested = (fc::uint128_t( begin_balance.value ) * elapsed_seconds / vesting_duration_seconds).to_uint64();
|
||||
}
|
||||
else
|
||||
{
|
||||
total_vested = begin_balance;
|
||||
}
|
||||
assert( total_vested >= 0 );
|
||||
|
||||
const share_type withdrawn_already = begin_balance - ctx.balance.amount;
|
||||
assert( withdrawn_already >= 0 );
|
||||
|
||||
allowed_withdraw = total_vested - withdrawn_already;
|
||||
assert( allowed_withdraw >= 0 );
|
||||
}
|
||||
}
|
||||
|
||||
return asset( allowed_withdraw, ctx.balance.asset_id );
|
||||
}
|
||||
|
||||
|
|
@ -210,6 +183,7 @@ bool dormant_vesting_policy::is_withdraw_allowed(const vesting_policy_context& c
|
|||
&& (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 );
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
|
|||
op.owner = alice_id;
|
||||
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
|
||||
|
|
@ -129,12 +130,13 @@ 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));
|
||||
BOOST_CHECK_EQUAL(deposit_vesting.policy.get<dormant_vesting_policy>().dormant_mode, true); // dormant while active
|
||||
auto now = db.head_block_time();
|
||||
BOOST_CHECK_EQUAL(deposit_vesting.is_withdraw_allowed(now, asset(50)), false); // cant withdraw
|
||||
|
||||
{
|
||||
son_delete_operation op;
|
||||
|
|
@ -151,10 +153,10 @@ BOOST_AUTO_TEST_CASE( delete_son_test ) {
|
|||
BOOST_REQUIRE( idx.empty() );
|
||||
|
||||
deposit_vesting = db.get<vesting_balance_object>(vesting_balance_id_type(0));
|
||||
BOOST_CHECK_EQUAL(deposit_vesting.policy.get<dormant_vesting_policy>().dormant_mode, false); // not sleeping anymore
|
||||
|
||||
auto now = db.head_block_time();
|
||||
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()));
|
||||
|
|
@ -164,6 +166,10 @@ BOOST_AUTO_TEST_CASE( delete_son_test ) {
|
|||
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