| 20 | static const uint64_t ORDER_OPEN_DEXOP_LIST_SIZE_MAX = 500; |
| 21 | |
| 22 | static bool ProcessDexOperatorFee(CBaseTx &tx, CTxExecuteContext& context, const string &action) { |
| 23 | |
| 24 | IMPLEMENT_DEFINE_CW_STATE; |
| 25 | uint64_t exchangeFee = 0; |
| 26 | if (action == OPERATOR_ACTION_REGISTER) { |
| 27 | if (!cw.sysParamCache.GetParam(DEX_OPERATOR_REGISTER_FEE, exchangeFee)) |
| 28 | return state.DoS(100, ERRORMSG("read param DEX_OPERATOR_REGISTER_FEE error"), |
| 29 | REJECT_INVALID, "read-sysparam-error"); |
| 30 | } else { |
| 31 | assert(action == OPERATOR_ACTION_UPDATE); |
| 32 | if (!cw.sysParamCache.GetParam(DEX_OPERATOR_UPDATE_FEE, exchangeFee)) |
| 33 | return state.DoS(100, ERRORMSG("read param DEX_OPERATOR_UPDATE_FEE error"), |
| 34 | REJECT_INVALID, "read-sysparam-error"); |
| 35 | } |
| 36 | |
| 37 | if (!tx.sp_tx_account->OperateBalance(SYMB::WICC, BalanceOpType::SUB_FREE, exchangeFee, |
| 38 | ReceiptType::DEX_OPERATOR_REG_UPDATE_FEE_FROM_OPERATOR, tx.receipts)) |
| 39 | return state.DoS(100, ERRORMSG("tx account insufficient funds for operator %s fee! fee=%llu, tx_addr=%s", |
| 40 | action, exchangeFee, tx.sp_tx_account->keyid.ToAddress()), |
| 41 | UPDATE_ACCOUNT_FAIL, "insufficent-funds"); |
| 42 | |
| 43 | uint64_t dexOperatorRiskFeeRatio; |
| 44 | if(!cw.sysParamCache.GetParam(SysParamType::DEX_OPERATOR_RISK_FEE_RATIO, dexOperatorRiskFeeRatio)) { |
| 45 | return state.DoS(100, ERRORMSG("ProcessDexOperatorFee, get dexOperatorRiskFeeRatio error"), |
| 46 | READ_SYS_PARAM_FAIL, "read-db-error"); |
| 47 | } |
| 48 | uint64_t riskFee = exchangeFee * dexOperatorRiskFeeRatio / RATIO_BOOST; |
| 49 | uint64_t minerTotalFee = exchangeFee - riskFee; |
| 50 | |
| 51 | auto spFcoinAccount = tx.GetAccount(context, SysCfg().GetFcoinGenesisRegId(), "fcoin"); |
| 52 | if (!spFcoinAccount) return false; |
| 53 | |
| 54 | ReceiptType code = (action == OPERATOR_ACTION_REGISTER) ? ReceiptType::DEX_OPERATOR_REG_FEE_TO_RESERVE : |
| 55 | ReceiptType::DEX_OPERATOR_UPDATED_FEE_TO_RESERVE; |
| 56 | |
| 57 | if (!spFcoinAccount->OperateBalance(SYMB::WICC, BalanceOpType::ADD_FREE, riskFee, code, tx.receipts)) { |
| 58 | return state.DoS(100, ERRORMSG("operate balance failed! add %s asset fee=%llu to risk reserve account error", |
| 59 | action, riskFee), UPDATE_ACCOUNT_FAIL, "update-account-failed"); |
| 60 | } |
| 61 | |
| 62 | VoteDelegateVector delegates; |
| 63 | if (!cw.delegateCache.GetActiveDelegates(delegates)) { |
| 64 | return state.DoS(100, ERRORMSG("GetActiveDelegates failed"), REJECT_INVALID, "get-delegates-failed"); |
| 65 | } |
| 66 | assert(delegates.size() != 0 ); |
| 67 | |
| 68 | for (size_t i = 0; i < delegates.size(); i++) { |
| 69 | const CRegID &delegateRegid = delegates[i].regid; |
| 70 | auto spDelegateAccount = tx.GetAccount(context, delegateRegid, "delegate_regid"); |
| 71 | if (!spDelegateAccount) return false; |
| 72 | uint64_t minerFee = minerTotalFee / delegates.size(); |
| 73 | if (i == 0) minerFee += minerTotalFee % delegates.size(); // give the dust amount to topmost miner |
| 74 | |
| 75 | ReceiptType code = (action == OPERATOR_ACTION_REGISTER) ? ReceiptType::DEX_OPERATOR_REG_FEE_TO_MINER : |
| 76 | ReceiptType::DEX_OPERATOR_UPDATED_FEE_TO_MINER; |
| 77 | |
| 78 | if (!spDelegateAccount->OperateBalance(SYMB::WICC, BalanceOpType::ADD_FREE, minerFee, code, tx.receipts)) { |
| 79 | return state.DoS(100, ERRORMSG("add %s asset fee to miner failed, miner regid=%s", |
no test coverage detected