Scorum
withdraw_scorumpower_evaluator.cpp
Go to the documentation of this file.
2 
4 
10 
15 
16 namespace scorum {
17 namespace chain {
18 
20 {
21 public:
22  withdraw_scorumpower_impl(data_service_factory_i& services)
23  : _dprops_service(services.dynamic_global_property_service())
24  , _withdraw_scorumpower_service(services.withdraw_scorumpower_service())
25  , _lock_withdraw_sp_until_timestamp(services.genesis_state_service().get_lock_withdraw_sp_until_timestamp())
26  {
27  }
28 
29  template <typename FromObjectType> void do_apply(const FromObjectType& from_object, const asset& scorumpower)
30  {
31  FC_ASSERT(_dprops_service.head_block_time() > _lock_withdraw_sp_until_timestamp,
32  "Withdraw scorumpower operation is locked until ${t}.", ("t", _lock_withdraw_sp_until_timestamp));
33  FC_ASSERT(scorumpower.amount >= 0);
34 
35  asset vesting_withdraw_rate = asset(0, SP_SYMBOL);
36  if (_withdraw_scorumpower_service.is_exists(from_object.id))
37  {
38  vesting_withdraw_rate = _withdraw_scorumpower_service.get(from_object.id).vesting_withdraw_rate;
39  }
40 
41  if (scorumpower.amount == 0)
42  {
43  FC_ASSERT(vesting_withdraw_rate.amount != 0, "This operation would not change the vesting withdraw rate.");
44 
45  remove_withdraw_scorumpower(from_object);
46  }
47  else
48  {
49  // SCORUM: We have to decide whether we use 13 weeks vesting period or low it down
50  // 13 weeks = 1 quarter of a year
51  auto new_vesting_withdraw_rate = scorumpower / SCORUM_VESTING_WITHDRAW_INTERVALS;
52 
53  if (new_vesting_withdraw_rate.amount == 0)
54  new_vesting_withdraw_rate.amount = 1;
55 
56  auto lmbNewVesting = [&](withdraw_scorumpower_object& wv) {
57  wv.from_id = from_object.id;
58  wv.vesting_withdraw_rate = new_vesting_withdraw_rate;
59  wv.next_vesting_withdrawal
60  = _dprops_service.head_block_time() + fc::seconds(SCORUM_VESTING_WITHDRAW_INTERVAL_SECONDS);
61  wv.to_withdraw = scorumpower;
62  wv.withdrawn = asset(0, SP_SYMBOL);
63  };
64 
65  if (!_withdraw_scorumpower_service.is_exists(from_object.id))
66  {
67  _withdraw_scorumpower_service.create(lmbNewVesting);
68  }
69  else
70  {
71  const withdraw_scorumpower_object& wv = _withdraw_scorumpower_service.get(from_object.id);
72  _withdraw_scorumpower_service.update(wv, lmbNewVesting);
73  }
74  }
75  }
76 
77  template <typename FromObjectType> void remove_withdraw_scorumpower(const FromObjectType& from_object)
78  {
79  if (_withdraw_scorumpower_service.is_exists(from_object.id))
80  {
81  const withdraw_scorumpower_object& wv = _withdraw_scorumpower_service.get(from_object.id);
82  _withdraw_scorumpower_service.remove(wv);
83  }
84  }
85 
86 private:
87  dynamic_global_property_service_i& _dprops_service;
88  withdraw_scorumpower_service_i& _withdraw_scorumpower_service;
89  const fc::time_point_sec _lock_withdraw_sp_until_timestamp;
90 };
91 
92 //
93 
95  : evaluator_impl<data_service_factory_i, withdraw_scorumpower_evaluator>(services)
96  , _impl(new withdraw_scorumpower_impl(services))
97  , _account_service(db().account_service())
98  , _dprops_service(db().dynamic_global_property_service())
99 {
100 }
101 
103 {
104 }
105 
107 {
108  const auto& account = _account_service.get_account(o.account);
109 
110  FC_ASSERT(account.scorumpower >= asset(0, SP_SYMBOL),
111  "Account does not have sufficient Scorum Power for withdraw.");
112  FC_ASSERT(account.scorumpower - account.delegated_scorumpower >= o.scorumpower,
113  "Account does not have sufficient Scorum Power for withdraw.");
114 
115  if (!account.created_by_genesis)
116  {
117  const auto& dprops = _dprops_service.get();
118  asset min_scorumpower = asset(dprops.median_chain_props.account_creation_fee.amount, SP_SYMBOL);
119  min_scorumpower *= SCORUM_START_WITHDRAW_COEFFICIENT;
120 
121  FC_ASSERT(account.scorumpower > min_scorumpower || o.scorumpower.amount == 0,
122  "Account registered by another account requires 10x account creation fee worth of Scorum Power "
123  "before it can be powered down.");
124  }
125 
126  _impl->do_apply(account, o.scorumpower);
127 }
128 
129 //
130 
131 withdraw_scorumpower_context::withdraw_scorumpower_context(data_service_factory_i& services, const asset& scorumpower)
132  : _services(services)
133  , _scorumpower(scorumpower)
134 {
135 }
136 
138 {
140 
141  dev_pool_service_i& dev_pool_service = ctx.services().dev_pool_service();
142 
143  const auto& pool = dev_pool_service.get();
144 
145  FC_ASSERT(pool.sp_balance >= ctx.scorumpower(), "Dev pool does not have sufficient Scorum Power for withdraw.");
146 
147  impl.do_apply(pool, ctx.scorumpower());
148 }
149 }
150 }
withdraw_scorumpower_context(data_service_factory_i &services, const asset &scorumpower)
withdraw_scorumpower_evaluator(data_service_factory_i &services)
void remove_withdraw_scorumpower(const FromObjectType &from_object)
withdraw_scorumpower_impl(data_service_factory_i &services)
void do_apply(const FromObjectType &from_object, const asset &scorumpower)
asset vesting_withdraw_rate
at the time this is updated it can be at most scorumpower/104
#define SCORUM_START_WITHDRAW_COEFFICIENT
Definition: config.hpp:124
#define SCORUM_VESTING_WITHDRAW_INTERVALS
Definition: config.hpp:155
#define SP_SYMBOL
Definition: config.hpp:104
#define SCORUM_VESTING_WITHDRAW_INTERVAL_SECONDS
Definition: config.hpp:156
Definition: asset.cpp:15
virtual const account_object & get_account(const account_name_type &) const =0
virtual void update(const modifier_type &modifier)=0
virtual const object_type & get() const =0
virtual const object_type & create(const modifier_type &modifier)=0
virtual fc::time_point_sec head_block_time() const =0
virtual const withdraw_scorumpower_object & get(const account_id_type &from) const =0
virtual bool is_exists(const account_id_type &from) const =0
share_type amount
Definition: asset.hpp:31