BitShares-Core  6.1.0
BitShares blockchain implementation and command-line interface software
asset_ops.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2018 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  */
25 
26 #include <fc/io/raw.hpp>
27 
28 #include <locale>
29 
30 namespace graphene { namespace protocol {
31 
38 bool is_valid_symbol( const string& symbol )
39 {
40  static const std::locale& loc = std::locale::classic();
41  if( symbol.size() < GRAPHENE_MIN_ASSET_SYMBOL_LENGTH )
42  return false;
43 
44  if( symbol.substr(0,3) == "BIT" )
45  return false;
46 
47  if( symbol.size() > GRAPHENE_MAX_ASSET_SYMBOL_LENGTH )
48  return false;
49 
50  if( !isalpha( symbol.front(), loc ) )
51  return false;
52 
53  if( !isalnum( symbol.back(), loc ) )
54  return false;
55 
56  bool dot_already_present = false;
57  for( const auto c : symbol )
58  {
59  if( (isalpha( c, loc ) && isupper( c, loc )) || isdigit( c, loc ) )
60  continue;
61 
62  if( c == '.' )
63  {
64  if( dot_already_present )
65  return false;
66 
67  dot_already_present = true;
68  continue;
69  }
70 
71  return false;
72  }
73 
74  return true;
75 }
76 
78 {
80 }
81 
83  const optional<uint64_t>& sub_asset_creation_fee )const
84 {
85  share_type core_fee_required = param.long_symbol;
86 
87  if( sub_asset_creation_fee.valid() && symbol.find('.') != std::string::npos )
88  {
89  core_fee_required = *sub_asset_creation_fee;
90  }
91  else
92  {
93  switch( symbol.size() )
94  {
95  case 3: core_fee_required = param.symbol3;
96  break;
97  case 4: core_fee_required = param.symbol4;
98  break;
99  default:
100  break;
101  }
102  }
103 
104  // common_options contains several lists and a string. Charge fees for its size
105  core_fee_required += calculate_data_fee( fc::raw::pack_size(*this), param.price_per_kbyte );
106 
107  return core_fee_required;
108 }
109 
111 {
112  FC_ASSERT( fee.amount >= 0 );
113  FC_ASSERT( is_valid_symbol(symbol) );
114  common_options.validate();
115  // TODO fix the missing check for witness_fed_asset and committee_fed_asset with a hard fork
116  if( 0 != ( common_options.issuer_permissions & NON_UIA_ONLY_ISSUER_PERMISSION_MASK
117  & (uint16_t)( ~(witness_fed_asset|committee_fed_asset) ) ) )
118  FC_ASSERT( bitasset_opts.valid() );
119  if( is_prediction_market )
120  {
121  FC_ASSERT( bitasset_opts.valid(), "Cannot have a User-Issued Asset implement a prediction market." );
122  FC_ASSERT( 0 != (common_options.issuer_permissions & global_settle) );
123  FC_ASSERT( 0 == (common_options.issuer_permissions & disable_bsrm_update) );
124  FC_ASSERT( !bitasset_opts->extensions.value.black_swan_response_method.valid(),
125  "Can not set black_swan_response_method for Prediction Markets" );
126  }
127  if( bitasset_opts ) bitasset_opts->validate();
128 
129  asset dummy = asset(1) * common_options.core_exchange_rate;
130  FC_ASSERT(dummy.asset_id == asset_id_type(1));
131  FC_ASSERT(precision <= 12);
132 }
133 
135 {
136  FC_ASSERT( fee.amount >= 0 );
137  if( new_issuer )
138  FC_ASSERT(issuer != *new_issuer);
139  new_options.validate();
140 
141  asset dummy = asset(1, asset_to_update) * new_options.core_exchange_rate;
142  FC_ASSERT(dummy.asset_id == asset_id_type());
143 
144  if( extensions.value.new_precision.valid() )
145  FC_ASSERT( *extensions.value.new_precision <= 12 );
146 
147  if( extensions.value.skip_core_exchange_rate.valid() )
148  {
149  FC_ASSERT( *extensions.value.skip_core_exchange_rate == true,
150  "If skip_core_exchange_rate is specified, it can only be true" );
151  }
152 }
153 
155 {
156  FC_ASSERT( fee.amount >= 0 );
157  FC_ASSERT( issuer != new_issuer );
158 }
159 
161 {
163 }
164 
165 
167 {
168  FC_ASSERT( fee.amount >= 0 );
169  feed.validate();
170 
171  // maybe some of these could be moved to feed.validate()
172  if( !feed.core_exchange_rate.is_null() )
173  {
174  feed.core_exchange_rate.validate();
175  }
176  if( (!feed.settlement_price.is_null()) && (!feed.core_exchange_rate.is_null()) )
177  {
178  FC_ASSERT( feed.settlement_price.base.asset_id == feed.core_exchange_rate.base.asset_id );
179  }
180 
181  FC_ASSERT( !feed.settlement_price.is_null() );
182  FC_ASSERT( !feed.core_exchange_rate.is_null() );
183  FC_ASSERT( feed.is_for( asset_id ) );
184 
185  if( extensions.value.initial_collateral_ratio.valid() )
186  {
187  FC_ASSERT( *extensions.value.initial_collateral_ratio >= GRAPHENE_MIN_COLLATERAL_RATIO );
188  FC_ASSERT( *extensions.value.initial_collateral_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
189  }
190 }
191 
193 {
194  FC_ASSERT( fee.amount >= 0 );
195  FC_ASSERT( amount_to_reserve.amount.value <= GRAPHENE_MAX_SHARE_SUPPLY );
196  FC_ASSERT( amount_to_reserve.amount.value > 0 );
197 }
198 
200 {
201  FC_ASSERT( fee.amount >= 0 );
204  FC_ASSERT( asset_to_issue.asset_id != asset_id_type(0) );
205 }
206 
208 {
209  FC_ASSERT( fee.amount >= 0 );
210  FC_ASSERT( fee.asset_id == asset_id_type() );
211  FC_ASSERT( amount > 0 );
212 }
213 
215 {
216  FC_ASSERT( fee.amount >= 0 );
217  FC_ASSERT( amount.amount >= 0 );
218 }
219 
221 {
222  FC_ASSERT( fee.amount >= 0 );
223  new_options.validate();
224 }
225 
227 {
228  FC_ASSERT( fee.amount >= 0 );
229 }
230 
232 {
233  FC_ASSERT( fee.amount >= 0 );
234  FC_ASSERT( asset_to_settle == settle_price.base.asset_id );
235 }
236 
238 {
239  FC_ASSERT(minimum_feeds > 0);
240  FC_ASSERT(force_settlement_offset_percent <= GRAPHENE_100_PERCENT);
241  FC_ASSERT(maximum_force_settlement_volume <= GRAPHENE_100_PERCENT);
242 
243  if( extensions.value.margin_call_fee_ratio.valid() )
244  FC_ASSERT( *extensions.value.margin_call_fee_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
245 
246  if( extensions.value.initial_collateral_ratio.valid() )
247  {
248  FC_ASSERT( *extensions.value.initial_collateral_ratio >= GRAPHENE_MIN_COLLATERAL_RATIO );
249  FC_ASSERT( *extensions.value.initial_collateral_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
250  }
251  if( extensions.value.maintenance_collateral_ratio.valid() )
252  {
253  FC_ASSERT( *extensions.value.maintenance_collateral_ratio >= GRAPHENE_MIN_COLLATERAL_RATIO );
254  FC_ASSERT( *extensions.value.maintenance_collateral_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
255  }
256  if( extensions.value.maximum_short_squeeze_ratio.valid() )
257  {
258  FC_ASSERT( *extensions.value.maximum_short_squeeze_ratio >= GRAPHENE_MIN_COLLATERAL_RATIO );
259  FC_ASSERT( *extensions.value.maximum_short_squeeze_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
260  }
261 
262  if( extensions.value.force_settle_fee_percent.valid() )
263  FC_ASSERT( *extensions.value.force_settle_fee_percent <= GRAPHENE_100_PERCENT );
264 
265  if( extensions.value.black_swan_response_method.valid() )
266  {
267  auto bsrm_count = static_cast<uint8_t>( black_swan_response_type::BSRM_TYPE_COUNT );
268  FC_ASSERT( *extensions.value.black_swan_response_method < bsrm_count,
269  "black_swan_response_method should be less than ${c}", ("c",bsrm_count) );
270  }
271 }
272 
274 {
275  FC_ASSERT( max_supply > 0 );
276  FC_ASSERT( max_supply <= GRAPHENE_MAX_SHARE_SUPPLY );
277  // The non-negative maker fee must be less than or equal to 100%
278  FC_ASSERT( market_fee_percent <= GRAPHENE_100_PERCENT );
279 
280  // The non-negative taker fee must be less than or equal to 100%
281  if( extensions.value.taker_fee_percent.valid() )
282  FC_ASSERT( *extensions.value.taker_fee_percent <= GRAPHENE_100_PERCENT );
283 
284  FC_ASSERT( max_market_fee >= 0 && max_market_fee <= GRAPHENE_MAX_SHARE_SUPPLY );
285  // There must be no high bits in permissions whose meaning is not known.
286  FC_ASSERT( 0 == (issuer_permissions & (uint16_t)(~ASSET_ISSUER_PERMISSION_MASK)) );
287  // The permission-only bits can not be set in flag
288  FC_ASSERT( 0 == (flags & global_settle),
289  "Can not set global_settle flag, it is for issuer permission only" );
290 
291  // the witness_fed and committee_fed flags cannot be set simultaneously
293  core_exchange_rate.validate();
294  FC_ASSERT( core_exchange_rate.base.asset_id.instance.value == 0 ||
295  core_exchange_rate.quote.asset_id.instance.value == 0 );
296 
297  if(!whitelist_authorities.empty() || !blacklist_authorities.empty())
298  FC_ASSERT( 0 != (flags & white_list) );
299  for( auto item : whitelist_markets )
300  {
301  FC_ASSERT( blacklist_markets.find(item) == blacklist_markets.end() );
302  }
303  for( auto item : blacklist_markets )
304  {
305  FC_ASSERT( whitelist_markets.find(item) == whitelist_markets.end() );
306  }
307  if( extensions.value.reward_percent.valid() )
308  FC_ASSERT( *extensions.value.reward_percent <= GRAPHENE_100_PERCENT );
309 }
310 
311 // Note: this function is only called after the BSIP 48/75 hardfork
312 void asset_options::validate_flags( bool is_market_issued, bool allow_disable_collateral_bid )const
313 {
314  FC_ASSERT( 0 == (flags & (uint16_t)(~ASSET_ISSUER_PERMISSION_MASK)),
315  "Can not set an unknown bit in flags" );
316  if( !allow_disable_collateral_bid ) // before core-2281 hf, can not set the disable_collateral_bidding bit
317  FC_ASSERT( 0 == (flags & disable_collateral_bidding),
318  "Can not set the 'disable_collateral_bidding' bit in flags between the core-2281 hardfork "
319  "and the BSIP_48_75 hardfork" );
320  // Note: global_settle is checked in validate(), so do not check again here
321  FC_ASSERT( 0 == (flags & disable_mcr_update),
322  "Can not set disable_mcr_update flag, it is for issuer permission only" );
323  FC_ASSERT( 0 == (flags & disable_icr_update),
324  "Can not set disable_icr_update flag, it is for issuer permission only" );
325  FC_ASSERT( 0 == (flags & disable_mssr_update),
326  "Can not set disable_mssr_update flag, it is for issuer permission only" );
327  FC_ASSERT( 0 == (flags & disable_bsrm_update),
328  "Can not set disable_bsrm_update flag, it is for issuer permission only" );
329  if( !is_market_issued )
330  {
331  FC_ASSERT( 0 == (flags & (uint16_t)(~UIA_ASSET_ISSUER_PERMISSION_MASK)),
332  "Can not set a flag for bitassets only to UIA" );
333  }
334 }
335 
337 {
338  return ( (issuer_permissions & ASSET_ISSUER_PERMISSION_ENABLE_BITS_MASK)
339  | ((uint16_t)(~issuer_permissions) & ASSET_ISSUER_PERMISSION_DISABLE_BITS_MASK) );
340 }
341 
343  FC_ASSERT( fee.amount >= 0 );
344  FC_ASSERT( amount_to_claim.amount > 0 );
345  if( extensions.value.claim_from_asset_id.valid() )
346  FC_ASSERT( *extensions.value.claim_from_asset_id != amount_to_claim.asset_id );
347 }
348 
350  FC_ASSERT( fee.amount >= 0 );
351  FC_ASSERT( fee.asset_id != asset_id);
352  FC_ASSERT( amount_to_claim.amount > 0 );
353  FC_ASSERT( amount_to_claim.asset_id == asset_id_type());
354 }
355 
356 } } // namespace graphene::protocol
357 
362 
365 
380 
share_type calculate_fee(const fee_parameters_type &k, const optional< uint64_t > &sub_asset_creation_fee) const
Definition: asset_ops.cpp:82
Update the set of feed-producing accounts for a BitAssetBitAssets have price feeds selected by taking...
Definition: asset_ops.hpp:430
Definition: api.cpp:48
The asset_options struct contains options available on all assets in the network. ...
Definition: asset_ops.hpp:47
used to transfer accumulated fees back to the issuer&#39;s balance.
Definition: asset_ops.hpp:529
Schedules a market-issued asset for automatic settlementHolders of market-issued assests may request ...
Definition: asset_ops.hpp:267
the bitasset owner can not update MSSR, permission only
Definition: types.hpp:221
the bitasset owner can not update MCR, permission only
Definition: types.hpp:219
Publish price feeds for market-issued assetsPrice feed providers use this operation to publish their ...
Definition: asset_ops.hpp:462
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
size_t pack_size(const T &v)
Definition: raw.hpp:757
used to take an asset out of circulation, returning to the issuer
Definition: asset_ops.hpp:513
void validate_flags(bool is_market_issued, bool allow_disable_collateral_bid=true) const
Definition: asset_ops.cpp:312
#define GRAPHENE_MAX_COLLATERAL_RATIO
higher than this is unnecessary and may exceed int16 storage
Definition: config.hpp:115
share_type calculate_fee(const fee_parameters_type &k) const
Definition: asset_ops.cpp:160
#define GRAPHENE_100_PERCENT
Definition: config.hpp:102
bool valid() const
Definition: optional.hpp:186
Update options specific to BitAssetsBitAssets have some options which are not relevant to other asset...
Definition: asset_ops.hpp:398
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
share_type calculate_fee(const fee_parameters_type &k) const
Definition: asset_ops.cpp:77
the bitasset owner can not update ICR, permission only
Definition: types.hpp:220
#define GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION(type)
Definition: types.hpp:86
account_id_type issuer
Must be asset_to_issue->asset_id->issuer.
Definition: asset_ops.hpp:493
Update options common to all assetsThere are a number of options which all assets in the network use...
Definition: asset_ops.hpp:351
uint16_t get_enabled_issuer_permissions_mask() const
Definition: asset_ops.cpp:336
accounts must be whitelisted in order to hold or transact this asset
Definition: types.hpp:195
Can not bid collateral after a global settlement.
Definition: types.hpp:223
Transfers BTS from the fee pool of a specified asset back to the issuer&#39;s balance.
Definition: asset_ops.hpp:601
#define GRAPHENE_MIN_COLLATERAL_RATIO
lower than this could result in divide by 0
Definition: config.hpp:114
the bitasset is to be fed by witnesses
Definition: types.hpp:201
asset_id_type asset_id
Definition: asset.hpp:37
allow the bitasset owner to force a global settlement, permission only
Definition: types.hpp:199
static uint64_t calculate_data_fee(uint64_t bytes, uint64_t price_per_kbyte)
Definition: operations.cpp:33
constexpr int64_t GRAPHENE_MAX_SHARE_SUPPLY(1000000000000000LL)
#define GRAPHENE_MAX_ASSET_SYMBOL_LENGTH
Definition: config.hpp:36
Update issuer of an assetAn issuer has general administrative power of an asset and in some cases als...
Definition: asset_ops.hpp:565
the bitasset is to be fed by the committee
Definition: types.hpp:202
#define GRAPHENE_MIN_ASSET_SYMBOL_LENGTH
Definition: config.hpp:35
the bitasset owner can not update BSRM, permission only
Definition: types.hpp:222
The bitasset_options struct contains configurable options available only to BitAssets.
Definition: asset_ops.hpp:109
bool is_valid_symbol(const string &symbol)
Definition: asset_ops.cpp:38
T value
Definition: safe.hpp:22
allows global settling of bitassets (black swan or prediction markets)
Definition: asset_ops.hpp:238