BitShares-Core  6.0.1
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  {
58  public:
59  static constexpr uint8_t space_id = implementation_ids;
60  static constexpr uint8_t type_id = impl_asset_dynamic_data_object_type;
61 
68  };
69 
77  class asset_object : public graphene::db::abstract_object<asset_object>
78  {
79  public:
80  static constexpr uint8_t space_id = protocol_ids;
81  static constexpr uint8_t type_id = asset_object_type;
82 
86  static bool is_valid_symbol( const string& symbol );
87 
89  bool is_market_issued()const { return bitasset_data_id.valid(); }
91  bool is_liquidity_pool_share_asset()const { return for_liquidity_pool.valid(); }
93  bool can_force_settle()const { return (0 == (options.flags & disable_force_settle)); }
95  bool can_global_settle()const { return (0 != (options.issuer_permissions & global_settle)); }
97  bool charges_market_fees()const { return (0 != (options.flags & charge_market_fee)); }
99  bool is_transfer_restricted()const { return (0 != (options.flags & transfer_restricted)); }
100  bool can_override()const { return (0 != (options.flags & override_authority)); }
101  bool allow_confidential()const
102  { return (0 == (options.flags & asset_issuer_permission_flags::disable_confidential)); }
104  bool can_update_max_supply()const { return (0 == (options.flags & lock_max_supply)); }
106  bool can_create_new_supply()const { return (0 == (options.flags & disable_new_supply)); }
108  bool can_owner_update_mcr()const { return (0 == (options.issuer_permissions & disable_mcr_update)); }
110  bool can_owner_update_icr()const { return (0 == (options.issuer_permissions & disable_icr_update)); }
112  bool can_owner_update_mssr()const { return (0 == (options.issuer_permissions & disable_mssr_update)); }
114  bool can_owner_update_bsrm()const { return (0 == (options.issuer_permissions & disable_bsrm_update)); }
116  bool can_bid_collateral()const { return (0 == (options.flags & disable_collateral_bidding)); }
117 
119  asset amount(share_type a)const { return asset(a, id); }
122  asset amount_from_string(string amount_string)const;
124  string amount_to_string(share_type amount)const;
126  string amount_to_string(const asset& amount)const
127  { FC_ASSERT(amount.asset_id == get_id()); return amount_to_string(amount.amount); }
130  { return amount_to_string(amount) + " " + symbol; }
132  string amount_to_pretty_string(const asset &amount)const
133  { FC_ASSERT(amount.asset_id == get_id()); return amount_to_pretty_string(amount.amount); }
134 
136  string symbol;
138  uint8_t precision = 0;
140  account_id_type issuer;
141 
143 
144 
146  asset_dynamic_data_id_type dynamic_asset_data_id;
148  optional<asset_bitasset_data_id_type> bitasset_data_id;
149 
150  optional<account_id_type> buyback_account;
151 
153  optional<liquidity_pool_id_type> for_liquidity_pool;
154 
155  asset_id_type get_id()const { return id; }
156 
157  void validate()const
158  {
159  // UIAs may not be prediction markets, have force settlement, or global settlements
160  if( !is_market_issued() )
161  {
162  FC_ASSERT(0 == (options.flags & disable_force_settle) && 0 == (options.flags & global_settle));
164  && 0 == (options.issuer_permissions & global_settle));
165  }
166  }
167 
168  template<class DB>
169  const asset_bitasset_data_object& bitasset_data(const DB& db)const
170  {
171  FC_ASSERT( bitasset_data_id.valid(),
172  "Asset ${a} (${id}) is not a market issued asset.",
173  ("a",this->symbol)("id",this->id) );
174  return db.get( *bitasset_data_id );
175  }
176 
177  template<class DB>
178  const asset_dynamic_data_object& dynamic_data(const DB& db)const
179  { return db.get(dynamic_asset_data_id); }
180 
184  template<class DB>
185  share_type reserved( const DB& db )const
186  { return options.max_supply - dynamic_data(db).current_supply; }
187 
189  template<class DB>
190  bool can_accumulate_fee(const DB& db, const asset& fee) const {
191  return (( fee.asset_id == get_id() ) ||
192  ( is_market_issued() && fee.asset_id == bitasset_data(db).options.short_backing_asset ));
193  }
194 
195  /***
196  * @brief receive a fee asset to accrue in dynamic_data object
197  *
198  * Asset owners define various fees (market fees, force-settle fees, etc.) to be
199  * collected for the asset owners. These fees are typically denominated in the asset
200  * itself, but for bitassets some of the fees are denominated in the collateral
201  * asset. This will place the fee in the right container.
202  */
203  template<class DB>
204  void accumulate_fee(DB& db, const asset& fee) const
205  {
206  if (fee.amount == 0) return;
207  FC_ASSERT( fee.amount >= 0, "Fee amount must be non-negative." );
208  const auto& dyn_data = dynamic_asset_data_id(db);
209  if (fee.asset_id == get_id()) { // fee same as asset
210  db.modify( dyn_data, [&fee]( asset_dynamic_data_object& obj ){
211  obj.accumulated_fees += fee.amount;
212  });
213  } else { // fee different asset; perhaps collateral-denominated fee
214  FC_ASSERT( is_market_issued(),
215  "Asset ${a} (${id}) cannot accept fee of asset (${fid}).",
216  ("a",this->symbol)("id",this->id)("fid",fee.asset_id) );
217  const auto & bad = bitasset_data(db);
218  FC_ASSERT( fee.asset_id == bad.options.short_backing_asset,
219  "Asset ${a} (${id}) cannot accept fee of asset (${fid}).",
220  ("a",this->symbol)("id",this->id)("fid",fee.asset_id) );
221  db.modify( dyn_data, [&fee]( asset_dynamic_data_object& obj ){
223  });
224  }
225  }
226 
227  };
228 
233  {
237  uint16_t initial_collateral_ratio = GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO;
238 
240  : price_feed(), initial_collateral_ratio( maintenance_collateral_ratio )
241  {}
242 
243  price_feed_with_icr( const price_feed& pf, const optional<uint16_t>& icr = {} )
244  : price_feed( pf ), initial_collateral_ratio( icr.valid() ? *icr : pf.maintenance_collateral_ratio )
245  {}
246 
249  price get_initial_collateralization()const;
250  };
251 
258  class asset_bitasset_data_object : public abstract_object<asset_bitasset_data_object>
259  {
260  public:
261  static constexpr uint8_t space_id = implementation_ids;
262  static constexpr uint8_t type_id = impl_asset_bitasset_data_object_type;
263 
265  asset_id_type asset_id;
266 
269 
273  flat_map<account_id_type, pair<time_point_sec,price_feed_with_icr>> feeds;
280 
283  { return ( median_feed.settlement_price != current_feed.settlement_price ); }
284 
294 
296  bool is_prediction_market = false;
297 
301  share_type max_force_settlement_volume(share_type current_supply)const;
302 
304  bool has_settlement()const { return !settlement_price.is_null(); }
305 
311  price settlement_price;
317 
327 
329  bool has_individual_settlement()const { return ( individual_settlement_debt != 0 ); }
330 
333  {
334  return asset( individual_settlement_debt, asset_id )
335  / asset( individual_settlement_fund, options.short_backing_asset );
336  }
337 
340  {
341  return options.get_black_swan_response_method();
342  }
343 
346  {
347  return current_feed.margin_call_order_price( options.extensions.value.margin_call_fee_ratio );
348  }
349 
352  {
353  return current_feed.margin_call_order_ratio( options.extensions.value.margin_call_fee_ratio );
354  }
355 
358  {
359  return current_feed.margin_call_pays_ratio( options.extensions.value.margin_call_fee_ratio );
360  }
361 
363  bool asset_cer_updated = false;
364 
366  bool feed_cer_updated = false;
367 
369  bool need_to_update_cer() const
370  {
371  return ( ( feed_cer_updated || asset_cer_updated ) && !current_feed.core_exchange_rate.is_null() );
372  }
373 
375  time_point_sec feed_expiration_time()const
376  {
377  uint32_t current_feed_seconds = current_feed_publication_time.sec_since_epoch();
378  if( (std::numeric_limits<uint32_t>::max() - current_feed_seconds) <= options.feed_lifetime_sec )
379  return time_point_sec::maximum();
380  else
381  return current_feed_publication_time + options.feed_lifetime_sec;
382  }
385  bool feed_is_expired_before_hf_615(time_point_sec current_time)const
386  { return feed_expiration_time() >= current_time; }
388  bool feed_is_expired(time_point_sec current_time)const
389  { return feed_expiration_time() <= current_time; }
390 
391  /******
392  * @brief calculate the median feed
393  *
394  * This calculates the median feed from @ref feeds, feed_lifetime_sec
395  * in @ref options, and the given parameters.
396  * It may update the @ref median_feed, @ref current_feed_publication_time,
397  * @ref current_initial_collateralization and
398  * @ref current_maintenance_collateralization member variables.
399  *
400  * @param current_time the current time to use in the calculations
401  * @param next_maintenance_time the next chain maintenance time
402  *
403  * @note Called by @ref database::update_bitasset_current_feed() which updates @ref current_feed afterwards.
404  */
405  void update_median_feeds(time_point_sec current_time, time_point_sec next_maintenance_time);
406  private:
409  void refresh_cache();
410  };
411 
414  {
415  using result_type = asset_id_type;
416  result_type operator() (const asset_bitasset_data_object& obj) const
417  {
418  return obj.options.short_backing_asset;
419  }
420  };
421 
422  struct by_short_backing_asset;
423  struct by_feed_expiration;
424  struct by_cer_update;
425 
426  using bitasset_data_multi_index_type = multi_index_container<
428  indexed_by<
429  ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
430  ordered_non_unique< tag<by_short_backing_asset>, bitasset_backing_asst_extractor >,
431  ordered_unique< tag<by_feed_expiration>,
432  composite_key< asset_bitasset_data_object,
433  const_mem_fun< asset_bitasset_data_object, time_point_sec,
435  member< asset_bitasset_data_object, asset_id_type, &asset_bitasset_data_object::asset_id >
436  >
437  >,
438  ordered_non_unique< tag<by_cer_update>,
439  const_mem_fun< asset_bitasset_data_object, bool,
441  >
442  >
443  >;
445 
446  struct by_symbol;
447  struct by_type;
448  struct by_issuer;
449  using asset_object_multi_index_type = multi_index_container<
450  asset_object,
451  indexed_by<
452  ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
453  ordered_unique< tag<by_symbol>, member<asset_object, string, &asset_object::symbol> >,
454  ordered_unique< tag<by_type>,
455  composite_key< asset_object,
456  const_mem_fun<asset_object, bool, &asset_object::is_market_issued>,
457  member< object, object_id_type, &object::id >
458  >
459  >,
460  ordered_unique< tag<by_issuer>,
461  composite_key< asset_object,
462  member< asset_object, account_id_type, &asset_object::issuer >,
463  member< object, object_id_type, &object::id >
464  >
465  >
466  >
467  >;
469 
470 } } // graphene::chain
471 
475 
477  (initial_collateral_ratio) )
478 
479 // Note: this is left here but not moved to a cpp file due to the extended_asset_object struct in API.
481  (symbol)
482  (precision)
483  (issuer)
484  (options)
485  (dynamic_asset_data_id)
486  (bitasset_data_id)
487  (buyback_account)
488  (for_liquidity_pool)
489  )
490 
493 
495 
the max supply of the asset can not be updated
Definition: types.hpp:172
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:160
share_type reserved(const DB &db) const
asset_id_type get_id() 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:56
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:98
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:184
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
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:182
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
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
object_id_type id
Definition: object.hpp:69
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
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:183
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:157
Use the Curiously Recurring Template Pattern to automatically add the ability to clone, serialize, and move objects polymorphically.
Definition: object.hpp:86
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:188
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:162
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:159
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:62
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:186
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:163
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