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_TIME_IN_FUTURE (60*60*24*7*4) // 1 month
|
||||||
#define TOURNAMENT_MAX_START_DELAY (60*60*24*7) // 1 week
|
#define TOURNAMENT_MAX_START_DELAY (60*60*24*7) // 1 week
|
||||||
#define MIN_SON_MEMBER_COUNT 15
|
#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_PERCENTAGE (2*GRAPHENE_1_PERCENT)
|
||||||
#define SWEEPS_DEFAULT_DISTRIBUTION_ASSET (graphene::chain::asset_id_type(0))
|
#define SWEEPS_DEFAULT_DISTRIBUTION_ASSET (graphene::chain::asset_id_type(0))
|
||||||
#define SWEEPS_VESTING_BALANCE_MULTIPLIER 100000000
|
#define SWEEPS_VESTING_BALANCE_MULTIPLIER 100000000
|
||||||
#define SWEEPS_ACCUMULATOR_ACCOUNT (graphene::chain::account_id_type(0))
|
#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 <graphene/chain/protocol/types.hpp>
|
||||||
#include <fc/smart_ref_fwd.hpp>
|
#include <fc/smart_ref_fwd.hpp>
|
||||||
|
|
||||||
|
#include <graphene/chain/hardfork.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace chain { struct fee_schedule; } }
|
namespace graphene { namespace chain { struct fee_schedule; } }
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
@ -41,6 +43,8 @@ namespace graphene { namespace chain {
|
||||||
optional< uint16_t > sweeps_distribution_percentage;
|
optional< uint16_t > sweeps_distribution_percentage;
|
||||||
optional< asset_id_type > sweeps_distribution_asset;
|
optional< asset_id_type > sweeps_distribution_asset;
|
||||||
optional< account_id_type > sweeps_vesting_accumulator_account;
|
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;
|
optional < uint32_t > son_pay_daily_max;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -125,6 +129,11 @@ namespace graphene { namespace chain {
|
||||||
inline uint16_t son_count()const {
|
inline uint16_t son_count()const {
|
||||||
return extensions.value.son_count.valid() ? *extensions.value.son_count : MIN_SON_MEMBER_COUNT;
|
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 {
|
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;
|
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_percentage)
|
||||||
(sweeps_distribution_asset)
|
(sweeps_distribution_asset)
|
||||||
(sweeps_vesting_accumulator_account)
|
(sweeps_vesting_accumulator_account)
|
||||||
|
(son_vesting_amount)
|
||||||
|
(son_vesting_period)
|
||||||
(son_pay_daily_max)
|
(son_pay_daily_max)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
enum class vesting_balance_type { normal, gpos, son };
|
||||||
|
|
||||||
struct linear_vesting_policy_initializer
|
struct linear_vesting_policy_initializer
|
||||||
{
|
{
|
||||||
/** while vesting begins on begin_timestamp, none may be claimed before vesting_cliff_seconds have passed */
|
/** while vesting begins on begin_timestamp, none may be claimed before vesting_cliff_seconds have passed */
|
||||||
|
|
@ -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){}
|
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.
|
* @brief Create a vesting balance.
|
||||||
|
|
@ -72,6 +75,7 @@ namespace graphene { namespace chain {
|
||||||
account_id_type owner; ///< Who is able to withdraw the balance
|
account_id_type owner; ///< Who is able to withdraw the balance
|
||||||
asset amount;
|
asset amount;
|
||||||
vesting_policy_initializer policy;
|
vesting_policy_initializer policy;
|
||||||
|
vesting_balance_type balance_type;
|
||||||
|
|
||||||
account_id_type fee_payer()const { return creator; }
|
account_id_type fee_payer()const { return creator; }
|
||||||
void validate()const
|
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_create_operation::fee_parameters_type, (fee) )
|
||||||
FC_REFLECT( graphene::chain::vesting_balance_withdraw_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::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::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::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_TYPENAME( graphene::chain::vesting_policy_initializer )
|
||||||
|
|
||||||
|
FC_REFLECT_ENUM( graphene::chain::vesting_balance_type, (normal)(gpos)(son) )
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <graphene/chain/protocol/asset.hpp>
|
#include <graphene/chain/protocol/asset.hpp>
|
||||||
|
#include <graphene/chain/protocol/vesting.hpp>
|
||||||
#include <graphene/db/object.hpp>
|
#include <graphene/db/object.hpp>
|
||||||
#include <graphene/db/generic_index.hpp>
|
#include <graphene/db/generic_index.hpp>
|
||||||
|
|
||||||
|
|
@ -118,10 +119,32 @@ namespace graphene { namespace chain {
|
||||||
void on_withdraw(const vesting_policy_context& ctx);
|
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<
|
typedef fc::static_variant<
|
||||||
linear_vesting_policy,
|
linear_vesting_policy,
|
||||||
cdd_vesting_policy
|
cdd_vesting_policy,
|
||||||
> vesting_policy;
|
dormant_vesting_policy
|
||||||
|
> vesting_policy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vesting balance object is a balance that is locked by the blockchain for a period of time.
|
* 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
|
/// The vesting policy stores details on when funds vest, and controls when they may be withdrawn
|
||||||
vesting_policy policy;
|
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() {}
|
vesting_balance_object() {}
|
||||||
|
|
||||||
asset_id_type get_asset_id() const { return balance.asset_id; }
|
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)
|
(coin_seconds_earned_last_update)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
FC_REFLECT(graphene::chain::dormant_vesting_policy, )
|
||||||
|
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::vesting_policy )
|
FC_REFLECT_TYPENAME( graphene::chain::vesting_policy )
|
||||||
|
|
||||||
FC_REFLECT_DERIVED(graphene::chain::vesting_balance_object, (graphene::db::object),
|
FC_REFLECT_DERIVED(graphene::chain::vesting_balance_object, (graphene::db::object),
|
||||||
(owner)
|
(owner)
|
||||||
(balance)
|
(balance)
|
||||||
(policy)
|
(policy)
|
||||||
|
(balance_type)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <graphene/chain/database.hpp>
|
#include <graphene/chain/database.hpp>
|
||||||
#include <graphene/chain/son_object.hpp>
|
#include <graphene/chain/son_object.hpp>
|
||||||
#include <graphene/chain/hardfork.hpp>
|
#include <graphene/chain/hardfork.hpp>
|
||||||
|
#include <graphene/chain/vesting_balance_object.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
|
@ -10,7 +11,9 @@ void_result create_son_evaluator::do_evaluate(const son_create_operation& op)
|
||||||
{ try{
|
{ try{
|
||||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK");
|
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.");
|
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) ) }
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
object_id_type create_son_evaluator::do_apply(const son_create_operation& 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)
|
void_result delete_son_evaluator::do_apply(const son_delete_operation& op)
|
||||||
{ try {
|
{ try {
|
||||||
const auto& idx = db().get_index_type<son_index>().indices().get<by_id>();
|
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();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
} 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( d.get_balance( creator_account.id, op.amount.asset_id ) >= op.amount );
|
||||||
FC_ASSERT( !op.amount.asset_id(d).is_transfer_restricted() );
|
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();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
|
@ -76,6 +82,11 @@ struct init_policy_visitor
|
||||||
policy.coin_seconds_earned_last_update = now;
|
policy.coin_seconds_earned_last_update = now;
|
||||||
p = policy;
|
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 )
|
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.
|
// If making changes to this logic, check if those changes should also be made there as well.
|
||||||
obj.owner = op.owner;
|
obj.owner = op.owner;
|
||||||
obj.balance = op.amount;
|
obj.balance = op.amount;
|
||||||
|
obj.balance_type = op.balance_type;
|
||||||
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;
|
return vbo.id;
|
||||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
} 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));
|
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) \
|
#define VESTING_VISITOR(NAME, MAYBE_CONST) \
|
||||||
struct NAME ## _visitor \
|
struct NAME ## _visitor \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
||||||
|
|
@ -1561,7 +1561,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_create_test )
|
||||||
op.amount = test_asset.amount( 100 );
|
op.amount = test_asset.amount( 100 );
|
||||||
//op.vesting_seconds = 60*60*24;
|
//op.vesting_seconds = 60*60*24;
|
||||||
op.policy = cdd_vesting_policy_initializer{ 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
|
// Fee must be non-negative
|
||||||
REQUIRE_OP_VALIDATION_SUCCESS( op, fee, core.amount(1) );
|
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.creator = alice_account.get_id();
|
||||||
op.owner = 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);
|
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.owner = owner;
|
||||||
create_op.amount = amount;
|
create_op.amount = amount;
|
||||||
create_op.policy = cdd_vesting_policy_initializer(vesting_seconds);
|
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 );
|
tx.operations.push_back( create_op );
|
||||||
set_expiration( db, tx );
|
set_expiration( db, tx );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1316,7 +1316,7 @@ BOOST_AUTO_TEST_CASE(zero_second_vbo)
|
||||||
create_op.owner = alice_id;
|
create_op.owner = alice_id;
|
||||||
create_op.amount = asset(500);
|
create_op.amount = asset(500);
|
||||||
create_op.policy = pinit;
|
create_op.policy = pinit;
|
||||||
//create_op.balance_type = vesting_balance_type::unspecified;
|
create_op.balance_type = vesting_balance_type::normal;
|
||||||
|
|
||||||
signed_transaction create_tx;
|
signed_transaction create_tx;
|
||||||
create_tx.operations.push_back( create_op );
|
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.owner = alice_id;
|
||||||
create_op.amount = asset(100, stuff_id);
|
create_op.amount = asset(100, stuff_id);
|
||||||
create_op.policy = pinit;
|
create_op.policy = pinit;
|
||||||
//create_op.balance_type = vesting_balance_type::unspecified;
|
create_op.balance_type = vesting_balance_type::normal;
|
||||||
|
|
||||||
signed_transaction create_tx;
|
signed_transaction create_tx;
|
||||||
create_tx.operations.push_back( create_op );
|
create_tx.operations.push_back( create_op );
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <graphene/chain/hardfork.hpp>
|
#include <graphene/chain/hardfork.hpp>
|
||||||
#include <graphene/chain/son_object.hpp>
|
#include <graphene/chain/son_object.hpp>
|
||||||
#include <graphene/chain/son_evaluator.hpp>
|
#include <graphene/chain/son_evaluator.hpp>
|
||||||
|
#include <graphene/chain/vesting_balance_object.hpp>
|
||||||
|
|
||||||
using namespace graphene::chain;
|
using namespace graphene::chain;
|
||||||
using namespace graphene::chain::test;
|
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 ) {
|
BOOST_AUTO_TEST_CASE( create_son_test ) {
|
||||||
generate_blocks(HARDFORK_SON_TIME);
|
generate_blocks(HARDFORK_SON_TIME);
|
||||||
while (db.head_block_time() <= HARDFORK_SON_TIME) {
|
|
||||||
generate_block();
|
|
||||||
}
|
|
||||||
generate_block();
|
generate_block();
|
||||||
set_expiration(db, trx);
|
set_expiration(db, trx);
|
||||||
|
|
||||||
|
|
@ -24,8 +22,8 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
|
||||||
upgrade_to_lifetime_member(alice);
|
upgrade_to_lifetime_member(alice);
|
||||||
upgrade_to_lifetime_member(bob);
|
upgrade_to_lifetime_member(bob);
|
||||||
|
|
||||||
transfer( committee_account, alice_id, asset( 100000 ) );
|
transfer( committee_account, alice_id, asset( 1000*GRAPHENE_BLOCKCHAIN_PRECISION ) );
|
||||||
transfer( committee_account, bob_id, asset( 100000 ) );
|
transfer( committee_account, bob_id, asset( 1000*GRAPHENE_BLOCKCHAIN_PRECISION ) );
|
||||||
|
|
||||||
set_expiration(db, trx);
|
set_expiration(db, trx);
|
||||||
std::string test_url = "https://create_son_test";
|
std::string test_url = "https://create_son_test";
|
||||||
|
|
@ -36,31 +34,51 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
|
||||||
vesting_balance_create_operation op;
|
vesting_balance_create_operation op;
|
||||||
op.creator = alice_id;
|
op.creator = alice_id;
|
||||||
op.owner = alice_id;
|
op.owner = alice_id;
|
||||||
op.amount = asset(10);
|
op.amount = asset(10*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||||
//op.balance_type = vesting_balance_type::unspecified;
|
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);
|
trx.operations.push_back(op);
|
||||||
set_expiration(db, trx);
|
|
||||||
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||||
trx.clear();
|
|
||||||
deposit = ptx.operation_results[0].get<object_id_type>();
|
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
|
generate_block();
|
||||||
vesting_balance_id_type payment;
|
set_expiration(db, trx);
|
||||||
|
|
||||||
|
// create payment normal vesting
|
||||||
|
vesting_balance_id_type payment ;
|
||||||
{
|
{
|
||||||
vesting_balance_create_operation op;
|
vesting_balance_create_operation op;
|
||||||
op.creator = alice_id;
|
op.creator = alice_id;
|
||||||
op.owner = alice_id;
|
op.owner = alice_id;
|
||||||
op.amount = asset(10);
|
op.amount = asset(1*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||||
//op.balance_type = vesting_balance_type::unspecified;
|
op.balance_type = vesting_balance_type::normal;
|
||||||
|
|
||||||
|
op.validate();
|
||||||
|
|
||||||
trx.operations.push_back(op);
|
trx.operations.push_back(op);
|
||||||
set_expiration(db, trx);
|
trx.validate();
|
||||||
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||||
trx.clear();
|
trx.clear();
|
||||||
payment = ptx.operation_results[0].get<object_id_type>();
|
payment = ptx.operation_results[0].get<object_id_type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generate_block();
|
||||||
|
set_expiration(db, trx);
|
||||||
|
|
||||||
// alice became son
|
// alice became son
|
||||||
{
|
{
|
||||||
son_create_operation op;
|
son_create_operation op;
|
||||||
|
|
@ -112,10 +130,14 @@ BOOST_AUTO_TEST_CASE( update_son_test ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( delete_son_test ) {
|
BOOST_AUTO_TEST_CASE( delete_son_test ) {
|
||||||
|
try {
|
||||||
INVOKE(create_son_test);
|
INVOKE(create_son_test);
|
||||||
GET_ACTOR(alice);
|
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;
|
son_delete_operation op;
|
||||||
op.owner_account = alice_id;
|
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>();
|
const auto& idx = db.get_index_type<son_index>().indices().get<by_account>();
|
||||||
BOOST_REQUIRE( idx.empty() );
|
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
|
BOOST_AUTO_TEST_CASE( update_delete_not_own ) { // fee payer needs to be the son object owner
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue