BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
vesting_balance_object.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
26 
27 #include <fc/io/raw.hpp>
28 
29 namespace graphene { namespace chain {
30 
31 inline bool sum_below_max_shares(const asset& a, const asset& b)
32 {
34  return (a.amount <= GRAPHENE_MAX_SHARE_SUPPLY)
36  && ((a.amount + b.amount) <= GRAPHENE_MAX_SHARE_SUPPLY);
37 }
38 
40 {
41  share_type allowed_withdraw = 0;
42 
43  if( ctx.now > begin_timestamp )
44  {
45  const auto elapsed_seconds = (ctx.now - begin_timestamp).to_seconds();
46  assert( elapsed_seconds > 0 );
47 
48  if( elapsed_seconds >= vesting_cliff_seconds )
49  {
50  share_type total_vested = 0;
51  if( elapsed_seconds < vesting_duration_seconds )
52  {
53  total_vested = static_cast<uint64_t>(fc::uint128_t( begin_balance.value ) * elapsed_seconds
55  }
56  else
57  {
58  total_vested = begin_balance;
59  }
60  assert( total_vested >= 0 );
61 
62  const share_type withdrawn_already = begin_balance - ctx.balance.amount;
63  assert( withdrawn_already >= 0 );
64 
65  allowed_withdraw = total_vested - withdrawn_already;
66  assert( allowed_withdraw >= 0 );
67  }
68  }
69 
70  return asset( allowed_withdraw, ctx.balance.asset_id );
71 }
72 
74 {
75 }
76 
78 {
79  return (ctx.amount.asset_id == ctx.balance.asset_id)
80  && sum_below_max_shares(ctx.amount, ctx.balance);
81 }
82 
84 {
85 }
86 
88 {
89  return (ctx.amount.asset_id == ctx.balance.asset_id)
90  && (ctx.amount <= get_allowed_withdraw(ctx));
91 }
92 
94 {
95  assert(ctx.now >= coin_seconds_earned_last_update);
96  int64_t delta_seconds = (ctx.now - coin_seconds_earned_last_update).to_seconds();
97  assert(delta_seconds >= 0);
98 
99  fc::uint128_t delta_coin_seconds = ctx.balance.amount.value;
100  delta_coin_seconds *= delta_seconds;
101 
102  fc::uint128_t coin_seconds_earned_cap = ctx.balance.amount.value;
103  coin_seconds_earned_cap *= std::max(vesting_seconds, 1u);
104 
105  return std::min(coin_seconds_earned + delta_coin_seconds, coin_seconds_earned_cap);
106 }
107 
109 {
112 }
113 
115 {
116  if(ctx.now <= start_claim)
117  return asset(0, ctx.balance.asset_id);
118  fc::uint128_t cs_earned = compute_coin_seconds_earned(ctx);
119  fc::uint128_t withdraw_available = cs_earned / std::max(vesting_seconds, 1u);
120  assert(withdraw_available <= static_cast<fc::uint128_t>(ctx.balance.amount.value));
121  return asset(static_cast<uint64_t>(withdraw_available), ctx.balance.asset_id);
122 }
123 
125 {
127 }
128 
130 {
131  on_deposit(ctx);
132  coin_seconds_earned += ctx.amount.amount.value * std::max(vesting_seconds, 1u);
133 }
134 
136 {
138  fc::uint128_t coin_seconds_needed = ctx.amount.amount.value;
139  coin_seconds_needed *= std::max(vesting_seconds, 1u);
140  // is_withdraw_allowed should forbid any withdrawal that
141  // would trigger this assert
142  assert(coin_seconds_needed <= coin_seconds_earned);
143 
144  coin_seconds_earned -= coin_seconds_needed;
145 }
146 
148 {
149  return (ctx.amount.asset_id == ctx.balance.asset_id)
150  && sum_below_max_shares(ctx.amount, ctx.balance);
151 }
152 
154 {
155  return is_deposit_allowed(ctx);
156 }
157 
159 {
160  return (ctx.amount <= get_allowed_withdraw(ctx));
161 }
162 
164 {
165  return ctx.balance;
166 }
167 
169 {
170 }
171 
173 {
174 
175 }
176 
178 {
179  return (ctx.amount.asset_id == ctx.balance.asset_id)
180  && sum_below_max_shares(ctx.amount, ctx.balance);
181 }
182 
184 {
185 }
186 
188 {
189  return (ctx.amount.asset_id == ctx.balance.asset_id)
190  && (ctx.amount <= get_allowed_withdraw(ctx));
191 }
192 
193 #define VESTING_VISITOR(NAME, MAYBE_CONST) \
194 struct NAME ## _visitor \
195 { \
196  typedef decltype( \
197  std::declval<linear_vesting_policy>().NAME( \
198  std::declval<vesting_policy_context>()) \
199  ) result_type; \
200  \
201  NAME ## _visitor( \
202  const asset& balance, \
203  const time_point_sec& now, \
204  const asset& amount \
205  ) \
206  : ctx(balance, now, amount) {} \
207  \
208  template< typename Policy > \
209  result_type \
210  operator()(MAYBE_CONST Policy& policy) MAYBE_CONST \
211  { \
212  return policy.NAME(ctx); \
213  } \
214  \
215  vesting_policy_context ctx; \
216 }
217 
218 VESTING_VISITOR(on_deposit,);
219 VESTING_VISITOR(on_deposit_vested,);
220 VESTING_VISITOR(on_withdraw,);
221 VESTING_VISITOR(is_deposit_allowed, const);
222 VESTING_VISITOR(is_deposit_vested_allowed, const);
223 VESTING_VISITOR(is_withdraw_allowed, const);
224 VESTING_VISITOR(get_allowed_withdraw, const);
225 
226 bool vesting_balance_object::is_deposit_allowed(const time_point_sec& now, const asset& amount)const
227 {
228  return policy.visit(is_deposit_allowed_visitor(balance, now, amount));
229 }
230 
231 bool vesting_balance_object::is_withdraw_allowed(const time_point_sec& now, const asset& amount)const
232 {
233  bool result = policy.visit(is_withdraw_allowed_visitor(balance, now, amount));
234  // if some policy allows you to withdraw more than your balance,
235  // there's a programming bug in the policy algorithm
236  assert((amount <= balance) || (!result));
237  return result;
238 }
239 
240 void vesting_balance_object::deposit(const time_point_sec& now, const asset& amount)
241 {
242  on_deposit_visitor vtor(balance, now, amount);
243  policy.visit(vtor);
244  balance += amount;
245 }
246 
247 void vesting_balance_object::deposit_vested(const time_point_sec& now, const asset& amount)
248 {
249  on_deposit_vested_visitor vtor(balance, now, amount);
250  policy.visit(vtor);
251  balance += amount;
252 }
253 
254 bool vesting_balance_object::is_deposit_vested_allowed(const time_point_sec& now, const asset& amount) const
255 {
256  return policy.visit(is_deposit_vested_allowed_visitor(balance, now, amount));
257 }
258 
259 void vesting_balance_object::withdraw(const time_point_sec& now, const asset& amount)
260 {
261  assert(amount <= balance);
262  on_withdraw_visitor vtor(balance, now, amount);
263  policy.visit(vtor);
264  balance -= amount;
265 }
266 
268 {
269  asset amount = asset();
270  return policy.visit(get_allowed_withdraw_visitor(balance, now, amount));
271 }
272 
273 } } // graphene::chain
274 
GRAPHENE_MAX_SHARE_SUPPLY
constexpr int64_t GRAPHENE_MAX_SHARE_SUPPLY(1000000000000000LL)
graphene::chain::cdd_vesting_policy
defines vesting in terms of coin-days accrued which allows for dynamic deposit/withdraw
Definition: vesting_balance_object.hpp:89
graphene::chain::linear_vesting_policy::begin_balance
share_type begin_balance
The total amount of asset to vest.
Definition: vesting_balance_object.hpp:70
graphene::chain::cdd_vesting_policy::coin_seconds_earned
fc::uint128_t coin_seconds_earned
Definition: vesting_balance_object.hpp:92
graphene::chain::instant_vesting_policy::on_withdraw
void on_withdraw(const vesting_policy_context &ctx)
Definition: vesting_balance_object.cpp:183
graphene::chain::cdd_vesting_policy::is_deposit_vested_allowed
bool is_deposit_vested_allowed(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:153
graphene::chain::linear_vesting_policy::vesting_duration_seconds
uint32_t vesting_duration_seconds
Duration of the vesting period, in seconds. Must be greater than 0 and greater than vesting_cliff_sec...
Definition: vesting_balance_object.hpp:68
graphene::chain::vesting_balance_object::is_deposit_allowed
bool is_deposit_allowed(const fc::time_point_sec &now, const asset &amount) const
Definition: vesting_balance_object.cpp:226
graphene::chain::vesting_policy_context::balance
asset balance
Definition: vesting_balance_object.hpp:48
graphene::chain::instant_vesting_policy::get_allowed_withdraw
asset get_allowed_withdraw(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:163
graphene::chain::linear_vesting_policy::on_deposit
void on_deposit(const vesting_policy_context &ctx)
Definition: vesting_balance_object.cpp:73
graphene::chain::vesting_policy_context
Definition: vesting_balance_object.hpp:40
GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION
#define GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION(type)
Definition: types.hpp:86
graphene::chain::vesting_balance_object::deposit
void deposit(const fc::time_point_sec &now, const asset &amount)
Deposit amount into vesting balance, requiring it to vest before withdrawal.
Definition: vesting_balance_object.cpp:240
graphene::chain::VESTING_VISITOR
VESTING_VISITOR(on_deposit,)
graphene::chain::vesting_policy_context::amount
asset amount
Definition: vesting_balance_object.hpp:50
graphene::chain::cdd_vesting_policy::update_coin_seconds_earned
void update_coin_seconds_earned(const vesting_policy_context &ctx)
Definition: vesting_balance_object.cpp:108
graphene::chain::linear_vesting_policy::is_deposit_allowed
bool is_deposit_allowed(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:77
graphene::chain::vesting_balance_object::policy
vesting_policy policy
The vesting policy stores details on when funds vest, and controls when they may be withdrawn.
Definition: vesting_balance_object.hpp:161
graphene::chain::cdd_vesting_policy::is_withdraw_allowed
bool is_withdraw_allowed(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:158
graphene::chain::vesting_balance_object
Definition: vesting_balance_object.hpp:151
graphene::chain::instant_vesting_policy::is_withdraw_allowed
bool is_withdraw_allowed(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:187
graphene::chain::cdd_vesting_policy::coin_seconds_earned_last_update
fc::time_point_sec coin_seconds_earned_last_update
Definition: vesting_balance_object.hpp:95
graphene::chain::instant_vesting_policy::on_deposit
void on_deposit(const vesting_policy_context &ctx)
Definition: vesting_balance_object.cpp:168
graphene::protocol::asset::asset_id
asset_id_type asset_id
Definition: asset.hpp:37
graphene::chain::cdd_vesting_policy::start_claim
fc::time_point_sec start_claim
Definition: vesting_balance_object.hpp:94
vesting_balance_object.hpp
graphene::chain::vesting_balance_object::get_allowed_withdraw
asset get_allowed_withdraw(const time_point_sec &now) const
Definition: vesting_balance_object.cpp:267
graphene::chain::vesting_balance_object::balance
asset balance
Definition: vesting_balance_object.hpp:159
graphene::chain::cdd_vesting_policy::on_withdraw
void on_withdraw(const vesting_policy_context &ctx)
Definition: vesting_balance_object.cpp:135
graphene::chain::cdd_vesting_policy::on_deposit_vested
void on_deposit_vested(const vesting_policy_context &ctx)
Definition: vesting_balance_object.cpp:129
graphene::chain::vesting_balance_object::withdraw
void withdraw(const fc::time_point_sec &now, const asset &amount)
Definition: vesting_balance_object.cpp:259
graphene::protocol::asset::amount
share_type amount
Definition: asset.hpp:36
graphene::chain::instant_vesting_policy::on_deposit_vested
void on_deposit_vested(const vesting_policy_context &)
Definition: vesting_balance_object.cpp:172
graphene::chain::vesting_balance_object::deposit_vested
void deposit_vested(const fc::time_point_sec &now, const asset &amount)
Deposit amount into vesting balance, making the new funds vest immediately.
Definition: vesting_balance_object.cpp:247
graphene::chain::cdd_vesting_policy::compute_coin_seconds_earned
fc::uint128_t compute_coin_seconds_earned(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:93
graphene::chain::vesting_balance_object::is_deposit_vested_allowed
bool is_deposit_vested_allowed(const fc::time_point_sec &now, const asset &amount) const
Definition: vesting_balance_object.cpp:254
graphene::chain::linear_vesting_policy::vesting_cliff_seconds
uint32_t vesting_cliff_seconds
No amount may be withdrawn before this many seconds of the vesting period have elapsed.
Definition: vesting_balance_object.hpp:66
graphene::chain::cdd_vesting_policy::is_deposit_allowed
bool is_deposit_allowed(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:147
fc::static_variant::visit
visitor::result_type visit(visitor &v)
Definition: static_variant.hpp:256
graphene::chain::linear_vesting_policy::is_withdraw_allowed
bool is_withdraw_allowed(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:87
graphene::chain::instant_vesting_policy::is_deposit_allowed
bool is_deposit_allowed(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:177
graphene::protocol::asset
Definition: asset.hpp:31
graphene::chain::sum_below_max_shares
bool sum_below_max_shares(const asset &a, const asset &b)
Definition: vesting_balance_object.cpp:31
graphene::chain::linear_vesting_policy::begin_timestamp
fc::time_point_sec begin_timestamp
This is the time at which funds begin vesting.
Definition: vesting_balance_object.hpp:64
graphene::chain::cdd_vesting_policy::get_allowed_withdraw
asset get_allowed_withdraw(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:114
graphene::chain::cdd_vesting_policy::vesting_seconds
uint32_t vesting_seconds
Definition: vesting_balance_object.hpp:91
fc::safe::value
T value
Definition: safe.hpp:28
graphene::chain::linear_vesting_policy::on_withdraw
void on_withdraw(const vesting_policy_context &ctx)
Definition: vesting_balance_object.cpp:83
graphene
Definition: api.cpp:48
graphene::chain::cdd_vesting_policy::on_deposit
void on_deposit(const vesting_policy_context &ctx)
Definition: vesting_balance_object.cpp:124
graphene::chain::vesting_policy_context::now
fc::time_point_sec now
Definition: vesting_balance_object.hpp:49
graphene::chain::linear_vesting_policy::get_allowed_withdraw
asset get_allowed_withdraw(const vesting_policy_context &ctx) const
Definition: vesting_balance_object.cpp:39
graphene::chain::linear_vesting_policy
Linear vesting balance with cliff.
Definition: vesting_balance_object.hpp:61
graphene::chain::vesting_balance_object::is_withdraw_allowed
bool is_withdraw_allowed(const fc::time_point_sec &now, const asset &amount) const
Definition: vesting_balance_object.cpp:231
raw.hpp
fc::safe
Definition: safe.hpp:26