BitShares-Core  4.0.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  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  if( common_options.issuer_permissions
117  FC_ASSERT( bitasset_opts.valid() );
118  if( is_prediction_market )
119  {
120  FC_ASSERT( bitasset_opts.valid(), "Cannot have a User-Issued Asset implement a prediction market." );
121  FC_ASSERT( common_options.issuer_permissions & global_settle );
122  }
123  if( bitasset_opts ) bitasset_opts->validate();
124 
125  asset dummy = asset(1) * common_options.core_exchange_rate;
126  FC_ASSERT(dummy.asset_id == asset_id_type(1));
127  FC_ASSERT(precision <= 12);
128 }
129 
131 {
132  FC_ASSERT( fee.amount >= 0 );
133  if( new_issuer )
134  FC_ASSERT(issuer != *new_issuer);
135  new_options.validate();
136 
137  asset dummy = asset(1, asset_to_update) * new_options.core_exchange_rate;
138  FC_ASSERT(dummy.asset_id == asset_id_type());
139 
140  if( extensions.value.new_precision.valid() )
141  FC_ASSERT( *extensions.value.new_precision <= 12 );
142 
143  if( extensions.value.skip_core_exchange_rate.valid() )
144  {
145  FC_ASSERT( *extensions.value.skip_core_exchange_rate == true,
146  "If skip_core_exchange_rate is specified, it can only be true" );
147  }
148 }
149 
151 {
152  FC_ASSERT( fee.amount >= 0 );
153  FC_ASSERT( issuer != new_issuer );
154 }
155 
157 {
159 }
160 
161 
163 {
164  FC_ASSERT( fee.amount >= 0 );
165  feed.validate();
166 
167  // maybe some of these could be moved to feed.validate()
168  if( !feed.core_exchange_rate.is_null() )
169  {
170  feed.core_exchange_rate.validate();
171  }
172  if( (!feed.settlement_price.is_null()) && (!feed.core_exchange_rate.is_null()) )
173  {
174  FC_ASSERT( feed.settlement_price.base.asset_id == feed.core_exchange_rate.base.asset_id );
175  }
176 
177  FC_ASSERT( !feed.settlement_price.is_null() );
178  FC_ASSERT( !feed.core_exchange_rate.is_null() );
179  FC_ASSERT( feed.is_for( asset_id ) );
180 
181  if( extensions.value.initial_collateral_ratio.valid() )
182  {
183  FC_ASSERT( *extensions.value.initial_collateral_ratio >= GRAPHENE_MIN_COLLATERAL_RATIO );
184  FC_ASSERT( *extensions.value.initial_collateral_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
185  }
186 }
187 
189 {
190  FC_ASSERT( fee.amount >= 0 );
191  FC_ASSERT( amount_to_reserve.amount.value <= GRAPHENE_MAX_SHARE_SUPPLY );
192  FC_ASSERT( amount_to_reserve.amount.value > 0 );
193 }
194 
196 {
197  FC_ASSERT( fee.amount >= 0 );
200  FC_ASSERT( asset_to_issue.asset_id != asset_id_type(0) );
201 }
202 
204 {
205  FC_ASSERT( fee.amount >= 0 );
206  FC_ASSERT( fee.asset_id == asset_id_type() );
207  FC_ASSERT( amount > 0 );
208 }
209 
211 {
212  FC_ASSERT( fee.amount >= 0 );
213  FC_ASSERT( amount.amount >= 0 );
214 }
215 
217 {
218  FC_ASSERT( fee.amount >= 0 );
219  new_options.validate();
220 }
221 
223 {
224  FC_ASSERT( fee.amount >= 0 );
225 }
226 
228 {
229  FC_ASSERT( fee.amount >= 0 );
230  FC_ASSERT( asset_to_settle == settle_price.base.asset_id );
231 }
232 
234 {
235  FC_ASSERT(minimum_feeds > 0);
236  FC_ASSERT(force_settlement_offset_percent <= GRAPHENE_100_PERCENT);
237  FC_ASSERT(maximum_force_settlement_volume <= GRAPHENE_100_PERCENT);
238 
239  if( extensions.value.margin_call_fee_ratio.valid() )
240  FC_ASSERT( *extensions.value.margin_call_fee_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
241 
242  if( extensions.value.initial_collateral_ratio.valid() )
243  {
244  FC_ASSERT( *extensions.value.initial_collateral_ratio >= GRAPHENE_MIN_COLLATERAL_RATIO );
245  FC_ASSERT( *extensions.value.initial_collateral_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
246  }
247  if( extensions.value.maintenance_collateral_ratio.valid() )
248  {
249  FC_ASSERT( *extensions.value.maintenance_collateral_ratio >= GRAPHENE_MIN_COLLATERAL_RATIO );
250  FC_ASSERT( *extensions.value.maintenance_collateral_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
251  }
252  if( extensions.value.maximum_short_squeeze_ratio.valid() )
253  {
254  FC_ASSERT( *extensions.value.maximum_short_squeeze_ratio >= GRAPHENE_MIN_COLLATERAL_RATIO );
255  FC_ASSERT( *extensions.value.maximum_short_squeeze_ratio <= GRAPHENE_MAX_COLLATERAL_RATIO );
256  }
257 
258  if( extensions.value.force_settle_fee_percent.valid() )
259  FC_ASSERT( *extensions.value.force_settle_fee_percent <= GRAPHENE_100_PERCENT );
260 
261 }
262 
264 {
265  FC_ASSERT( max_supply > 0 );
266  FC_ASSERT( max_supply <= GRAPHENE_MAX_SHARE_SUPPLY );
267  // The non-negative maker fee must be less than or equal to 100%
268  FC_ASSERT( market_fee_percent <= GRAPHENE_100_PERCENT );
269 
270  // The non-negative taker fee must be less than or equal to 100%
271  if( extensions.value.taker_fee_percent.valid() )
272  FC_ASSERT( *extensions.value.taker_fee_percent <= GRAPHENE_100_PERCENT );
273 
274  FC_ASSERT( max_market_fee >= 0 && max_market_fee <= GRAPHENE_MAX_SHARE_SUPPLY );
275  // There must be no high bits in permissions whose meaning is not known.
276  FC_ASSERT( !(issuer_permissions & ~ASSET_ISSUER_PERMISSION_MASK) );
277  // The permission-only bits can not be set in flag
278  FC_ASSERT( !(flags & global_settle),
279  "Can not set global_settle flag, it is for issuer permission only" );
280 
281  // the witness_fed and committee_fed flags cannot be set simultaneously
283  core_exchange_rate.validate();
284  FC_ASSERT( core_exchange_rate.base.asset_id.instance.value == 0 ||
285  core_exchange_rate.quote.asset_id.instance.value == 0 );
286 
287  if(!whitelist_authorities.empty() || !blacklist_authorities.empty())
288  FC_ASSERT( flags & white_list );
289  for( auto item : whitelist_markets )
290  {
291  FC_ASSERT( blacklist_markets.find(item) == blacklist_markets.end() );
292  }
293  for( auto item : blacklist_markets )
294  {
295  FC_ASSERT( whitelist_markets.find(item) == whitelist_markets.end() );
296  }
297  if( extensions.value.reward_percent.valid() )
298  FC_ASSERT( *extensions.value.reward_percent <= GRAPHENE_100_PERCENT );
299 }
300 
301 void asset_options::validate_flags( bool is_market_issued )const
302 {
303  FC_ASSERT( !(flags & ~ASSET_ISSUER_PERMISSION_MASK),
304  "Can not set an unknown bit in flags" );
305  // Note: global_settle is checked in validate(), so do not check again here
306  FC_ASSERT( !(flags & disable_mcr_update),
307  "Can not set disable_mcr_update flag, it is for issuer permission only" );
308  FC_ASSERT( !(flags & disable_icr_update),
309  "Can not set disable_icr_update flag, it is for issuer permission only" );
310  FC_ASSERT( !(flags & disable_mssr_update),
311  "Can not set disable_mssr_update flag, it is for issuer permission only" );
312  if( !is_market_issued )
313  {
314  FC_ASSERT( !(flags & ~UIA_ASSET_ISSUER_PERMISSION_MASK),
315  "Can not set a flag for bitassets only to UIA" );
316  }
317 }
318 
320 {
321  return ( (issuer_permissions & ASSET_ISSUER_PERMISSION_ENABLE_BITS_MASK)
322  | (~issuer_permissions & ASSET_ISSUER_PERMISSION_DISABLE_BITS_MASK) );
323 }
324 
326  FC_ASSERT( fee.amount >= 0 );
327  FC_ASSERT( amount_to_claim.amount > 0 );
328  if( extensions.value.claim_from_asset_id.valid() )
329  FC_ASSERT( *extensions.value.claim_from_asset_id != amount_to_claim.asset_id );
330 }
331 
333  FC_ASSERT( fee.amount >= 0 );
334  FC_ASSERT( fee.asset_id != asset_id);
335  FC_ASSERT( amount_to_claim.amount > 0 );
336  FC_ASSERT( amount_to_claim.asset_id == asset_id_type());
337 }
338 
339 } } // namespace graphene::protocol
340 
345 
348 
363 
Update the set of feed-producing accounts for a BitAssetBitAssets have price feeds selected by taking...
Definition: asset_ops.hpp:384
Definition: api.cpp:56
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:482
Schedules a market-issued asset for automatic settlementHolders of market-issued assests may request ...
Definition: asset_ops.hpp:226
bool valid() const
Definition: optional.hpp:186
the bitasset owner can not update MCR, permisison only
Definition: types.hpp:163
Publish price feeds for market-issued assetsPrice feed providers use this operation to publish their ...
Definition: asset_ops.hpp:415
#define GRAPHENE_MAX_SHARE_SUPPLY
Definition: config.hpp:38
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
share_type calculate_fee(const fee_parameters_type &k, optional< uint64_t > sub_asset_creation_fee) const
Definition: asset_ops.cpp:82
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:466
share_type calculate_fee(const fee_parameters_type &k) const
Definition: asset_ops.cpp:77
share_type calculate_fee(const fee_parameters_type &k) const
Definition: asset_ops.cpp:156
#define GRAPHENE_MAX_COLLATERAL_RATIO
higher than this is unnecessary and may exceed int16 storage
Definition: config.hpp:115
#define GRAPHENE_100_PERCENT
Definition: config.hpp:102
uint16_t get_enabled_issuer_permissions_mask() const
Definition: asset_ops.cpp:319
Update options specific to BitAssetsBitAssets have some options which are not relevant to other asset...
Definition: asset_ops.hpp:353
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
the bitasset owner can not update ICR, permisison only
Definition: types.hpp:164
#define GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION(type)
Definition: types.hpp:74
account_id_type issuer
Must be asset_to_issue->asset_id->issuer.
Definition: asset_ops.hpp:446
Update options common to all assetsThere are a number of options which all assets in the network use...
Definition: asset_ops.hpp:307
accounts must be whitelisted in order to hold or transact this asset
Definition: types.hpp:141
Transfers BTS from the fee pool of a specified asset back to the issuer&#39;s balance.
Definition: asset_ops.hpp:554
#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:147
asset_id_type asset_id
Definition: asset.hpp:39
allow the bitasset owner to force a global settling, permission only
Definition: types.hpp:145
static uint64_t calculate_data_fee(uint64_t bytes, uint64_t price_per_kbyte)
Definition: operations.cpp:33
void validate_flags(bool is_market_issued) const
Definition: asset_ops.cpp:301
#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:518
#define GRAPHENE_MIN_ASSET_SYMBOL_LENGTH
Definition: config.hpp:35
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:199