From bf166105b44bb0e663f0fcc9743b1ed19de3daaf Mon Sep 17 00:00:00 2001 From: Niven Date: Wed, 19 Jul 2023 11:56:58 +0800 Subject: [PATCH] Rename DUSD loops to dusd-vault attribute key (#2187) * Implement new vaults gov attribute, shift dusd vaults * Fixes to key id and key names * Revert changes to test_runner * New vault keys for dusd vault enabled * Change naming --- src/masternodes/errors.h | 4 ++ src/masternodes/govvariables/attributes.cpp | 62 +++++++++++++++++++-- src/masternodes/govvariables/attributes.h | 14 ++++- src/masternodes/mn_checks.cpp | 6 +- test/functional/feature_dusd_loans.py | 22 ++------ 5 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/masternodes/errors.h b/src/masternodes/errors.h index 9258b4337a..626ace1f0d 100644 --- a/src/masternodes/errors.h +++ b/src/masternodes/errors.h @@ -266,6 +266,10 @@ class DeFiErrors { return Res::Err("Unsupported key for Transfer Domain {%d}", type); } + static Res GovVarVariableUnsupportedVaultsType(const unsigned char type) { + return Res::Err("Unsupported key for Vaults {%d}", type); + } + static Res GovVarVariableUnsupportedParamType() { return Res::Err("Unsupported Param ID"); } diff --git a/src/masternodes/govvariables/attributes.cpp b/src/masternodes/govvariables/attributes.cpp index 236b1c4f7f..f6dc74e88c 100644 --- a/src/masternodes/govvariables/attributes.cpp +++ b/src/masternodes/govvariables/attributes.cpp @@ -59,6 +59,7 @@ const std::map &ATTRIBUTES::allowedTypes() { {"gov", AttributeTypes::Governance}, {"consortium", AttributeTypes::Consortium}, {"transferdomain", AttributeTypes::Transfer }, + {"vaults", AttributeTypes::Vaults }, }; return types; } @@ -74,6 +75,7 @@ const std::map &ATTRIBUTES::displayTypes() { {AttributeTypes::Governance, "gov" }, {AttributeTypes::Consortium, "consortium" }, {AttributeTypes::Transfer, "transferdomain"}, + {AttributeTypes::Vaults, "vaults" }, }; return types; } @@ -158,6 +160,20 @@ const std::map &ATTRIBUTES::displayTransferIDs() { return params; } +const std::map &ATTRIBUTES::allowedVaultIDs() { + static const std::map params{ + {"dusd-vault", VaultIDs::DUSDVault}, + }; + return params; +} + +const std::map &ATTRIBUTES::displayVaultIDs() { + static const std::map params{ + {VaultIDs::DUSDVault, "dusd-vault"}, + }; + return params; +} + const std::map> &ATTRIBUTES::allowedKeys() { static const std::map> keys{ {AttributeTypes::Token, @@ -212,7 +228,6 @@ const std::map> &ATTRIBUTES::allowedKeys {"gov-payout", DFIPKeys::CFPPayout}, {"emission-unused-fund", DFIPKeys::EmissionUnusedFund}, {"mint-tokens-to-address", DFIPKeys::MintTokens}, - {"allow-dusd-loops", DFIPKeys::AllowDUSDLoops}, {"transferdomain", DFIPKeys::TransferDomain}, }}, {AttributeTypes::Governance, @@ -235,6 +250,10 @@ const std::map> &ATTRIBUTES::allowedKeys {"evm-dvm", TransferKeys::EVM_DVM}, {"dvm-evm", TransferKeys::DVM_EVM}, }}, + {AttributeTypes::Vaults, + { + {"enabled", VaultKeys::DUSDVaultEnabled}, + }}, }; return keys; } @@ -296,7 +315,6 @@ const std::map> &ATTRIBUTES::displayKeys {DFIPKeys::CFPPayout, "gov-payout"}, {DFIPKeys::EmissionUnusedFund, "emission-unused-fund"}, {DFIPKeys::MintTokens, "mint-tokens-to-address"}, - {DFIPKeys::AllowDUSDLoops, "allow-dusd-loops"}, {DFIPKeys::TransferDomain, "transferdomain"}, }}, {AttributeTypes::Live, @@ -338,6 +356,10 @@ const std::map> &ATTRIBUTES::displayKeys {TransferKeys::EVM_DVM, "evm-dvm"}, {TransferKeys::DVM_EVM, "dvm-evm"}, }}, + {AttributeTypes::Vaults, + { + {VaultKeys::DUSDVaultEnabled, "enabled"}, + }}, }; return keys; } @@ -631,7 +653,6 @@ const std::map( {DFIPKeys::CFPPayout, VerifyBool}, {DFIPKeys::EmissionUnusedFund, VerifyBool}, {DFIPKeys::MintTokens, VerifyBool}, - {DFIPKeys::AllowDUSDLoops, VerifyBool}, {DFIPKeys::TransferDomain, VerifyBool}, }}, {AttributeTypes::Locks, @@ -662,6 +683,10 @@ const std::map( {TransferKeys::EVM_DVM, VerifyBool}, {TransferKeys::DVM_EVM, VerifyBool}, }}, + {AttributeTypes::Vaults, + { + {VaultKeys::DUSDVaultEnabled, VerifyBool}, + }}, }; return parsers; } @@ -787,7 +812,14 @@ Res ATTRIBUTES::ProcessVariable(const std::string &key, return DeFiErrors::GovVarVariableInvalidKey("transferdomain", allowedTransferIDs()); } typeId = id->second; - } else { + } else if (type == AttributeTypes::Vaults) { + auto id = allowedVaultIDs().find(keys[2]); + if (id == allowedVaultIDs().end()) { + return DeFiErrors::GovVarVariableInvalidKey("vaults", allowedVaultIDs()); + } + typeId = id->second; + } + else { auto id = VerifyInt32(keys[2]); if (!id) { return id; @@ -855,7 +887,7 @@ Res ATTRIBUTES::ProcessVariable(const std::string &key, typeKey != DFIPKeys::ConsortiumEnabled && typeKey != DFIPKeys::CFPPayout && typeKey != DFIPKeys::EmissionUnusedFund && typeKey != DFIPKeys::MintTokens && typeKey != DFIPKeys::EVMEnabled && typeKey != DFIPKeys::ICXEnabled && - typeKey != DFIPKeys::AllowDUSDLoops && typeKey != DFIPKeys::TransferDomain) { + typeKey != DFIPKeys::TransferDomain) { return DeFiErrors::GovVarVariableUnsupportedFeatureType(typeKey); } } else if (typeId == ParamIDs::Foundation) { @@ -884,6 +916,14 @@ Res ATTRIBUTES::ProcessVariable(const std::string &key, } else { return DeFiErrors::GovVarVariableUnsupportedGovType(); } + } else if (type == AttributeTypes::Vaults) { + if (typeId == VaultIDs::DUSDVault) { + if (typeKey != VaultKeys::DUSDVaultEnabled) { + return DeFiErrors::GovVarVariableUnsupportedVaultsType(typeKey); + } + } else { + return DeFiErrors::GovVarVariableUnsupportedGovType(); + } } attrV0 = CDataStructureV0{type, typeId, typeKey}; @@ -1192,8 +1232,10 @@ UniValue ATTRIBUTES::ExportFiltered(GovVarsFilter filter, const std::string &pre id = displayOracleIDs().at(attrV0->typeId); } else if (attrV0->type == AttributeTypes::Governance) { id = displayGovernanceIDs().at(attrV0->typeId); - } else if (attrV0->type == AttributeTypes::Transfer) { + } else if (attrV0->type == AttributeTypes::Transfer) { id = displayTransferIDs().at(attrV0->typeId); + } else if (attrV0->type == AttributeTypes::Vaults) { + id = displayVaultIDs().at(attrV0->typeId); } else { id = KeyBuilder(attrV0->typeId); } @@ -1611,6 +1653,14 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { } break; + case AttributeTypes::Vaults: + if (attrV0->typeId == VaultIDs::DUSDVault && attrV0->key == VaultKeys::DUSDVaultEnabled) { + if (view.GetLastHeight() < Params().GetConsensus().NextNetworkUpgradeHeight) { + return Res::Err("Cannot be set before NextNetworkUpgrade"); + } + } + break; + default: return Res::Err("Unrecognised type (%d)", attrV0->type); } diff --git a/src/masternodes/govvariables/attributes.h b/src/masternodes/govvariables/attributes.h index 973eb925cb..4ccdb2b7a9 100644 --- a/src/masternodes/govvariables/attributes.h +++ b/src/masternodes/govvariables/attributes.h @@ -24,6 +24,7 @@ enum AttributeTypes : uint8_t { Governance = 'g', Consortium = 'c', Transfer = 'b', + Vaults = 'v', }; enum ParamIDs : uint8_t { @@ -51,6 +52,10 @@ enum TransferIDs : uint8_t { Edges = 'a', }; +enum VaultIDs : uint8_t { + DUSDVault = 'a', +}; + enum EconomyKeys : uint8_t { PaybackDFITokens = 'a', PaybackTokens = 'b', @@ -93,8 +98,7 @@ enum DFIPKeys : uint8_t { MintTokens = 't', EVMEnabled = 'u', ICXEnabled = 'v', - AllowDUSDLoops = 'w', - TransferDomain = 'x', + TransferDomain = 'w', }; enum GovernanceKeys : uint8_t { @@ -149,6 +153,10 @@ enum TransferKeys : uint8_t { EVM_DVM = 'b', }; +enum VaultKeys : uint8_t { + DUSDVaultEnabled = 'w', +}; + struct CDataStructureV0 { uint8_t type; uint32_t typeId; @@ -436,6 +444,7 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator &displayConsortiumIDs(); static const std::map &displayGovernanceIDs(); static const std::map &displayTransferIDs(); + static const std::map &displayVaultIDs(); static const std::map> &displayKeys(); Res RefundFuturesContracts(CCustomCSView &mnview, @@ -460,6 +469,7 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator &allowedConsortiumIDs(); static const std::map &allowedGovernanceIDs(); static const std::map &allowedTransferIDs(); + static const std::map &allowedVaultIDs(); static const std::map> &allowedKeys(); static const std::map(const std::string &)>>> &parseValue(); diff --git a/src/masternodes/mn_checks.cpp b/src/masternodes/mn_checks.cpp index 2daf413f7d..f52c707cf2 100644 --- a/src/masternodes/mn_checks.cpp +++ b/src/masternodes/mn_checks.cpp @@ -3043,11 +3043,11 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor { auto isPostNext = static_cast(height) >= consensus.ChangiIntermediateHeight2; // Change to NextNetworkUpgradeHeight on mainnet release if(isPostNext) { - const CDataStructureV0 enabledKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::AllowDUSDLoops}; + const CDataStructureV0 enabledKey{AttributeTypes::Vaults, VaultIDs::DUSDVault, VaultKeys::DUSDVaultEnabled}; auto attributes = mnview.GetAttributes(); assert(attributes); - auto DUSDLoopsAllowed= attributes->GetValue(enabledKey, false); - if(DUSDLoopsAllowed && hasDUSDColl && !hasOtherColl) { + auto DUSDVaultsAllowed = attributes->GetValue(enabledKey, false); + if(DUSDVaultsAllowed && hasDUSDColl && !hasOtherColl) { return Res::Ok(); //every loan ok when DUSD loops allowed and 100% DUSD collateral } } diff --git a/test/functional/feature_dusd_loans.py b/test/functional/feature_dusd_loans.py index 9c16e6b7fd..89311f7ed8 100755 --- a/test/functional/feature_dusd_loans.py +++ b/test/functional/feature_dusd_loans.py @@ -535,30 +535,21 @@ def check_looped_dusd(self): ERR_STRING_MIN_COLLATERAL_DFI_PCT, self.takeloan_withdraw, vault_id, "1.00000000@DUSD", 'takeloan') - self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/allow-dusd-loops': 'true'}}) - self.nodes[0].generate(1) - - #still not allowed before hardfork - assert_raises_rpc_error(-32600, - ERR_STRING_MIN_COLLATERAL_DFI_PCT, - self.takeloan_withdraw, vault_id, "1.00000000@DUSD", 'takeloan') - self.goto_next_height() - # min coll ratio still applies assert_raises_rpc_error(-32600, "Vault does not have enough collateralization ratio defined by loan scheme - 148 < 150", self.takeloan_withdraw, vault_id, "67.00000000@DUSD", 'takeloan') - + self.goto_next_height() + self.nodes[0].setgov({"ATTRIBUTES": {'v0/vaults/dusd-vault/enabled': 'true'}}) self.nodes[0].generate(1) + self.takeloan_withdraw(vault_id, "1.00000000@DUSD", 'takeloan') self.nodes[0].generate(1) self.takeloan_withdraw(vault_id, "1.00000000@DUSD", 'withdraw') self.nodes[0].generate(1) - # not sure why this is needed like this. but it works self.update_oracle_price() - #also fails with other crypto in self.nodes[0].deposittovault(vault_id, self.account0, "100.00000000@BTC") self.nodes[0].generate(1) assert_raises_rpc_error(-32600, @@ -569,15 +560,14 @@ def check_looped_dusd(self): ERR_STRING_MIN_COLLATERAL_DFI_PCT, self.takeloan_withdraw, vault_id, "5.00000000@BTC", 'withdraw') - # full withdrawal (go to 100% DUSD) should work + # full withdrawal to go back to 100% DUSD vault self.takeloan_withdraw(vault_id, "100.00000000@BTC", 'withdraw') self.nodes[0].generate(1) - - self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/allow-dusd-loops': 'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/vaults/dusd-vault/enabled': 'false'}}) self.nodes[0].generate(1) - #not allowed if attribute false + # not allowed if attribute false assert_raises_rpc_error(-32600, ERR_STRING_MIN_COLLATERAL_DFI_PCT,