BitShares-Core  5.0.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  class database;
44  using namespace graphene::db;
45 
58  class asset_dynamic_data_object : public abstract_object<asset_dynamic_data_object>
59  {
60  public:
61  static constexpr uint8_t space_id = implementation_ids;
62  static constexpr uint8_t type_id = impl_asset_dynamic_data_object_type;
63 
70  };
71 
79  class asset_object : public graphene::db::abstract_object<asset_object>
80  {
81  public:
82  static constexpr uint8_t space_id = protocol_ids;
83  static constexpr uint8_t type_id = asset_object_type;
84 
88  static bool is_valid_symbol( const string& symbol );
89 
91  bool is_market_issued()const { return bitasset_data_id.valid(); }
93  bool is_liquidity_pool_share_asset()const { return for_liquidity_pool.valid(); }
95  bool can_force_settle()const { return !(options.flags & disable_force_settle); }
97  bool can_global_settle()const { return options.issuer_permissions & global_settle; }
99  bool charges_market_fees()const { return options.flags & charge_market_fee; }
101  bool is_transfer_restricted()const { return options.flags & transfer_restricted; }
102  bool can_override()const { return options.flags & override_authority; }
105  bool can_update_max_supply()const { return !(options.flags & lock_max_supply); }
107  bool can_create_new_supply()const { return !(options.flags & disable_new_supply); }
109  bool can_owner_update_mcr()const { return !(options.issuer_permissions & disable_mcr_update); }
111  bool can_owner_update_icr()const { return !(options.issuer_permissions & disable_icr_update); }
113  bool can_owner_update_mssr()const { return !(options.issuer_permissions & disable_mssr_update); }
114 
116  asset amount(share_type a)const { return asset(a, id); }
119  asset amount_from_string(string amount_string)const;
121  string amount_to_string(share_type amount)const;
123  string amount_to_string(const asset& amount)const
124  { FC_ASSERT(amount.asset_id == get_id()); return amount_to_string(amount.amount); }
127  { return amount_to_string(amount) + " " + symbol; }
129  string amount_to_pretty_string(const asset &amount)const
130  { FC_ASSERT(amount.asset_id == get_id()); return amount_to_pretty_string(amount.amount); }
131 
133  string symbol;
135  uint8_t precision = 0;
137  account_id_type issuer;
138 
140 
141 
143  asset_dynamic_data_id_type dynamic_asset_data_id;
146 
148 
151 
152  asset_id_type get_id()const { return id; }
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(!(options.flags & disable_force_settle || options.flags & global_settle));
161  }
162  }
163 
164  template<class DB>
165  const asset_bitasset_data_object& bitasset_data(const DB& db)const
166  {
167  FC_ASSERT( bitasset_data_id.valid(),
168  "Asset ${a} (${id}) is not a market issued asset.",
169  ("a",this->symbol)("id",this->id) );
170  return db.get( *bitasset_data_id );
171  }
172 
173  template<class DB>
174  const asset_dynamic_data_object& dynamic_data(const DB& db)const
175  { return db.get(dynamic_asset_data_id); }
176 
180  template<class DB>
181  share_type reserved( const DB& db )const
182  { return options.max_supply - dynamic_data(db).current_supply; }
183 
185  template<class DB>
186  bool can_accumulate_fee(const DB& db, const asset& fee) const {
187  return (( fee.asset_id == get_id() ) ||
188  ( is_market_issued() && fee.asset_id == bitasset_data(db).options.short_backing_asset ));
189  }
190 
191  /***
192  * @brief receive a fee asset to accrue in dynamic_data object
193  *
194  * Asset owners define various fees (market fees, force-settle fees, etc.) to be
195  * collected for the asset owners. These fees are typically denominated in the asset
196  * itself, but for bitassets some of the fees are denominated in the collateral
197  * asset. This will place the fee in the right container.
198  */
199  template<class DB>
200  void accumulate_fee(DB& db, const asset& fee) const
201  {
202  if (fee.amount == 0) return;
203  FC_ASSERT( fee.amount >= 0, "Fee amount must be non-negative." );
204  const auto& dyn_data = dynamic_asset_data_id(db);
205  if (fee.asset_id == get_id()) { // fee same as asset
206  db.modify( dyn_data, [&fee]( asset_dynamic_data_object& obj ){
207  obj.accumulated_fees += fee.amount;
208  });
209  } else { // fee different asset; perhaps collateral-denominated fee
210  FC_ASSERT( is_market_issued(),
211  "Asset ${a} (${id}) cannot accept fee of asset (${fid}).",
212  ("a",this->symbol)("id",this->id)("fid",fee.asset_id) );
213  const auto & bad = bitasset_data(db);
214  FC_ASSERT( fee.asset_id == bad.options.short_backing_asset,
215  "Asset ${a} (${id}) cannot accept fee of asset (${fid}).",
216  ("a",this->symbol)("id",this->id)("fid",fee.asset_id) );
217  db.modify( dyn_data, [&fee]( asset_dynamic_data_object& obj ){
219  });
220  }
221  }
222 
223  };
224 
229  {
233  uint16_t initial_collateral_ratio = GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO;
234 
236  : price_feed(), initial_collateral_ratio( maintenance_collateral_ratio )
237  {}
238 
239  price_feed_with_icr( const price_feed& pf, const optional<uint16_t>& icr = {} )
240  : price_feed( pf ), initial_collateral_ratio( icr.valid() ? *icr : pf.maintenance_collateral_ratio )
241  {}
242 
245  price calculate_initial_collateralization()const;
246  };
247 
254  class asset_bitasset_data_object : public abstract_object<asset_bitasset_data_object>
255  {
256  public:
257  static constexpr uint8_t space_id = implementation_ids;
258  static constexpr uint8_t type_id = impl_asset_bitasset_data_object_type;
259 
261  asset_id_type asset_id;
262 
265 
269  flat_map<account_id_type, pair<time_point_sec,price_feed_with_icr>> feeds;
275 
285 
288  void refresh_cache();
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 
307  price settlement_price;
313 
315  bool asset_cer_updated = false;
316 
318  bool feed_cer_updated = false;
319 
321  bool need_to_update_cer() const
322  {
323  return ( ( feed_cer_updated || asset_cer_updated ) && !current_feed.core_exchange_rate.is_null() );
324  }
325 
328  {
329  uint32_t current_feed_seconds = current_feed_publication_time.sec_since_epoch();
330  if( std::numeric_limits<uint32_t>::max() - current_feed_seconds <= options.feed_lifetime_sec )
331  return time_point_sec::maximum();
332  else
333  return current_feed_publication_time + options.feed_lifetime_sec;
334  }
336  { return feed_expiration_time() >= current_time; }
337  bool feed_is_expired(time_point_sec current_time)const
338  { return feed_expiration_time() <= current_time; }
339 
340  /******
341  * @brief calculate the median feed
342  *
343  * This calculates the median feed from @ref feeds, feed_lifetime_sec
344  * in @ref options, and the given parameters.
345  * It may update the current_feed_publication_time, current_feed and
346  * current_maintenance_collateralization member variables.
347  *
348  * @param current_time the current time to use in the calculations
349  * @param next_maintenance_time the next chain maintenance time
350  */
351  void update_median_feeds(time_point_sec current_time, time_point_sec next_maintenance_time);
352  };
353 
354  // key extractor for short backing asset
356  {
357  typedef asset_id_type result_type;
358  result_type operator() (const asset_bitasset_data_object& obj) const
359  {
360  return obj.options.short_backing_asset;
361  }
362  };
363 
364  struct by_short_backing_asset;
365  struct by_feed_expiration;
366  struct by_cer_update;
367 
368  typedef multi_index_container<
370  indexed_by<
371  ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
372  ordered_non_unique< tag<by_short_backing_asset>, bitasset_short_backing_asset_extractor >,
373  ordered_unique< tag<by_feed_expiration>,
374  composite_key< asset_bitasset_data_object,
375  const_mem_fun< asset_bitasset_data_object, time_point_sec, &asset_bitasset_data_object::feed_expiration_time >,
376  member< asset_bitasset_data_object, asset_id_type, &asset_bitasset_data_object::asset_id >
377  >
378  >,
379  ordered_non_unique< tag<by_cer_update>,
380  const_mem_fun< asset_bitasset_data_object, bool, &asset_bitasset_data_object::need_to_update_cer >
381  >
382  >
385 
386  struct by_symbol;
387  struct by_type;
388  struct by_issuer;
389  typedef multi_index_container<
390  asset_object,
391  indexed_by<
392  ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
393  ordered_unique< tag<by_symbol>, member<asset_object, string, &asset_object::symbol> >,
394  ordered_unique< tag<by_type>,
395  composite_key< asset_object,
396  const_mem_fun<asset_object, bool, &asset_object::is_market_issued>,
397  member< object, object_id_type, &object::id >
398  >
399  >,
400  ordered_unique< tag<by_issuer>,
401  composite_key< asset_object,
402  member< asset_object, account_id_type, &asset_object::issuer >,
403  member< object, object_id_type, &object::id >
404  >
405  >
406  >
409 
410 } } // graphene::chain
411 
415 
417  (initial_collateral_ratio) )
418 
419 FC_REFLECT_DERIVED( graphene::chain::asset_object, (graphene::db::object),
420  (symbol)
421  (precision)
422  (issuer)
423  (options)
424  (dynamic_asset_data_id)
425  (bitasset_data_id)
426  (buyback_account)
427  (for_liquidity_pool)
428  )
429 
432 
433 GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::chain::price_feed_with_icr )
434 
the max supply of the asset can not be updated
Definition: types.hpp:155
asset_id_type asset_id
The asset this object belong to.
time_point_sec feed_expiration_time() const
The time when current_feed would expire.
require the issuer to be one party to every transfer
Definition: types.hpp:143
contains properties that only apply to bitassets (market issued assets)
share_type force_settled_volume
This is the volume of this asset which has been force-settled this maintanence interval.
uint32_t sec_since_epoch() const
Definition: time.hpp:90
bool can_accumulate_fee(const DB &db, const asset &fee) const
generic_index< asset_bitasset_data_object, asset_bitasset_data_object_multi_index_type > asset_bitasset_data_index
Definition: api.cpp:56
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
#define GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO
Call when collateral only pays off 175% the debt.
Definition: config.hpp:116
bool valid() const
Definition: optional.hpp:186
optional< account_id_type > buyback_account
defines market parameters for margin positions, extended with an initial_collateral_ratio field ...
generic_index< asset_object, asset_object_multi_index_type > asset_index
bool feed_is_expired(time_point_sec current_time) const
account_id_type issuer
ID of the account which issued this asset.
the bitasset owner can not update MCR, permisison only
Definition: types.hpp:163
FC_REFLECT_DERIVED(graphene::app::extended_asset_object,(graphene::chain::asset_object),(total_in_collateral)(total_backing_collateral))
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={})
bool is_null() const
Definition: asset.cpp:225
share_type accumulated_collateral_fees
accumulated collateral-denominated fees (for bitassets)
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
string amount_to_pretty_string(const asset &amount) const
Convert an asset to a textual representation with symbol, i.e. "123.45 USD".
FC_REFLECT_TYPENAME(fc::log_message)
void accumulate_fee(DB &db, const asset &fee) const
static time_point_sec maximum()
Definition: time.hpp:86
uint16_t maintenance_collateral_ratio
Definition: asset.hpp:190
#define GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION(type)
Definition: types.hpp:73
bool feed_is_expired_before_hardfork_615(time_point_sec current_time) const
The price struct stores asset prices in the BitShares system.
Definition: asset.hpp:114
string amount_to_pretty_string(share_type amount) const
Convert an asset to a textual representation with symbol, i.e. "123.45 USD".
asset amount(share_type a) const
Helper function to get an asset object with the given amount in this asset&#39;s type.
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".
void update_median_feeds(database &db)
Definition: db_maint.cpp:991
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
tracks the asset information that changes frequentlyBecause the asset_object is very large it doesn&#39;t...
the bitasset owner can not update ICR, permisison only
Definition: types.hpp:164
uint32_t feed_lifetime_sec
Time before a price feed expires.
Definition: asset_ops.hpp:126
market trades in this asset may be charged
Definition: types.hpp:140
bool need_to_update_cer() const
Whether need to update core_exchange_rate in asset_object.
Use the Curiously Recurring Template Pattern to automatically add the ability to clone, serialize, and move objects polymorphically.
Definition: object.hpp:86
bool is_liquidity_pool_share_asset() const
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...
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
defines market parameters for margin positions
Definition: asset.hpp:164
string amount_to_string(const asset &amount) const
Convert an asset to a textual representation, i.e. "123.45".
asset_id_type asset_id
Definition: asset.hpp:39
allow the bitasset owner to force a global settling, permission only
Definition: types.hpp:145
bitasset_options options
The tunable options for BitAssets are stored in this field.
share_type confidential_supply
total asset held in confidential balances
asset_id_type get_id() const
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:142
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...
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
const asset_bitasset_data_object & bitasset_data(const DB &db) const
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_short_backing_asset_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 > > > > asset_bitasset_data_object_multi_index_type
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.
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
const asset_dynamic_data_object & dynamic_data(const DB &db) const
disallow the asset to be used with confidential transactions
Definition: types.hpp:146
share_type reserved(const DB &db) const
price core_exchange_rate
Price at which automatically exchanging this asset for CORE from fee pool occurs (used for paying fee...
Definition: asset.hpp:187