From bf6ac84ffb1953691fff0c058b05ffee559c16c5 Mon Sep 17 00:00:00 2001 From: Bushstar Date: Tue, 14 Mar 2023 11:55:34 +0000 Subject: [PATCH 1/2] Remove require from ATTRIBUTES --- src/masternodes/errors.h | 200 ++++++++++ src/masternodes/govvariables/attributes.cpp | 409 ++++++++++++++------ 2 files changed, 482 insertions(+), 127 deletions(-) diff --git a/src/masternodes/errors.h b/src/masternodes/errors.h index e2022b1442a..30fe3ab6fb5 100644 --- a/src/masternodes/errors.h +++ b/src/masternodes/errors.h @@ -128,6 +128,206 @@ class DeFiErrors { static Res AmountOverflowAsValuePrice(const CAmount amount, const CAmount price) { return Res::Err("Value/price too high (%s/%s)", GetDecimalString(amount), GetDecimalString(price)); } + + static Res GovVarVerifyInt() { + return Res::Err("Value must be an integer"); + } + + static Res GovVarVerifyPositiveNumber() { + return Res::Err("Value must be a positive integer"); + } + + static Res GovVarInvalidNumber() { + return Res::Err("Amount must be a valid number"); + } + + static Res GovVarVerifySplitValues() { + return Res::Err("Two int values expected for split in id/mutliplier"); + } + + static Res GovVarVerifyMultiplier() { + return Res::Err("Mutliplier cannot be zero"); + } + + static Res GovVarVerifyPair() { + return Res::Err("Exactly two entires expected for currency pair"); + } + + static Res GovVarVerifyValues() { + return Res::Err("Empty token / currency"); + } + + static Res GovVarVerifyFeeDirection() { + return Res::Err("Fee direction value must be both, in or out"); + } + + static Res GovVarVariableLength() { + return Res::Err("Identifier exceeds maximum length (128)"); + } + + static Res GovVarVariableNoVersion() { + return Res::Err("Empty version"); + } + + static Res GovVarUnsupportedVersion() { + return Res::Err("Unsupported version"); + } + + static Res GovVarVariableNumberOfKey() { + return Res::Err("Incorrect key for . Object of ['//ID/','value'] expected"); + } + + static Res GovVarVariableInvalidKey(const std::string &key, const std::map &keys) { + std::string error{"Unrecognised " + key + " argument provided, valid " + key + "s are:"}; + for (const auto &pair : keys) { + error += ' ' + pair.first + ','; + } + return Res::Err(error); + } + + static Res GovVarVariableUnsupportedType(const unsigned char type) { + return Res::Err("Unsupported type {%d}", type); + } + + static Res GovVarVariableUnsupportedDFIPType(const unsigned char type) { + return Res::Err("Unsupported type for DFIP2206A {%d}", type); + } + + static Res GovVarVariableUnsupportedFeatureType(const unsigned char type) { + return Res::Err("Unsupported type for Feature {%d}", type); + } + + static Res GovVarVariableUnsupportedFoundationType(const unsigned char type) { + return Res::Err("Unsupported type for Foundation {%d}", type); + } + + static Res GovVarVariableUnsupportedProposalType(const unsigned char type) { + return Res::Err("Unsupported key for Governance Proposal section - {%d}", type); + } + + static Res GovVarVariableUnsupportedParamType() { + return Res::Err("Unsupported Param ID"); + } + + static Res GovVarVariableUnsupportedGovType() { + return Res::Err("Unsupported Governance ID"); + } + + static Res GovVarVariableKeyCount(const uint32_t expected, const std::vector &keys) { + return Res::Err("Exact %d keys are required {%d}", expected, keys.size()); + } + + static Res GovVarImportObjectExpected() { + return Res::Err("Object of values expected"); + } + + static Res GovVarValidateFortCanningHill() { + return Res::Err("Cannot be set before FortCanningHill"); + } + + static Res GovVarValidateFortCanningEpilogue() { + return Res::Err("Cannot be set before FortCanningEpilogue"); + } + + static Res GovVarValidateFortCanningRoad() { + return Res::Err("Cannot be set before FortCanningRoad"); + } + + static Res GovVarValidateFortCanningCrunch() { + return Res::Err("Cannot be set before FortCanningCrunch"); + } + + static Res GovVarValidateFortCanningSpring() { + return Res::Err("Cannot be set before FortCanningSpringHeight"); + } + + static Res GovVarValidateToken(const uint32_t token) { + return Res::Err("No such token (%d)", token); + } + + static Res GovVarValidateTokenExist(const uint32_t token) { + return Res::Err("Token (%d) does not exist", token); + } + + static Res GovVarValidateLoanToken(const uint32_t token) { + return Res::Err("No such loan token (%d)", token); + } + + static Res GovVarValidateLoanTokenID(const uint32_t token) { + return Res::Err("No loan token with id (%d)", token); + } + + static Res GovVarValidateExcessAmount() { + return Res::Err("Percentage exceeds 100%%"); + } + + static Res GovVarValidateNegativeAmount() { + return Res::Err("Amount must be a positive value"); + } + + static Res GovVarValidateCurrencyPair() { + return Res::Err("Fixed interval price currency pair must be set first"); + } + + static Res GovVarUnsupportedValue() { + return Res::Err("Unsupported value"); + } + + static Res GovVarValidateUnsupportedKey() { + return Res::Err("Unsupported key"); + } + + static Res GovVarValidateSplitDFI() { + return Res::Err("Tokenised DFI cannot be split"); + } + + static Res GovVarValidateSplitPool() { + return Res::Err("Pool tokens cannot be split"); + } + + static Res GovVarValidateSplitDAT() { + return Res::Err("Only DATs can be split"); + } + + static Res GovVarApplyUnexpectedType() { + return Res::Err("Unexpected type"); + } + + static Res GovVarApplyInvalidPool(const uint32_t pool) { + return Res::Err("No such pool (%d)", pool); + } + + static Res GovVarApplyInvalidFactor(const CAmount ratio) { + return Res::Err("Factor cannot be more than or equal to the lowest scheme rate of %d", GetDecimalString(ratio * CENT)); + } + + static Res GovVarApplyDFIPActive(const std::string &str) { + return Res::Err("Cannot set block period while %d is active", str); + } + + static Res GovVarApplyBelowHeight() { + return Res::Err("Cannot be set at or below current height"); + } + + static Res GovVarApplyAutoNoToken(const uint32_t token) { + return Res::Err("Auto lock. No loan token with id (%d)", token); + } + + static Res GovVarApplyLockFail() { + return Res::Err("Failed to create Gov var for lock"); + } + + static Res GovVarApplyCastFail() { + return Res::Err("Failed to cast Gov var to ATTRIBUTES"); + } + + static Res GovVarEraseLive() { + return Res::Err("Live attribute cannot be deleted"); + } + + static Res GovVarEraseNonExist(const uint32_t type) { + return Res::Err("Attribute {%d} not exists", type); + } }; #endif // DEFI_MASTERNODES_ERRORS_H diff --git a/src/masternodes/govvariables/attributes.cpp b/src/masternodes/govvariables/attributes.cpp index 849de0cf0c1..ddef9bb8211 100644 --- a/src/masternodes/govvariables/attributes.cpp +++ b/src/masternodes/govvariables/attributes.cpp @@ -6,6 +6,7 @@ #include #include /// CAccountsHistoryWriter +#include /// DeFiErrors #include /// CHiistoryWriter #include /// CCustomCSView #include /// GetAggregatePrice / CustomTxType @@ -309,39 +310,49 @@ const std::map> &ATTRIBUTES::displayKeys static ResVal VerifyInt32(const std::string &str) { int32_t int32; - Require(ParseInt32(str, &int32), []{ return "Value must be an integer"; }); + if (!ParseInt32(str, &int32)) { + return DeFiErrors::GovVarVerifyInt(); + } return {int32, Res::Ok()}; } static ResVal VerifyPositiveInt32(const std::string &str) { int32_t int32; - Require(ParseInt32(str, &int32) && int32 >= 0, []{ return "Value must be a positive integer"; }); + if (!ParseInt32(str, &int32) || int32 < 0) { + return DeFiErrors::GovVarVerifyPositiveNumber(); + } return {int32, Res::Ok()}; } static ResVal VerifyUInt32(const std::string &str) { uint32_t uint32; if (!ParseUInt32(str, &uint32)) { - return Res::Err("Value must be an integer"); + return DeFiErrors::GovVarVerifyInt(); } return {uint32, Res::Ok()}; } static ResVal VerifyInt64(const std::string &str) { CAmount int64; - Require(ParseInt64(str, &int64) && int64 >= 0, []{ return "Value must be a positive integer"; }); + if (!ParseInt64(str, &int64) || int64 < 0) { + return DeFiErrors::GovVarVerifyPositiveNumber(); + } return {int64, Res::Ok()}; } static ResVal VerifyFloat(const std::string &str) { CAmount amount = 0; - Require(ParseFixedPoint(str, 8, &amount), []{ return "Amount must be a valid number"; }); + if (!ParseFixedPoint(str, 8, &amount)) { + return DeFiErrors::GovVarInvalidNumber(); + } return {amount, Res::Ok()}; } ResVal VerifyPositiveFloat(const std::string &str) { CAmount amount = 0; - Require(ParseFixedPoint(str, 8, &amount) && amount >= 0, []{ return "Amount must be a positive value"; }); + if (!ParseFixedPoint(str, 8, &amount) || amount < 0) { + return DeFiErrors::GovVarValidateNegativeAmount(); + } return {amount, Res::Ok()}; } @@ -382,13 +393,21 @@ static ResVal VerifyBool(const std::string &str) { static ResVal VerifySplit(const std::string &str) { OracleSplits splits; const auto pairs = KeyBreaker(str); - Require(pairs.size() == 2, []{ return "Two int values expected for split in id/mutliplier"; }); + if (pairs.size() != 2) { + return DeFiErrors::GovVarVerifySplitValues(); + } const auto resId = VerifyPositiveInt32(pairs[0]); - Require(resId); + if (!resId) { + return resId; + } const auto resMultiplier = VerifyInt32(pairs[1]); - Require(resMultiplier); - Require(*resMultiplier != 0, []{ return "Mutliplier cannot be zero"; }); + if (!resMultiplier) { + return resMultiplier; + } + if (*resMultiplier == 0) { + return DeFiErrors::GovVarVerifyMultiplier(); + } splits[*resId] = *resMultiplier; @@ -435,11 +454,15 @@ static ResVal VerifyMember(const UniValue &array) { static ResVal VerifyCurrencyPair(const std::string &str) { const auto value = KeyBreaker(str); - Require(value.size() == 2, []{ return "Exactly two entires expected for currency pair"; }); + if (value.size() != 2) { + return DeFiErrors::GovVarVerifyPair(); + } auto token = trim_all_ws(value[0]).substr(0, CToken::MAX_TOKEN_SYMBOL_LENGTH); auto currency = trim_all_ws(value[1]).substr(0, CToken::MAX_TOKEN_SYMBOL_LENGTH); - Require(!token.empty() && !currency.empty(), []{ return "Empty token / currency"; }); + if (token.empty() || currency.empty()) { + return DeFiErrors::GovVarVerifyValues(); + } return { CTokenCurrencyPair{token, currency}, Res::Ok() @@ -451,7 +474,9 @@ static std::set dirSet{"both", "in", "out"}; static ResVal VerifyFeeDirection(const std::string &str) { auto lowerStr = ToLower(str); const auto it = dirSet.find(lowerStr); - Require(it != dirSet.end(), []{ return "Fee direction value must be both, in or out"; }); + if (it == dirSet.end()) { + return DeFiErrors::GovVarVerifyFeeDirection(); + } return {CFeeDir{static_cast(std::distance(dirSet.begin(), it))}, Res::Ok()}; } @@ -608,14 +633,6 @@ ResVal GetFutureSwapContractAddress(const std::string &contract) { return {contractAddress, Res::Ok()}; } -std::string ShowError(const std::string &key, const std::map &keys) { - std::string error{"Unrecognised " + key + " argument provided, valid " + key + "s are:"}; - for (const auto &pair : keys) { - error += ' ' + pair.first + ','; - } - return error; -} - static void TrackLiveBalance(CCustomCSView &mnview, const CTokenAmount &amount, const EconomyKeys dataKey, @@ -666,45 +683,66 @@ void TrackLiveBalances(CCustomCSView &mnview, const CBalances &balances, const u Res ATTRIBUTES::ProcessVariable(const std::string &key, const std::optional &value, std::function applyVariable) { - Require(key.size() <= 128, []{ return "Identifier exceeds maximum length (128)"; }); + if (key.size() > 128) { + return DeFiErrors::GovVarVariableLength(); + } const auto keys = KeyBreaker(key); - Require(!keys.empty() && !keys[0].empty(), []{ return "Empty version"; }); + if (keys.empty() || keys[0].empty()) { + return DeFiErrors::GovVarVariableNoVersion(); + } auto iver = allowedVersions().find(keys[0]); - Require(iver != allowedVersions().end(), []{ return "Unsupported version"; }); + if (iver == allowedVersions().end()) { + return DeFiErrors::GovVarUnsupportedVersion(); + } auto version = iver->second; - Require(version == VersionTypes::v0, []{ return "Unsupported version"; }); + if (version != VersionTypes::v0) { + return DeFiErrors::GovVarUnsupportedVersion(); + } - Require(keys.size() >= 4 && !keys[1].empty() && !keys[2].empty() && !keys[3].empty(), - []{ return "Incorrect key for . Object of ['//ID/','value'] expected"; }); + if (keys.size() < 4 || keys[1].empty() || keys[2].empty() || keys[3].empty()) { + return DeFiErrors::GovVarVariableNumberOfKey(); + } auto itype = allowedTypes().find(keys[1]); - Require(itype != allowedTypes().end(), [=]{ return ::ShowError("type", allowedTypes()); }); + if (itype == allowedTypes().end()) { + return DeFiErrors::GovVarVariableInvalidKey("type", allowedTypes()); + } const auto type = itype->second; uint32_t typeId{0}; if (type == AttributeTypes::Param) { auto id = allowedParamIDs().find(keys[2]); - Require(id != allowedParamIDs().end(), [=]{ return ::ShowError("param", allowedParamIDs()); }); + if (id == allowedParamIDs().end()) { + return DeFiErrors::GovVarVariableInvalidKey("param", allowedParamIDs()); + } typeId = id->second; } else if (type == AttributeTypes::Locks) { auto id = allowedLocksIDs().find(keys[2]); - Require(id != allowedLocksIDs().end(), [=]{ return ::ShowError("locks", allowedLocksIDs()); }); + if (id == allowedLocksIDs().end()) { + return DeFiErrors::GovVarVariableInvalidKey("locks", allowedLocksIDs()); + } typeId = id->second; } else if (type == AttributeTypes::Oracles) { auto id = allowedOracleIDs().find(keys[2]); - Require(id != allowedOracleIDs().end(), [=]{ return ::ShowError("oracles", allowedOracleIDs()); }); + if (id == allowedOracleIDs().end()) { + return DeFiErrors::GovVarVariableInvalidKey("oracles", allowedOracleIDs()); + } typeId = id->second; } else if (type == AttributeTypes::Governance) { auto id = allowedGovernanceIDs().find(keys[2]); - Require(id != allowedGovernanceIDs().end(), [=]{ return ::ShowError("governance", allowedGovernanceIDs()); }); + if (id == allowedGovernanceIDs().end()) { + return DeFiErrors::GovVarVariableInvalidKey("governance", allowedGovernanceIDs()); + } typeId = id->second; } else { auto id = VerifyInt32(keys[2]); - Require(id); + if (!id) { + return id; + } typeId = *id.val; } @@ -723,7 +761,9 @@ Res ATTRIBUTES::ProcessVariable(const std::string &key, } } else { auto ikey = allowedKeys().find(type); - Require(ikey != allowedKeys().end(), [=]{ return strprintf("Unsupported type {%d}", type); }); + if (ikey == allowedKeys().end()) { + return DeFiErrors::GovVarVariableUnsupportedType(type); + } // Alias of reward_pct in Export. if (keys[3] == "fee_pct") { @@ -731,7 +771,9 @@ Res ATTRIBUTES::ProcessVariable(const std::string &key, } itype = ikey->second.find(keys[3]); - Require(itype != ikey->second.end(), [=]{ return ::ShowError("key", ikey->second); }); + if (itype == ikey->second.end()) { + return DeFiErrors::GovVarVariableInvalidKey("key", ikey->second); + } typeKey = itype->second; @@ -754,23 +796,23 @@ Res ATTRIBUTES::ProcessVariable(const std::string &key, } } } else if (typeId == ParamIDs::DFIP2206A) { - Require(typeKey == DFIPKeys::DUSDInterestBurn || typeKey == DFIPKeys::DUSDLoanBurn, - [=]{ return strprintf("Unsupported type for DFIP2206A {%d}", - typeKey); }); + if (typeKey != DFIPKeys::DUSDInterestBurn && typeKey != DFIPKeys::DUSDLoanBurn) { + return DeFiErrors::GovVarVariableUnsupportedDFIPType(typeKey); + } } else if (typeId == ParamIDs::Feature) { if (typeKey != DFIPKeys::GovUnset && typeKey != DFIPKeys::GovFoundation && typeKey != DFIPKeys::MNSetRewardAddress && typeKey != DFIPKeys::MNSetOperatorAddress && typeKey != DFIPKeys::MNSetOwnerAddress && typeKey != DFIPKeys::GovernanceEnabled && typeKey != DFIPKeys::ConsortiumEnabled && typeKey != DFIPKeys::CFPPayout && typeKey != DFIPKeys::EmissionUnusedFund && typeKey != DFIPKeys::MintTokens) { - return Res::Err("Unsupported type for Feature {%d}", typeKey); + return DeFiErrors::GovVarVariableUnsupportedFeatureType(typeKey); } } else if (typeId == ParamIDs::Foundation) { if (typeKey != DFIPKeys::Members) { - return Res::Err("Unsupported type for Foundation {%d}", typeKey); + return DeFiErrors::GovVarVariableUnsupportedFoundationType(typeKey); } } else { - return Res::Err("Unsupported Param ID"); + return DeFiErrors::GovVarVariableUnsupportedParamType(); } } else if (type == AttributeTypes::Governance) { if (typeId == GovernanceIDs::Proposals) { @@ -780,9 +822,9 @@ Res ATTRIBUTES::ProcessVariable(const std::string &key, typeKey != GovernanceKeys::VOCEmergencyPeriod && typeKey != GovernanceKeys::VOCEmergencyFee && typeKey != GovernanceKeys::VOCEmergencyQuorum && typeKey != GovernanceKeys::Quorum && typeKey != GovernanceKeys::VotingPeriod && typeKey != GovernanceKeys::CFPMaxCycles) - return Res::Err("Unsupported key for Governance Proposal section - {%d}", typeKey); + return DeFiErrors::GovVarVariableUnsupportedProposalType(typeKey); } else { - return Res::Err("Unsupported Governance ID"); + return DeFiErrors::GovVarVariableUnsupportedGovType(); } } @@ -790,12 +832,18 @@ Res ATTRIBUTES::ProcessVariable(const std::string &key, } if (attrV0.IsExtendedSize()) { - Require(keys.size() == 5 && !keys[4].empty(), [=]{ return strprintf("Exact 5 keys are required {%d}", keys.size()); }); + if (keys.size() != 5 || keys[4].empty()) { + return DeFiErrors::GovVarVariableKeyCount(5, keys); + } auto id = VerifyInt32(keys[4]); - Require(id); + if (!id) { + return id; + } attrV0.keyId = *id.val; } else { - Require(keys.size() == 4, [=]{ return strprintf("Exact 4 keys are required {%d}", keys.size()); }); + if (keys.size() != 4) { + return DeFiErrors::GovVarVariableKeyCount(4, keys); + } } if (!value) { @@ -885,15 +933,21 @@ Res ATTRIBUTES::RefundFuturesContracts(CCustomCSView &mnview, const uint32_t hei mnview.EraseFuturesUserValues(key); CAccountsHistoryWriter subView(mnview, currentHeight, GetNextAccPosition(), {}, uint8_t(CustomTxType::FutureSwapRefund)); - Require(subView.SubBalance(*contractAddressValue, value.source)); + if (auto res = subView.SubBalance(*contractAddressValue, value.source); !res) { + return res; + } subView.Flush(); CAccountsHistoryWriter addView(mnview, currentHeight, GetNextAccPosition(), {}, uint8_t(CustomTxType::FutureSwapRefund)); - Require(addView.AddBalance(key.owner, value.source)); + if (auto res = addView.AddBalance(key.owner, value.source); !res) { + return res; + } addView.Flush(); - Require(balances.Sub(value.source)); + if (auto res = balances.Sub(value.source); !res) { + return res; + } } SetValue(liveKey, std::move(balances)); @@ -942,7 +996,10 @@ Res ATTRIBUTES::RefundFuturesDUSD(CCustomCSView &mnview, const uint32_t height) } addView.Flush(); - Require(balances.Sub({DCT_ID{}, amount})); + res = balances.Sub({DCT_ID{}, amount}); + if (!res) { + return res; + } } SetValue(liveKey, std::move(balances)); @@ -951,7 +1008,9 @@ Res ATTRIBUTES::RefundFuturesDUSD(CCustomCSView &mnview, const uint32_t height) } Res ATTRIBUTES::Import(const UniValue &val) { - Require(val.isObject(), []{ return "Object of values expected"; }); + if (!val.isObject()) { + return DeFiErrors::GovVarImportObjectExpected(); + } std::map objMap; val.getObjMap(objMap); @@ -1230,73 +1289,101 @@ UniValue ATTRIBUTES::Export() const { } Res ATTRIBUTES::Validate(const CCustomCSView &view) const { - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningHillHeight, - []{ return "Cannot be set before FortCanningHill"; }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningHillHeight) { + return DeFiErrors::GovVarValidateFortCanningHill(); + } for (const auto &[key, value] : attributes) { const auto attrV0 = std::get_if(&key); - Require(attrV0, []{ return "Unsupported version"; }); + if (!attrV0) { + return DeFiErrors::GovVarUnsupportedVersion(); + } switch (attrV0->type) { case AttributeTypes::Token: switch (attrV0->key) { case TokenKeys::LoanPaybackCollateral: - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningEpilogueHeight, - []{ return "Cannot be set before FortCanningEpilogue"; }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningEpilogueHeight) { + return DeFiErrors::GovVarValidateFortCanningEpilogue(); + } [[fallthrough]]; case TokenKeys::PaybackDFI: case TokenKeys::PaybackDFIFeePCT: - Require(view.GetLoanTokenByID({attrV0->typeId}), [=]{ return strprintf("No such loan token (%d)", attrV0->typeId); }); + if (!view.GetLoanTokenByID({attrV0->typeId})) { + return DeFiErrors::GovVarValidateLoanToken(attrV0->typeId); + } break; case TokenKeys::LoanPayback: case TokenKeys::LoanPaybackFeePCT: - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningRoadHeight, - []{ return "Cannot be set before FortCanningRoad"; }); - Require( - view.GetLoanTokenByID(DCT_ID{attrV0->typeId}), "No such loan token (%d)", attrV0->typeId); - Require(view.GetToken(DCT_ID{attrV0->keyId}), [=]{ return strprintf("No such token (%d)", attrV0->keyId); }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningRoadHeight) { + return DeFiErrors::GovVarValidateFortCanningRoad(); + } + if (!view.GetLoanTokenByID({attrV0->typeId})) { + return DeFiErrors::GovVarValidateLoanToken(attrV0->typeId); + } + if (!view.GetToken(DCT_ID{attrV0->keyId})) { + return DeFiErrors::GovVarValidateToken(attrV0->keyId); + } break; case TokenKeys::DexInFeePct: case TokenKeys::DexOutFeePct: - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningRoadHeight, - []{ return "Cannot be set before FortCanningRoad"; }); - Require(view.GetToken(DCT_ID{attrV0->typeId}), [=]{ return strprintf("No such token (%d)", attrV0->typeId); }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningRoadHeight) { + return DeFiErrors::GovVarValidateFortCanningRoad(); + } + if (!view.GetToken(DCT_ID{attrV0->typeId})) { + return DeFiErrors::GovVarValidateToken(attrV0->typeId); + } break; case TokenKeys::LoanCollateralFactor: if (view.GetLastHeight() < Params().GetConsensus().FortCanningEpilogueHeight) { const auto amount = std::get_if(&value); - if (amount) - Require(*amount <= COIN, []{ return "Percentage exceeds 100%%"; }); + if (amount) { + if (*amount > COIN) { + return DeFiErrors::GovVarValidateExcessAmount(); + } + } } [[fallthrough]]; case TokenKeys::LoanMintingInterest: if (view.GetLastHeight() < Params().GetConsensus().FortCanningGreatWorldHeight) { const auto amount = std::get_if(&value); - if (amount) - Require(*amount >= 0, []{ return "Amount must be a positive value"; }); + if (amount) { + if (*amount < 0) { + return DeFiErrors::GovVarValidateNegativeAmount(); + } + } } [[fallthrough]]; case TokenKeys::LoanCollateralEnabled: case TokenKeys::LoanMintingEnabled: { - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningCrunchHeight, - []{ return "Cannot be set before FortCanningCrunch"; }); - Require(VerifyToken(view, attrV0->typeId), [=]{ return strprintf("No such token (%d)", attrV0->typeId); }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningCrunchHeight) { + return DeFiErrors::GovVarValidateFortCanningCrunch(); + } + if (!VerifyToken(view, attrV0->typeId)) { + return DeFiErrors::GovVarValidateToken(attrV0->typeId); + } CDataStructureV0 intervalPriceKey{ AttributeTypes::Token, attrV0->typeId, TokenKeys::FixedIntervalPriceId}; - Require(!(GetValue(intervalPriceKey, CTokenCurrencyPair{}) == CTokenCurrencyPair{}), - []{ return "Fixed interval price currency pair must be set first"; }); + if (GetValue(intervalPriceKey, CTokenCurrencyPair{}) == CTokenCurrencyPair{}) { + return DeFiErrors::GovVarValidateCurrencyPair(); + } break; } case TokenKeys::FixedIntervalPriceId: - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningCrunchHeight, - []{ return "Cannot be set before FortCanningCrunch"; }); - Require(VerifyToken(view, attrV0->typeId), [=]{ return strprintf("No such token (%d)", attrV0->typeId); }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningCrunchHeight) { + return DeFiErrors::GovVarValidateFortCanningCrunch(); + } + if (!VerifyToken(view, attrV0->typeId)) { + return DeFiErrors::GovVarValidateToken(attrV0->typeId); + } break; case TokenKeys::DFIP2203Enabled: - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningRoadHeight, - []{ return "Cannot be set before FortCanningRoad"; }); - Require( - view.GetLoanTokenByID(DCT_ID{attrV0->typeId}), [=]{ return strprintf("No such loan token (%d)", attrV0->typeId); }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningRoadHeight) { + return DeFiErrors::GovVarValidateFortCanningRoad(); + } + if (!view.GetLoanTokenByID({attrV0->typeId})) { + return DeFiErrors::GovVarValidateLoanToken(attrV0->typeId); + } break; case TokenKeys::Ascendant: case TokenKeys::Descendant: @@ -1354,23 +1441,35 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { break; case AttributeTypes::Oracles: - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningCrunchHeight, - []{ return "Cannot be set before FortCanningCrunch"; }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningCrunchHeight) { + return DeFiErrors::GovVarValidateFortCanningCrunch(); + } if (attrV0->typeId == OracleIDs::Splits) { const auto splitMap = std::get_if(&value); - Require(splitMap, []{ return "Unsupported value"; }); + if (!splitMap) { + return DeFiErrors::GovVarUnsupportedValue(); + } for (const auto &[tokenId, multipler] : *splitMap) { - Require(tokenId != 0, []{ return "Tokenised DFI cannot be split"; }); - Require(!view.HasPoolPair(DCT_ID{tokenId}), []{ return "Pool tokens cannot be split"; }); + if (tokenId == 0) { + return DeFiErrors::GovVarValidateSplitDFI(); + } + if (view.HasPoolPair({tokenId})) { + return DeFiErrors::GovVarValidateSplitPool(); + } const auto token = view.GetToken(DCT_ID{tokenId}); - Require(token, [tokenId=tokenId]{ return strprintf("Token (%d) does not exist", tokenId); }); - Require(token->IsDAT(), []{ return "Only DATs can be split"; }); - Require( - view.GetLoanTokenByID(DCT_ID{tokenId}).has_value(), [tokenId=tokenId]{ return strprintf("No loan token with id (%d)", tokenId); }); + if (!token) { + return DeFiErrors::GovVarValidateTokenExist(tokenId); + } + if (!token->IsDAT()) { + return DeFiErrors::GovVarValidateSplitDAT(); + } + if (!view.GetLoanTokenByID({tokenId})) { + return DeFiErrors::GovVarValidateLoanTokenID(tokenId); + } } } else { - return Res::Err("Unsupported key"); + return DeFiErrors::GovVarValidateUnsupportedKey(); } break; @@ -1378,13 +1477,18 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { switch (attrV0->key) { case PoolKeys::TokenAFeePCT: case PoolKeys::TokenBFeePCT: - Require(view.GetPoolPair({attrV0->typeId}), [=]{ return strprintf("No such pool (%d)", attrV0->typeId); }); + if (!view.GetPoolPair({attrV0->typeId})) { + return DeFiErrors::GovVarApplyInvalidPool(attrV0->typeId); + } break; case PoolKeys::TokenAFeeDir: case PoolKeys::TokenBFeeDir: - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningSpringHeight, - []{ return "Cannot be set before FortCanningSpringHeight"; }); - Require(view.GetPoolPair({attrV0->typeId}), [=]{ return strprintf("No such pool (%d)", attrV0->typeId); }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningSpringHeight) { + return DeFiErrors::GovVarValidateFortCanningSpring(); + } + if (!view.GetPoolPair({attrV0->typeId})) { + return DeFiErrors::GovVarApplyInvalidPool(attrV0->typeId); + } break; default: return Res::Err("Unsupported key"); @@ -1411,8 +1515,9 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { return Res::Err("Cannot be set before FortCanningSpringHeight"); } } else if (attrV0->typeId == ParamIDs::DFIP2203) { - Require(view.GetLastHeight() >= Params().GetConsensus().FortCanningRoadHeight, - []{ return "Cannot be set before FortCanningRoadHeight"; }); + if (view.GetLastHeight() < Params().GetConsensus().FortCanningRoadHeight) { + return DeFiErrors::GovVarValidateFortCanningRoad(); + } } else if (attrV0->typeId != ParamIDs::DFIP2201) { return Res::Err("Unrecognised param id"); } @@ -1458,11 +1563,15 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { if (attrV0->key == PoolKeys::TokenAFeePCT || attrV0->key == PoolKeys::TokenBFeePCT) { auto poolId = DCT_ID{attrV0->typeId}; auto pool = mnview.GetPoolPair(poolId); - Require(pool, [=]{ return strprintf("No such pool (%d)", poolId.v); }); + if (!pool) { + return DeFiErrors::GovVarApplyInvalidPool(poolId.v); + } auto tokenId = attrV0->key == PoolKeys::TokenAFeePCT ? pool->idTokenA : pool->idTokenB; const auto valuePct = std::get_if(&attribute.second); - Require(valuePct, []{ return "Unexpected type"; }); + if (!valuePct) { + return DeFiErrors::GovVarApplyUnexpectedType(); + } if (auto res = mnview.SetDexFeePct(poolId, tokenId, *valuePct); !res) { return res; } @@ -1474,7 +1583,9 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { std::swap(tokenA, tokenB); } const auto valuePct = std::get_if(&attribute.second); - Require(valuePct, []{ return "Unexpected type"; }); + if (!valuePct) { + return DeFiErrors::GovVarApplyUnexpectedType(); + } if (auto res = mnview.SetDexFeePct(tokenA, tokenB, *valuePct); !res) { return res; } @@ -1498,20 +1609,26 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { if (aggregatePrice) { fixedIntervalPrice.priceRecord[1] = aggregatePrice; } - Require(mnview.SetFixedIntervalPrice(fixedIntervalPrice)); + if (auto res = mnview.SetFixedIntervalPrice(fixedIntervalPrice); !res) { + return res; + } } else { return Res::Err("Unrecognised value for FixedIntervalPriceId"); } } else if (attrV0->key == TokenKeys::DFIP2203Enabled) { const auto value = std::get_if(&attribute.second); - Require(value, []{ return "Unexpected type"; }); + if (!value) { + return DeFiErrors::GovVarApplyUnexpectedType(); + } if (*value) { continue; } const auto token = mnview.GetLoanTokenByID(DCT_ID{attrV0->typeId}); - Require(token, [=]{ return strprintf("No such loan token (%d)", attrV0->typeId); }); + if (!token) { + return DeFiErrors::GovVarValidateLoanTokenID(attrV0->typeId); + } // Special case: DUSD will be used as a source for swaps but will // be set as disabled for Future swap destination. @@ -1519,12 +1636,16 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { continue; } - Require(RefundFuturesContracts(mnview, height, attrV0->typeId)); + if (auto res = RefundFuturesContracts(mnview, height, attrV0->typeId); !res) { + return res; + } } else if (attrV0->key == TokenKeys::LoanMintingInterest) { if (height >= static_cast(Params().GetConsensus().FortCanningGreatWorldHeight) && interestTokens.count(attrV0->typeId)) { const auto tokenInterest = std::get_if(&attribute.second); - Require(tokenInterest, []{ return "Unexpected type"; }); + if (!tokenInterest) { + return DeFiErrors::GovVarApplyUnexpectedType(); + } std::set affectedVaults; mnview.ForEachLoanTokenAmount([&](const CVaultId &vaultId, const CBalances &balances) { @@ -1565,10 +1686,12 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { } } else { const auto factor = std::get_if(&attribute.second); - Require(factor, []{ return "Unexpected type"; }); - Require(*factor < *ratio.begin() * CENT, [=]{ return strprintf( - "Factor cannot be more than or equal to the lowest scheme rate of %d\n", - GetDecimalString(*ratio.begin() * CENT)); }); + if (!factor) { + return DeFiErrors::GovVarApplyUnexpectedType(); + } + if (*factor >= *ratio.begin() * CENT) { + return DeFiErrors::GovVarApplyInvalidFactor(*ratio.begin()); + } } } } @@ -1576,13 +1699,17 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { if (attrV0->typeId == ParamIDs::DFIP2203) { if (attrV0->key == DFIPKeys::Active) { const auto value = std::get_if(&attribute.second); - Require(value, []{ return "Unexpected type"; }); + if (!value) { + return DeFiErrors::GovVarApplyUnexpectedType(); + } if (*value) { continue; } - Require(RefundFuturesContracts(mnview, height)); + if (auto res = RefundFuturesContracts(mnview, height); !res) { + return res; + } } else if (attrV0->key == DFIPKeys::BlockPeriod || attrV0->key == DFIPKeys::StartBlock) { // Only check this when block period has been set, otherwise // it will fail when DFIP2203 active is set to true. @@ -1591,18 +1718,24 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { } CDataStructureV0 activeKey{AttributeTypes::Param, ParamIDs::DFIP2203, DFIPKeys::Active}; - Require(!GetValue(activeKey, false), []{ return "Cannot set block period while DFIP2203 is active"; }); + if (GetValue(activeKey, false)) { + return DeFiErrors::GovVarApplyDFIPActive("DFIP2203"); + } } } else if (attrV0->typeId == ParamIDs::DFIP2206F) { if (attrV0->key == DFIPKeys::Active) { const auto value = std::get_if(&attribute.second); - Require(value, []{ return "Unexpected type"; }); + if (!value) { + return DeFiErrors::GovVarApplyUnexpectedType(); + } if (*value) { continue; } - Require(RefundFuturesDUSD(mnview, height)); + if (auto res = RefundFuturesDUSD(mnview, height); !res) { + return res; + } } else if (attrV0->key == DFIPKeys::BlockPeriod) { // Only check this when block period has been set, otherwise // it will fail when DFIP2206F active is set to true. @@ -1611,42 +1744,55 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { } CDataStructureV0 activeKey{AttributeTypes::Param, ParamIDs::DFIP2206F, DFIPKeys::Active}; - Require(!GetValue(activeKey, false), []{ return "Cannot set block period while DFIP2206F is active"; }); + if (GetValue(activeKey, false)) { + return DeFiErrors::GovVarApplyDFIPActive("DFIP2206F"); + } } } } else if (attrV0->type == AttributeTypes::Oracles && attrV0->typeId == OracleIDs::Splits) { const auto value = std::get_if(&attribute.second); - Require(value, []{ return "Unsupported value"; }); + if (!value) { + return DeFiErrors::GovVarUnsupportedValue(); + } for (const auto split : tokenSplits) { if (auto it{value->find(split)}; it == value->end()) { continue; } - Require(attrV0->key > height, []{ return "Cannot be set at or below current height"; }); + if (attrV0->key <= height) { + return DeFiErrors::GovVarApplyBelowHeight(); + } CDataStructureV0 lockKey{AttributeTypes::Locks, ParamIDs::TokenID, split}; if (GetValue(lockKey, false)) { continue; } - Require( - mnview.GetLoanTokenByID(DCT_ID{split}).has_value(), [=]{ return strprintf("Auto lock. No loan token with id (%d)", split); }); + if (!mnview.GetLoanTokenByID(DCT_ID{split})) { + return DeFiErrors::GovVarApplyAutoNoToken(split); + } const auto startHeight = attrV0->key - Params().GetConsensus().blocksPerDay() / 2; if (height < startHeight) { auto var = GovVariable::Create("ATTRIBUTES"); - Require(var, []{ return "Failed to create Gov var for lock"; }); + if (!var) { + return DeFiErrors::GovVarApplyLockFail(); + } auto govVar = std::dynamic_pointer_cast(var); - Require(govVar, []{ return "Failed to cast Gov var to ATTRIBUTES"; }); + if (!govVar) { + return DeFiErrors::GovVarApplyCastFail(); + } govVar->attributes[lockKey] = true; CGovernanceHeightMessage lock; lock.startHeight = startHeight; lock.govVar = govVar; - Require(storeGovVars(lock, mnview)); + if (auto res = storeGovVars(lock, mnview); !res) { + return res; + } } else { // Less than a day's worth of blocks, apply instant lock SetValue(lockKey, true); @@ -1659,17 +1805,23 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { Res ATTRIBUTES::Erase(CCustomCSView &mnview, uint32_t, const std::vector &keys) { for (const auto &key : keys) { - Require(ProcessVariable(key, {}, [&](const CAttributeType &attribute, const CAttributeValue &) { + auto res = ProcessVariable(key, {}, [&](const CAttributeType &attribute, const CAttributeValue &) { auto attrV0 = std::get_if(&attribute); if (!attrV0) { return Res::Ok(); } - Require(attrV0->type != AttributeTypes::Live, []{ return "Live attribute cannot be deleted"; }); - Require(EraseKey(attribute), [=]{ return strprintf("Attribute {%d} not exists", attrV0->type); }); + if (attrV0->type == AttributeTypes::Live) { + return DeFiErrors::GovVarEraseLive(); + } + if (!EraseKey(attribute)) { + return DeFiErrors::GovVarEraseNonExist(attrV0->type); + } if (attrV0->type == AttributeTypes::Poolpairs) { auto poolId = DCT_ID{attrV0->typeId}; auto pool = mnview.GetPoolPair(poolId); - Require(pool, [=]{ return strprintf("No such pool (%d)", poolId.v); }); + if (!pool) { + return DeFiErrors::GovVarApplyInvalidPool(poolId.v); + } auto tokenId = attrV0->key == PoolKeys::TokenAFeePCT ? pool->idTokenA : pool->idTokenB; return mnview.EraseDexFeePct(poolId, tokenId); @@ -1683,7 +1835,10 @@ Res ATTRIBUTES::Erase(CCustomCSView &mnview, uint32_t, const std::vector Date: Wed, 15 Mar 2023 10:41:56 +0800 Subject: [PATCH 2/2] Fix format of errors for strings --- src/masternodes/errors.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/masternodes/errors.h b/src/masternodes/errors.h index 30fe3ab6fb5..f6ff28caaec 100644 --- a/src/masternodes/errors.h +++ b/src/masternodes/errors.h @@ -298,11 +298,11 @@ class DeFiErrors { } static Res GovVarApplyInvalidFactor(const CAmount ratio) { - return Res::Err("Factor cannot be more than or equal to the lowest scheme rate of %d", GetDecimalString(ratio * CENT)); + return Res::Err("Factor cannot be more than or equal to the lowest scheme rate of %s", GetDecimalString(ratio * CENT)); } static Res GovVarApplyDFIPActive(const std::string &str) { - return Res::Err("Cannot set block period while %d is active", str); + return Res::Err("Cannot set block period while %s is active", str); } static Res GovVarApplyBelowHeight() {