BitShares-Core  6.0.1
BitShares blockchain implementation and command-line interface software
samet_fund_evaluator.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 Abit More, 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  */
26 
28 
31 #include <graphene/chain/hardfork.hpp>
33 
35 
36 namespace graphene { namespace chain {
37 
39 { try {
40  const database& d = db();
41  const auto block_time = d.head_block_time();
42 
43  FC_ASSERT( HARDFORK_CORE_2351_PASSED(block_time), "Not allowed until the core-2351 hardfork" );
44 
46  "The account is unauthorized by the asset" );
47 
48  return void_result();
49 } FC_CAPTURE_AND_RETHROW( (op) ) }
50 
52 { try {
53  database& d = db();
54 
56 
57  const auto& new_samet_fund_object = d.create<samet_fund_object>([&op](samet_fund_object& obj){
58  obj.owner_account = op.owner_account;
59  obj.asset_type = op.asset_type;
60  obj.balance = op.balance;
61  obj.fee_rate = op.fee_rate;
62  // unpaid amount is 0 by default
63  });
64  return new_samet_fund_object.id;
65 } FC_CAPTURE_AND_RETHROW( (op) ) }
66 
68 { try {
69  const database& d = db();
70 
71  _fund = &op.fund_id(d);
72 
73  FC_ASSERT( _fund->owner_account == op.owner_account, "The account is not the owner of the SameT Fund" );
74 
75  FC_ASSERT( _fund->unpaid_amount == 0, "Can only delete a SameT Fund when the unpaid amount is zero" );
76 
77  // Note: no asset authorization check here, allow funds to be moved to account balance
78 
79  return void_result();
80 } FC_CAPTURE_AND_RETHROW( (op) ) }
81 
83 { try {
84  database& d = db();
85 
86  asset released( _fund->balance, _fund->asset_type );
87 
88  d.adjust_balance( op.owner_account, released );
89 
90  d.remove( *_fund );
91 
92  return released;
93 } FC_CAPTURE_AND_RETHROW( (op) ) }
94 
96 { try {
97  const database& d = db();
98 
99  _fund = &op.fund_id(d);
100 
101  FC_ASSERT( _fund->owner_account == op.owner_account, "The account is not the owner of the SameT Fund" );
102 
103  if( op.delta_amount.valid() )
104  {
105  FC_ASSERT( _fund->asset_type == op.delta_amount->asset_id, "Asset type mismatch" );
106  FC_ASSERT( _fund->unpaid_amount == 0,
107  "Can only update the balance of a SameT Fund when the unpaid amount is zero" );
108 
109  if( op.delta_amount->amount > 0 )
110  {
111  // Check asset authorization only when moving funds from account balance to somewhere else
112  FC_ASSERT( is_authorized_asset( d, *fee_paying_account, _fund->asset_type(d) ),
113  "The account is unauthorized by the asset" );
114  }
115  else
116  {
117  FC_ASSERT( _fund->balance > -op.delta_amount->amount, "Insufficient balance in the SameT Fund" );
118  }
119  }
120 
121  if( op.new_fee_rate.valid() )
122  {
123  FC_ASSERT( _fund->fee_rate != *op.new_fee_rate,
124  "New fee rate should not be the same as the original fee rate" );
125  }
126 
127  return void_result();
128 } FC_CAPTURE_AND_RETHROW( (op) ) }
129 
131 { try {
132  database& d = db();
133 
134  if( op.delta_amount.valid() )
135  d.adjust_balance( op.owner_account, -(*op.delta_amount) );
136 
137  d.modify( *_fund, [&op]( samet_fund_object& sfo ){
138  if( op.delta_amount.valid() )
139  sfo.balance += op.delta_amount->amount;
140  if( op.new_fee_rate.valid() )
141  sfo.fee_rate = *op.new_fee_rate;
142  });
143 
144  // Defensive check
145  FC_ASSERT( _fund->balance > 0, "Balance in the SameT Fund should be positive" );
146 
147  return void_result();
148 } FC_CAPTURE_AND_RETHROW( (op) ) }
149 
151 { try {
152  const database& d = db();
153 
154  _fund = &op.fund_id(d);
155 
156  FC_ASSERT( _fund->asset_type == op.borrow_amount.asset_id, "Asset type mismatch" );
157 
158  FC_ASSERT( _fund->balance >= _fund->unpaid_amount + op.borrow_amount.amount,
159  "Insufficient balance in the SameT Fund thus unable to borrow" );
160 
161  FC_ASSERT( is_authorized_asset( d, *fee_paying_account, _fund->asset_type(d) ),
162  "The account is unauthorized by the asset" );
163 
164  return void_result();
165 } FC_CAPTURE_AND_RETHROW( (op) ) }
166 
168 { try {
169  database& d = db();
170 
171  d.modify( *_fund, [&op]( samet_fund_object& sfo ){
173  });
174 
176 
177  // Defensive check
178  FC_ASSERT( _fund->balance >= _fund->unpaid_amount, "Should not borrow more than available" );
179 
181  result.value.impacted_accounts = flat_set<account_id_type>({ _fund->owner_account });
182 
183  return result;
184 } FC_CAPTURE_AND_RETHROW( (op) ) }
185 
187 { try {
188  const database& d = db();
189 
190  _fund = &op.fund_id(d);
191 
192  FC_ASSERT( _fund->asset_type == op.repay_amount.asset_id, "Asset type mismatch" );
193 
194  FC_ASSERT( is_authorized_asset( d, *fee_paying_account, _fund->asset_type(d) ),
195  "The account is unauthorized by the asset" );
196 
197  FC_ASSERT( op.repay_amount.amount <= _fund->unpaid_amount,
198  "Repay amount should not be greater than unpaid amount" );
199 
200  // Note: the result can be larger than 64 bit, but since we don't store it, it is allowed
201  auto required_fee = ( ( ( fc::uint128_t( op.repay_amount.amount.value ) * _fund->fee_rate )
202  + GRAPHENE_FEE_RATE_DENOM ) - 1 ) / GRAPHENE_FEE_RATE_DENOM; // Round up
203 
204  FC_ASSERT( fc::uint128_t(op.fund_fee.amount.value) >= required_fee,
205  "Insuffient fund fee, requires ${r}, offered ${p}",
206  ("r", required_fee) ("p", op.fund_fee.amount) );
207 
208  return void_result();
209 } FC_CAPTURE_AND_RETHROW( (op) ) }
210 
212 { try {
213  database& d = db();
214 
215  d.adjust_balance( op.account, -( op.repay_amount + op.fund_fee ) );
216 
217  d.modify( *_fund, [op]( samet_fund_object& sfo ){
218  sfo.balance += op.fund_fee.amount;
220  });
221 
223  result.value.impacted_accounts = flat_set<account_id_type>({ _fund->owner_account });
224 
225  return result;
226 } FC_CAPTURE_AND_RETHROW( (op) ) }
227 
228 } } // graphene::chain
share_type unpaid_amount
Unpaid amount.
void_result do_evaluate(const samet_fund_create_operation &op) const
void modify(const T &obj, const Lambda &m)
void_result do_evaluate(const samet_fund_repay_operation &op)
uint32_t fee_rate
Fee rate, the demominator is GRAPHENE_FEE_RATE_DENOM.
void adjust_balance(account_id_type account, asset delta)
Adjust a particular account&#39;s balance in a given asset by a delta.
Definition: db_balance.cpp:54
bool is_authorized_asset(const database &d, const account_object &acct, const asset_object &asset_obj)
time_point_sec head_block_time() const
Definition: db_getter.cpp:67
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
Definition: api.cpp:56
const account_object * fee_paying_account
Definition: evaluator.hpp:116
asset fund_fee
Fee for using the fund.
Definition: samet_fund.hpp:121
void_result do_evaluate(const samet_fund_delete_operation &op)
Create a new SameT Fund objectA SameT Fund is a fund which can be used by a borrower and have to be r...
Definition: samet_fund.hpp:36
object_id_type do_apply(const samet_fund_create_operation &op) const
asset_id_type asset_type
Asset type in the fund.
Definition: samet_fund.hpp:42
account_id_type owner_account
Owner of the fund.
Definition: samet_fund.hpp:79
extendable_operation_result do_apply(const samet_fund_repay_operation &op) const
optional< uint32_t > new_fee_rate
New fee rate, optional.
Definition: samet_fund.hpp:82
object_id_type id
Definition: object.hpp:69
optional< asset > delta_amount
Delta amount, optional.
Definition: samet_fund.hpp:81
bool valid() const
Definition: optional.hpp:186
samet_fund_id_type fund_id
ID of the SameT Fund.
Definition: samet_fund.hpp:119
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:479
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
account_id_type borrower
The account who borrows from the fund.
Definition: samet_fund.hpp:99
asset do_apply(const samet_fund_delete_operation &op) const
share_type balance
Usable amount in the fund.
Definition: samet_fund.hpp:43
samet_fund_id_type fund_id
ID of the SameT Fund object.
Definition: samet_fund.hpp:80
uint32_t fee_rate
Fee rate, the demominator is GRAPHENE_FEE_RATE_DENOM.
Definition: samet_fund.hpp:44
constexpr uint32_t GRAPHENE_FEE_RATE_DENOM
Denominator for SameT Fund fee calculation.
Definition: config.hpp:121
account_id_type account
The account who repays to the SameT Fund.
Definition: samet_fund.hpp:118
void_result do_evaluate(const samet_fund_update_operation &op)
samet_fund_id_type fund_id
ID of the SameT Fund object.
Definition: samet_fund.hpp:62
asset_id_type asset_id
Definition: asset.hpp:37
samet_fund_id_type fund_id
ID of the SameT Fund.
Definition: samet_fund.hpp:100
void_result do_evaluate(const samet_fund_borrow_operation &op)
A SameT Fund is a fund which can be used by a borrower and have to be repaid in the same transaction...
void remove(const object &obj)
account_id_type owner_account
Owner of the fund.
Definition: samet_fund.hpp:41
account_id_type owner_account
The account who owns the SameT Fund object.
Definition: samet_fund.hpp:61
void_result do_apply(const samet_fund_update_operation &op) const
share_type balance
Usable amount in the fund.
const T & create(F &&constructor)
extendable_operation_result do_apply(const samet_fund_borrow_operation &op) const
T value
Definition: safe.hpp:22