diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index a06f0e6d..536450cd 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -58,7 +58,7 @@ void_result asset_create_evaluator::do_evaluate( const asset_create_operation& o FC_ASSERT( op.bitasset_options->feed_lifetime_sec > chain_parameters.block_interval && op.bitasset_options->force_settlement_delay_sec > chain_parameters.block_interval ); } - if( op.is_prediction_market ) + if( op.is_prediction_market ) { FC_ASSERT( op.bitasset_options ); FC_ASSERT( op.precision == op.bitasset_options->short_backing_asset(d).precision ); @@ -313,6 +313,9 @@ void_result asset_update_feed_producers_evaluator::do_apply(const asset_update_f a.feeds[*itr]; a.update_median_feeds(db().head_block_time()); }); + db().modify(o.asset_to_update(db()), [this](asset_object& a) { + a.options.core_exchange_rate = bitasset_to_update->current_feed.core_exchange_rate; + }); db().check_call_orders( o.asset_to_update(db()) ); return void_result(); @@ -429,9 +432,12 @@ void_result asset_publish_feeds_evaluator::do_apply(const asset_publish_feed_ope a.feeds[o.publisher] = make_pair(d.head_block_time(), o.feed); a.update_median_feeds(d.head_block_time()); }); + d.modify(base, [&d](asset_object& a) { + a.options.core_exchange_rate = a.bitasset_data(d).current_feed.core_exchange_rate; + }); /// TODO: optimization: only do this if the median feed actually changed, otherwise there is no point - db().check_call_orders( base ); + db().check_call_orders(base); return void_result(); } FC_CAPTURE_AND_RETHROW((o)) } diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index 8890313d..51353ed8 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -219,16 +219,24 @@ void database::clear_expired_orders() void database::update_expired_feeds() { - auto& asset_idx = get_index_type(); - for( const asset_bitasset_data_object* b : asset_idx ) - if( b->feed_is_expired(head_block_time()) ) + auto& asset_idx = get_index_type().indices(); + for( const asset_object& a : asset_idx ) + { + if( !a.is_market_issued() ) + continue; + + const asset_bitasset_data_object& b = a.bitasset_data(*this); + if( b.feed_is_expired(head_block_time()) ) { - modify(*b, [this](asset_bitasset_data_object& a) { + modify(b, [this](asset_bitasset_data_object& a) { a.update_median_feeds(head_block_time()); }); - - check_call_orders( b->current_feed.settlement_price.base.asset_id(*this) ); + modify(a, [&b](asset_object& a) { + a.options.core_exchange_rate = b.current_feed.core_exchange_rate; + }); + check_call_orders(b.current_feed.settlement_price.base.asset_id(*this)); } + } } void database::update_withdraw_permissions() diff --git a/libraries/chain/include/graphene/chain/asset.hpp b/libraries/chain/include/graphene/chain/asset.hpp index 697099a8..af9d1719 100644 --- a/libraries/chain/include/graphene/chain/asset.hpp +++ b/libraries/chain/include/graphene/chain/asset.hpp @@ -141,10 +141,13 @@ namespace graphene { namespace chain { */ ///@{ /** - * Forced settlements will evaluate using this price, defined as BITASSET / COLLATERAL + * Forced settlements will evaluate using this price, defined as BITASSET / COLLATERAL */ price settlement_price; + /// Price at which automatically exchanging this asset for CORE from fee pool occurs (used for paying fees) + price core_exchange_rate; + /** Fixed point between 1.000 and 10.000, implied fixed point denominator is GRAPHENE_COLLATERAL_RATIO_DENOM */ uint16_t maintenance_collateral_ratio = GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO; @@ -154,14 +157,14 @@ namespace graphene { namespace chain { /** * When updating a call order the following condition must be maintained: * - * debt * maintenance_price() < collateral + * debt * maintenance_price() < collateral * debt * settlement_price < debt * maintenance - * debt * maintenance_price() < debt * max_short_squeeze_price() + * debt * maintenance_price() < debt * max_short_squeeze_price() price maintenance_price()const; */ - /** When selling collateral to pay off debt, the least amount of debt to receive should be - * min_usd = max_short_squeeze_price() * collateral + /** When selling collateral to pay off debt, the least amount of debt to receive should be + * min_usd = max_short_squeeze_price() * collateral * * This is provided to ensure that a black swan cannot be trigged due to poor liquidity alone, it * must be confirmed by having the max_short_squeeze_price() move below the black swan price. @@ -183,7 +186,8 @@ namespace graphene { namespace chain { FC_REFLECT( graphene::chain::asset, (amount)(asset_id) ) FC_REFLECT( graphene::chain::price, (base)(quote) ) -#define GRAPHENE_PRICE_FEED_FIELDS (settlement_price)(maintenance_collateral_ratio)(maximum_short_squeeze_ratio) +#define GRAPHENE_PRICE_FEED_FIELDS (settlement_price)(maintenance_collateral_ratio)(maximum_short_squeeze_ratio) \ + (core_exchange_rate) FC_REFLECT( graphene::chain::price_feed, GRAPHENE_PRICE_FEED_FIELDS ) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 84c45313..458a242a 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -400,7 +400,7 @@ const asset_object& database_fixture::create_bitasset( creator.fee = asset(); creator.symbol = name; creator.common_options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; - creator.precision = 2; + creator.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS; creator.common_options.market_fee_percent = market_fee_percent; creator.common_options.issuer_permissions = flags; creator.common_options.flags = flags & ~global_settle;