BitShares-Core  4.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 const uint8_t space_id = implementation_ids;
62  static const 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 const uint8_t space_id = protocol_ids;
83  static const 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 can_force_settle()const { return !(options.flags & disable_force_settle); }
95  bool can_global_settle()const { return options.issuer_permissions & global_settle; }
97  bool charges_market_fees()const { return options.flags & charge_market_fee; }
99  bool is_transfer_restricted()const { return options.flags & transfer_restricted; }
100  bool can_override()const { return options.flags & override_authority; }
103  bool can_update_max_supply()const { return !(options.flags & lock_max_supply); }
105  bool can_create_new_supply()const { return !(options.flags & disable_new_supply); }
107  bool can_owner_update_mcr()const { return !(options.issuer_permissions & disable_mcr_update); }
109  bool can_owner_update_icr()const { return !(options.issuer_permissions & disable_icr_update); }
111  bool can_owner_update_mssr()const { return !(options.issuer_permissions & disable_mssr_update); }
112 
114  asset amount(share_type a)const { return asset(a, 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 
139 
141  asset_dynamic_data_id_type dynamic_asset_data_id;
144 
146 
147  asset_id_type get_id()const { return id; }
148 
149  void validate()const
150  {
151  // UIAs may not be prediction markets, have force settlement, or global settlements
152  if( !is_market_issued() )
153  {
154  FC_ASSERT(!(options.flags & disable_force_settle || options.flags & global_settle));
156  }
157  }
158 
159  template<class DB>
160  const asset_bitasset_data_object& bitasset_data(const DB& db)const
161  {
162  FC_ASSERT( bitasset_data_id.valid(),
163  "Asset ${a} (${id}) is not a market issued asset.",
164  ("a",this->symbol)("id",this->id) );
165  return db.get( *bitasset_data_id );
166  }
167 
168  template<class DB>
169  const asset_dynamic_data_object& dynamic_data(const DB& db)const
170  { return db.get(dynamic_asset_data_id); }
171 
175  template<class DB>
176  share_type reserved( const DB& db )const
177  { return options.max_supply - dynamic_data(db).current_supply; }
178 
180  template<class DB>
181  bool can_accumulate_fee(const DB& db, const asset& fee) const {
182  return (( fee.asset_id == get_id() ) ||
183  ( is_market_issued() && fee.asset_id == bitasset_data(db).options.short_backing_asset ));
184  }
185 
186  /***
187  * @brief receive a fee asset to accrue in dynamic_data object
188  *
189  * Asset owners define various fees (market fees, force-settle fees, etc.) to be
190  * collected for the asset owners. These fees are typically denominated in the asset
191  * itself, but for bitassets some of the fees are denominated in the collateral
192  * asset. This will place the fee in the right container.
193  */
194  template<class DB>
195  void accumulate_fee(DB& db, const asset& fee) const
196  {
197  if (fee.amount == 0) return;
198  FC_ASSERT( fee.amount >= 0, "Fee amount must be non-negative." );
199  const auto& dyn_data = dynamic_asset_data_id(db);
200  if (fee.asset_id == get_id()) { // fee same as asset
201  db.modify( dyn_data, [&fee]( asset_dynamic_data_object& obj ){
202  obj.accumulated_fees += fee.amount;
203  });
204  } else { // fee different asset; perhaps collateral-denominated fee
205  FC_ASSERT( is_market_issued(),
206  "Asset ${a} (${id}) cannot accept fee of asset (${fid}).",
207  ("a",this->symbol)("id",this->id)("fid",fee.asset_id) );
208  const auto & bad = bitasset_data(db);
209  FC_ASSERT( fee.asset_id == bad.options.short_backing_asset,
210  "Asset ${a} (${id}) cannot accept fee of asset (${fid}).",
211  ("a",this->symbol)("id",this->id)("fid",fee.asset_id) );
212  db.modify( dyn_data, [&fee]( asset_dynamic_data_object& obj ){
214  });
215  }
216  }
217 
218  };
219 
224  {
228  uint16_t initial_collateral_ratio = GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO;
229 
231  : price_feed(), initial_collateral_ratio( maintenance_collateral_ratio )
232  {}
233 
234  price_feed_with_icr( const price_feed& pf, const optional<uint16_t>& icr = {} )
235  : price_feed( pf ), initial_collateral_ratio( icr.valid() ? *icr : pf.maintenance_collateral_ratio )
236  {}
237 
240  price calculate_initial_collateralization()const;
241  };
242 
249  class asset_bitasset_data_object : public abstract_object<asset_bitasset_data_object>
250  {
251  public:
252  static const uint8_t space_id = implementation_ids;
253  static const uint8_t type_id = impl_asset_bitasset_data_object_type;
254 
256  asset_id_type asset_id;
257 
260 
264  flat_map<account_id_type, pair<time_point_sec,price_feed_with_icr>> feeds;
270 
280 
283  void refresh_cache();
284 
286  bool is_prediction_market = false;
287 
291  share_type max_force_settlement_volume(share_type current_supply)const;
292 
294  bool has_settlement()const { return !settlement_price.is_null(); }
295 
302  price settlement_price;
308 
310  bool asset_cer_updated = false;
311 
313  bool feed_cer_updated = false;
314 
316  bool need_to_update_cer() const
317  {
318  return ( ( feed_cer_updated || asset_cer_updated ) && !current_feed.core_exchange_rate.is_null() );
319  }
320 
323  {
324  uint32_t current_feed_seconds = current_feed_publication_time.sec_since_epoch();
325  if( std::numeric_limits<uint32_t>::max() - current_feed_seconds <= options.feed_lifetime_sec )
326  return time_point_sec::maximum();
327  else
328  return current_feed_publication_time + options.feed_lifetime_sec;
329  }
331  { return feed_expiration_time() >= current_time; }
332  bool feed_is_expired(time_point_sec current_time)const
333  { return feed_expiration_time() <= current_time; }
334 
335  /******
336  * @brief calculate the median feed
337  *
338  * This calculates the median feed from @ref feeds, feed_lifetime_sec
339  * in @ref options, and the given parameters.
340  * It may update the current_feed_publication_time, current_feed and
341  * current_maintenance_collateralization member variables.
342  *
343  * @param current_time the current time to use in the calculations
344  * @param next_maintenance_time the next chain maintenance time
345  */
346  void update_median_feeds(time_point_sec current_time, time_point_sec next_maintenance_time);
347  };
348 
349  // key extractor for short backing asset
351  {
352  typedef asset_id_type result_type;
353  result_type operator() (const asset_bitasset_data_object& obj) const
354  {
355  return obj.options.short_backing_asset;
356  }
357  };
358 
359  struct by_short_backing_asset;
360  struct by_feed_expiration;
361  struct by_cer_update;
362 
363  typedef multi_index_container<
365  indexed_by<
366  ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
367  ordered_non_unique< tag<by_short_backing_asset>, bitasset_short_backing_asset_extractor >,
368  ordered_unique< tag<by_feed_expiration>,
369  composite_key< asset_bitasset_data_object,
370  const_mem_fun< asset_bitasset_data_object, time_point_sec, &asset_bitasset_data_object::feed_expiration_time >,
371  member< asset_bitasset_data_object, asset_id_type, &asset_bitasset_data_object::asset_id >
372  >
373  >,
374  ordered_non_unique< tag<by_cer_update>,
375  const_mem_fun< asset_bitasset_data_object, bool, &asset_bitasset_data_object::need_to_update_cer >
376  >
377  >
380 
381  struct by_symbol;
382  struct by_type;
383  struct by_issuer;
384  typedef multi_index_container<
385  asset_object,
386  indexed_by<
387  ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
388  ordered_unique< tag<by_symbol>, member<asset_object, string, &asset_object::symbol> >,
389  ordered_unique< tag<by_type>,
390  composite_key< asset_object,
391  const_mem_fun<asset_object, bool, &asset_object::is_market_issued>,
392  member< object, object_id_type, &object::id >
393  >
394  >,
395  ordered_unique< tag<by_issuer>,
396  composite_key< asset_object,
397  member< asset_object, account_id_type, &asset_object::issuer >,
398  member< object, object_id_type, &object::id >
399  >
400  >
401  >
404 
405 } } // graphene::chain
406 
410 
412  (initial_collateral_ratio) )
413 
414 FC_REFLECT_DERIVED( graphene::chain::asset_object, (graphene::db::object),
415  (symbol)
416  (precision)
417  (issuer)
418  (options)
419  (dynamic_asset_data_id)
420  (bitasset_data_id)
421  (buyback_account)
422  )
423 
426 
427 GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::chain::price_feed_with_icr )
428 
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))
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:990
#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:90
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.
bool is_transfer_restricted() const
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