diff --git a/libraries/chain/include/graphene/chain/market_evaluator.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp index 6696f62c6..26d90c229 100644 --- a/libraries/chain/include/graphene/chain/market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -65,7 +65,7 @@ namespace graphene { namespace chain { using operation_type = limit_order_update_operation; void_result do_evaluate(const limit_order_update_operation& o); - void_result do_apply(const limit_order_update_operation& o) const; + void_result do_apply(const limit_order_update_operation& o); /** override the default behavior defined by generic_evaluator */ @@ -77,9 +77,12 @@ namespace graphene { namespace chain { void pay_fee() override; private: + void process_deferred_fee(); + share_type _deferred_fee; asset _deferred_paid_fee; const limit_order_object* _order = nullptr; + const account_statistics_object* _seller_acc_stats = nullptr; }; class limit_order_cancel_evaluator : public evaluator diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index e33c99007..c44210f2e 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -243,104 +243,110 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o return {}; } -void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) const +void limit_order_update_evaluator::process_deferred_fee() { - database& d = db(); + // Attempt to deduct a possibly discounted order cancellation fee, and refund the remainder. + // Only deduct fee if there is any fee deferred. + // TODO fix duplicate code (see database::cancel_limit_order()) + if( _order->deferred_fee <= 0 ) + return; - const account_statistics_object* seller_acc_stats = nullptr; + database& d = db(); - // Adjust account balance - if( o.delta_amount_to_sell ) + share_type deferred_fee = _order->deferred_fee; + asset deferred_paid_fee = _order->deferred_paid_fee; + const asset_dynamic_data_object* fee_asset_dyn_data = nullptr; + const auto& current_fees = d.current_fee_schedule(); + asset core_cancel_fee = current_fees.calculate_fee( limit_order_cancel_operation() ); + if( core_cancel_fee.amount > 0 ) { - d.adjust_balance( o.seller, -*o.delta_amount_to_sell ); - if( o.delta_amount_to_sell->asset_id == asset_id_type() ) + // maybe-discounted cancel_fee calculation: + // limit_order_cancel_fee * limit_order_update_fee / limit_order_create_fee + asset core_create_fee = current_fees.calculate_fee( limit_order_create_operation() ); + fc::uint128_t fee128( core_cancel_fee.amount.value ); + if( core_create_fee.amount > 0 ) { - seller_acc_stats = &d.get_account_stats_by_owner( o.seller ); - d.modify( *seller_acc_stats, [&o]( account_statistics_object& bal ) { - bal.total_core_in_orders += o.delta_amount_to_sell->amount; - }); + asset core_update_fee = current_fees.calculate_fee( limit_order_update_operation() ); + fee128 *= core_update_fee.amount.value; + fee128 /= core_create_fee.amount.value; } + // cap the fee + if( fee128 > static_cast( deferred_fee.value ) ) + fee128 = deferred_fee.value; + core_cancel_fee.amount = static_cast( fee128 ); } - // Process deferred fee in the order. - // Attempt to deduct a possibly discounted order cancellation fee, and refund the remainder. - // Only deduct fee if there is any fee deferred. - // TODO fix duplicate code (see database::cancel_limit_order()) - if( _order->deferred_fee > 0 ) + // if there is any CORE fee to deduct, redirect it to referral program + if( core_cancel_fee.amount > 0 ) { - share_type deferred_fee = _order->deferred_fee; - asset deferred_paid_fee = _order->deferred_paid_fee; - const asset_dynamic_data_object* fee_asset_dyn_data = nullptr; - const auto& current_fees = d.current_fee_schedule(); - asset core_cancel_fee = current_fees.calculate_fee( limit_order_cancel_operation() ); - if( core_cancel_fee.amount > 0 ) + if( !_seller_acc_stats ) + _seller_acc_stats = &d.get_account_stats_by_owner( _order->seller ); + d.modify( *_seller_acc_stats, [&core_cancel_fee, &d]( account_statistics_object& obj ) { + obj.pay_fee( core_cancel_fee.amount, d.get_global_properties().parameters.cashback_vesting_threshold ); + } ); + deferred_fee -= core_cancel_fee.amount; + // handle originally paid fee if any: + // to_deduct = round_up( paid_fee * core_cancel_fee / deferred_core_fee_before_deduct ) + if( deferred_paid_fee.amount > 0 ) { - // maybe-discounted cancel_fee calculation: - // limit_order_cancel_fee * limit_order_update_fee / limit_order_create_fee - asset core_create_fee = current_fees.calculate_fee( limit_order_create_operation() ); - fc::uint128_t fee128( core_cancel_fee.amount.value ); - if( core_create_fee.amount > 0 ) - { - asset core_update_fee = current_fees.calculate_fee( limit_order_update_operation() ); - fee128 *= core_update_fee.amount.value; - fee128 /= core_create_fee.amount.value; - } - // cap the fee - if( fee128 > static_cast( deferred_fee.value ) ) - fee128 = deferred_fee.value; - core_cancel_fee.amount = static_cast( fee128 ); - } - // if there is any CORE fee to deduct, redirect it to referral program - if( core_cancel_fee.amount > 0 ) - { - if( !seller_acc_stats ) - seller_acc_stats = &d.get_account_stats_by_owner( o.seller ); - d.modify( *seller_acc_stats, [&core_cancel_fee, &d]( account_statistics_object& obj ) { - obj.pay_fee( core_cancel_fee.amount, d.get_global_properties().parameters.cashback_vesting_threshold ); - } ); - deferred_fee -= core_cancel_fee.amount; - // handle originally paid fee if any: - // to_deduct = round_up( paid_fee * core_cancel_fee / deferred_core_fee_before_deduct ) - if( deferred_paid_fee.amount > 0 ) - { - fc::uint128_t fee128( deferred_paid_fee.amount.value ); - fee128 *= core_cancel_fee.amount.value; - // to round up - fee128 += _order->deferred_fee.value; - fee128 -= 1; - fee128 /= _order->deferred_fee.value; - share_type cancel_fee_amount = static_cast(fee128); - // cancel_fee should be positive, pay it to asset's accumulated_fees - fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); - d.modify( *fee_asset_dyn_data, [&cancel_fee_amount](asset_dynamic_data_object& addo) { - addo.accumulated_fees += cancel_fee_amount; - }); - // cancel_fee should be no more than deferred_paid_fee - deferred_paid_fee.amount -= cancel_fee_amount; - } + fc::uint128_t fee128( deferred_paid_fee.amount.value ); + fee128 *= core_cancel_fee.amount.value; + // to round up + fee128 += _order->deferred_fee.value; + fee128 -= 1; + fee128 /= _order->deferred_fee.value; + share_type cancel_fee_amount = static_cast(fee128); + // cancel_fee should be positive, pay it to asset's accumulated_fees + fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); + d.modify( *fee_asset_dyn_data, [&cancel_fee_amount](asset_dynamic_data_object& addo) { + addo.accumulated_fees += cancel_fee_amount; + }); + // cancel_fee should be no more than deferred_paid_fee + deferred_paid_fee.amount -= cancel_fee_amount; } + } - // refund fee - if( 0 == _order->deferred_paid_fee.amount ) - { - // be here, order.create_time <= HARDFORK_CORE_604_TIME, or fee paid in CORE, or no fee to refund. - // if order was created before hard fork 604 then cancelled no matter before or after hard fork 604, - // see it as fee paid in CORE, deferred_fee should be refunded to order owner but not fee pool - d.adjust_balance( _order->seller, deferred_fee ); - } - else // need to refund fee in originally paid asset + // refund fee + if( 0 == _order->deferred_paid_fee.amount ) + { + // be here, order.create_time <= HARDFORK_CORE_604_TIME, or fee paid in CORE, or no fee to refund. + // if order was created before hard fork 604 then cancelled no matter before or after hard fork 604, + // see it as fee paid in CORE, deferred_fee should be refunded to order owner but not fee pool + d.adjust_balance( _order->seller, deferred_fee ); + } + else // need to refund fee in originally paid asset + { + d.adjust_balance( _order->seller, deferred_paid_fee ); + // be here, must have: fee_asset != CORE + if( !fee_asset_dyn_data ) + fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); + d.modify( *fee_asset_dyn_data, [&deferred_fee](asset_dynamic_data_object& addo) { + addo.fee_pool += deferred_fee; + }); + } + +} + +void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) +{ + database& d = db(); + + // Adjust account balance + if( o.delta_amount_to_sell ) + { + d.adjust_balance( o.seller, -*o.delta_amount_to_sell ); + if( o.delta_amount_to_sell->asset_id == asset_id_type() ) { - d.adjust_balance( _order->seller, deferred_paid_fee ); - // be here, must have: fee_asset != CORE - if( !fee_asset_dyn_data ) - fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); - d.modify( *fee_asset_dyn_data, [&deferred_fee](asset_dynamic_data_object& addo) { - addo.fee_pool += deferred_fee; + _seller_acc_stats = &d.get_account_stats_by_owner( o.seller ); + d.modify( *_seller_acc_stats, [&o]( account_statistics_object& bal ) { + bal.total_core_in_orders += o.delta_amount_to_sell->amount; }); } - } + // Process deferred fee in the order. + process_deferred_fee(); + // Update order d.modify(*_order, [&o,this](limit_order_object& loo) { if (o.new_price)