BitShares-Core  6.1.0
BitShares blockchain implementation and command-line interface software
asset_object.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 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 #pragma once
25 #include <graphene/chain/types.hpp>
28 
29 #include <boost/multi_index/composite_key.hpp>
30 
41 namespace graphene { namespace chain {
42  class asset_bitasset_data_object;
43 
56  class asset_dynamic_data_object : public abstract_object<asset_dynamic_data_object,
57  implementation_ids, impl_asset_dynamic_data_object_type>
58  {
59  public:
66  };
67 
75  class asset_object : public graphene::db::abstract_object<asset_object, protocol_ids, asset_object_type>
76  {
77  public:
81  static bool is_valid_symbol( const string& symbol );
82 
84  bool is_market_issued()const { return bitasset_data_id.valid(); }
86  bool is_liquidity_pool_share_asset()const { return for_liquidity_pool.valid(); }
88  bool can_force_settle()const { return (0 == (options.flags & disable_force_settle)); }
90  bool can_global_settle()const { return (0 != (options.issuer_permissions & global_settle)); }
92  bool charges_market_fees()const { return (0 != (options.flags & charge_market_fee)); }
94  bool is_transfer_restricted()const { return (0 != (options.flags & transfer_restricted)); }
95  bool can_override()const { return (0 != (options.flags & override_authority)); }
96  bool allow_confidential()const
97  { return (0 == (options.flags & asset_issuer_permission_flags::disable_confidential)); }
99  bool can_update_max_supply()const { return (0 == (options.flags & lock_max_supply)); }
101  bool can_create_new_supply()const { return (0 == (options.flags & disable_new_supply)); }
103  bool can_owner_update_mcr()const { return (0 == (options.issuer_permissions & disable_mcr_update)); }
105  bool can_owner_update_icr()const { return (0 == (options.issuer_permissions & disable_icr_update)); }
107  bool can_owner_update_mssr()const { return (0 == (options.issuer_permissions & disable_mssr_update)); }
109  bool can_owner_update_bsrm()const { return (0 == (options.issuer_permissions & disable_bsrm_update)); }
111  bool can_bid_collateral()const { return (0 == (options.flags & disable_collateral_bidding)); }
112 
114  asset amount(share_type a)const { return asset(a, asset_id_type(id)); }
117  asset amount_from_string(string amount_string)const;
119  string amount_to_string(share_type amount)const;
121  string amount_to_string(const asset& amount)const
122  { FC_ASSERT(amount.asset_id == get_id()); return amount_to_string(amount.amount); }
125  { return amount_to_string(amount) + " " + symbol; }
127  string amount_to_pretty_string(const asset &amount)const
128  { FC_ASSERT(amount.asset_id == get_id()); return amount_to_pretty_string(amount.amount); }
129 
131  string symbol;
133  uint8_t precision = 0;
135  account_id_type issuer;
136 
138 
140  asset_dynamic_data_id_type dynamic_asset_data_id;
143 
145 
148 
150  uint32_t creation_block_num = 0;
153 
154  void validate()const
155  {
156  // UIAs may not be prediction markets, have force settlement, or global settlements
157  if( !is_market_issued() )
158  {
159  FC_ASSERT(0 == (options.flags & disable_force_settle) && 0 == (options.flags & global_settle));
161  && 0 == (options.issuer_permissions & global_settle));
162  }
163  }
164 
165  template<class DB>
166  const asset_bitasset_data_object& bitasset_data(const DB& db)const
167  {
168  FC_ASSERT( bitasset_data_id.valid(),
169  "Asset ${a} (${id}) is not a market issued asset.",
170  ("a",this->symbol)("id",this->id) );
171  return db.get( *bitasset_data_id );
172  }
173 
174  template<class DB>
175  const asset_dynamic_data_object& dynamic_data(const DB& db)const
176  { return db.get(dynamic_asset_data_id); }
177 
181  template<class DB>
182  share_type reserved( const DB& db )const
183  { return options.max_supply - dynamic_data(db).current_supply; }
184 
186  template<class DB>
187  bool can_accumulate_fee(const DB& db, const asset& fee) const {
188  return (( fee.asset_id == get_id() ) ||
189  ( is_market_issued() && fee.asset_id == bitasset_data(db).options.short_backing_asset ));
190  }
191 
192  /***
193  * @brief receive a fee asset to accrue in dynamic_data object
194  *
195  * Asset owners define various fees (market fees, force-settle fees, etc.) to be
196  * collected for the asset owners. These fees are typically denominated in the asset
197  * itself, but for bitassets some of the fees are denominated in the collateral
198  * asset. This will place the fee in the right container.
199  */
200  template<class DB>
201  void accumulate_fee(DB& db, const asset& fee) const
202  {
203  if (fee.amount == 0) return;
204  FC_ASSERT( fee.amount >= 0, "Fee amount must be non-negative." );
205  const auto& dyn_data = dynamic_asset_data_id(db);
206  if (fee.asset_id == get_id()) { // fee same as asset
207  db.modify( dyn_data, [&fee]( asset_dynamic_data_object& obj ){
208  obj.accumulated_fees += fee.amount;
209  });
210  } else { // fee different asset; perhaps collateral-denominated fee
211  FC_ASSERT( is_market_issued(),
212  "Asset ${a} (${id}) cannot accept fee of asset (${fid}).",
213  ("a",this->symbol)("id",this->id)("fid",fee.asset_id) );
214  const auto & bad = bitasset_data(db);
215  FC_ASSERT( fee.asset_id == bad.options.short_backing_asset,
216  "Asset ${a} (${id}) cannot accept fee of asset (${fid}).",
217  ("a",this->symbol)("id",this->id)("fid",fee.asset_id) );
218  db.modify( dyn_data, [&fee]( asset_dynamic_data_object& obj ){
220  });
221  }
222  }
223 
224  };
225 
230  {
234  uint16_t initial_collateral_ratio = GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO;
235 
237  : price_feed(), initial_collateral_ratio( maintenance_collateral_ratio )
238  {}
239 
240  price_feed_with_icr( const price_feed& pf, const optional<uint16_t>& icr = {} )
241  : price_feed( pf ), initial_collateral_ratio( icr.valid() ? *icr : pf.maintenance_collateral_ratio )
242  {}
243 
246  price get_initial_collateralization()const;
247  };
248 
255  class asset_bitasset_data_object : public abstract_object<asset_bitasset_data_object,
256  implementation_ids, impl_asset_bitasset_data_object_type>
257  {
258  public:
260  asset_id_type asset_id;
261 
264 
268  flat_map<account_id_type, pair<time_point_sec,price_feed_with_icr>> feeds;
275 
278  { return ( median_feed.settlement_price != current_feed.settlement_price ); }
279 
289 
291  bool is_prediction_market = false;
292 
296  share_type max_force_settlement_volume(share_type current_supply)const;
297 
299  bool has_settlement()const { return !settlement_price.is_null(); }
300 
306  price settlement_price;
312 
322 
324  bool has_individual_settlement()const { return ( individual_settlement_debt != 0 ); }
325 
328  {
329  return asset( individual_settlement_debt, asset_id )
330  / asset( individual_settlement_fund, options.short_backing_asset );
331  }
332 
335  {
336  return options.get_black_swan_response_method();
337  }
338 
341  {
342  return current_feed.margin_call_order_price( options.extensions.value.margin_call_fee_ratio );
343  }
344 
347  {
348  return current_feed.margin_call_order_ratio( options.extensions.value.margin_call_fee_ratio );
349  }
350 
353  {
354  return current_feed.margin_call_pays_ratio( options.extensions.value.margin_call_fee_ratio );
355  }
356 
358  bool asset_cer_updated = false;
359 
361  bool feed_cer_updated = false;
362 
364  bool need_to_update_cer() const
365  {
366  return ( ( feed_cer_updated || asset_cer_updated ) && !current_feed.core_exchange_rate.is_null() );
367  }
368 
370  time_point_sec feed_expiration_time()const
371  {
372  uint32_t current_feed_seconds = current_feed_publication_time.sec_since_epoch();
373  if( (std::numeric_limits<uint32_t>::max() - current_feed_seconds) <= options.feed_lifetime_sec )
374  return time_point_sec::maximum();
375  else
376  return current_feed_publication_time + options.feed_lifetime_sec;
377  }
380  bool feed_is_expired_before_hf_615(time_point_sec current_time)const
381  { return feed_expiration_time() >= current_time; }
383  bool feed_is_expired(time_point_sec current_time)const
384  { return feed_expiration_time() <= current_time; }
385 
386  /******
387  * @brief calculate the median feed
388  *
389  * This calculates the median feed from @ref feeds, feed_lifetime_sec
390  * in @ref options, and the given parameters.
391  * It may update the @ref median_feed, @ref current_feed_publication_time,
392  * @ref current_initial_collateralization and
393  * @ref current_maintenance_collateralization member variables.
394  *
395  * @param current_time the current time to use in the calculations
396  * @param next_maintenance_time the next chain maintenance time
397  *
398  * @note Called by @ref database::update_bitasset_current_feed() which updates @ref current_feed afterwards.
399  */
400  void update_median_feeds(time_point_sec current_time, time_point_sec next_maintenance_time);
401  private:
404  void refresh_cache();
405  };
406 
409  {
410  using result_type = asset_id_type;
411  result_type operator() (const asset_bitasset_data_object& obj) const
412  {
413  return obj.options.short_backing_asset;
414  }
415  };
416 
417  struct by_short_backing_asset;
418  struct by_feed_expiration;
419  struct by_cer_update;
420 
421  using bitasset_data_multi_index_type = multi_index_container<
423  indexed_by<
424  ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
425  ordered_non_unique< tag<by_short_backing_asset>, bitasset_backing_asst_extractor >,
426  ordered_unique< tag<by_feed_expiration>,
427  composite_key< asset_bitasset_data_object,
428  const_mem_fun< asset_bitasset_data_object, time_point_sec,
430  member< asset_bitasset_data_object, asset_id_type, &asset_bitasset_data_object::asset_id >
431  >
432  >,
433  ordered_non_unique< tag<by_cer_update>,
434  const_mem_fun< asset_bitasset_data_object, bool,
436  >
437  >
438  >;
440 
441  struct by_symbol;
442  struct by_type;
443  struct by_issuer;
444  using asset_object_multi_index_type = multi_index_container<
445  asset_object,
446  indexed_by<
447  ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
448  ordered_unique< tag<by_symbol>, member<asset_object, string, &asset_object::symbol> >,
449  ordered_unique< tag<by_type>,
450  composite_key< asset_object,
451  const_mem_fun<asset_object, bool, &asset_object::is_market_issued>,
452  member< object, object_id_type, &object::id >
453  >
454  >,
455  ordered_unique< tag<by_issuer>,
456  composite_key< asset_object,
457  member< asset_object, account_id_type, &asset_object::issuer >,
458  member< object, object_id_type, &object::id >
459  >
460  >
461  >
462  >;
464 
465 } } // graphene::chain
466 
470 
472  (initial_collateral_ratio) )
473 
474 // Note: this is left here but not moved to a cpp file due to the extended_asset_object struct in API.
476  (symbol)
477  (precision)
478  (issuer)
479  (options)
480  (dynamic_asset_data_id)
481  (bitasset_data_id)
482  (buyback_account)
483  (for_liquidity_pool)
484  (creation_block_num)
485  (creation_time)
486  )
487 
490 
492 
the max supply of the asset can not be updated
Definition: types.hpp:211
ratio_type get_margin_call_order_ratio() const
Get margin call order ratio (MCOR) of this bitasset.
asset_id_type asset_id
The asset this object belong to.
multi_index_container< asset_object, indexed_by< ordered_unique< tag< by_id >, member< object, object_id_type, &object::id > >, ordered_unique< tag< by_symbol >, member< asset_object, string, &asset_object::symbol > >, ordered_unique< tag< by_type >, composite_key< asset_object, const_mem_fun< asset_object, bool, &asset_object::is_market_issued >, member< object, object_id_type, &object::id > > >, ordered_unique< tag< by_issuer >, composite_key< asset_object, member< asset_object, account_id_type, &asset_object::issuer >, member< object, object_id_type, &object::id > > > > > asset_object_multi_index_type
black_swan_response_type get_black_swan_response_method() const
Get the effective black swan response method.
Definition: asset_ops.hpp:180
price get_margin_call_order_price() const
Get margin call order price (MCOP) of this bitasset.
price get_individual_settlement_price() const
Get the price of the individual settlement pool.
require the issuer to be one party to every transfer
Definition: types.hpp:197
share_type reserved(const DB &db) const
contains properties that only apply to bitassets (market issued assets)
black_swan_response_type
Defines how a BitAsset would respond to black swan events.
Definition: asset_ops.hpp:112
share_type force_settled_volume
This is the volume of this asset which has been force-settled this maintanence interval.
bool can_accumulate_fee(const DB &db, const asset &fee) const
boost::rational< int32_t > ratio_type
Definition: types.hpp:150
bitasset_options::black_swan_response_type get_black_swan_response_method() const
Get the effective black swan response method of this bitasset.
Definition: api.cpp:48
ratio_type margin_call_pays_ratio(const fc::optional< uint16_t > &margin_call_fee_ratio) const
Definition: asset.cpp:334
The asset_options struct contains options available on all assets in the network. ...
Definition: asset_ops.hpp:47
#define MAP_OBJECT_ID_TO_TYPE(OBJECT)
Definition: object_id.hpp:93
multi_index_container< asset_bitasset_data_object, indexed_by< ordered_unique< tag< by_id >, member< object, object_id_type, &object::id > >, ordered_non_unique< tag< by_short_backing_asset >, bitasset_backing_asst_extractor >, ordered_unique< tag< by_feed_expiration >, composite_key< asset_bitasset_data_object, const_mem_fun< asset_bitasset_data_object, time_point_sec, &asset_bitasset_data_object::feed_expiration_time >, member< asset_bitasset_data_object, asset_id_type, &asset_bitasset_data_object::asset_id > > >, ordered_non_unique< tag< by_cer_update >, const_mem_fun< asset_bitasset_data_object, bool, &asset_bitasset_data_object::need_to_update_cer > > > > bitasset_data_multi_index_type
#define GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO
Call when collateral only pays off 175% the debt.
Definition: config.hpp:116
the bitasset owner can not update MSSR, permission only
Definition: types.hpp:221
ratio_type margin_call_order_ratio(const fc::optional< uint16_t > &margin_call_fee_ratio) const
Definition: asset.cpp:326
const asset_dynamic_data_object & dynamic_data(const DB &db) const
optional< account_id_type > buyback_account
time_point_sec creation_time
The time when the asset object was created.
defines market parameters for margin positions, extended with an initial_collateral_ratio field ...
void accumulate_fee(DB &db, const asset &fee) const
string amount_to_string(const asset &amount) const
Convert an asset to a textual representation, i.e. "123.45".
account_id_type issuer
ID of the account which issued this asset.
the bitasset owner can not update MCR, permission only
Definition: types.hpp:219
optional< liquidity_pool_id_type > for_liquidity_pool
The ID of the liquidity pool if the asset is the share asset of a liquidity pool. ...
price_feed_with_icr(const price_feed &pf, const optional< uint16_t > &icr={})
share_type accumulated_collateral_fees
accumulated collateral-denominated fees (for bitassets)
bool feed_is_expired(time_point_sec current_time) const
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
unable to create new supply for the asset
Definition: types.hpp:212
const asset_bitasset_data_object & bitasset_data(const DB &db) const
FC_REFLECT_TYPENAME(fc::log_message)
asset amount(share_type a) const
Helper function to get an asset object with the given amount in this asset&#39;s type.
static time_point_sec maximum()
Definition: time.hpp:86
price margin_call_order_price(const fc::optional< uint16_t > &margin_call_fee_ratio) const
Definition: asset.cpp:308
time_point_sec feed_expiration_time() const
The time when current_feed would expire.
uint16_t maintenance_collateral_ratio
Definition: asset.hpp:186
string amount_to_pretty_string(share_type amount) const
Convert an asset to a textual representation with symbol, i.e. "123.45 USD".
ratio_type get_margin_call_pays_ratio() const
Get margin call pays ratio (MCPR) of this bitasset.
#define GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION(type)
Definition: types.hpp:85
The price struct stores asset prices in the BitShares system.
Definition: asset.hpp:108
bool valid() const
Definition: optional.hpp:186
uint16_t issuer_permissions
The flags which the issuer has permission to update. See asset_issuer_permission_flags.
Definition: asset_ops.hpp:61
asset_dynamic_data_id_type dynamic_asset_data_id
Current supply, fee pool, and collected fees are stored in a separate object as they change frequentl...
string symbol
Ticker symbol for this asset, i.e. "USD".
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
price_feed_with_icr current_feed
This is the currently active price feed, calculated from median_feed and other parameters.
bool need_to_update_cer() const
Whether need to update core_exchange_rate in asset_object.
tracks the asset information that changes frequentlyBecause the asset_object is very large it doesn&#39;t...
the bitasset owner can not update ICR, permission only
Definition: types.hpp:220
uint32_t feed_lifetime_sec
Time before a price feed expires.
Definition: asset_ops.hpp:156
market trades in this asset may be charged
Definition: types.hpp:194
share_type individual_settlement_fund
Amount of collateral which is available for force settlement due to individual settlements.
Can not bid collateral after a global settlement.
Definition: types.hpp:223
share_type accumulated_fees
fees accumulate to be paid out over time
tracks the parameters of an assetAll assets have a globally unique symbol name that controls how they...
defines market parameters for margin positions
Definition: asset.hpp:160
asset_id_type asset_id
Definition: asset.hpp:37
allow the bitasset owner to force a global settlement, permission only
Definition: types.hpp:199
bitasset_options options
The tunable options for BitAssets are stored in this field.
#define FC_REFLECT_DERIVED(TYPE, INHERITS, MEMBERS)
Specializes fc::reflector for TYPE where type inherits other reflected classes.
Definition: reflect.hpp:305
string amount_to_pretty_string(const asset &amount) const
Convert an asset to a textual representation with symbol, i.e. "123.45 USD".
share_type confidential_supply
total asset held in confidential balances
uint16_t flags
The currently active flags on this permission. See asset_issuer_permission_flags. ...
Definition: asset_ops.hpp:63
issuer may transfer asset back to himself
Definition: types.hpp:196
bool is_liquidity_pool_share_asset() const
optional< asset_bitasset_data_id_type > bitasset_data_id
Extra data associated with BitAssets. This field is non-null if and only if is_market_issued() return...
base for all database objects
Definition: object.hpp:61
share_type current_supply
The number of shares currently in existence.
flat_map< account_id_type, pair< time_point_sec, price_feed_with_icr > > feeds
bool is_null() const
Definition: asset.cpp:229
Key extractor for short backing asset.
bool feed_is_expired_before_hf_615(time_point_sec current_time) const
the bitasset owner can not update BSRM, permission only
Definition: types.hpp:222
time_point_sec current_feed_publication_time
This is the publication time of the oldest feed which was factored into current_feed.
share_type settlement_fund
Amount of collateral which is available for force settlement due to global settlement.
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
price_feed_with_icr median_feed
This is the median of values from the currently active feeds.
disallow the asset to be used with confidential transactions
Definition: types.hpp:200
price core_exchange_rate
Price at which automatically exchanging this asset for CORE from fee pool occurs (used for paying fee...
Definition: asset.hpp:183