diff --git a/src/masternodes/govvariables/attributes.cpp b/src/masternodes/govvariables/attributes.cpp index b0365186065..abaafda7aea 100644 --- a/src/masternodes/govvariables/attributes.cpp +++ b/src/masternodes/govvariables/attributes.cpp @@ -916,7 +916,10 @@ Res ATTRIBUTES::Apply(CCustomCSView & mnview, const uint32_t height) if (aggregatePrice) { fixedIntervalPrice.priceRecord[1] = aggregatePrice; } - mnview.SetFixedIntervalPrice(fixedIntervalPrice); + const auto res = mnview.SetFixedIntervalPrice(fixedIntervalPrice); + if (!res) { + return res; + } } else { return Res::Err("Unrecognised value for FixedIntervalPriceId"); } diff --git a/src/masternodes/loan.cpp b/src/masternodes/loan.cpp index b5e79e01d2d..7fac131f34e 100644 --- a/src/masternodes/loan.cpp +++ b/src/masternodes/loan.cpp @@ -66,9 +66,6 @@ Res CLoanView::SetLoanToken(CLoanSetLoanTokenImpl const & loanToken, DCT_ID cons if (GetLoanTokenByID(id)) return Res::Err("setLoanToken with creation tx %s already exists!", loanToken.creationTx.GetHex()); - if (loanToken.interest < 0) - return Res::Err("interest rate cannot be less than 0!"); - WriteBy(id, loanToken); WriteBy(loanToken.creationTx, id); diff --git a/src/masternodes/mn_checks.cpp b/src/masternodes/mn_checks.cpp index 9098b8f54dc..da816359efc 100644 --- a/src/masternodes/mn_checks.cpp +++ b/src/masternodes/mn_checks.cpp @@ -2383,29 +2383,32 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor if (!HasFoundationAuth()) return Res::Err("tx not from foundation member!"); + if (obj.interest < 0) { + return Res::Err("interest rate cannot be less than 0!"); + } + + CTokenImplementation token; + token.symbol = trim_ws(obj.symbol).substr(0, CToken::MAX_TOKEN_SYMBOL_LENGTH); + token.name = trim_ws(obj.name).substr(0, CToken::MAX_TOKEN_NAME_LENGTH); + token.creationTx = tx.GetHash(); + token.creationHeight = height; + token.flags = obj.mintable ? static_cast(CToken::TokenFlags::Default) : static_cast(CToken::TokenFlags::Tradeable); + token.flags |= static_cast(CToken::TokenFlags::LoanToken) | static_cast(CToken::TokenFlags::DAT); + + auto tokenId = mnview.CreateToken(token); + if (!tokenId) + return std::move(tokenId); + if (height >= static_cast(consensus.FortCanningCrunchHeight)) { - CTokenImplementation token; - token.symbol = trim_ws(obj.symbol).substr(0, CToken::MAX_TOKEN_SYMBOL_LENGTH); - token.name = trim_ws(obj.name).substr(0, CToken::MAX_TOKEN_NAME_LENGTH); - token.creationTx = tx.GetHash(); - token.creationHeight = height; - token.flags = obj.mintable ? static_cast(CToken::TokenFlags::Default) : static_cast(CToken::TokenFlags::Tradeable); - token.flags |= (uint8_t)CToken::TokenFlags::LoanToken | (uint8_t)CToken::TokenFlags::DAT; - - auto resVal = mnview.CreateToken(token); - if ( !resVal) { - return res; - } - - const auto& tokenId = resVal.val->v; + const auto& id = tokenId.val->v; auto attributes = mnview.GetAttributes(); attributes->time = time; - CDataStructureV0 mintEnabled{AttributeTypes::Token, tokenId, TokenKeys::LoanMintingEnabled}; - CDataStructureV0 mintInterest{AttributeTypes::Token, tokenId, TokenKeys::LoanMintingInterest}; - CDataStructureV0 pairKey{AttributeTypes::Token, tokenId, TokenKeys::FixedIntervalPriceId}; + CDataStructureV0 mintEnabled{AttributeTypes::Token, id, TokenKeys::LoanMintingEnabled}; + CDataStructureV0 mintInterest{AttributeTypes::Token, id, TokenKeys::LoanMintingInterest}; + CDataStructureV0 pairKey{AttributeTypes::Token, id, TokenKeys::FixedIntervalPriceId}; attributes->SetValue(mintEnabled, obj.mintable); attributes->SetValue(mintInterest, obj.interest); @@ -2428,37 +2431,22 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor loanToken.creationTx = tx.GetHash(); loanToken.creationHeight = height; - CFixedIntervalPrice fixedIntervalPrice; - fixedIntervalPrice.priceFeedId = loanToken.fixedIntervalPriceId; - - auto nextPrice = GetAggregatePrice(mnview, loanToken.fixedIntervalPriceId.first, loanToken.fixedIntervalPriceId.second, time); + auto nextPrice = GetAggregatePrice(mnview, obj.fixedIntervalPriceId.first, obj.fixedIntervalPriceId.second, time); if (!nextPrice) return Res::Err(nextPrice.msg); + if (!OraclePriceFeed(mnview, obj.fixedIntervalPriceId)) + return Res::Err("Price feed %s/%s does not belong to any oracle", obj.fixedIntervalPriceId.first, obj.fixedIntervalPriceId.second); + + CFixedIntervalPrice fixedIntervalPrice; + fixedIntervalPrice.priceFeedId = loanToken.fixedIntervalPriceId; fixedIntervalPrice.priceRecord[1] = nextPrice; fixedIntervalPrice.timestamp = time; - LogPrint(BCLog::ORACLE,"CLoanSetLoanTokenMessage()->"); /* Continued */ auto resSetFixedPrice = mnview.SetFixedIntervalPrice(fixedIntervalPrice); if (!resSetFixedPrice) return Res::Err(resSetFixedPrice.msg); - if (!OraclePriceFeed(mnview, loanToken.fixedIntervalPriceId)) - return Res::Err("Price feed %s/%s does not belong to any oracle", loanToken.fixedIntervalPriceId.first, loanToken.fixedIntervalPriceId.second); - - CTokenImplementation token; - token.flags = loanToken.mintable ? (uint8_t)CToken::TokenFlags::Default : (uint8_t)CToken::TokenFlags::Tradeable; - token.flags |= (uint8_t)CToken::TokenFlags::LoanToken | (uint8_t)CToken::TokenFlags::DAT; - - token.symbol = trim_ws(loanToken.symbol).substr(0, CToken::MAX_TOKEN_SYMBOL_LENGTH); - token.name = trim_ws(loanToken.name).substr(0, CToken::MAX_TOKEN_NAME_LENGTH); - token.creationTx = tx.GetHash(); - token.creationHeight = height; - - auto tokenId = mnview.CreateToken(token); - if (!tokenId) - return std::move(tokenId); - return mnview.SetLoanToken(loanToken, *(tokenId.val)); } diff --git a/test/functional/feature_loan_setloantoken.py b/test/functional/feature_loan_setloantoken.py index 4bb1b788207..194e288be52 100755 --- a/test/functional/feature_loan_setloantoken.py +++ b/test/functional/feature_loan_setloantoken.py @@ -8,7 +8,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal +from test_framework.util import assert_equal,assert_raises_rpc_error from decimal import Decimal import calendar @@ -153,6 +153,14 @@ def run_test(self): # Move to fork height self.nodes[0].generate(110 - self.nodes[0].getblockcount()) + assert_raises_rpc_error(-32600, 'token symbol should be non-empty and starts with a letter', self.nodes[0].setloantoken, { + 'symbol': "", + 'name': "Google", + 'fixedIntervalPriceId': "MSFT/USD", + 'mintable': True, + 'interest': 0.01 + }) + # Create loan tokens self.nodes[0].setloantoken({ 'symbol': "GOOGL",