diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 20e92d7684..aa7b6421de 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1468,7 +1468,9 @@ void ClearCheckpoints(CChainParams ¶ms) { Res UpdateCheckpointsFromFile(CChainParams ¶ms, const std::string &fileName) { std::ifstream file(fileName); - Require(file.good(), [=]{ return strprintf("Could not read %s. Ensure it exists and has read permissions", fileName); }); + if (!file.good()) { + return Res::Err("Could not read %s. Ensure it exists and has read permissions", fileName); + } ClearCheckpoints(params); @@ -1480,13 +1482,19 @@ Res UpdateCheckpointsFromFile(CChainParams ¶ms, const std::string &fileName) std::istringstream iss(trimmed); std::string hashStr, heightStr; - Require((iss >> heightStr >> hashStr), [=]{ return strprintf("Error parsing line %s", trimmed); }); + if (!(iss >> heightStr >> hashStr)) { + return Res::Err("Error parsing line %s", trimmed); + } uint256 hash; - Require(ParseHashStr(hashStr, hash), [=]{ return strprintf("Invalid hash: %s", hashStr); }); + if (!ParseHashStr(hashStr, hash)) { + return Res::Err("Invalid hash: %s", hashStr); + } int32_t height; - Require(ParseInt32(heightStr, &height), [=]{ return strprintf("Invalid height: %s", heightStr); }); + if (!ParseInt32(heightStr, &height)) { + return Res::Err("Invalid height: %s", heightStr); + } params.checkpointData.mapCheckpoints[height] = hash; } diff --git a/src/dfi/consensus/accounts.cpp b/src/dfi/consensus/accounts.cpp index 46937b398c..5977cde38b 100644 --- a/src/dfi/consensus/accounts.cpp +++ b/src/dfi/consensus/accounts.cpp @@ -11,7 +11,9 @@ static ResVal BurntTokens(const CTransaction &tx) { CBalances balances; for (const auto &out : tx.vout) { if (out.scriptPubKey.size() > 0 && out.scriptPubKey[0] == OP_RETURN) { - Require(balances.Add(out.TokenAmount())); + if (auto res = balances.Add(out.TokenAmount()); !res) { + return res; + } } } return {balances, Res::Ok()}; @@ -20,13 +22,15 @@ static ResVal BurntTokens(const CTransaction &tx) { Res CAccountsConsensus::operator()(const CUtxosToAccountMessage &obj) const { // check enough tokens are "burnt" auto burnt = BurntTokens(tx); - Require(burnt); + if (!burnt) { + return burnt; + } const auto mustBeBurnt = SumAllTransfers(obj.to); - Require(*burnt.val == mustBeBurnt, - "transfer tokens mismatch burnt tokens: (%s) != (%s)", - mustBeBurnt.ToString(), - burnt.val->ToString()); + if (*burnt.val != mustBeBurnt) { + return Res::Err( + "transfer tokens mismatch burnt tokens: (%s) != (%s)", mustBeBurnt.ToString(), burnt.val->ToString()); + } // transfer return AddBalancesSetShares(obj.to); @@ -34,21 +38,28 @@ Res CAccountsConsensus::operator()(const CUtxosToAccountMessage &obj) const { Res CAccountsConsensus::operator()(const CAccountToUtxosMessage &obj) const { // check auth - Require(HasAuth(obj.from)); + if (auto res = HasAuth(obj.from); !res) { + return res; + } // check that all tokens are minted, and no excess tokens are minted auto minted = MintedTokens(obj.mintingOutputsStart); - Require(minted); + if (!minted) { + return minted; + } - Require(obj.balances == *minted.val, - "amount of minted tokens in UTXOs and metadata do not match: (%s) != (%s)", - minted.val->ToString(), - obj.balances.ToString()); + if (obj.balances != *minted.val) { + return Res::Err("amount of minted tokens in UTXOs and metadata do not match: (%s) != (%s)", + minted.val->ToString(), + obj.balances.ToString()); + } // block for non-DFI transactions for (const auto &kv : obj.balances.balances) { const DCT_ID &tokenId = kv.first; - Require(tokenId == DCT_ID{0}, "only available for DFI transactions"); + if (tokenId != DCT_ID{0}) { + return Res::Err("only available for DFI transactions"); + } } // transfer @@ -57,28 +68,38 @@ Res CAccountsConsensus::operator()(const CAccountToUtxosMessage &obj) const { Res CAccountsConsensus::operator()(const CAccountToAccountMessage &obj) const { // check auth - Require(HasAuth(obj.from)); + if (auto res = HasAuth(obj.from); !res) { + return res; + } // transfer - Require(SubBalanceDelShares(obj.from, SumAllTransfers(obj.to))); + if (auto res = SubBalanceDelShares(obj.from, SumAllTransfers(obj.to)); !res) { + return res; + } return AddBalancesSetShares(obj.to); } Res CAccountsConsensus::operator()(const CAnyAccountsToAccountsMessage &obj) const { // check auth for (const auto &kv : obj.from) { - Require(HasAuth(kv.first)); + if (auto res = HasAuth(kv.first); !res) { + return res; + } } // compare const auto sumFrom = SumAllTransfers(obj.from); const auto sumTo = SumAllTransfers(obj.to); - Require(sumFrom == sumTo, "sum of inputs (from) != sum of outputs (to)"); + if (sumFrom != sumTo) { + return Res::Err("sum of inputs (from) != sum of outputs (to)"); + } // transfer // subtraction - Require(SubBalancesDelShares(obj.from)); + if (auto res = SubBalancesDelShares(obj.from); !res) { + return res; + } // addition return AddBalancesSetShares(obj.to); } diff --git a/src/dfi/consensus/governance.cpp b/src/dfi/consensus/governance.cpp index fa605d91c9..b964be1b6f 100644 --- a/src/dfi/consensus/governance.cpp +++ b/src/dfi/consensus/governance.cpp @@ -8,7 +8,9 @@ Res CGovernanceConsensus::operator()(const CGovernanceMessage &obj) const { // check foundation auth - Require(HasFoundationAuth()); + if (auto res = HasFoundationAuth(); !res) { + return res; + } for (const auto &gov : obj.govs) { if (!gov.second) { return Res::Err("'%s': variable does not registered", gov.first); diff --git a/src/dfi/consensus/icxorders.cpp b/src/dfi/consensus/icxorders.cpp index c70cbf36ca..d54af628ee 100644 --- a/src/dfi/consensus/icxorders.cpp +++ b/src/dfi/consensus/icxorders.cpp @@ -61,7 +61,9 @@ Res CICXOrdersConsensus::operator()(const CICXCreateOrderMessage &obj) const { return DeFiErrors::ICXDisabled(); } - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } CICXOrderImplemetation order; static_cast(order) = obj; @@ -69,17 +71,25 @@ Res CICXOrdersConsensus::operator()(const CICXCreateOrderMessage &obj) const { order.creationTx = tx.GetHash(); order.creationHeight = height; - Require(HasAuth(order.ownerAddress), "tx must have at least one input from order owner"); + if (!HasAuth(order.ownerAddress)) { + return Res::Err("tx must have at least one input from order owner"); + } - Require(mnview.GetToken(order.idToken), "token %s does not exist!", order.idToken.ToString()); + if (!mnview.GetToken(order.idToken)) { + return Res::Err("token %s does not exist!", order.idToken.ToString()); + } if (order.orderType == CICXOrder::TYPE_INTERNAL) { - Require(order.receivePubkey.IsFullyValid(), "receivePubkey must be valid pubkey"); + if (!order.receivePubkey.IsFullyValid()) { + return Res::Err("receivePubkey must be valid pubkey"); + } // subtract the balance from tokenFrom to dedicate them for the order CScript txidAddr(order.creationTx.begin(), order.creationTx.end()); CalculateOwnerRewards(order.ownerAddress); - Require(TransferTokenBalance(order.idToken, order.amountFrom, order.ownerAddress, txidAddr)); + if (auto res = TransferTokenBalance(order.idToken, order.amountFrom, order.ownerAddress, txidAddr); !res) { + return res; + } } return mnview.ICXCreateOrder(order); @@ -90,7 +100,9 @@ Res CICXOrdersConsensus::operator()(const CICXMakeOfferMessage &obj) const { return DeFiErrors::ICXDisabled(); } - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } CICXMakeOfferImplemetation makeoffer; static_cast(makeoffer) = obj; @@ -98,15 +110,21 @@ Res CICXOrdersConsensus::operator()(const CICXMakeOfferMessage &obj) const { makeoffer.creationTx = tx.GetHash(); makeoffer.creationHeight = height; - Require(HasAuth(makeoffer.ownerAddress), "tx must have at least one input from order owner"); + if (!HasAuth(makeoffer.ownerAddress)) { + return Res::Err("tx must have at least one input from order owner"); + } auto order = mnview.GetICXOrderByCreationTx(makeoffer.orderTx); - Require(order, "order with creation tx " + makeoffer.orderTx.GetHex() + " does not exists!"); + if (!order) { + return Res::Err("order with creation tx " + makeoffer.orderTx.GetHex() + " does not exists!"); + } auto expiry = static_cast(height) < consensus.DF10EunosPayaHeight ? CICXMakeOffer::DEFAULT_EXPIRY : CICXMakeOffer::EUNOSPAYA_DEFAULT_EXPIRY; - Require(makeoffer.expiry >= expiry, "offer expiry must be greater than %d!", expiry - 1); + if (makeoffer.expiry < expiry) { + return Res::Err("offer expiry must be greater than %d!", expiry - 1); + } CScript txidAddr(makeoffer.creationTx.begin(), makeoffer.creationTx.end()); @@ -114,7 +132,9 @@ Res CICXOrdersConsensus::operator()(const CICXMakeOfferMessage &obj) const { // calculating takerFee makeoffer.takerFee = CalculateTakerFee(makeoffer.amount); } else if (order->orderType == CICXOrder::TYPE_EXTERNAL) { - Require(makeoffer.receivePubkey.IsFullyValid(), "receivePubkey must be valid pubkey"); + if (!makeoffer.receivePubkey.IsFullyValid()) { + return Res::Err("receivePubkey must be valid pubkey"); + } // calculating takerFee CAmount BTCAmount(static_cast( @@ -124,7 +144,9 @@ Res CICXOrdersConsensus::operator()(const CICXMakeOfferMessage &obj) const { // locking takerFee in offer txidaddr CalculateOwnerRewards(makeoffer.ownerAddress); - Require(TransferTokenBalance(DCT_ID{0}, makeoffer.takerFee, makeoffer.ownerAddress, txidAddr)); + if (auto res = TransferTokenBalance(DCT_ID{0}, makeoffer.takerFee, makeoffer.ownerAddress, txidAddr); !res) { + return res; + } return mnview.ICXMakeOffer(makeoffer); } @@ -134,7 +156,9 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitDFCHTLCMessage &obj) const { return DeFiErrors::ICXDisabled(); } - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } CICXSubmitDFCHTLCImplemetation submitdfchtlc; static_cast(submitdfchtlc) = obj; @@ -143,22 +167,31 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitDFCHTLCMessage &obj) const { submitdfchtlc.creationHeight = height; auto offer = mnview.GetICXMakeOfferByCreationTx(submitdfchtlc.offerTx); - Require(offer, "offer with creation tx %s does not exists!", submitdfchtlc.offerTx.GetHex()); + if (!offer) { + return Res::Err("offer with creation tx %s does not exists!", submitdfchtlc.offerTx.GetHex()); + } auto order = mnview.GetICXOrderByCreationTx(offer->orderTx); - Require(order, "order with creation tx %s does not exists!", offer->orderTx.GetHex()); + if (!order) { + return Res::Err("order with creation tx %s does not exists!", offer->orderTx.GetHex()); + } - Require(order->creationHeight + order->expiry >= height + submitdfchtlc.timeout, - "order will expire before dfc htlc expires!"); - Require(!mnview.HasICXSubmitDFCHTLCOpen(submitdfchtlc.offerTx), "dfc htlc already submitted!"); + if (order->creationHeight + order->expiry < height + submitdfchtlc.timeout) { + return Res::Err("order will expire before dfc htlc expires!"); + } + if (mnview.HasICXSubmitDFCHTLCOpen(submitdfchtlc.offerTx)) { + return Res::Err("dfc htlc already submitted!"); + } CScript srcAddr; if (order->orderType == CICXOrder::TYPE_INTERNAL) { // check auth - Require(HasAuth(order->ownerAddress), "tx must have at least one input from order owner"); - Require(mnview.HasICXMakeOfferOpen(offer->orderTx, submitdfchtlc.offerTx), - "offerTx (%s) has expired", - submitdfchtlc.offerTx.GetHex()); + if (!HasAuth(order->ownerAddress)) { + return Res::Err("tx must have at least one input from order owner"); + } + if (!mnview.HasICXMakeOfferOpen(offer->orderTx, submitdfchtlc.offerTx)) { + return Res::Err("offerTx (%s) has expired", submitdfchtlc.offerTx.GetHex()); + } uint32_t timeout; if (static_cast(height) < consensus.DF10EunosPayaHeight) { @@ -167,14 +200,18 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitDFCHTLCMessage &obj) const { timeout = CICXSubmitDFCHTLC::EUNOSPAYA_MINIMUM_TIMEOUT; } - Require(submitdfchtlc.timeout >= timeout, "timeout must be greater than %d", timeout - 1); + if (submitdfchtlc.timeout < timeout) { + return Res::Err("timeout must be greater than %d", timeout - 1); + } srcAddr = CScript(order->creationTx.begin(), order->creationTx.end()); CScript offerTxidAddr(offer->creationTx.begin(), offer->creationTx.end()); auto calcAmount = MultiplyAmounts(submitdfchtlc.amount, order->orderPrice); - Require(calcAmount <= offer->amount, "amount must be lower or equal the offer one"); + if (calcAmount > offer->amount) { + return Res::Err("amount must be lower or equal the offer one"); + } CAmount takerFee = offer->takerFee; // EunosPaya: calculating adjusted takerFee only if amount in htlc different than in offer @@ -191,7 +228,11 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitDFCHTLCMessage &obj) const { // refund the rest of locked takerFee if there is difference if (offer->takerFee - takerFee) { CalculateOwnerRewards(offer->ownerAddress); - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee - takerFee, offerTxidAddr, offer->ownerAddress)); + if (auto res = + TransferTokenBalance(DCT_ID{0}, offer->takerFee - takerFee, offerTxidAddr, offer->ownerAddress); + !res) { + return res; + } // update the offer with adjusted takerFee offer->takerFee = takerFee; @@ -199,31 +240,42 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitDFCHTLCMessage &obj) const { } // burn takerFee - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee, offerTxidAddr, consensus.burnAddress)); + if (auto res = TransferTokenBalance(DCT_ID{0}, offer->takerFee, offerTxidAddr, consensus.burnAddress); !res) { + return res; + } // burn makerDeposit CalculateOwnerRewards(order->ownerAddress); - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee, order->ownerAddress, consensus.burnAddress)); + if (auto res = TransferTokenBalance(DCT_ID{0}, offer->takerFee, order->ownerAddress, consensus.burnAddress); + !res) { + return res; + } } else if (order->orderType == CICXOrder::TYPE_EXTERNAL) { // check auth - Require(HasAuth(offer->ownerAddress), "tx must have at least one input from offer owner"); + if (!HasAuth(offer->ownerAddress)) { + return Res::Err("tx must have at least one input from offer owner"); + } srcAddr = offer->ownerAddress; CalculateOwnerRewards(offer->ownerAddress); auto exthtlc = mnview.HasICXSubmitEXTHTLCOpen(submitdfchtlc.offerTx); - Require(exthtlc, - "offer (%s) needs to have ext htlc submitted first, but no external htlc found!", - submitdfchtlc.offerTx.GetHex()); + if (!exthtlc) { + return Res::Err("offer (%s) needs to have ext htlc submitted first, but no external htlc found!", + submitdfchtlc.offerTx.GetHex()); + } auto calcAmount = MultiplyAmounts(exthtlc->amount, order->orderPrice); - Require(submitdfchtlc.amount == calcAmount, "amount must be equal to calculated exthtlc amount"); + if (submitdfchtlc.amount != calcAmount) { + return Res::Err("amount must be equal to calculated exthtlc amount"); + } - Require(submitdfchtlc.hash == exthtlc->hash, - "Invalid hash, dfc htlc hash is different than extarnal htlc hash - %s != %s", - submitdfchtlc.hash.GetHex(), - exthtlc->hash.GetHex()); + if (submitdfchtlc.hash != exthtlc->hash) { + return Res::Err("Invalid hash, dfc htlc hash is different than extarnal htlc hash - %s != %s", + submitdfchtlc.hash.GetHex(), + exthtlc->hash.GetHex()); + } uint32_t timeout, btcBlocksInDfi; if (static_cast(height) < consensus.DF10EunosPayaHeight) { @@ -234,15 +286,20 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitDFCHTLCMessage &obj) const { btcBlocksInDfi = CICXSubmitEXTHTLC::BTC_BLOCKS_IN_DFI_BLOCKS; } - Require(submitdfchtlc.timeout >= timeout, "timeout must be greater than %d", timeout - 1); - Require(submitdfchtlc.timeout < (exthtlc->creationHeight + (exthtlc->timeout * btcBlocksInDfi)) - height, - "timeout must be less than expiration period of 1st htlc in DFI blocks"); + if (submitdfchtlc.timeout < timeout) { + return Res::Err("timeout must be greater than %d", timeout - 1); + } + if (submitdfchtlc.timeout >= (exthtlc->creationHeight + (exthtlc->timeout * btcBlocksInDfi)) - height) { + return Res::Err("timeout must be less than expiration period of 1st htlc in DFI blocks"); + } } // subtract the balance from order txidaddr or offer owner address and dedicate them for the dfc htlc CScript htlcTxidAddr(submitdfchtlc.creationTx.begin(), submitdfchtlc.creationTx.end()); - Require(TransferTokenBalance(order->idToken, submitdfchtlc.amount, srcAddr, htlcTxidAddr)); + if (auto res = TransferTokenBalance(order->idToken, submitdfchtlc.amount, srcAddr, htlcTxidAddr); !res) { + return res; + } return mnview.ICXSubmitDFCHTLC(submitdfchtlc); } @@ -251,7 +308,9 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitEXTHTLCMessage &obj) const { return DeFiErrors::ICXDisabled(); } - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } CICXSubmitEXTHTLCImplemetation submitexthtlc; static_cast(submitexthtlc) = obj; @@ -260,29 +319,42 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitEXTHTLCMessage &obj) const { submitexthtlc.creationHeight = height; auto offer = mnview.GetICXMakeOfferByCreationTx(submitexthtlc.offerTx); - Require(offer, "order with creation tx %s does not exists!", submitexthtlc.offerTx.GetHex()); + if (!offer) { + return Res::Err("order with creation tx %s does not exists!", submitexthtlc.offerTx.GetHex()); + } auto order = mnview.GetICXOrderByCreationTx(offer->orderTx); - Require(order, "order with creation tx %s does not exists!", offer->orderTx.GetHex()); + if (!order) { + return Res::Err("order with creation tx %s does not exists!", offer->orderTx.GetHex()); + } - Require(order->creationHeight + order->expiry >= - height + (submitexthtlc.timeout * CICXSubmitEXTHTLC::BTC_BLOCKS_IN_DFI_BLOCKS), - "order will expire before ext htlc expires!"); + if (order->creationHeight + order->expiry < + height + (submitexthtlc.timeout * CICXSubmitEXTHTLC::BTC_BLOCKS_IN_DFI_BLOCKS)) { + return Res::Err("order will expire before ext htlc expires!"); + } - Require(!mnview.HasICXSubmitEXTHTLCOpen(submitexthtlc.offerTx), "ext htlc already submitted!"); + if (mnview.HasICXSubmitEXTHTLCOpen(submitexthtlc.offerTx)) { + return Res::Err("ext htlc already submitted!"); + } if (order->orderType == CICXOrder::TYPE_INTERNAL) { - Require(HasAuth(offer->ownerAddress), "tx must have at least one input from offer owner"); + if (!HasAuth(offer->ownerAddress)) { + return Res::Err("tx must have at least one input from offer owner"); + } auto dfchtlc = mnview.HasICXSubmitDFCHTLCOpen(submitexthtlc.offerTx); - Require(dfchtlc, - "offer (%s) needs to have dfc htlc submitted first, but no dfc htlc found!", - submitexthtlc.offerTx.GetHex()); + if (!dfchtlc) { + return Res::Err("offer (%s) needs to have dfc htlc submitted first, but no dfc htlc found!", + submitexthtlc.offerTx.GetHex()); + } auto calcAmount = MultiplyAmounts(dfchtlc->amount, order->orderPrice); - Require(submitexthtlc.amount == calcAmount, "amount must be equal to calculated dfchtlc amount"); - Require(submitexthtlc.hash == dfchtlc->hash, - "Invalid hash, external htlc hash is different than dfc htlc hash"); + if (submitexthtlc.amount != calcAmount) { + return Res::Err("amount must be equal to calculated dfchtlc amount"); + } + if (submitexthtlc.hash != dfchtlc->hash) { + return Res::Err("Invalid hash, external htlc hash is different than dfc htlc hash"); + } uint32_t timeout, btcBlocksInDfi; if (static_cast(height) < consensus.DF10EunosPayaHeight) { @@ -293,15 +365,20 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitEXTHTLCMessage &obj) const { btcBlocksInDfi = CICXSubmitEXTHTLC::EUNOSPAYA_BTC_BLOCKS_IN_DFI_BLOCKS; } - Require(submitexthtlc.timeout >= timeout, "timeout must be greater than %d", timeout - 1); - Require(submitexthtlc.timeout * btcBlocksInDfi < (dfchtlc->creationHeight + dfchtlc->timeout) - height, - "timeout must be less than expiration period of 1st htlc in DFC blocks"); + if (submitexthtlc.timeout < timeout) { + return Res::Err("timeout must be greater than %d", timeout - 1); + } + if (submitexthtlc.timeout * btcBlocksInDfi >= (dfchtlc->creationHeight + dfchtlc->timeout) - height) { + return Res::Err("timeout must be less than expiration period of 1st htlc in DFC blocks"); + } } else if (order->orderType == CICXOrder::TYPE_EXTERNAL) { - Require(HasAuth(order->ownerAddress), "tx must have at least one input from order owner"); - Require(mnview.HasICXMakeOfferOpen(offer->orderTx, submitexthtlc.offerTx), - "offerTx (%s) has expired", - submitexthtlc.offerTx.GetHex()); + if (!HasAuth(order->ownerAddress)) { + return Res::Err("tx must have at least one input from order owner"); + } + if (!mnview.HasICXMakeOfferOpen(offer->orderTx, submitexthtlc.offerTx)) { + return Res::Err("offerTx (%s) has expired", submitexthtlc.offerTx.GetHex()); + } uint32_t timeout; if (static_cast(height) < consensus.DF10EunosPayaHeight) { @@ -310,12 +387,16 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitEXTHTLCMessage &obj) const { timeout = CICXSubmitEXTHTLC::EUNOSPAYA_MINIMUM_TIMEOUT; } - Require(submitexthtlc.timeout >= timeout, "timeout must be greater than %d", timeout - 1); + if (submitexthtlc.timeout < timeout) { + return Res::Err("timeout must be greater than %d", timeout - 1); + } CScript offerTxidAddr(offer->creationTx.begin(), offer->creationTx.end()); auto calcAmount = MultiplyAmounts(submitexthtlc.amount, order->orderPrice); - Require(calcAmount <= offer->amount, "amount must be lower or equal the offer one"); + if (calcAmount > offer->amount) { + return Res::Err("amount must be lower or equal the offer one"); + } CAmount takerFee = offer->takerFee; // EunosPaya: calculating adjusted takerFee only if amount in htlc different than in offer @@ -331,7 +412,11 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitEXTHTLCMessage &obj) const { // refund the rest of locked takerFee if there is difference if (offer->takerFee - takerFee) { CalculateOwnerRewards(offer->ownerAddress); - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee - takerFee, offerTxidAddr, offer->ownerAddress)); + if (auto res = + TransferTokenBalance(DCT_ID{0}, offer->takerFee - takerFee, offerTxidAddr, offer->ownerAddress); + !res) { + return res; + } // update the offer with adjusted takerFee offer->takerFee = takerFee; @@ -339,11 +424,16 @@ Res CICXOrdersConsensus::operator()(const CICXSubmitEXTHTLCMessage &obj) const { } // burn takerFee - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee, offerTxidAddr, consensus.burnAddress)); + if (auto res = TransferTokenBalance(DCT_ID{0}, offer->takerFee, offerTxidAddr, consensus.burnAddress); !res) { + return res; + } // burn makerDeposit CalculateOwnerRewards(order->ownerAddress); - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee, order->ownerAddress, consensus.burnAddress)); + if (auto res = TransferTokenBalance(DCT_ID{0}, offer->takerFee, order->ownerAddress, consensus.burnAddress); + !res) { + return res; + } } return mnview.ICXSubmitEXTHTLC(submitexthtlc); @@ -354,7 +444,9 @@ Res CICXOrdersConsensus::operator()(const CICXClaimDFCHTLCMessage &obj) const { return DeFiErrors::ICXDisabled(); } - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } CICXClaimDFCHTLCImplemetation claimdfchtlc; static_cast(claimdfchtlc) = obj; @@ -363,29 +455,40 @@ Res CICXOrdersConsensus::operator()(const CICXClaimDFCHTLCMessage &obj) const { claimdfchtlc.creationHeight = height; auto dfchtlc = mnview.GetICXSubmitDFCHTLCByCreationTx(claimdfchtlc.dfchtlcTx); - Require(dfchtlc, "dfc htlc with creation tx %s does not exists!", claimdfchtlc.dfchtlcTx.GetHex()); + if (!dfchtlc) { + return Res::Err("dfc htlc with creation tx %s does not exists!", claimdfchtlc.dfchtlcTx.GetHex()); + } - Require(mnview.HasICXSubmitDFCHTLCOpen(dfchtlc->offerTx), "dfc htlc not found or already claimed or refunded!"); + if (!mnview.HasICXSubmitDFCHTLCOpen(dfchtlc->offerTx)) { + return Res::Err("dfc htlc not found or already claimed or refunded!"); + } uint256 calcHash; uint8_t calcSeedBytes[32]; CSHA256().Write(claimdfchtlc.seed.data(), claimdfchtlc.seed.size()).Finalize(calcSeedBytes); calcHash.SetHex(HexStr(calcSeedBytes, calcSeedBytes + 32)); - Require(dfchtlc->hash == calcHash, - "hash generated from given seed is different than in dfc htlc: %s - %s!", - calcHash.GetHex(), - dfchtlc->hash.GetHex()); + if (dfchtlc->hash != calcHash) { + return Res::Err("hash generated from given seed is different than in dfc htlc: %s - %s!", + calcHash.GetHex(), + dfchtlc->hash.GetHex()); + } auto offer = mnview.GetICXMakeOfferByCreationTx(dfchtlc->offerTx); - Require(offer, "offer with creation tx %s does not exists!", dfchtlc->offerTx.GetHex()); + if (!offer) { + return Res::Err("offer with creation tx %s does not exists!", dfchtlc->offerTx.GetHex()); + } auto order = mnview.GetICXOrderByCreationTx(offer->orderTx); - Require(order, "order with creation tx %s does not exists!", offer->orderTx.GetHex()); + if (!order) { + return Res::Err("order with creation tx %s does not exists!", offer->orderTx.GetHex()); + } auto exthtlc = mnview.HasICXSubmitEXTHTLCOpen(dfchtlc->offerTx); if (static_cast(height) < consensus.DF10EunosPayaHeight) { - Require(exthtlc, "cannot claim, external htlc for this offer does not exists or expired!"); + if (!exthtlc) { + return Res::Err("cannot claim, external htlc for this offer does not exists or expired!"); + } } // claim DFC HTLC to receiveAddress @@ -393,16 +496,24 @@ Res CICXOrdersConsensus::operator()(const CICXClaimDFCHTLCMessage &obj) const { CScript htlcTxidAddr(dfchtlc->creationTx.begin(), dfchtlc->creationTx.end()); if (order->orderType == CICXOrder::TYPE_INTERNAL) { - Require(TransferTokenBalance(order->idToken, dfchtlc->amount, htlcTxidAddr, offer->ownerAddress)); + if (auto res = TransferTokenBalance(order->idToken, dfchtlc->amount, htlcTxidAddr, offer->ownerAddress); !res) { + return res; + } } else if (order->orderType == CICXOrder::TYPE_EXTERNAL) { - Require(TransferTokenBalance(order->idToken, dfchtlc->amount, htlcTxidAddr, order->ownerAddress)); + if (auto res = TransferTokenBalance(order->idToken, dfchtlc->amount, htlcTxidAddr, order->ownerAddress); !res) { + return res; + } } // refund makerDeposit - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee, CScript(), order->ownerAddress)); + if (auto res = TransferTokenBalance(DCT_ID{0}, offer->takerFee, CScript(), order->ownerAddress); !res) { + return res; + } // makerIncentive - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee * 25 / 100, CScript(), order->ownerAddress)); + if (auto res = TransferTokenBalance(DCT_ID{0}, offer->takerFee * 25 / 100, CScript(), order->ownerAddress); !res) { + return res; + } // maker bonus only on fair dBTC/BTC (1:1) trades for now DCT_ID BTC = FindTokenByPartialSymbolName(CICXOrder::TOKEN_BTC); @@ -418,10 +529,16 @@ Res CICXOrdersConsensus::operator()(const CICXClaimDFCHTLCMessage &obj) const { if (ICXBugPath(height)) { // Proceed with bug behavoir - Require(TransferTokenBalance(BTC, offer->takerFee * 50 / 100, CScript(), order->ownerAddress)); + if (auto res = TransferTokenBalance(BTC, offer->takerFee * 50 / 100, CScript(), order->ownerAddress); + !res) { + return res; + } } else { // Bug fixed - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee * 50 / 100, CScript(), order->ownerAddress)); + if (auto res = TransferTokenBalance(DCT_ID{0}, offer->takerFee * 50 / 100, CScript(), order->ownerAddress); + !res) { + return res; + } } } @@ -436,14 +553,22 @@ Res CICXOrdersConsensus::operator()(const CICXClaimDFCHTLCMessage &obj) const { if (order->amountToFill == 0) { order->closeTx = claimdfchtlc.creationTx; order->closeHeight = height; - Require(mnview.ICXCloseOrderTx(*order, CICXOrder::STATUS_FILLED)); + if (auto res = mnview.ICXCloseOrderTx(*order, CICXOrder::STATUS_FILLED); !res) { + return res; + } } - Require(mnview.ICXClaimDFCHTLC(claimdfchtlc, offer->creationTx, *order)); + if (auto res = mnview.ICXClaimDFCHTLC(claimdfchtlc, offer->creationTx, *order); !res) { + return res; + } // Close offer - Require(mnview.ICXCloseMakeOfferTx(*offer, CICXMakeOffer::STATUS_CLOSED)); + if (auto res = mnview.ICXCloseMakeOfferTx(*offer, CICXMakeOffer::STATUS_CLOSED); !res) { + return res; + } - Require(mnview.ICXCloseDFCHTLC(*dfchtlc, CICXSubmitDFCHTLC::STATUS_CLAIMED)); + if (auto res = mnview.ICXCloseDFCHTLC(*dfchtlc, CICXSubmitDFCHTLC::STATUS_CLAIMED); !res) { + return res; + } if (static_cast(height) >= consensus.DF10EunosPayaHeight) { if (exthtlc) { @@ -457,7 +582,9 @@ Res CICXOrdersConsensus::operator()(const CICXClaimDFCHTLCMessage &obj) const { } Res CICXOrdersConsensus::operator()(const CICXCloseOrderMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } CICXCloseOrderImplemetation closeorder; static_cast(closeorder) = obj; @@ -466,15 +593,21 @@ Res CICXOrdersConsensus::operator()(const CICXCloseOrderMessage &obj) const { closeorder.creationHeight = height; auto order = mnview.GetICXOrderByCreationTx(closeorder.orderTx); - Require(order, "order with creation tx %s does not exists!", closeorder.orderTx.GetHex()); + if (!order) { + return Res::Err("order with creation tx %s does not exists!", closeorder.orderTx.GetHex()); + } - Require(order->closeTx.IsNull(), "order with creation tx %s is already closed!", closeorder.orderTx.GetHex()); - Require(mnview.HasICXOrderOpen(order->idToken, order->creationTx), - "order with creation tx %s is already closed!", - closeorder.orderTx.GetHex()); + if (!order->closeTx.IsNull()) { + return Res::Err("order with creation tx %s is already closed!", closeorder.orderTx.GetHex()); + } + if (!mnview.HasICXOrderOpen(order->idToken, order->creationTx)) { + return Res::Err("order with creation tx %s is already closed!", closeorder.orderTx.GetHex()); + } // check auth - Require(HasAuth(order->ownerAddress), "tx must have at least one input from order owner"); + if (!HasAuth(order->ownerAddress)) { + return Res::Err("tx must have at least one input from order owner"); + } order->closeTx = closeorder.creationTx; order->closeHeight = closeorder.creationHeight; @@ -483,15 +616,21 @@ Res CICXOrdersConsensus::operator()(const CICXCloseOrderMessage &obj) const { // subtract the balance from txidAddr and return to owner CScript txidAddr(order->creationTx.begin(), order->creationTx.end()); CalculateOwnerRewards(order->ownerAddress); - Require(TransferTokenBalance(order->idToken, order->amountToFill, txidAddr, order->ownerAddress)); + if (auto res = TransferTokenBalance(order->idToken, order->amountToFill, txidAddr, order->ownerAddress); !res) { + return res; + } } - Require(mnview.ICXCloseOrder(closeorder)); + if (auto res = mnview.ICXCloseOrder(closeorder); !res) { + return res; + } return mnview.ICXCloseOrderTx(*order, CICXOrder::STATUS_CLOSED); } Res CICXOrdersConsensus::operator()(const CICXCloseOfferMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } CICXCloseOfferImplemetation closeoffer; static_cast(closeoffer) = obj; @@ -500,18 +639,26 @@ Res CICXOrdersConsensus::operator()(const CICXCloseOfferMessage &obj) const { closeoffer.creationHeight = height; auto offer = mnview.GetICXMakeOfferByCreationTx(closeoffer.offerTx); - Require(offer, "offer with creation tx %s does not exists!", closeoffer.offerTx.GetHex()); + if (!offer) { + return Res::Err("offer with creation tx %s does not exists!", closeoffer.offerTx.GetHex()); + } - Require(offer->closeTx.IsNull(), "offer with creation tx %s is already closed!", closeoffer.offerTx.GetHex()); - Require(mnview.HasICXMakeOfferOpen(offer->orderTx, offer->creationTx), - "offer with creation tx %s does not exists!", - closeoffer.offerTx.GetHex()); + if (!offer->closeTx.IsNull()) { + return Res::Err("offer with creation tx %s is already closed!", closeoffer.offerTx.GetHex()); + } + if (!mnview.HasICXMakeOfferOpen(offer->orderTx, offer->creationTx)) { + return Res::Err("offer with creation tx %s does not exists!", closeoffer.offerTx.GetHex()); + } auto order = mnview.GetICXOrderByCreationTx(offer->orderTx); - Require(order, "order with creation tx %s does not exists!", offer->orderTx.GetHex()); + if (!order) { + return Res::Err("order with creation tx %s does not exists!", offer->orderTx.GetHex()); + } // check auth - Require(HasAuth(offer->ownerAddress), "tx must have at least one input from offer owner"); + if (!HasAuth(offer->ownerAddress)) { + return Res::Err("tx must have at least one input from offer owner"); + } offer->closeTx = closeoffer.creationTx; offer->closeHeight = closeoffer.creationHeight; @@ -523,20 +670,28 @@ Res CICXOrdersConsensus::operator()(const CICXCloseOfferMessage &obj) const { // subtract takerFee from txidAddr and return to owner CScript txidAddr(offer->creationTx.begin(), offer->creationTx.end()); CalculateOwnerRewards(offer->ownerAddress); - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee, txidAddr, offer->ownerAddress)); + if (auto res = TransferTokenBalance(DCT_ID{0}, offer->takerFee, txidAddr, offer->ownerAddress); !res) { + return res; + } } else if (order->orderType == CICXOrder::TYPE_EXTERNAL) { // subtract the balance from txidAddr and return to owner CScript txidAddr(offer->creationTx.begin(), offer->creationTx.end()); CalculateOwnerRewards(offer->ownerAddress); if (isPreEunosPaya) { - Require(TransferTokenBalance(order->idToken, offer->amount, txidAddr, offer->ownerAddress)); + if (auto res = TransferTokenBalance(order->idToken, offer->amount, txidAddr, offer->ownerAddress); !res) { + return res; + } } if (!mnview.ExistedICXSubmitEXTHTLC(offer->creationTx, isPreEunosPaya)) { - Require(TransferTokenBalance(DCT_ID{0}, offer->takerFee, txidAddr, offer->ownerAddress)); + if (auto res = TransferTokenBalance(DCT_ID{0}, offer->takerFee, txidAddr, offer->ownerAddress); !res) { + return res; + } } } - Require(mnview.ICXCloseOffer(closeoffer)); + if (auto res = mnview.ICXCloseOffer(closeoffer); !res) { + return res; + } return mnview.ICXCloseMakeOfferTx(*offer, CICXMakeOffer::STATUS_CLOSED); } diff --git a/src/dfi/consensus/loans.cpp b/src/dfi/consensus/loans.cpp index af65b76775..16b4e964be 100644 --- a/src/dfi/consensus/loans.cpp +++ b/src/dfi/consensus/loans.cpp @@ -173,9 +173,13 @@ bool CLoansConsensus::IsTokensMigratedToGovVar() const { } Res CLoansConsensus::operator()(const CLoanSetCollateralTokenMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } - Require(HasFoundationAuth(), "tx not from foundation member!"); + if (!HasFoundationAuth()) { + return Res::Err("tx not from foundation member!"); + } if (height >= static_cast(consensus.DF16FortCanningCrunchHeight) && IsTokensMigratedToGovVar()) { const auto &tokenId = obj.idToken.v; @@ -188,18 +192,28 @@ Res CLoansConsensus::operator()(const CLoanSetCollateralTokenMessage &obj) const CDataStructureV0 pairKey{AttributeTypes::Token, tokenId, TokenKeys::FixedIntervalPriceId}; auto gv = GovVariable::Create("ATTRIBUTES"); - Require(gv, "Failed to create ATTRIBUTES Governance variable"); + if (!gv) { + return Res::Err("Failed to create ATTRIBUTES Governance variable"); + } auto var = std::dynamic_pointer_cast(gv); - Require(var, "Failed to convert ATTRIBUTES Governance variable"); + if (!var) { + return Res::Err("Failed to convert ATTRIBUTES Governance variable"); + } var->SetValue(collateralEnabled, true); var->SetValue(collateralFactor, obj.factor); var->SetValue(pairKey, obj.fixedIntervalPriceId); - Require(attributes->Import(var->Export())); - Require(attributes->Validate(mnview)); - Require(attributes->Apply(mnview, height)); + if (auto res = attributes->Import(var->Export()); !res) { + return res; + } + if (auto res = attributes->Validate(mnview); !res) { + return res; + } + if (auto res = attributes->Apply(mnview, height); !res) { + return res; + } return mnview.SetVariable(*attributes); } @@ -211,42 +225,57 @@ Res CLoansConsensus::operator()(const CLoanSetCollateralTokenMessage &obj) const collToken.creationHeight = height; auto token = mnview.GetToken(collToken.idToken); - Require(token, "token %s does not exist!", collToken.idToken.ToString()); + if (!token) { + return Res::Err("token %s does not exist!", collToken.idToken.ToString()); + } if (!collToken.activateAfterBlock) { collToken.activateAfterBlock = height; } - Require(collToken.activateAfterBlock >= height, "activateAfterBlock cannot be less than current height!"); + if (collToken.activateAfterBlock < height) { + return Res::Err("activateAfterBlock cannot be less than current height!"); + } - Require(OraclePriceFeed(mnview, collToken.fixedIntervalPriceId), - "Price feed %s/%s does not belong to any oracle", - collToken.fixedIntervalPriceId.first, - collToken.fixedIntervalPriceId.second); + if (!OraclePriceFeed(mnview, collToken.fixedIntervalPriceId)) { + return Res::Err("Price feed %s/%s does not belong to any oracle", + collToken.fixedIntervalPriceId.first, + collToken.fixedIntervalPriceId.second); + } CFixedIntervalPrice fixedIntervalPrice; fixedIntervalPrice.priceFeedId = collToken.fixedIntervalPriceId; auto price = GetAggregatePrice(mnview, collToken.fixedIntervalPriceId.first, collToken.fixedIntervalPriceId.second, time); - Require(price, price.msg); + if (!price) { + return price; + } fixedIntervalPrice.priceRecord[1] = price; fixedIntervalPrice.timestamp = time; auto resSetFixedPrice = mnview.SetFixedIntervalPrice(fixedIntervalPrice); - Require(resSetFixedPrice, resSetFixedPrice.msg); + if (!resSetFixedPrice) { + return resSetFixedPrice; + } return mnview.CreateLoanCollateralToken(collToken); } Res CLoansConsensus::operator()(const CLoanSetLoanTokenMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } - Require(HasFoundationAuth(), "tx not from foundation member!"); + if (!HasFoundationAuth()) { + return Res::Err("tx not from foundation member!"); + } if (height < static_cast(consensus.DF18FortCanningGreatWorldHeight)) { - Require(obj.interest >= 0, "interest rate cannot be less than 0!"); + if (obj.interest < 0) { + return Res::Err("interest rate cannot be less than 0!"); + } } CTokenImplementation token; @@ -262,7 +291,9 @@ Res CLoansConsensus::operator()(const CLoanSetLoanTokenMessage &obj) const { token.flags |= static_cast(CToken::TokenFlags::LoanToken) | static_cast(CToken::TokenFlags::DAT); auto tokenId = mnview.CreateToken(token, false, isEvmEnabledForBlock, evmTemplateId); - Require(tokenId); + if (!tokenId) { + return tokenId; + } if (height >= static_cast(consensus.DF16FortCanningCrunchHeight) && IsTokensMigratedToGovVar()) { const auto &id = tokenId.val->v; @@ -276,18 +307,28 @@ Res CLoansConsensus::operator()(const CLoanSetLoanTokenMessage &obj) const { CDataStructureV0 pairKey{AttributeTypes::Token, id, TokenKeys::FixedIntervalPriceId}; auto gv = GovVariable::Create("ATTRIBUTES"); - Require(gv, "Failed to create ATTRIBUTES Governance variable"); + if (!gv) { + return Res::Err("Failed to create ATTRIBUTES Governance variable"); + } auto var = std::dynamic_pointer_cast(gv); - Require(var, "Failed to convert ATTRIBUTES Governance variable"); + if (!var) { + return Res::Err("Failed to convert ATTRIBUTES Governance variable"); + } var->SetValue(mintEnabled, obj.mintable); var->SetValue(mintInterest, obj.interest); var->SetValue(pairKey, obj.fixedIntervalPriceId); - Require(attributes->Import(var->Export())); - Require(attributes->Validate(mnview)); - Require(attributes->Apply(mnview, height)); + if (auto res = attributes->Import(var->Export()); !res) { + return res; + } + if (auto res = attributes->Validate(mnview); !res) { + return res; + } + if (auto res = attributes->Apply(mnview, height); !res) { + return res; + } return mnview.SetVariable(*attributes); } @@ -298,12 +339,15 @@ Res CLoansConsensus::operator()(const CLoanSetLoanTokenMessage &obj) const { loanToken.creationHeight = height; auto nextPrice = GetAggregatePrice(mnview, obj.fixedIntervalPriceId.first, obj.fixedIntervalPriceId.second, time); - Require(nextPrice, nextPrice.msg); + if (!nextPrice) { + return nextPrice; + } - Require(OraclePriceFeed(mnview, obj.fixedIntervalPriceId), - "Price feed %s/%s does not belong to any oracle", - obj.fixedIntervalPriceId.first, - obj.fixedIntervalPriceId.second); + 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; @@ -311,29 +355,41 @@ Res CLoansConsensus::operator()(const CLoanSetLoanTokenMessage &obj) const { fixedIntervalPrice.timestamp = time; auto resSetFixedPrice = mnview.SetFixedIntervalPrice(fixedIntervalPrice); - Require(resSetFixedPrice, resSetFixedPrice.msg); + if (!resSetFixedPrice) { + return resSetFixedPrice; + } return mnview.SetLoanToken(loanToken, *(tokenId.val)); } Res CLoansConsensus::operator()(const CLoanUpdateLoanTokenMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } - Require(HasFoundationAuth(), "tx not from foundation member!"); + if (!HasFoundationAuth()) { + return Res::Err("tx not from foundation member!"); + } if (height < static_cast(consensus.DF18FortCanningGreatWorldHeight)) { - Require(obj.interest >= 0, "interest rate cannot be less than 0!"); + if (obj.interest < 0) { + return Res::Err("interest rate cannot be less than 0!"); + } } auto pair = mnview.GetTokenByCreationTx(obj.tokenTx); - Require(pair, "Loan token (%s) does not exist!", obj.tokenTx.GetHex()); + if (!pair) { + return Res::Err("Loan token (%s) does not exist!", obj.tokenTx.GetHex()); + } auto loanToken = (height >= static_cast(consensus.DF16FortCanningCrunchHeight) && IsTokensMigratedToGovVar()) ? mnview.GetLoanTokenByID(pair->first) : mnview.GetLoanToken(obj.tokenTx); - Require(loanToken, "Loan token (%s) does not exist!", obj.tokenTx.GetHex()); + if (!loanToken) { + return Res::Err("Loan token (%s) does not exist!", obj.tokenTx.GetHex()); + } if (obj.mintable != loanToken->mintable) { loanToken->mintable = obj.mintable; @@ -355,7 +411,9 @@ Res CLoansConsensus::operator()(const CLoanUpdateLoanTokenMessage &obj) const { pair->second.flags ^= (uint8_t)CToken::TokenFlags::Mintable; } - Require(mnview.UpdateToken(pair->second)); + if (auto res = mnview.UpdateToken(pair->second); !res) { + return res; + } if (height >= static_cast(consensus.DF16FortCanningCrunchHeight) && IsTokensMigratedToGovVar()) { const auto &id = pair->first.v; @@ -368,26 +426,37 @@ Res CLoansConsensus::operator()(const CLoanUpdateLoanTokenMessage &obj) const { CDataStructureV0 pairKey{AttributeTypes::Token, id, TokenKeys::FixedIntervalPriceId}; auto gv = GovVariable::Create("ATTRIBUTES"); - Require(gv, "Failed to create ATTRIBUTES Governance variable"); + if (!gv) { + return Res::Err("Failed to create ATTRIBUTES Governance variable"); + } auto var = std::dynamic_pointer_cast(gv); - Require(var, "Failed to convert ATTRIBUTES Governance variable"); + if (!var) { + return Res::Err("Failed to convert ATTRIBUTES Governance variable"); + } var->SetValue(mintEnabled, obj.mintable); var->SetValue(mintInterest, obj.interest); var->SetValue(pairKey, obj.fixedIntervalPriceId); - Require(attributes->Import(var->Export())); - Require(attributes->Validate(mnview)); - Require(attributes->Apply(mnview, height)); + if (auto res = attributes->Import(var->Export()); !res) { + return res; + } + if (auto res = attributes->Validate(mnview); !res) { + return res; + } + if (auto res = attributes->Apply(mnview, height); !res) { + return res; + } return mnview.SetVariable(*attributes); } if (obj.fixedIntervalPriceId != loanToken->fixedIntervalPriceId) { - Require(OraclePriceFeed(mnview, obj.fixedIntervalPriceId), - "Price feed %s/%s does not belong to any oracle", - obj.fixedIntervalPriceId.first, - obj.fixedIntervalPriceId.second); + if (!OraclePriceFeed(mnview, obj.fixedIntervalPriceId)) { + return Res::Err("Price feed %s/%s does not belong to any oracle", + obj.fixedIntervalPriceId.first, + obj.fixedIntervalPriceId.second); + } loanToken->fixedIntervalPriceId = obj.fixedIntervalPriceId; } @@ -396,15 +465,25 @@ Res CLoansConsensus::operator()(const CLoanUpdateLoanTokenMessage &obj) const { } Res CLoansConsensus::operator()(const CLoanSchemeMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } - Require(HasFoundationAuth(), "tx not from foundation member!"); + if (!HasFoundationAuth()) { + return Res::Err("tx not from foundation member!"); + } - Require(obj.ratio >= 100, "minimum collateral ratio cannot be less than 100"); + if (obj.ratio < 100) { + return Res::Err("minimum collateral ratio cannot be less than 100"); + } - Require(obj.rate >= 1000000, "interest rate cannot be less than 0.01"); + if (obj.rate < 1000000) { + return Res::Err("interest rate cannot be less than 0.01"); + } - Require(!obj.identifier.empty() && obj.identifier.length() <= 8, "id cannot be empty or more than 8 chars long"); + if (obj.identifier.empty() || obj.identifier.length() > 8) { + return Res::Err("id cannot be empty or more than 8 chars long"); + } // Look for loan scheme which already has matching rate and ratio bool duplicateLoan = false; @@ -419,7 +498,9 @@ Res CLoansConsensus::operator()(const CLoanSchemeMessage &obj) const { return true; }); - Require(!duplicateLoan, "Loan scheme %s with same interestrate and mincolratio already exists", duplicateID); + if (duplicateLoan) { + return Res::Err("Loan scheme %s with same interestrate and mincolratio already exists", duplicateID); + } // Look for delayed loan scheme which already has matching rate and ratio std::pair duplicateKey; @@ -433,21 +514,28 @@ Res CLoansConsensus::operator()(const CLoanSchemeMessage &obj) const { return true; }); - Require(!duplicateLoan, - "Loan scheme %s with same interestrate and mincolratio pending on block %d", - duplicateKey.first, - duplicateKey.second); + if (duplicateLoan) { + return Res::Err("Loan scheme %s with same interestrate and mincolratio pending on block %d", + duplicateKey.first, + duplicateKey.second); + } // New loan scheme, no duplicate expected. if (mnview.GetLoanScheme(obj.identifier)) { - Require(obj.updateHeight, "Loan scheme already exist with id %s", obj.identifier); + if (!obj.updateHeight) { + return Res::Err("Loan scheme already exist with id %s", obj.identifier); + } } else { - Require(!obj.updateHeight, "Cannot find existing loan scheme with id %s", obj.identifier); + if (obj.updateHeight) { + return Res::Err("Cannot find existing loan scheme with id %s", obj.identifier); + } } // Update set, not max uint64_t which indicates immediate update and not updated on this block. if (obj.updateHeight && obj.updateHeight != std::numeric_limits::max() && obj.updateHeight != height) { - Require(obj.updateHeight >= height, "Update height below current block height, set future height"); + if (obj.updateHeight < height) { + return Res::Err("Update height below current block height, set future height"); + } return mnview.StoreDelayedLoanScheme(obj); } @@ -460,35 +548,59 @@ Res CLoansConsensus::operator()(const CLoanSchemeMessage &obj) const { } Res CLoansConsensus::operator()(const CDefaultLoanSchemeMessage &obj) const { - Require(CheckCustomTx()); - Require(HasFoundationAuth(), "tx not from foundation member!"); + if (auto res = CheckCustomTx(); !res) { + return res; + } + if (!HasFoundationAuth()) { + return Res::Err("tx not from foundation member!"); + } - Require(!obj.identifier.empty() && obj.identifier.length() <= 8, "id cannot be empty or more than 8 chars long"); - Require(mnview.GetLoanScheme(obj.identifier), "Cannot find existing loan scheme with id %s", obj.identifier); + if (obj.identifier.empty() || obj.identifier.length() > 8) { + return Res::Err("id cannot be empty or more than 8 chars long"); + } + if (!mnview.GetLoanScheme(obj.identifier)) { + return Res::Err("Cannot find existing loan scheme with id %s", obj.identifier); + } if (auto currentID = mnview.GetDefaultLoanScheme()) { - Require(*currentID != obj.identifier, "Loan scheme with id %s is already set as default", obj.identifier); + if (*currentID == obj.identifier) { + return Res::Err("Loan scheme with id %s is already set as default", obj.identifier); + } } const auto height = mnview.GetDestroyLoanScheme(obj.identifier); - Require(!height, "Cannot set %s as default, set to destroyed on block %d", obj.identifier, *height); + if (height) { + return Res::Err("Cannot set %s as default, set to destroyed on block %d", obj.identifier, *height); + } return mnview.StoreDefaultLoanScheme(obj.identifier); } Res CLoansConsensus::operator()(const CDestroyLoanSchemeMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } - Require(HasFoundationAuth(), "tx not from foundation member!"); + if (!HasFoundationAuth()) { + return Res::Err("tx not from foundation member!"); + } - Require(!obj.identifier.empty() && obj.identifier.length() <= 8, "id cannot be empty or more than 8 chars long"); - Require(mnview.GetLoanScheme(obj.identifier), "Cannot find existing loan scheme with id %s", obj.identifier); + if (obj.identifier.empty() || obj.identifier.length() > 8) { + return Res::Err("id cannot be empty or more than 8 chars long"); + } + if (!mnview.GetLoanScheme(obj.identifier)) { + return Res::Err("Cannot find existing loan scheme with id %s", obj.identifier); + } const auto currentID = mnview.GetDefaultLoanScheme(); - Require(currentID && *currentID != obj.identifier, "Cannot destroy default loan scheme, set new default first"); + if (!currentID || *currentID == obj.identifier) { + return Res::Err("Cannot destroy default loan scheme, set new default first"); + } // Update set and not updated on this block. if (obj.destroyHeight && obj.destroyHeight != height) { - Require(obj.destroyHeight >= height, "Destruction height below current block height, set future height"); + if (obj.destroyHeight < height) { + return Res::Err("Destruction height below current block height, set future height"); + } return mnview.StoreDelayedDestroyScheme(obj); } @@ -504,21 +616,32 @@ Res CLoansConsensus::operator()(const CDestroyLoanSchemeMessage &obj) const { } Res CLoansConsensus::operator()(const CLoanTakeLoanMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } const auto vault = mnview.GetVault(obj.vaultId); - Require(vault, "Vault <%s> not found", obj.vaultId.GetHex()); + if (!vault) { + return Res::Err("Vault <%s> not found", obj.vaultId.GetHex()); + } - Require(!vault->isUnderLiquidation, "Cannot take loan on vault under liquidation"); + if (vault->isUnderLiquidation) { + return Res::Err("Cannot take loan on vault under liquidation"); + } // vault owner auth - Require(HasAuth(vault->ownerAddress), "tx must have at least one input from vault owner"); + if (!HasAuth(vault->ownerAddress)) { + return Res::Err("tx must have at least one input from vault owner"); + } - Require(IsVaultPriceValid(mnview, obj.vaultId, height), - "Cannot take loan while any of the asset's price in the vault is not live"); + if (!IsVaultPriceValid(mnview, obj.vaultId, height)) { + return Res::Err("Cannot take loan while any of the asset's price in the vault is not live"); + } auto collaterals = mnview.GetVaultCollaterals(obj.vaultId); - Require(collaterals, "Vault with id %s has no collaterals", obj.vaultId.GetHex()); + if (!collaterals) { + return Res::Err("Vault with id %s has no collaterals", obj.vaultId.GetHex()); + } const auto loanAmounts = mnview.GetLoanTokens(obj.vaultId); @@ -532,15 +655,20 @@ Res CLoansConsensus::operator()(const CLoanTakeLoanMessage &obj) const { uint64_t totalLoansActivePrice = 0, totalLoansNextPrice = 0; for (const auto &[tokenId, tokenAmount] : obj.amounts.balances) { if (height >= static_cast(consensus.DF18FortCanningGreatWorldHeight)) { - Require(tokenAmount > 0, "Valid loan amount required (input: %d@%d)", tokenAmount, tokenId.v); + if (tokenAmount <= 0) { + return Res::Err("Valid loan amount required (input: %d@%d)", tokenAmount, tokenId.v); + } } auto loanToken = mnview.GetLoanTokenByID(tokenId); - Require(loanToken, "Loan token with id (%s) does not exist!", tokenId.ToString()); + if (!loanToken) { + return Res::Err("Loan token with id (%s) does not exist!", tokenId.ToString()); + } - Require(loanToken->mintable, - "Loan cannot be taken on token with id (%s) as \"mintable\" is currently false", - tokenId.ToString()); + if (!loanToken->mintable) { + return Res::Err("Loan cannot be taken on token with id (%s) as \"mintable\" is currently false", + tokenId.ToString()); + } if (tokenDUSD && tokenId == tokenDUSD->first) { hasDUSDLoans = true; } @@ -581,7 +709,9 @@ Res CLoansConsensus::operator()(const CLoanTakeLoanMessage &obj) const { TrackDUSDAdd(mnview, {tokenId, loanAmountChange}); } - Require(mnview.AddLoanToken(obj.vaultId, CTokenAmount{tokenId, loanAmountChange})); + if (auto res = mnview.AddLoanToken(obj.vaultId, CTokenAmount{tokenId, loanAmountChange}); !res) { + return res; + } } else { const auto subAmount = currentLoanAmount > std::abs(loanAmountChange) ? std::abs(loanAmountChange) : currentLoanAmount; @@ -590,47 +720,59 @@ Res CLoansConsensus::operator()(const CLoanTakeLoanMessage &obj) const { TrackDUSDSub(mnview, {tokenId, subAmount}); } - Require(mnview.SubLoanToken(obj.vaultId, CTokenAmount{tokenId, subAmount})); + if (auto res = mnview.SubLoanToken(obj.vaultId, CTokenAmount{tokenId, subAmount}); !res) { + return res; + } } if (resetInterestToHeight) { mnview.ResetInterest(height, obj.vaultId, vault->schemeId, tokenId); } else { - Require(mnview.IncreaseInterest( - height, obj.vaultId, vault->schemeId, tokenId, loanToken->interest, loanAmountChange)); + if (auto res = mnview.IncreaseInterest( + height, obj.vaultId, vault->schemeId, tokenId, loanToken->interest, loanAmountChange); + !res) { + return res; + } } const auto tokenCurrency = loanToken->fixedIntervalPriceId; auto priceFeed = mnview.GetFixedIntervalPrice(tokenCurrency); - Require(priceFeed, priceFeed.msg); + if (!priceFeed) { + return priceFeed; + } - Require(priceFeed.val->isLive(mnview.GetPriceDeviation()), - "No live fixed prices for %s/%s", - tokenCurrency.first, - tokenCurrency.second); + if (!priceFeed.val->isLive(mnview.GetPriceDeviation())) { + return Res::Err("No live fixed prices for %s/%s", tokenCurrency.first, tokenCurrency.second); + } for (int i = 0; i < 2; i++) { // check active and next price auto price = priceFeed.val->priceRecord[int(i > 0)]; auto amount = MultiplyAmounts(price, tokenAmount); if (price > COIN) { - Require(amount >= tokenAmount, - "Value/price too high (%s/%s)", - GetDecimalString(tokenAmount), - GetDecimalString(price)); + if (amount < tokenAmount) { + return Res::Err( + "Value/price too high (%s/%s)", GetDecimalString(tokenAmount), GetDecimalString(price)); + } } auto &totalLoans = i > 0 ? totalLoansNextPrice : totalLoansActivePrice; auto prevLoans = totalLoans; totalLoans += amount; - Require(prevLoans <= totalLoans, "Exceed maximum loans"); + if (prevLoans > totalLoans) { + return Res::Err("Exceed maximum loans"); + } } - Require(mnview.AddMintedTokens(tokenId, tokenAmount)); + if (auto res = mnview.AddMintedTokens(tokenId, tokenAmount); !res) { + return res; + } const auto &address = !obj.to.empty() ? obj.to : vault->ownerAddress; CalculateOwnerRewards(address); - Require(mnview.AddBalance(address, CTokenAmount{tokenId, tokenAmount})); + if (auto res = mnview.AddBalance(address, CTokenAmount{tokenId, tokenAmount}); !res) { + return res; + } } auto scheme = mnview.GetLoanScheme(vault->schemeId); @@ -639,14 +781,19 @@ Res CLoansConsensus::operator()(const CLoanTakeLoanMessage &obj) const { bool useNextPrice = i > 0, requireLivePrice = true; auto vaultAssets = mnview.GetVaultAssets(obj.vaultId, *collaterals, height, time, useNextPrice, requireLivePrice); - Require(vaultAssets); + if (!vaultAssets) { + return vaultAssets; + } - Require(vaultAssets.val->ratio() >= scheme->ratio, - "Vault does not have enough collateralization ratio defined by loan scheme - %d < %d", - vaultAssets.val->ratio(), - scheme->ratio); + if (vaultAssets.val->ratio() < scheme->ratio) { + return Res::Err("Vault does not have enough collateralization ratio defined by loan scheme - %d < %d", + vaultAssets.val->ratio(), + scheme->ratio); + } - Require(CollateralPctCheck(hasDUSDLoans, vaultAssets, scheme->ratio)); + if (auto res = CollateralPctCheck(hasDUSDLoans, vaultAssets, scheme->ratio); !res) { + return res; + } } return Res::Ok(); } @@ -862,10 +1009,12 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message &obj) const { return DeFiErrors::TokenInterestRateInvalid(loanToken->symbol); } - Require(newRate->interestPerBlock.amount != 0, + if (newRate->interestPerBlock.amount == 0) { + return Res::Err( "Cannot payback this amount of loan for %s, either payback full amount or less than this " "amount!", loanToken->symbol); + } } CalculateOwnerRewards(obj.from); @@ -1005,17 +1154,25 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message &obj) const { } Res CLoansConsensus::operator()(const CPaybackWithCollateralMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } // vault exists const auto vault = mnview.GetVault(obj.vaultId); - Require(vault, "Vault <%s> not found", obj.vaultId.GetHex()); + if (!vault) { + return Res::Err("Vault <%s> not found", obj.vaultId.GetHex()); + } // vault under liquidation - Require(!vault->isUnderLiquidation, "Cannot payback vault with collateral while vault's under liquidation"); + if (vault->isUnderLiquidation) { + return Res::Err("Cannot payback vault with collateral while vault's under liquidation"); + } // owner auth - Require(HasAuth(vault->ownerAddress), "tx must have at least one input from token owner"); + if (!HasAuth(vault->ownerAddress)) { + return Res::Err("tx must have at least one input from token owner"); + } return PaybackWithCollateral(mnview, *vault, obj.vaultId, height, time); } diff --git a/src/dfi/consensus/masternodes.cpp b/src/dfi/consensus/masternodes.cpp index 1f684d5913..bd621da875 100644 --- a/src/dfi/consensus/masternodes.cpp +++ b/src/dfi/consensus/masternodes.cpp @@ -11,18 +11,23 @@ #include Res CMasternodesConsensus::CheckMasternodeCreationTx() const { - Require(tx.vout.size() >= 2 && tx.vout[0].nValue >= GetMnCreationFee(height) && tx.vout[0].nTokenId == DCT_ID{0} && - tx.vout[1].nValue == GetMnCollateralAmount(height) && tx.vout[1].nTokenId == DCT_ID{0}, - "malformed tx vouts (wrong creation fee or collateral amount)"); + if (tx.vout.size() < 2 || tx.vout[0].nValue < GetMnCreationFee(height) || tx.vout[0].nTokenId != DCT_ID{0} || + tx.vout[1].nValue != GetMnCollateralAmount(height) || tx.vout[1].nTokenId != DCT_ID{0}) { + return Res::Err("malformed tx vouts (wrong creation fee or collateral amount)"); + } return Res::Ok(); } Res CMasternodesConsensus::operator()(const CCreateMasterNodeMessage &obj) const { - Require(CheckMasternodeCreationTx()); + if (auto res = CheckMasternodeCreationTx(); !res) { + return res; + } if (height >= static_cast(consensus.DF8EunosHeight)) { - Require(HasAuth(tx.vout[1].scriptPubKey), "masternode creation needs owner auth"); + if (!HasAuth(tx.vout[1].scriptPubKey)) { + return Res::Err("masternode creation needs owner auth"); + } } if (height >= static_cast(consensus.DF10EunosPayaHeight)) { @@ -35,7 +40,9 @@ Res CMasternodesConsensus::operator()(const CCreateMasterNodeMessage &obj) const return Res::Err("Timelock must be set to either 0, 5 or 10 years"); } } else { - Require(obj.timelock == 0, "collateral timelock cannot be set below EunosPaya"); + if (obj.timelock != 0) { + return Res::Err("collateral timelock cannot be set below EunosPaya"); + } } CMasternode node; @@ -80,7 +87,9 @@ Res CMasternodesConsensus::operator()(const CCreateMasterNodeMessage &obj) const return Res::ErrCode(CustomTxErrCodes::Fatal, "Masternode exist with that owner address pending"); } - Require(mnview.CreateMasternode(tx.GetHash(), node, obj.timelock)); + if (auto res = mnview.CreateMasternode(tx.GetHash(), node, obj.timelock); !res) { + return res; + } // Build coinage from the point of masternode creation if (height >= static_cast(consensus.DF10EunosPayaHeight)) { @@ -102,7 +111,10 @@ Res CMasternodesConsensus::operator()(const CResignMasterNodeMessage &obj) const return DeFiErrors::MNInvalid(obj.ToString()); } - Require(HasCollateralAuth(node->collateralTx.IsNull() ? static_cast(obj) : node->collateralTx)); + if (auto res = HasCollateralAuth(node->collateralTx.IsNull() ? static_cast(obj) : node->collateralTx); + !res) { + return res; + } return mnview.ResignMasternode(*node, obj, tx.GetHash(), height); } @@ -121,7 +133,9 @@ Res CMasternodesConsensus::operator()(const CUpdateMasterNodeMessage &obj) const } const auto collateralTx = node->collateralTx.IsNull() ? obj.mnId : node->collateralTx; - Require(HasCollateralAuth(collateralTx)); + if (auto res = HasCollateralAuth(collateralTx); !res) { + return res; + } auto state = node->GetState(height, mnview); if (state != CMasternode::ENABLED) { diff --git a/src/dfi/consensus/oracles.cpp b/src/dfi/consensus/oracles.cpp index 58589255ce..d9590a0427 100644 --- a/src/dfi/consensus/oracles.cpp +++ b/src/dfi/consensus/oracles.cpp @@ -11,7 +11,9 @@ Res COraclesConsensus::NormalizeTokenCurrencyPair(std::set & for (const auto &pair : tokenCurrency) { auto token = trim_ws(pair.first).substr(0, CToken::MAX_TOKEN_SYMBOL_LENGTH); auto currency = trim_ws(pair.second).substr(0, CToken::MAX_TOKEN_SYMBOL_LENGTH); - Require(!token.empty() && !currency.empty(), "empty token / currency"); + if (token.empty() || currency.empty()) { + return Res::Err("empty token / currency"); + } trimmed.emplace(token, currency); } tokenCurrency = std::move(trimmed); @@ -34,12 +36,16 @@ Res COraclesConsensus::operator()(const CUpdateOracleAppointMessage &obj) const } COracle oracle; static_cast(oracle) = obj.newOracleAppoint; - Require(NormalizeTokenCurrencyPair(oracle.availablePairs)); + if (auto res = NormalizeTokenCurrencyPair(oracle.availablePairs); !res) { + return res; + } return mnview.UpdateOracle(obj.oracleId, std::move(oracle)); } Res COraclesConsensus::operator()(const CRemoveOracleAppointMessage &obj) const { - Require(HasFoundationAuth()); + if (auto res = HasFoundationAuth(); !res) { + return res; + } return mnview.RemoveOracle(obj.oracleId); } diff --git a/src/dfi/consensus/poolpairs.cpp b/src/dfi/consensus/poolpairs.cpp index ff8be2c8ec..09273fc603 100644 --- a/src/dfi/consensus/poolpairs.cpp +++ b/src/dfi/consensus/poolpairs.cpp @@ -12,7 +12,9 @@ Res CPoolPairsConsensus::EraseEmptyBalances(TAmounts &balances) const { for (auto it = balances.begin(), next_it = it; it != balances.end(); it = next_it) { ++next_it; - Require(mnview.GetToken(it->first), "reward token %d does not exist!", it->first.v); + if (!mnview.GetToken(it->first)) { + return Res::Err("reward token %d does not exist!", it->first.v); + } if (it->second == 0) { balances.erase(it); @@ -23,11 +25,17 @@ Res CPoolPairsConsensus::EraseEmptyBalances(TAmounts &balances) const { Res CPoolPairsConsensus::operator()(const CCreatePoolPairMessage &obj) const { // check foundation auth - Require(HasFoundationAuth()); - Require(obj.commission >= 0 && obj.commission <= COIN, "wrong commission"); + if (auto res = HasFoundationAuth(); !res) { + return res; + } + if (obj.commission < 0 || obj.commission > COIN) { + return Res::Err("wrong commission"); + } if (height >= static_cast(consensus.DF16FortCanningCrunchHeight)) { - Require(obj.pairSymbol.find('/') == std::string::npos, "token symbol should not contain '/'"); + if (obj.pairSymbol.find('/') != std::string::npos) { + return Res::Err("token symbol should not contain '/'"); + } } /// @todo ownerAddress validity checked only in rpc. is it enough? @@ -39,10 +47,14 @@ Res CPoolPairsConsensus::operator()(const CCreatePoolPairMessage &obj) const { auto &rewards = poolPair.rewards; auto tokenA = mnview.GetToken(poolPair.idTokenA); - Require(tokenA, "token %s does not exist!", poolPair.idTokenA.ToString()); + if (!tokenA) { + return Res::Err("token %s does not exist!", poolPair.idTokenA.ToString()); + } auto tokenB = mnview.GetToken(poolPair.idTokenB); - Require(tokenB, "token %s does not exist!", poolPair.idTokenB.ToString()); + if (!tokenB) { + return Res::Err("token %s does not exist!", poolPair.idTokenB.ToString()); + } const auto symbolLength = height >= static_cast(consensus.DF11FortCanningHeight) ? CToken::MAX_TOKEN_POOLPAIR_LENGTH @@ -63,12 +75,16 @@ Res CPoolPairsConsensus::operator()(const CCreatePoolPairMessage &obj) const { token.creationHeight = height; auto tokenId = mnview.CreateToken(token, false); - Require(tokenId); + if (!tokenId) { + return tokenId; + } rewards = obj.rewards; if (!rewards.balances.empty()) { // Check tokens exist and remove empty reward amounts - Require(EraseEmptyBalances(rewards.balances)); + if (auto res = EraseEmptyBalances(rewards.balances); !res) { + return res; + } } return mnview.SetPoolPair(tokenId, height, poolPair); @@ -76,7 +92,9 @@ Res CPoolPairsConsensus::operator()(const CCreatePoolPairMessage &obj) const { Res CPoolPairsConsensus::operator()(const CUpdatePoolPairMessage &obj) const { // check foundation auth - Require(HasFoundationAuth()); + if (auto res = HasFoundationAuth(); !res) { + return res; + } auto rewards = obj.rewards; if (!rewards.balances.empty()) { @@ -85,7 +103,9 @@ Res CPoolPairsConsensus::operator()(const CUpdatePoolPairMessage &obj) const { rewards.balances.cbegin()->first == DCT_ID{std::numeric_limits::max()} && rewards.balances.cbegin()->second == std::numeric_limits::max())) { // Check if tokens exist and remove empty reward amounts - Require(EraseEmptyBalances(rewards.balances)); + if (auto res = EraseEmptyBalances(rewards.balances); !res) { + return res; + } } } return mnview.UpdatePoolPair(obj.poolId, height, obj.status, obj.commission, obj.ownerAddress, rewards); @@ -93,38 +113,52 @@ Res CPoolPairsConsensus::operator()(const CUpdatePoolPairMessage &obj) const { Res CPoolPairsConsensus::operator()(const CPoolSwapMessage &obj) const { // check auth - Require(HasAuth(obj.from)); + if (auto res = HasAuth(obj.from); !res) { + return res; + } return CPoolSwap(obj, height).ExecuteSwap(mnview, {}, consensus); } Res CPoolPairsConsensus::operator()(const CPoolSwapMessageV2 &obj) const { // check auth - Require(HasAuth(obj.swapInfo.from)); + if (auto res = HasAuth(obj.swapInfo.from); !res) { + return res; + } return CPoolSwap(obj.swapInfo, height).ExecuteSwap(mnview, obj.poolIDs, consensus); } Res CPoolPairsConsensus::operator()(const CLiquidityMessage &obj) const { CBalances sumTx = SumAllTransfers(obj.from); - Require(sumTx.balances.size() == 2, "the pool pair requires two tokens"); + if (sumTx.balances.size() != 2) { + return Res::Err("the pool pair requires two tokens"); + } std::pair amountA = *sumTx.balances.begin(); std::pair amountB = *(std::next(sumTx.balances.begin(), 1)); // checked internally too. remove here? - Require(amountA.second > 0 && amountB.second > 0, "amount cannot be less than or equal to zero"); + if (amountA.second <= 0 || amountB.second <= 0) { + return Res::Err("amount cannot be less than or equal to zero"); + } auto pair = mnview.GetPoolPair(amountA.first, amountB.first); - Require(pair, "there is no such pool pair"); + if (!pair) { + return Res::Err("there is no such pool pair"); + } for (const auto &kv : obj.from) { - Require(HasAuth(kv.first)); + if (auto res = HasAuth(kv.first); !res) { + return res; + } } for (const auto &kv : obj.from) { CalculateOwnerRewards(kv.first); - Require(mnview.SubBalances(kv.first, kv.second)); + if (auto res = mnview.SubBalances(kv.first, kv.second); !res) { + return res; + } } const auto &lpTokenID = pair->first; @@ -136,14 +170,18 @@ Res CPoolPairsConsensus::operator()(const CLiquidityMessage &obj) const { } bool slippageProtection = static_cast(height) >= consensus.DF3BayfrontMarinaHeight; - Require(pool.AddLiquidity( - amountA.second, - amountB.second, - [&] /*onMint*/ (CAmount liqAmount) { - CBalances balance{TAmounts{{lpTokenID, liqAmount}}}; - return AddBalanceSetShares(obj.shareAddress, balance); - }, - slippageProtection)); + if (auto res = pool.AddLiquidity( + amountA.second, + amountB.second, + [&] /*onMint*/ (CAmount liqAmount) { + CBalances balance{TAmounts{{lpTokenID, liqAmount}}}; + return AddBalanceSetShares(obj.shareAddress, balance); + }, + slippageProtection); + !res) { + return res; + } + return mnview.SetPoolPair(lpTokenID, height, pool); } @@ -152,26 +190,38 @@ Res CPoolPairsConsensus::operator()(const CRemoveLiquidityMessage &obj) const { auto amount = obj.amount; // checked internally too. remove here? - Require(amount.nValue > 0, "amount cannot be less than or equal to zero"); + if (amount.nValue <= 0) { + return Res::Err("amount cannot be less than or equal to zero"); + } auto pair = mnview.GetPoolPair(amount.nTokenId); - Require(pair, "there is no such pool pair"); + if (!pair) { + return Res::Err("there is no such pool pair"); + } - Require(HasAuth(from)); + if (auto res = HasAuth(from); !res) { + return res; + } CPoolPair &pool = pair.value(); // subtract liq.balance BEFORE RemoveLiquidity call to check balance correctness CBalances balance{TAmounts{{amount.nTokenId, amount.nValue}}}; - Require(SubBalanceDelShares(from, balance)); - - Require(pool.RemoveLiquidity(amount.nValue, [&](CAmount amountA, CAmount amountB) { - CalculateOwnerRewards(from); - CBalances balances{ - TAmounts{{pool.idTokenA, amountA}, {pool.idTokenB, amountB}} - }; - return mnview.AddBalances(from, balances); - })); + if (auto res = SubBalanceDelShares(from, balance); !res) { + return res; + } + + if (auto res = pool.RemoveLiquidity(amount.nValue, + [&](CAmount amountA, CAmount amountB) { + CalculateOwnerRewards(from); + CBalances balances{ + TAmounts{{pool.idTokenA, amountA}, {pool.idTokenB, amountB}} + }; + return mnview.AddBalances(from, balances); + }); + !res) { + return res; + } return mnview.SetPoolPair(amount.nTokenId, height, pool); } diff --git a/src/dfi/consensus/proposals.cpp b/src/dfi/consensus/proposals.cpp index f962b0e8d1..46b4cbf146 100644 --- a/src/dfi/consensus/proposals.cpp +++ b/src/dfi/consensus/proposals.cpp @@ -18,9 +18,11 @@ Res CProposalsConsensus::IsOnChainGovernanceEnabled() const { CDataStructureV0 enabledKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovernanceEnabled}; auto attributes = mnview.GetAttributes(); - Require(attributes, "Attributes unavailable"); + assert(attributes); - Require(attributes->GetValue(enabledKey, false), "Cannot create tx, on-chain governance is not enabled"); + if (!attributes->GetValue(enabledKey, false)) { + return Res::Err("Cannot create tx, on-chain governance is not enabled"); + } return Res::Ok(); } diff --git a/src/dfi/consensus/smartcontracts.cpp b/src/dfi/consensus/smartcontracts.cpp index 7026630cb5..904f33c9f0 100644 --- a/src/dfi/consensus/smartcontracts.cpp +++ b/src/dfi/consensus/smartcontracts.cpp @@ -11,25 +11,37 @@ Res CSmartContractsConsensus::HandleDFIP2201Contract(const CSmartContractMessage &obj) const { const auto attributes = mnview.GetAttributes(); - Require(attributes, "Attributes unavailable"); + assert(attributes); CDataStructureV0 activeKey{AttributeTypes::Param, ParamIDs::DFIP2201, DFIPKeys::Active}; - Require(attributes->GetValue(activeKey, false), "DFIP2201 smart contract is not enabled"); + if (!attributes->GetValue(activeKey, false)) { + return Res::Err("DFIP2201 smart contract is not enabled"); + } - Require(obj.name == SMART_CONTRACT_DFIP_2201, "DFIP2201 contract mismatch - got: " + obj.name); + if (obj.name != SMART_CONTRACT_DFIP_2201) { + return Res::Err("DFIP2201 contract mismatch - got: " + obj.name); + } - Require(obj.accounts.size() == 1, "Only one address entry expected for " + obj.name); + if (obj.accounts.size() != 1) { + return Res::Err("Only one address entry expected for " + obj.name); + } - Require(obj.accounts.begin()->second.balances.size() == 1, "Only one amount entry expected for " + obj.name); + if (obj.accounts.begin()->second.balances.size() != 1) { + return Res::Err("Only one amount entry expected for " + obj.name); + } const auto &script = obj.accounts.begin()->first; - Require(HasAuth(script), "Must have at least one input from supplied address"); + if (!HasAuth(script)) { + return Res::Err("Must have at least one input from supplied address"); + } const auto &id = obj.accounts.begin()->second.balances.begin()->first; const auto &amount = obj.accounts.begin()->second.balances.begin()->second; - Require(amount > 0, "Amount out of range"); + if (amount <= 0) { + return Res::Err("Amount out of range"); + } CDataStructureV0 minSwapKey{AttributeTypes::Param, ParamIDs::DFIP2201, DFIPKeys::MinSwap}; auto minSwap = attributes->GetValue(minSwapKey, CAmount{0}); @@ -39,23 +51,30 @@ Res CSmartContractsConsensus::HandleDFIP2201Contract(const CSmartContractMessage } const auto token = mnview.GetToken(id); - Require(token, "Specified token not found"); + if (!token) { + return Res::Err("Specified token not found"); + } - Require(token->symbol == "BTC" && token->name == "Bitcoin" && token->IsDAT(), - "Only Bitcoin can be swapped in " + obj.name); + if (token->symbol != "BTC" || token->name != "Bitcoin" || !token->IsDAT()) { + return Res::Err("Only Bitcoin can be swapped in " + obj.name); + } if (height >= static_cast(consensus.DF22MetachainHeight)) { mnview.CalculateOwnerRewards(script, height); } - Require(mnview.SubBalance(script, {id, amount})); + if (auto res = mnview.SubBalance(script, {id, amount}); !res) { + return res; + } const CTokenCurrencyPair btcUsd{"BTC", "USD"}; const CTokenCurrencyPair dfiUsd{"DFI", "USD"}; bool useNextPrice{false}, requireLivePrice{true}; auto resVal = mnview.GetValidatedIntervalPrice(btcUsd, useNextPrice, requireLivePrice); - Require(resVal); + if (!resVal) { + return resVal; + } CDataStructureV0 premiumKey{AttributeTypes::Param, ParamIDs::DFIP2201, DFIPKeys::Premium}; auto premium = attributes->GetValue(premiumKey, CAmount{2500000}); @@ -63,23 +82,33 @@ Res CSmartContractsConsensus::HandleDFIP2201Contract(const CSmartContractMessage const auto &btcPrice = MultiplyAmounts(*resVal.val, premium + COIN); resVal = mnview.GetValidatedIntervalPrice(dfiUsd, useNextPrice, requireLivePrice); - Require(resVal); + if (!resVal) { + return resVal; + } const auto totalDFI = MultiplyAmounts(DivideAmounts(btcPrice, *resVal.val), amount); - Require(mnview.SubBalance(consensus.smartContracts.begin()->second, {{0}, totalDFI})); + if (auto res = mnview.SubBalance(consensus.smartContracts.begin()->second, {{0}, totalDFI}); !res) { + return res; + } - Require(mnview.AddBalance(script, {{0}, totalDFI})); + if (auto res = mnview.AddBalance(script, {{0}, totalDFI}); !res) { + return res; + } return Res::Ok(); } Res CSmartContractsConsensus::operator()(const CSmartContractMessage &obj) const { - Require(!obj.accounts.empty(), "Contract account parameters missing"); + if (obj.accounts.empty()) { + return Res::Err("Contract account parameters missing"); + } auto contracts = consensus.smartContracts; auto contract = contracts.find(obj.name); - Require(contract != contracts.end(), "Specified smart contract not found"); + if (contract == contracts.end()) { + return Res::Err("Specified smart contract not found"); + } // Convert to switch when it's long enough. if (obj.name == SMART_CONTRACT_DFIP_2201) { @@ -90,10 +119,12 @@ Res CSmartContractsConsensus::operator()(const CSmartContractMessage &obj) const } Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { - Require(HasAuth(obj.owner), "Transaction must have at least one input from owner"); + if (!HasAuth(obj.owner)) { + return Res::Err("Transaction must have at least one input from owner"); + } const auto attributes = mnview.GetAttributes(); - Require(attributes, "Attributes unavailable"); + assert(attributes); bool dfiToDUSD = !obj.source.nTokenId.v; const auto paramID = dfiToDUSD ? ParamIDs::DFIP2206F : ParamIDs::DFIP2203; @@ -102,54 +133,79 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { CDataStructureV0 blockKey{AttributeTypes::Param, paramID, DFIPKeys::BlockPeriod}; CDataStructureV0 rewardKey{AttributeTypes::Param, paramID, DFIPKeys::RewardPct}; - Require(attributes->GetValue(activeKey, false) && attributes->CheckKey(blockKey) && attributes->CheckKey(rewardKey), - "%s not currently active", - dfiToDUSD ? "DFIP2206F" : "DFIP2203"); + if (!attributes->GetValue(activeKey, false) || !attributes->CheckKey(blockKey) || + !attributes->CheckKey(rewardKey)) { + return Res::Err("%s not currently active", dfiToDUSD ? "DFIP2206F" : "DFIP2203"); + } CDataStructureV0 startKey{AttributeTypes::Param, paramID, DFIPKeys::StartBlock}; if (const auto startBlock = attributes->GetValue(startKey, CAmount{})) { - Require(height >= startBlock, "%s not active until block %d", dfiToDUSD ? "DFIP2206F" : "DFIP2203", startBlock); + if (height < startBlock) { + return Res::Err("%s not active until block %d", dfiToDUSD ? "DFIP2206F" : "DFIP2203", startBlock); + } } - Require(obj.source.nValue > 0, "Source amount must be more than zero"); + if (obj.source.nValue <= 0) { + return Res::Err("Source amount must be more than zero"); + } const auto source = mnview.GetLoanTokenByID(obj.source.nTokenId); - Require(dfiToDUSD || source, "Could not get source loan token %d", obj.source.nTokenId.v); + if (!dfiToDUSD && !source) { + return Res::Err("Could not get source loan token %d", obj.source.nTokenId.v); + } if (!dfiToDUSD && source->symbol == "DUSD") { CDataStructureV0 tokenKey{AttributeTypes::Token, obj.destination, TokenKeys::DFIP2203Enabled}; const auto enabled = attributes->GetValue(tokenKey, true); - Require(enabled, "DFIP2203 currently disabled for token %d", obj.destination); + if (!enabled) { + return Res::Err("DFIP2203 currently disabled for token %d", obj.destination); + } const auto loanToken = mnview.GetLoanTokenByID({obj.destination}); - Require(loanToken, "Could not get destination loan token %d. Set valid destination.", obj.destination); + if (!loanToken) { + return Res::Err("Could not get destination loan token %d. Set valid destination.", obj.destination); + } - Require(!mnview.AreTokensLocked({obj.destination}), "Cannot create future swap for locked token"); + if (mnview.AreTokensLocked({obj.destination})) { + return Res::Err("Cannot create future swap for locked token"); + } } else { if (!dfiToDUSD) { - Require(obj.destination == 0, "Destination should not be set when source amount is dToken or DFI"); + if (obj.destination != 0) { + return Res::Err("Destination should not be set when source amount is dToken or DFI"); + } - Require(!mnview.AreTokensLocked({obj.source.nTokenId.v}), "Cannot create future swap for locked token"); + if (mnview.AreTokensLocked({obj.source.nTokenId.v})) { + return Res::Err("Cannot create future swap for locked token"); + } CDataStructureV0 tokenKey{AttributeTypes::Token, obj.source.nTokenId.v, TokenKeys::DFIP2203Enabled}; const auto enabled = attributes->GetValue(tokenKey, true); - Require(enabled, "DFIP2203 currently disabled for token %s", obj.source.nTokenId.ToString()); + if (!enabled) { + return Res::Err("DFIP2203 currently disabled for token %s", obj.source.nTokenId.ToString()); + } } else { DCT_ID id{}; const auto token = mnview.GetTokenGuessId("DUSD", id); - Require(token, "No DUSD token defined"); + if (!token) { + return Res::Err("No DUSD token defined"); + } - Require(mnview.GetFixedIntervalPrice({"DFI", "USD"}), "DFI / DUSD fixed interval price not found"); + if (!mnview.GetFixedIntervalPrice({"DFI", "USD"})) { + return Res::Err("DFI / DUSD fixed interval price not found"); + } - Require(obj.destination == id.v, - "Incorrect destination defined for DFI swap, DUSD destination expected id: %d", - id.v); + if (obj.destination != id.v) { + return Res::Err("Incorrect destination defined for DFI swap, DUSD destination expected id: %d", id.v); + } } } const auto contractType = dfiToDUSD ? SMART_CONTRACT_DFIP2206F : SMART_CONTRACT_DFIP_2203; const auto contractAddressValue = GetFutureSwapContractAddress(contractType); - Require(contractAddressValue); + if (!contractAddressValue) { + return contractAddressValue; + } const auto economyKey = dfiToDUSD ? EconomyKeys::DFIP2206FCurrent : EconomyKeys::DFIP2203Current; CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Economy, economyKey}; @@ -198,27 +254,46 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { } } - Require(totalFutures.Sub(obj.source.nValue)); + if (auto res = totalFutures.Sub(obj.source.nValue); !res) { + return res; + } if (totalFutures.nValue > 0) { - Res res{}; if (!dfiToDUSD) { - Require(mnview.StoreFuturesUserValues({height, obj.owner, txn}, {totalFutures, obj.destination})); + if (auto res = mnview.StoreFuturesUserValues({height, obj.owner, txn}, {totalFutures, obj.destination}); + !res) { + return res; + } } else { - Require(mnview.StoreFuturesDUSD({height, obj.owner, txn}, totalFutures.nValue)); + if (auto res = mnview.StoreFuturesDUSD({height, obj.owner, txn}, totalFutures.nValue); !res) { + return res; + } } } - Require(TransferTokenBalance(obj.source.nTokenId, obj.source.nValue, *contractAddressValue, obj.owner)); + if (auto res = TransferTokenBalance(obj.source.nTokenId, obj.source.nValue, *contractAddressValue, obj.owner); + !res) { + return res; + } - Require(balances.Sub(obj.source)); + if (auto res = balances.Sub(obj.source); !res) { + return res; + } } else { - Require(TransferTokenBalance(obj.source.nTokenId, obj.source.nValue, obj.owner, *contractAddressValue)); + if (auto res = TransferTokenBalance(obj.source.nTokenId, obj.source.nValue, obj.owner, *contractAddressValue); + !res) { + return res; + } if (!dfiToDUSD) { - Require(mnview.StoreFuturesUserValues({height, obj.owner, txn}, {obj.source, obj.destination})); + if (auto res = mnview.StoreFuturesUserValues({height, obj.owner, txn}, {obj.source, obj.destination}); + !res) { + return res; + } } else { - Require(mnview.StoreFuturesDUSD({height, obj.owner, txn}, obj.source.nValue)); + if (auto res = mnview.StoreFuturesDUSD({height, obj.owner, txn}, obj.source.nValue); !res) { + return res; + } } balances.Add(obj.source); } diff --git a/src/dfi/consensus/tokens.cpp b/src/dfi/consensus/tokens.cpp index 22b243cbe8..2fce316ffc 100644 --- a/src/dfi/consensus/tokens.cpp +++ b/src/dfi/consensus/tokens.cpp @@ -10,10 +10,11 @@ #include Res CTokensConsensus::CheckTokenCreationTx() const { - Require(tx.vout.size() >= 2 && tx.vout[0].nValue >= GetTokenCreationFee(height) && - tx.vout[0].nTokenId == DCT_ID{0} && tx.vout[1].nValue == GetTokenCollateralAmount() && - tx.vout[1].nTokenId == DCT_ID{0}, - "malformed tx vouts (wrong creation fee or collateral amount)"); + if (tx.vout.size() < 2 || tx.vout[0].nValue < GetTokenCreationFee(height) || tx.vout[0].nTokenId != DCT_ID{0} || + tx.vout[1].nValue != GetTokenCollateralAmount() || tx.vout[1].nTokenId != DCT_ID{0}, + "malformed tx vouts (wrong creation fee or collateral amount)") { + ; + } return Res::Ok(); } @@ -126,16 +127,23 @@ Res CTokensConsensus::operator()(const CUpdateTokenPreAMKMessage &obj) const { Res CTokensConsensus::operator()(const CUpdateTokenMessage &obj) const { auto pair = mnview.GetTokenByCreationTx(obj.tokenTx); - Require(pair, "token with creationTx %s does not exist", obj.tokenTx.ToString()); - Require(pair->first != DCT_ID{0}, "Can't alter DFI token!"); + if (!pair) { + return Res::Err("token with creationTx %s does not exist", obj.tokenTx.ToString()); + } + if (pair->first == DCT_ID{0}) { + return Res::Err("Can't alter DFI token!"); + } - Require(!mnview.AreTokensLocked({pair->first.v}), "Cannot update token during lock"); + if (mnview.AreTokensLocked({pair->first.v})) { + return Res::Err("Cannot update token during lock"); + } const auto &token = pair->second; // need to check it exectly here cause lps has no collateral auth (that checked next) - Require( - !token.IsPoolShare(), "token %s is the LPS token! Can't alter pool share's tokens!", obj.tokenTx.ToString()); + if (token.IsPoolShare()) { + return Res::Err("token %s is the LPS token! Can't alter pool share's tokens!", obj.tokenTx.ToString()); + } // check auth, depends from token's "origins" const Coin &auth = coins.AccessCoin(COutPoint(token.creationTx, 1)); // always n=1 output @@ -152,16 +160,21 @@ Res CTokensConsensus::operator()(const CUpdateTokenMessage &obj) const { : consensus.foundationMembers.count(auth.out.scriptPubKey) > 0; if (isFoundersToken) { - Require(HasFoundationAuth()); + if (auto res = HasFoundationAuth(); !res) { + return res; + } } else { - Require(HasCollateralAuth(token.creationTx)); + if (auto res = HasCollateralAuth(token.creationTx); !res) { + return res; + } } // Check for isDAT change in non-foundation token after set height if (static_cast(height) >= consensus.DF3BayfrontMarinaHeight) { // check foundation auth - Require(obj.token.IsDAT() == token.IsDAT() || HasFoundationAuth(), - "can't set isDAT to true, tx not from foundation member"); + if (obj.token.IsDAT() != token.IsDAT() && !HasFoundationAuth()) { + return Res::Err("can't set isDAT to true, tx not from foundation member"); + } } CTokenImplementation updatedToken{obj.token}; @@ -388,7 +401,7 @@ Res CTokensConsensus::operator()(const CBurnTokensMessage &obj) const { } auto attributes = mnview.GetAttributes(); - Require(attributes, "Cannot read from attributes gov variable!"); + assert(attributes); CDataStructureV0 membersKey{AttributeTypes::Consortium, tokenId.v, ConsortiumKeys::MemberValues}; const auto members = attributes->GetValue(membersKey, CConsortiumMembers{}); diff --git a/src/dfi/consensus/txvisitor.cpp b/src/dfi/consensus/txvisitor.cpp index 5ee80e5144..1c3ae2a827 100644 --- a/src/dfi/consensus/txvisitor.cpp +++ b/src/dfi/consensus/txvisitor.cpp @@ -116,7 +116,9 @@ Res CCustomTxVisitor::HasAuth(const CScript &auth) const { Res CCustomTxVisitor::HasCollateralAuth(const uint256 &collateralTx) const { const Coin &auth = coins.AccessCoin(COutPoint(collateralTx, 1)); // always n=1 output - Require(HasAuth(auth.out.scriptPubKey), "tx must have at least one input from the owner"); + if (!HasAuth(auth.out.scriptPubKey)) { + return Res::Err("tx must have at least one input from the owner"); + } return Res::Ok(); } @@ -144,10 +146,14 @@ Res CCustomTxVisitor::HasFoundationAuth() const { Res CCustomTxVisitor::CheckCustomTx() const { if (static_cast(height) < consensus.DF10EunosPayaHeight) { - Require(tx.vout.size() == 2, "malformed tx vouts ((wrong number of vouts)"); + if (tx.vout.size() != 2) { + return Res::Err("malformed tx vouts ((wrong number of vouts)"); + } } if (static_cast(height) >= consensus.DF10EunosPayaHeight) { - Require(tx.vout[0].nValue == 0, "malformed tx vouts, first vout must be OP_RETURN vout with value 0"); + if (tx.vout[0].nValue != 0) { + return Res::Err("malformed tx vouts, first vout must be OP_RETURN vout with value 0"); + } } return Res::Ok(); } @@ -158,12 +164,16 @@ Res CCustomTxVisitor::TransferTokenBalance(DCT_ID id, CAmount amount, const CScr CTokenAmount tokenAmount{id, amount}; // if "from" not supplied it will only add balance on "to" address if (!from.empty()) { - Require(mnview.SubBalance(from, tokenAmount)); + if (auto res = mnview.SubBalance(from, tokenAmount); !res) { + return res; + } } // if "to" not supplied it will only sub balance from "form" address if (!to.empty()) { - Require(mnview.AddBalance(to, tokenAmount)); + if (auto res = mnview.AddBalance(to, tokenAmount); !res) { + return res; + } } return Res::Ok(); } @@ -171,7 +181,9 @@ Res CCustomTxVisitor::TransferTokenBalance(DCT_ID id, CAmount amount, const CScr ResVal CCustomTxVisitor::MintedTokens(uint32_t mintingOutputsStart) const { CBalances balances; for (uint32_t i = mintingOutputsStart; i < (uint32_t)tx.vout.size(); i++) { - Require(balances.Add(tx.vout[i].TokenAmount())); + if (auto res = balances.Add(tx.vout[i].TokenAmount()); !res) { + return res; + } } return {balances, Res::Ok()}; } @@ -182,7 +194,9 @@ Res CCustomTxVisitor::SetShares(const CScript &owner, const TAmounts &balances) if (token && token->IsPoolShare()) { const auto bal = mnview.GetBalance(owner, balance.first); if (bal.nValue == balance.second) { - Require(mnview.SetShare(balance.first, owner, height)); + if (auto res = mnview.SetShare(balance.first, owner, height); !res) { + return res; + } } } } @@ -195,7 +209,9 @@ Res CCustomTxVisitor::DelShares(const CScript &owner, const TAmounts &balances) if (token && token->IsPoolShare()) { const auto balance = mnview.GetBalance(owner, kv.first); if (balance.nValue == 0) { - Require(mnview.DelShare(kv.first, owner)); + if (auto res = mnview.DelShare(kv.first, owner); !res) { + return res; + } } } } @@ -220,20 +236,26 @@ Res CCustomTxVisitor::SubBalanceDelShares(const CScript &owner, const CBalances Res CCustomTxVisitor::AddBalanceSetShares(const CScript &owner, const CBalances &balance) const { CalculateOwnerRewards(owner); - Require(mnview.AddBalances(owner, balance)); + if (auto res = mnview.AddBalances(owner, balance); !res) { + return res; + } return SetShares(owner, balance.balances); } Res CCustomTxVisitor::AddBalancesSetShares(const CAccounts &accounts) const { for (const auto &account : accounts) { - Require(AddBalanceSetShares(account.first, account.second)); + if (auto res = AddBalanceSetShares(account.first, account.second); !res) { + return res; + } } return Res::Ok(); } Res CCustomTxVisitor::SubBalancesDelShares(const CAccounts &accounts) const { for (const auto &account : accounts) { - Require(SubBalanceDelShares(account.first, account.second)); + if (auto res = SubBalanceDelShares(account.first, account.second); !res) { + return res; + } } return Res::Ok(); } diff --git a/src/dfi/consensus/vaults.cpp b/src/dfi/consensus/vaults.cpp index 6a9d89ee37..663460e506 100644 --- a/src/dfi/consensus/vaults.cpp +++ b/src/dfi/consensus/vaults.cpp @@ -12,9 +12,9 @@ extern std::string ScriptToString(const CScript &script); Res CVaultsConsensus::operator()(const CVaultMessage &obj) const { auto vaultCreationFee = consensus.vaultCreationFee; - Require(tx.vout[0].nValue == vaultCreationFee && tx.vout[0].nTokenId == DCT_ID{0}, - "Malformed tx vouts, creation vault fee is %s DFI", - GetDecimalString(vaultCreationFee)); + if (tx.vout[0].nValue != vaultCreationFee || tx.vout[0].nTokenId != DCT_ID{0}) { + return Res::Err("Malformed tx vouts, creation vault fee is %s DFI", GetDecimalString(vaultCreationFee)); + } CVaultData vault{}; static_cast(vault) = obj; @@ -22,42 +22,60 @@ Res CVaultsConsensus::operator()(const CVaultMessage &obj) const { // set loan scheme to default if non provided if (obj.schemeId.empty()) { auto defaultScheme = mnview.GetDefaultLoanScheme(); - Require(defaultScheme, "There is no default loan scheme"); + if (!defaultScheme) { + return Res::Err("There is no default loan scheme"); + } vault.schemeId = *defaultScheme; } // loan scheme exists - Require(mnview.GetLoanScheme(vault.schemeId), "Cannot find existing loan scheme with id %s", vault.schemeId); + if (!mnview.GetLoanScheme(vault.schemeId)) { + return Res::Err("Cannot find existing loan scheme with id %s", vault.schemeId); + } // check loan scheme is not to be destroyed auto height = mnview.GetDestroyLoanScheme(obj.schemeId); - Require(!height, "Cannot set %s as loan scheme, set to be destroyed on block %d", obj.schemeId, *height); + if (height) { + return Res::Err("Cannot set %s as loan scheme, set to be destroyed on block %d", obj.schemeId, *height); + } auto vaultId = tx.GetHash(); return mnview.StoreVault(vaultId, vault); } Res CVaultsConsensus::operator()(const CCloseVaultMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } // vault exists auto vault = mnview.GetVault(obj.vaultId); - Require(vault, "Vault <%s> not found", obj.vaultId.GetHex()); + if (!vault) { + return Res::Err("Vault <%s> not found", obj.vaultId.GetHex()); + } // vault under liquidation - Require(!vault->isUnderLiquidation, "Cannot close vault under liquidation"); + if (vault->isUnderLiquidation) { + return Res::Err("Cannot close vault under liquidation"); + } // owner auth - Require(HasAuth(vault->ownerAddress), "tx must have at least one input from token owner"); + if (!HasAuth(vault->ownerAddress)) { + return Res::Err("tx must have at least one input from token owner"); + } if (const auto loans = mnview.GetLoanTokens(obj.vaultId)) { for (const auto &[tokenId, amount] : loans->balances) { const auto rate = mnview.GetInterestRate(obj.vaultId, tokenId, height); - Require(rate, "Cannot get interest rate for this token (%d)", tokenId.v); + if (!rate) { + return Res::Err("Cannot get interest rate for this token (%d)", tokenId.v); + } const auto totalInterest = TotalInterest(*rate, height); - Require(amount + totalInterest <= 0, "Vault <%s> has loans", obj.vaultId.GetHex()); + if (amount + totalInterest > 0) { + return Res::Err("Vault <%s> has loans", obj.vaultId.GetHex()); + } // If there is an amount negated by interested remove it from loan tokens. if (amount > 0) { @@ -74,43 +92,61 @@ Res CVaultsConsensus::operator()(const CCloseVaultMessage &obj) const { CalculateOwnerRewards(obj.to); if (auto collaterals = mnview.GetVaultCollaterals(obj.vaultId)) { for (const auto &col : collaterals->balances) { - Require(mnview.AddBalance(obj.to, {col.first, col.second})); + if (auto res = mnview.AddBalance(obj.to, {col.first, col.second}); !res) { + return res; + } } } // delete all interest to vault - Require(mnview.EraseInterest(obj.vaultId, height)); + if (auto res = mnview.EraseInterest(obj.vaultId, height); !res) { + return res; + } // return half fee, the rest is burned at creation auto feeBack = consensus.vaultCreationFee / 2; - Require(mnview.AddBalance(obj.to, {DCT_ID{0}, feeBack})); + if (auto res = mnview.AddBalance(obj.to, {DCT_ID{0}, feeBack}); !res) { + return res; + } return mnview.EraseVault(obj.vaultId); } Res CVaultsConsensus::operator()(const CUpdateVaultMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } // vault exists auto vault = mnview.GetVault(obj.vaultId); - Require(vault, "Vault <%s> not found", obj.vaultId.GetHex()); + if (!vault) { + return Res::Err("Vault <%s> not found", obj.vaultId.GetHex()); + } // vault under liquidation - Require(!vault->isUnderLiquidation, "Cannot update vault under liquidation"); + if (vault->isUnderLiquidation) { + return Res::Err("Cannot update vault under liquidation"); + } // owner auth - Require(HasAuth(vault->ownerAddress), "tx must have at least one input from token owner"); + if (!HasAuth(vault->ownerAddress)) { + return Res::Err("tx must have at least one input from token owner"); + } // loan scheme exists const auto scheme = mnview.GetLoanScheme(obj.schemeId); - Require(scheme, "Cannot find existing loan scheme with id %s", obj.schemeId); + if (!scheme) { + return Res::Err("Cannot find existing loan scheme with id %s", obj.schemeId); + } // loan scheme is not set to be destroyed auto destroyHeight = mnview.GetDestroyLoanScheme(obj.schemeId); - Require( - !destroyHeight, "Cannot set %s as loan scheme, set to be destroyed on block %d", obj.schemeId, *destroyHeight); + if (destroyHeight) { + return Res::Err("Cannot set %s as loan scheme, set to be destroyed on block %d", obj.schemeId, *destroyHeight); + } - Require(IsVaultPriceValid(mnview, obj.vaultId, height), - "Cannot update vault while any of the asset's price is invalid"); + if (!IsVaultPriceValid(mnview, obj.vaultId, height)) { + return Res::Err("Cannot update vault while any of the asset's price is invalid"); + } // don't allow scheme change when vault is going to be in liquidation if (vault->schemeId != obj.schemeId) { @@ -129,8 +165,11 @@ Res CVaultsConsensus::operator()(const CUpdateVaultMessage &obj) const { for (const auto &[tokenId, tokenAmount] : loanTokens->balances) { const auto loanToken = mnview.GetLoanTokenByID(tokenId); assert(loanToken); - Require( - mnview.IncreaseInterest(height, obj.vaultId, obj.schemeId, tokenId, loanToken->interest, 0)); + if (auto res = + mnview.IncreaseInterest(height, obj.vaultId, obj.schemeId, tokenId, loanToken->interest, 0); + !res) { + return res; + } } } } @@ -142,62 +181,86 @@ Res CVaultsConsensus::operator()(const CUpdateVaultMessage &obj) const { } Res CVaultsConsensus::operator()(const CDepositToVaultMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } // owner auth - Require(HasAuth(obj.from), "tx must have at least one input from token owner"); + if (!HasAuth(obj.from)) { + return Res::Err("tx must have at least one input from token owner"); + } // vault exists auto vault = mnview.GetVault(obj.vaultId); - Require(vault, "Vault <%s> not found", obj.vaultId.GetHex()); + if (!vault) { + return Res::Err("Vault <%s> not found", obj.vaultId.GetHex()); + } // vault under liquidation - Require(!vault->isUnderLiquidation, "Cannot deposit to vault under liquidation"); + if (vault->isUnderLiquidation) { + return Res::Err("Cannot deposit to vault under liquidation"); + } // If collateral token exist make sure it is enabled. if (mnview.GetCollateralTokenFromAttributes(obj.amount.nTokenId)) { CDataStructureV0 collateralKey{AttributeTypes::Token, obj.amount.nTokenId.v, TokenKeys::LoanCollateralEnabled}; if (const auto attributes = mnview.GetAttributes()) { - Require( - attributes->GetValue(collateralKey, false), "Collateral token (%d) is disabled", obj.amount.nTokenId.v); + if (!attributes->GetValue(collateralKey, false)) { + return Res::Err("Collateral token (%d) is disabled", obj.amount.nTokenId.v); + } } } // check balance CalculateOwnerRewards(obj.from); - Require(mnview.SubBalance(obj.from, obj.amount), [&](const std::string &msg) { - return strprintf("Insufficient funds: can't subtract balance of %s: %s\n", ScriptToString(obj.from), msg); - }); + if (auto res = mnview.SubBalance(obj.from, obj.amount); !res) { + return Res::Err("Insufficient funds: can't subtract balance of %s: %s\n", ScriptToString(obj.from), res.msg); + } - Require(mnview.AddVaultCollateral(obj.vaultId, obj.amount)); + if (auto res = mnview.AddVaultCollateral(obj.vaultId, obj.amount); !res) { + return res; + } bool useNextPrice = false, requireLivePrice = false; auto collaterals = mnview.GetVaultCollaterals(obj.vaultId); auto vaultAssets = mnview.GetVaultAssets(obj.vaultId, *collaterals, height, time, useNextPrice, requireLivePrice); - Require(vaultAssets); + if (!vaultAssets) { + return vaultAssets; + } auto scheme = mnview.GetLoanScheme(vault->schemeId); return CheckCollateralRatio(obj.vaultId, *scheme, *collaterals, useNextPrice, requireLivePrice); } Res CVaultsConsensus::operator()(const CWithdrawFromVaultMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } // vault exists auto vault = mnview.GetVault(obj.vaultId); - Require(vault, "Vault <%s> not found", obj.vaultId.GetHex()); + if (!vault) { + return Res::Err("Vault <%s> not found", obj.vaultId.GetHex()); + } // vault under liquidation - Require(!vault->isUnderLiquidation, "Cannot withdraw from vault under liquidation"); + if (vault->isUnderLiquidation) { + return Res::Err("Cannot withdraw from vault under liquidation"); + } // owner auth - Require(HasAuth(vault->ownerAddress), "tx must have at least one input from token owner"); + if (!HasAuth(vault->ownerAddress)) { + return Res::Err("tx must have at least one input from token owner"); + } - Require(IsVaultPriceValid(mnview, obj.vaultId, height), - "Cannot withdraw from vault while any of the asset's price is invalid"); + if (!IsVaultPriceValid(mnview, obj.vaultId, height)) { + return Res::Err("Cannot withdraw from vault while any of the asset's price is invalid"); + } - Require(mnview.SubVaultCollateral(obj.vaultId, obj.amount)); + if (auto res = mnview.SubVaultCollateral(obj.vaultId, obj.amount); !res) { + return res; + } auto hasDUSDLoans = false; @@ -230,7 +293,9 @@ Res CVaultsConsensus::operator()(const CWithdrawFromVaultMessage &obj) const { TrackDUSDSub(mnview, {tokenId, subAmount}); } - Require(mnview.SubLoanToken(obj.vaultId, CTokenAmount{tokenId, subAmount})); + if (auto res = mnview.SubLoanToken(obj.vaultId, CTokenAmount{tokenId, subAmount}); !res) { + return res; + } TrackNegativeInterest(mnview, {tokenId, subAmount}); @@ -244,14 +309,20 @@ Res CVaultsConsensus::operator()(const CWithdrawFromVaultMessage &obj) const { bool useNextPrice = i > 0, requireLivePrice = true; auto vaultAssets = mnview.GetVaultAssets(obj.vaultId, *collaterals, height, time, useNextPrice, requireLivePrice); - Require(vaultAssets); + if (!vaultAssets) { + return vaultAssets; + } - Require(vaultAssets.val->ratio() >= scheme->ratio, + if (vaultAssets.val->ratio() < scheme->ratio) { + return Res::Err( "Vault does not have enough collateralization ratio defined by loan scheme - %d < %d", vaultAssets.val->ratio(), scheme->ratio); + } - Require(CollateralPctCheck(hasDUSDLoans, vaultAssets, scheme->ratio)); + if (auto res = CollateralPctCheck(hasDUSDLoans, vaultAssets, scheme->ratio); !res) { + return res; + } } } else { return Res::Err("Cannot withdraw all collaterals as there are still active loans in this vault"); @@ -266,32 +337,47 @@ Res CVaultsConsensus::operator()(const CWithdrawFromVaultMessage &obj) const { } Res CVaultsConsensus::operator()(const CAuctionBidMessage &obj) const { - Require(CheckCustomTx()); + if (auto res = CheckCustomTx(); !res) { + return res; + } // owner auth - Require(HasAuth(obj.from), "tx must have at least one input from token owner"); + if (!HasAuth(obj.from)) { + return Res::Err("tx must have at least one input from token owner"); + } // vault exists auto vault = mnview.GetVault(obj.vaultId); - Require(vault, "Vault <%s> not found", obj.vaultId.GetHex()); + if (!vault) { + return Res::Err("Vault <%s> not found", obj.vaultId.GetHex()); + } // vault under liquidation - Require(vault->isUnderLiquidation, "Cannot bid to vault which is not under liquidation"); + if (!vault->isUnderLiquidation) { + return Res::Err("Cannot bid to vault which is not under liquidation"); + } auto data = mnview.GetAuction(obj.vaultId, height); - Require(data, "No auction data to vault %s", obj.vaultId.GetHex()); + if (!data) { + return Res::Err("No auction data to vault %s", obj.vaultId.GetHex()); + } auto batch = mnview.GetAuctionBatch({obj.vaultId, obj.index}); - Require(batch, "No batch to vault/index %s/%d", obj.vaultId.GetHex(), obj.index); + if (!batch) { + return Res::Err("No batch to vault/index %s/%d", obj.vaultId.GetHex(), obj.index); + } - Require(obj.amount.nTokenId == batch->loanAmount.nTokenId, "Bid token does not match auction one"); + if (obj.amount.nTokenId != batch->loanAmount.nTokenId) { + return Res::Err("Bid token does not match auction one"); + } auto bid = mnview.GetAuctionBid({obj.vaultId, obj.index}); if (!bid) { auto amount = MultiplyAmounts(batch->loanAmount.nValue, COIN + data->liquidationPenalty); - Require(amount <= obj.amount.nValue, - "First bid should include liquidation penalty of %d%%", - data->liquidationPenalty * 100 / COIN); + if (amount > obj.amount.nValue) { + return Res::Err("First bid should include liquidation penalty of %d%%", + data->liquidationPenalty * 100 / COIN); + } if (static_cast(height) >= consensus.DF12FortCanningMuseumHeight && data->liquidationPenalty && obj.amount.nValue == batch->loanAmount.nValue) { @@ -299,7 +385,9 @@ Res CVaultsConsensus::operator()(const CAuctionBidMessage &obj) const { } } else { auto amount = MultiplyAmounts(bid->second.nValue, COIN + (COIN / 100)); - Require(amount <= obj.amount.nValue, "Bid override should be at least 1%% higher than current one"); + if (amount > obj.amount.nValue) { + return Res::Err("Bid override should be at least 1%% higher than current one"); + } if (static_cast(height) >= consensus.DF12FortCanningMuseumHeight && obj.amount.nValue == bid->second.nValue) { @@ -312,6 +400,8 @@ Res CVaultsConsensus::operator()(const CAuctionBidMessage &obj) const { } // check balance CalculateOwnerRewards(obj.from); - Require(mnview.SubBalance(obj.from, obj.amount)); + if (auto res = mnview.SubBalance(obj.from, obj.amount); !res) { + return res; + } return mnview.StoreAuctionBid({obj.vaultId, obj.index}, {obj.from, obj.amount}); } diff --git a/src/dfi/govvariables/icx_takerfee_per_btc.cpp b/src/dfi/govvariables/icx_takerfee_per_btc.cpp index b632161b28..6d95da7257 100644 --- a/src/dfi/govvariables/icx_takerfee_per_btc.cpp +++ b/src/dfi/govvariables/icx_takerfee_per_btc.cpp @@ -21,7 +21,9 @@ UniValue ICX_TAKERFEE_PER_BTC::Export() const { } Res ICX_TAKERFEE_PER_BTC::Validate(const CCustomCSView &mnview) const { - Require(takerFeePerBTC > 0, [] { return "takerFeePerBTC cannot be 0 or less"; }); + if (takerFeePerBTC <= 0) { + return Res::Err("takerFeePerBTC cannot be 0 or less"); + } return Res::Ok(); } diff --git a/src/dfi/govvariables/loan_daily_reward.cpp b/src/dfi/govvariables/loan_daily_reward.cpp index 706414a544..ca43b52d03 100644 --- a/src/dfi/govvariables/loan_daily_reward.cpp +++ b/src/dfi/govvariables/loan_daily_reward.cpp @@ -22,8 +22,9 @@ UniValue LP_DAILY_LOAN_TOKEN_REWARD::Export() const { } Res LP_DAILY_LOAN_TOKEN_REWARD::Validate(const CCustomCSView &view) const { - Require(view.GetLastHeight() >= Params().GetConsensus().DF11FortCanningHeight, - [] { return "Cannot be set before FortCanning"; }); + if (view.GetLastHeight() < Params().GetConsensus().DF11FortCanningHeight) { + return Res::Err("Cannot be set before FortCanning"); + } return Res::Err("Cannot be set manually."); } diff --git a/src/dfi/govvariables/loan_liquidation_penalty.cpp b/src/dfi/govvariables/loan_liquidation_penalty.cpp index 40befd2f2e..ef08bcfde1 100644 --- a/src/dfi/govvariables/loan_liquidation_penalty.cpp +++ b/src/dfi/govvariables/loan_liquidation_penalty.cpp @@ -22,9 +22,12 @@ UniValue LOAN_LIQUIDATION_PENALTY::Export() const { } Res LOAN_LIQUIDATION_PENALTY::Validate(const CCustomCSView &view) const { - Require(view.GetLastHeight() >= Params().GetConsensus().DF11FortCanningHeight, - [] { return "Cannot be set before FortCanning"; }); - Require(penalty >= COIN / 100, [] { return "Penalty cannot be less than 0.01 DFI"; }); + if (view.GetLastHeight() < Params().GetConsensus().DF11FortCanningHeight) { + return Res::Err("Cannot be set before FortCanning"); + } + if (penalty < COIN / 100) { + return Res::Err("Penalty cannot be less than 0.01 DFI"); + } return Res::Ok(); } diff --git a/src/dfi/govvariables/loan_splits.cpp b/src/dfi/govvariables/loan_splits.cpp index f0753fd650..14307c3455 100644 --- a/src/dfi/govvariables/loan_splits.cpp +++ b/src/dfi/govvariables/loan_splits.cpp @@ -13,11 +13,15 @@ bool LP_LOAN_TOKEN_SPLITS::IsEmpty() const { } Res LP_LOAN_TOKEN_SPLITS::Import(const UniValue &val) { - Require(val.isObject(), [] { return "object of {poolId: rate,... } expected"; }); + if (!val.isObject()) { + return Res::Err("object of {poolId: rate,... } expected"); + } for (const std::string &key : val.getKeys()) { auto id = DCT_ID::FromString(key); - Require(id); + if (!id) { + return id; + } splits.emplace(*id.val, AmountFromValue(val[key])); } return Res::Ok(); @@ -32,22 +36,26 @@ UniValue LP_LOAN_TOKEN_SPLITS::Export() const { } Res LP_LOAN_TOKEN_SPLITS::Validate(const CCustomCSView &mnview) const { - Require(mnview.GetLastHeight() >= Params().GetConsensus().DF11FortCanningHeight, - [] { return "Cannot be set before FortCanning"; }); + if (mnview.GetLastHeight() < Params().GetConsensus().DF11FortCanningHeight) { + return Res::Err("Cannot be set before FortCanning"); + } CAmount total{0}; for (const auto &kv : splits) { - Require(mnview.HasPoolPair(kv.first), - [=] { return strprintf("pool with id=%s not found", kv.first.ToString()); }); + if (!mnview.HasPoolPair(kv.first)) { + return Res::Err("pool with id=%s not found", kv.first.ToString()); + } - Require(kv.second >= 0 && kv.second <= COIN, [=] { - return strprintf( + if (kv.second < 0 || kv.second > COIN) { + return Res::Err( "wrong percentage for pool with id=%s, value = %s", kv.first.ToString(), std::to_string(kv.second)); - }); + } total += kv.second; } - Require(total == COIN, [=] { return strprintf("total = %d vs expected %d", total, COIN); }); + if (total != COIN) { + return Res::Err("total = %d vs expected %d", total, COIN); + } return Res::Ok(); } diff --git a/src/dfi/govvariables/lp_daily_dfi_reward.cpp b/src/dfi/govvariables/lp_daily_dfi_reward.cpp index 915a4f2c90..9c67ff4296 100644 --- a/src/dfi/govvariables/lp_daily_dfi_reward.cpp +++ b/src/dfi/govvariables/lp_daily_dfi_reward.cpp @@ -22,8 +22,9 @@ UniValue LP_DAILY_DFI_REWARD::Export() const { } Res LP_DAILY_DFI_REWARD::Validate(const CCustomCSView &view) const { - Require(view.GetLastHeight() < Params().GetConsensus().DF8EunosHeight, - [] { return "Cannot be set manually after Eunos hard fork"; }); + if (view.GetLastHeight() >= Params().GetConsensus().DF8EunosHeight) { + return Res::Err("Cannot be set manually after Eunos hard fork"); + } // nothing to do return Res::Ok(); } diff --git a/src/dfi/govvariables/lp_splits.cpp b/src/dfi/govvariables/lp_splits.cpp index 15ccb7d947..bdd08d64ad 100644 --- a/src/dfi/govvariables/lp_splits.cpp +++ b/src/dfi/govvariables/lp_splits.cpp @@ -13,13 +13,15 @@ bool LP_SPLITS::IsEmpty() const { } Res LP_SPLITS::Import(const UniValue &val) { - Require(val.isObject(), [] { - return "object of {poolId: rate,... } expected"; - }); /// throw here? cause "AmountFromValue" can throw! + if (!val.isObject()) { + return Res::Err("object of {poolId: rate,... } expected"); + } for (const std::string &key : val.getKeys()) { auto id = DCT_ID::FromString(key); - Require(id); + if (!id) { + return id; + } splits.emplace(*id.val, AmountFromValue(val[key])); // todo: AmountFromValue } return Res::Ok(); @@ -36,17 +38,20 @@ UniValue LP_SPLITS::Export() const { Res LP_SPLITS::Validate(const CCustomCSView &mnview) const { CAmount total{0}; for (const auto &[poolId, amount] : splits) { - Require(mnview.HasPoolPair(poolId), - [poolId = poolId] { return strprintf("pool with id=%s not found", poolId.ToString()); }); + if (!mnview.HasPoolPair(poolId)) { + return Res::Err("pool with id=%s not found", poolId.ToString()); + } - Require(amount >= 0 && amount <= COIN, [amount = amount, poolId = poolId] { - return strprintf( + if (amount < 0 || amount > COIN) { + return Res::Err( "wrong percentage for pool with id=%s, value = %s", poolId.ToString(), std::to_string(amount)); - }); + } total += amount; } - Require(total == COIN, [=] { return strprintf("total = %d vs expected %d", total, COIN); }); + if (total != COIN) { + return Res::Err("total = %d vs expected %d", total, COIN); + } return Res::Ok(); } diff --git a/src/dfi/govvariables/oracle_block_interval.cpp b/src/dfi/govvariables/oracle_block_interval.cpp index 6230805d83..1a7a9b8826 100644 --- a/src/dfi/govvariables/oracle_block_interval.cpp +++ b/src/dfi/govvariables/oracle_block_interval.cpp @@ -13,7 +13,9 @@ bool ORACLE_BLOCK_INTERVAL::IsEmpty() const { } Res ORACLE_BLOCK_INTERVAL::Import(const UniValue &val) { - Require(val.isNum(), [] { return "Block interval amount is not a number"; }); + if (!val.isNum()) { + return Res::Err("Block interval amount is not a number"); + } blockInterval = val.get_int(); return Res::Ok(); @@ -24,9 +26,12 @@ UniValue ORACLE_BLOCK_INTERVAL::Export() const { } Res ORACLE_BLOCK_INTERVAL::Validate(const CCustomCSView &view) const { - Require(view.GetLastHeight() >= Params().GetConsensus().DF11FortCanningHeight, - [] { return "Cannot be set before FortCanning"; }); - Require(blockInterval > 0, [] { return "Block interval cannot be less than 1"; }); + if (view.GetLastHeight() < Params().GetConsensus().DF11FortCanningHeight) { + return Res::Err("Cannot be set before FortCanning"); + } + if (blockInterval < 1) { + return Res::Err("Block interval cannot be less than 1"); + } return Res::Ok(); } diff --git a/src/dfi/govvariables/oracle_deviation.cpp b/src/dfi/govvariables/oracle_deviation.cpp index 7bddf87de6..f61d787cb4 100644 --- a/src/dfi/govvariables/oracle_deviation.cpp +++ b/src/dfi/govvariables/oracle_deviation.cpp @@ -22,9 +22,12 @@ UniValue ORACLE_DEVIATION::Export() const { } Res ORACLE_DEVIATION::Validate(const CCustomCSView &view) const { - Require(view.GetLastHeight() >= Params().GetConsensus().DF11FortCanningHeight, - [] { return "Cannot be set before FortCanning"; }); - Require(deviation >= COIN / 100, [] { return "Deviation cannot be less than 1 percent"; }); + if (view.GetLastHeight() < Params().GetConsensus().DF11FortCanningHeight) { + return Res::Err("Cannot be set before FortCanning"); + } + if (deviation < COIN / 100) { + return Res::Err("Deviation cannot be less than 1 percent"); + } return Res::Ok(); } diff --git a/src/dfi/incentivefunding.cpp b/src/dfi/incentivefunding.cpp index a1e610c810..66be900c4f 100644 --- a/src/dfi/incentivefunding.cpp +++ b/src/dfi/incentivefunding.cpp @@ -15,7 +15,9 @@ CAmount CCommunityBalancesView::GetCommunityBalance(CommunityAccountType account Res CCommunityBalancesView::SetCommunityBalance(CommunityAccountType account, CAmount amount) { // deny negative values on db level! - Require(amount >= 0, [] { return "negative amount"; }); + if (amount < 0) { + return Res::Err("negative amount"); + } WriteBy(static_cast(account), amount); return Res::Ok(); } @@ -34,7 +36,9 @@ Res CCommunityBalancesView::AddCommunityBalance(CommunityAccountType account, CA return Res::Ok(); } auto sum = SafeAdd(amount, GetCommunityBalance(account)); - Require(sum); + if (!sum) { + return sum; + } return SetCommunityBalance(account, sum); } @@ -42,8 +46,12 @@ Res CCommunityBalancesView::SubCommunityBalance(CommunityAccountType account, CA if (amount == 0) { return Res::Ok(); } - Require(amount > 0, [] { return "negative amount"; }); + if (amount < 0) { + return Res::Err("negative amount"); + } CAmount oldBalance = GetCommunityBalance(account); - Require(oldBalance >= amount, [=] { return strprintf("Amount %d is less than %d", oldBalance, amount); }); + if (oldBalance < amount) { + return Res::Err("Amount %d is less than %d", oldBalance, amount); + } return SetCommunityBalance(account, oldBalance - amount); } diff --git a/src/dfi/loan.cpp b/src/dfi/loan.cpp index 4ed29a9078..48cc952ace 100644 --- a/src/dfi/loan.cpp +++ b/src/dfi/loan.cpp @@ -12,13 +12,15 @@ std::optional CLoanView::GetLoanCollater Res CLoanView::CreateLoanCollateralToken(const CLoanSetCollateralTokenImpl &collToken) { // this should not happen, but for sure - Require(!GetLoanCollateralToken(collToken.creationTx), [=] { - return strprintf("setCollateralToken with creation tx %s already exists!", collToken.creationTx.GetHex()); - }); - Require(collToken.factor <= COIN, [=] { - return strprintf("setCollateralToken factor must be lower or equal than %s!", GetDecimalString(COIN)); - }); - Require(collToken.factor >= 0, [] { return "setCollateralToken factor must not be negative!"; }); + if (GetLoanCollateralToken(collToken.creationTx)) { + return Res::Err("setCollateralToken with creation tx %s already exists!", collToken.creationTx.GetHex()); + } + if (collToken.factor > COIN) { + return Res::Err("setCollateralToken factor must be lower or equal than %s!", GetDecimalString(COIN)); + } + if (collToken.factor < 0) { + return Res::Err("setCollateralToken factor must not be negative!"); + } WriteBy(collToken.creationTx, collToken); @@ -60,9 +62,9 @@ std::optional CLoanView::GetLoanToken(const ui Res CLoanView::SetLoanToken(const CLoanSetLoanTokenImpl &loanToken, DCT_ID const &id) { // this should not happen, but for sure - Require(!GetLoanTokenByID(id), [=] { - return strprintf("setLoanToken with creation tx %s already exists!", loanToken.creationTx.GetHex()); - }); + if (GetLoanTokenByID(id)) { + return Res::Err("setLoanToken with creation tx %s already exists!", loanToken.creationTx.GetHex()); + } WriteBy(id, loanToken); WriteBy(loanToken.creationTx, id); @@ -295,17 +297,23 @@ Res CLoanView::IncreaseInterest(const uint32_t height, const CAmount tokenInterest, const CAmount loanIncreased) { const auto scheme = GetLoanScheme(loanSchemeID); - Require(scheme, [=] { return strprintf("No such scheme id %s", loanSchemeID); }); + if (!scheme) { + return Res::Err("No such scheme id %s", loanSchemeID); + } auto token = GetLoanTokenByID(id); - Require(token, [=] { return strprintf("No such loan token id %s", id.ToString()); }); + if (!token) { + return Res::Err("No such loan token id %s", id.ToString()); + } CInterestRateV3 rate{}; if (auto readRate = GetInterestRate(vaultId, id, height)) { rate = *readRate; } - Require(height >= rate.height, [] { return "Cannot store height in the past"; }); + if (height < rate.height) { + return Res::Err("Cannot store height in the past"); + } rate.interestToHeight = TotalInterestCalculation(rate, height); rate.height = height; @@ -344,19 +352,27 @@ Res CLoanView::DecreaseInterest(const uint32_t height, const CAmount loanDecreased, const CAmount interestDecreased) { const auto scheme = GetLoanScheme(loanSchemeID); - Require(scheme, [=] { return strprintf("No such scheme id %s", loanSchemeID); }); + if (!scheme) { + return Res::Err("No such scheme id %s", loanSchemeID); + } auto token = GetLoanTokenByID(id); - Require(token, [=] { return strprintf("No such loan token id %s", id.ToString()); }); + if (!token) { + return Res::Err("No such loan token id %s", id.ToString()); + } CInterestRateV3 rate{}; if (auto readRate = GetInterestRate(vaultId, id, height)) { rate = *readRate; } - Require(height >= rate.height, [] { return "Cannot store height in the past"; }); + if (height < rate.height) { + return Res::Err("Cannot store height in the past"); + } - Require(rate.height != 0, [] { return "Data mismatch height == 0"; }); + if (rate.height == 0) { + return Res::Err("Data mismatch height == 0"); + } const auto interestToHeight = TotalInterestCalculation(rate, height); const auto interestDecreasedHP = ToHigherPrecision(interestDecreased, height); @@ -540,12 +556,15 @@ void CLoanView::MigrateInterestRateToV3(CVaultView &view, uint32_t height) { } Res CLoanView::AddLoanToken(const CVaultId &vaultId, CTokenAmount amount) { - Require(GetLoanTokenByID(amount.nTokenId), - [=] { return strprintf("No such loan token id %s", amount.nTokenId.ToString()); }); + if (!GetLoanTokenByID(amount.nTokenId)) { + return Res::Err("No such loan token id %s", amount.nTokenId.ToString()); + } CBalances amounts; ReadBy(vaultId, amounts); - Require(amounts.Add(amount)); + if (auto res = amounts.Add(amount); !res) { + return res; + } if (!amounts.balances.empty()) { WriteBy(vaultId, amounts); @@ -555,12 +574,18 @@ Res CLoanView::AddLoanToken(const CVaultId &vaultId, CTokenAmount amount) { } Res CLoanView::SubLoanToken(const CVaultId &vaultId, CTokenAmount amount) { - Require(GetLoanTokenByID(amount.nTokenId), - [=] { return strprintf("No such loan token id %s", amount.nTokenId.ToString()); }); + if (!GetLoanTokenByID(amount.nTokenId)) { + return Res::Err("No such loan token id %s", amount.nTokenId.ToString()); + } auto amounts = GetLoanTokens(vaultId); - Require(amounts && amounts->Sub(amount), - [=] { return strprintf("Loan token for vault <%s> not found", vaultId.GetHex()); }); + if (!amounts) { + return Res::Err("Loan token for vault <%s> not found", vaultId.GetHex()); + } + + if (auto res = amounts->Sub(amount); !res) { + return res; + } if (amounts->balances.empty()) { EraseBy(vaultId); diff --git a/src/dfi/masternodes.cpp b/src/dfi/masternodes.cpp index 013704744d..832b275541 100644 --- a/src/dfi/masternodes.cpp +++ b/src/dfi/masternodes.cpp @@ -317,8 +317,9 @@ Res CMasternodesView::CreateMasternode(const uint256 &nodeId, const CMasternode Res CMasternodesView::ResignMasternode(CMasternode &node, const uint256 &nodeId, const uint256 &txid, int height) { auto state = node.GetState(height, *this); if (height >= Params().GetConsensus().DF10EunosPayaHeight) { - Require(state == CMasternode::ENABLED, - [=] { return strprintf("node %s state is not 'ENABLED'", nodeId.ToString()); }); + if (state != CMasternode::ENABLED) { + return Res::Err("node %s state is not 'ENABLED'", nodeId.ToString()); + } } else if ((state != CMasternode::PRE_ENABLED && state != CMasternode::ENABLED)) { return Res::Err("node %s state is not 'PRE_ENABLED' or 'ENABLED'", nodeId.ToString()); } @@ -327,8 +328,9 @@ Res CMasternodesView::ResignMasternode(CMasternode &node, const uint256 &nodeId, if (!timelock) { return Res::Err("Failed to get timelock for masternode"); } - Require(timelock.value() == CMasternode::ZEROYEAR, - [=] { return "Trying to resign masternode before timelock expiration."; }); + if (timelock.value() != CMasternode::ZEROYEAR) { + return Res::Err("Trying to resign masternode before timelock expiration."); + } node.resignTx = txid; node.resignHeight = height; @@ -1090,14 +1092,18 @@ Res CCustomCSView::PopulateLoansData(CVaultAssets &result, for (const auto &[loanTokenId, loanTokenAmount] : loanTokens->balances) { const auto token = GetLoanTokenByID(loanTokenId); - Require(token, [loanTokenId = loanTokenId] { - return strprintf("Loan token with id (%s) does not exist!", loanTokenId.ToString()); - }); + if (!token) { + return Res::Err("Loan token with id (%s) does not exist!", loanTokenId.ToString()); + } const auto rate = GetInterestRate(vaultId, loanTokenId, height); - Require(rate, [=] { return strprintf("Cannot get interest rate for token (%s)!", token->symbol); }); + if (!rate) { + return Res::Err("Cannot get interest rate for token (%s)!", token->symbol); + } - Require(height >= rate->height, [] { return "Trying to read loans in the past"; }); + if (height < rate->height) { + return Res::Err("Trying to read loans in the past"); + } auto totalAmount = loanTokenAmount + TotalInterest(*rate, height); if (totalAmount < 0) { @@ -1112,7 +1118,9 @@ Res CCustomCSView::PopulateLoansData(CVaultAssets &result, auto prevLoans = result.totalLoans; result.totalLoans += *amountInCurrency.val; - Require(prevLoans <= result.totalLoans, [] { return "Exceeded maximum loans"; }); + if (prevLoans > result.totalLoans) { + return Res::Err("Exceeded maximum loans"); + } result.loans.push_back({loanTokenId, amountInCurrency}); } @@ -1131,18 +1139,24 @@ Res CCustomCSView::PopulateCollateralData(CVaultAssets &result, auto tokenAmount = col.second; auto token = HasLoanCollateralToken({tokenId, height}); - Require(token, [=] { return strprintf("Collateral token with id (%s) does not exist!", tokenId.ToString()); }); + if (!token) { + return Res::Err("Collateral token with id (%s) does not exist!", tokenId.ToString()); + } auto amountInCurrency = GetAmountInCurrency(tokenAmount, token->fixedIntervalPriceId, useNextPrice, requireLivePrice); - Require(amountInCurrency); + if (!amountInCurrency) { + return amountInCurrency; + } auto amountFactor = MultiplyAmounts(token->factor, *amountInCurrency.val); auto prevCollaterals = result.totalCollaterals; result.totalCollaterals += amountFactor; - Require(prevCollaterals <= result.totalCollaterals, [] { return "Exceeded maximum collateral"; }); + if (prevCollaterals > result.totalCollaterals) { + return Res::Err("Exceeded maximum collateral"); + } result.collaterals.push_back({tokenId, amountInCurrency}); } diff --git a/src/dfi/mn_checks.cpp b/src/dfi/mn_checks.cpp index d3769e09e9..3ae1092b11 100644 --- a/src/dfi/mn_checks.cpp +++ b/src/dfi/mn_checks.cpp @@ -673,7 +673,9 @@ ResVal ApplyAnchorRewardTx(CCustomCSView &mnview, const uint256 &prevStakeModifier, const std::vector &metadata, const Consensus::Params &consensusParams) { - Require(height < consensusParams.DF6DakotaHeight, "Old anchor TX type after Dakota fork. Height %d", height); + if (height >= consensusParams.DF6DakotaHeight) { + return Res::Err("Old anchor TX type after Dakota fork. Height %d", height); + } CDataStream ss(metadata, SER_NETWORK, PROTOCOL_VERSION); CAnchorFinalizationMessage finMsg; @@ -753,7 +755,9 @@ ResVal ApplyAnchorRewardTxPlus(CCustomCSView &mnview, int height, const std::vector &metadata, const Consensus::Params &consensusParams) { - Require(height >= consensusParams.DF6DakotaHeight, "New anchor TX type before Dakota fork. Height %d", height); + if (height < consensusParams.DF6DakotaHeight) { + return Res::Err("New anchor TX type before Dakota fork. Height %d", height); + } CDataStream ss(metadata, SER_NETWORK, PROTOCOL_VERSION); CAnchorFinalizationMessagePlus finMsg; @@ -780,29 +784,36 @@ ResVal ApplyAnchorRewardTxPlus(CCustomCSView &mnview, } auto quorum = GetMinAnchorQuorum(*team); - Require(finMsg.sigs.size() >= quorum, "anchor sigs (%d) < min quorum (%) ", finMsg.sigs.size(), quorum); - Require(uniqueKeys >= quorum, "anchor unique keys (%d) < min quorum (%) ", uniqueKeys, quorum); + if (finMsg.sigs.size() < quorum) { + return Res::Err("anchor sigs (%d) < min quorum (%) ", finMsg.sigs.size(), quorum); + } + if (uniqueKeys < quorum) { + return Res::Err("anchor unique keys (%d) < min quorum (%) ", uniqueKeys, quorum); + } // Make sure anchor block height and hash exist in chain. auto *anchorIndex = ::ChainActive()[finMsg.anchorHeight]; - Require(anchorIndex, - "Active chain does not contain block height %d. Chain height %d", - finMsg.anchorHeight, - ::ChainActive().Height()); - Require(anchorIndex->GetBlockHash() == finMsg.dfiBlockHash, - "Anchor and blockchain mismatch at height %d. Expected %s found %s", - finMsg.anchorHeight, - anchorIndex->GetBlockHash().ToString(), - finMsg.dfiBlockHash.ToString()); + if (!anchorIndex) { + return Res::Err("Active chain does not contain block height %d. Chain height %d", + finMsg.anchorHeight, + ::ChainActive().Height()); + } + if (anchorIndex->GetBlockHash() != finMsg.dfiBlockHash) { + return Res::Err("Anchor and blockchain mismatch at height %d. Expected %s found %s", + finMsg.anchorHeight, + anchorIndex->GetBlockHash().ToString(), + finMsg.dfiBlockHash.ToString()); + } // check reward sum const auto cbValues = tx.GetValuesOut(); - Require(cbValues.size() == 1 && cbValues.begin()->first == DCT_ID{0}, "anchor reward should be paid in DFI only"); + if (cbValues.size() != 1 || cbValues.begin()->first != DCT_ID{0}) { + return Res::Err("anchor reward should be paid in DFI only"); + } const auto anchorReward = mnview.GetCommunityBalance(CommunityAccountType::AnchorReward); - Require(cbValues.begin()->second == anchorReward, - "anchor pays wrong amount (actual=%d vs expected=%d)", - cbValues.begin()->second, - anchorReward); + if (cbValues.begin()->second != anchorReward) { + return Res::Err("anchor pays wrong amount (actual=%d vs expected=%d)", cbValues.begin()->second, anchorReward); + } CTxDestination destination; if (height < consensusParams.DF22MetachainHeight) { @@ -964,7 +975,9 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView &view, poolIDs.clear(); } - Require(obj.amountFrom > 0, "Input amount should be positive"); + if (obj.amountFrom <= 0) { + return Res::Err("Input amount should be positive"); + } if (height >= static_cast(consensus.DF14FortCanningHillHeight) && poolIDs.size() > MAX_POOL_SWAPS) { return Res::Err( @@ -976,7 +989,9 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView &view, std::optional > poolPair; if (poolIDs.empty()) { poolPair = view.GetPoolPair(obj.idTokenFrom, obj.idTokenTo); - Require(poolPair, "Cannot find the pool pair."); + if (!poolPair) { + return Res::Err("Cannot find the pool pair."); + } // Add single swap pool to vector for loop poolIDs.push_back(poolPair->first); @@ -1012,7 +1027,9 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView &view, } else // Or get pools from IDs provided for composite swap { pool = view.GetPoolPair(currentID); - Require(pool, "Cannot find the pool pair."); + if (!pool) { + return Res::Err("Cannot find the pool pair."); + } } // Check if last pool swap @@ -1021,11 +1038,13 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView &view, const auto swapAmount = swapAmountResult; if (height >= static_cast(consensus.DF14FortCanningHillHeight) && lastSwap) { - Require(obj.idTokenTo != swapAmount.nTokenId, - "Final swap should have idTokenTo as destination, not source"); + if (obj.idTokenTo == swapAmount.nTokenId) { + return Res::Err("Final swap should have idTokenTo as destination, not source"); + } - Require(pool->idTokenA == obj.idTokenTo || pool->idTokenB == obj.idTokenTo, - "Final swap pool should have idTokenTo, incorrect final pool ID provided"); + if (pool->idTokenA != obj.idTokenTo && pool->idTokenB != obj.idTokenTo) { + return Res::Err("Final swap pool should have idTokenTo, incorrect final pool ID provided"); + } } if (view.AreTokensLocked({pool->idTokenA.v, pool->idTokenB.v})) { @@ -1184,14 +1203,18 @@ Res SwapToDFIorDUSD(CCustomCSView &mnview, auto poolSwap = CPoolSwap(obj, height); auto token = mnview.GetToken(tokenId); - Require(token, "Cannot find token with id %s!", tokenId.ToString()); + if (!token) { + return Res::Err("Cannot find token with id %s!", tokenId.ToString()); + } // TODO: Optimize double look up later when first token is DUSD. auto dUsdToken = mnview.GetToken("DUSD"); - Require(dUsdToken, "Cannot find token DUSD"); + if (!dUsdToken) { + return Res::Err("Cannot find token DUSD"); + } const auto attributes = mnview.GetAttributes(); - Require(attributes, "Attributes unavailable"); + assert(attributes); CDataStructureV0 directBurnKey{AttributeTypes::Param, ParamIDs::DFIP2206A, DFIPKeys::DUSDInterestBurn}; // Direct swap from DUSD to DFI as defined in the CPoolSwapMessage. @@ -1200,7 +1223,9 @@ Res SwapToDFIorDUSD(CCustomCSView &mnview, // direct burn dUSD CTokenAmount dUSD{dUsdToken->first, amount}; - Require(mnview.SubBalance(from, dUSD)); + if (auto res = mnview.SubBalance(from, dUSD); !res) { + return res; + } return mnview.AddBalance(to, dUSD); } else { @@ -1210,10 +1235,14 @@ Res SwapToDFIorDUSD(CCustomCSView &mnview, } auto pooldUSDDFI = mnview.GetPoolPair(dUsdToken->first, DCT_ID{0}); - Require(pooldUSDDFI, "Cannot find pool pair DUSD-DFI!"); + if (!pooldUSDDFI) { + return Res::Err("Cannot find pool pair DUSD-DFI!"); + } auto poolTokendUSD = mnview.GetPoolPair(tokenId, dUsdToken->first); - Require(poolTokendUSD, "Cannot find pool pair %s-DUSD!", token->symbol); + if (!poolTokendUSD) { + return Res::Err("Cannot find pool pair %s-DUSD!", token->symbol); + } if (to == consensus.burnAddress && !forceLoanSwap && attributes->GetValue(directBurnKey, false)) { obj.idTokenTo = dUsdToken->first; diff --git a/src/dfi/oracles.cpp b/src/dfi/oracles.cpp index ceee17f394..b05ffb4c6d 100644 --- a/src/dfi/oracles.cpp +++ b/src/dfi/oracles.cpp @@ -13,8 +13,9 @@ bool COracle::SupportsPair(const std::string &token, const std::string ¤cy } Res COracle::SetTokenPrice(const std::string &token, const std::string ¤cy, CAmount amount, int64_t timestamp) { - Require(SupportsPair(token, currency), - [=] { return strprintf("token <%s> - currency <%s> is not allowed", token, currency); }); + if (!SupportsPair(token, currency)) { + return Res::Err("token <%s> - currency <%s> is not allowed", token, currency); + } tokenPrices[token][currency] = std::make_pair(amount, timestamp); @@ -22,25 +23,30 @@ Res COracle::SetTokenPrice(const std::string &token, const std::string ¤cy } ResVal COracle::GetTokenPrice(const std::string &token, const std::string ¤cy) { - Require(SupportsPair(token, currency), - [=] { return strprintf("token <%s> - currency <%s> is not allowed", token, currency); }); + if (!SupportsPair(token, currency)) { + return Res::Err("token <%s> - currency <%s> is not allowed", token, currency); + } return ResVal(tokenPrices[token][currency].first, Res::Ok()); } Res COracleView::AppointOracle(const COracleId &oracleId, const COracle &oracle) { - Require(WriteBy(oracleId, oracle), - [=] { return strprintf("failed to appoint the new oracle <%s>", oracleId.GetHex()); }); + if (!WriteBy(oracleId, oracle)) { + return Res::Err("failed to appoint the new oracle <%s>", oracleId.GetHex()); + } return Res::Ok(); } Res COracleView::UpdateOracle(const COracleId &oracleId, COracle &&newOracle) { COracle oracle; - Require(ReadBy(oracleId, oracle), [=] { return strprintf("oracle <%s> not found", oracleId.GetHex()); }); + if (!ReadBy(oracleId, oracle)) { + return Res::Err("oracle <%s> not found", oracleId.GetHex()); + } - Require(newOracle.tokenPrices.empty(), - [=] { return strprintf("oracle <%s> has token prices on update", oracleId.GetHex()); }); + if (!newOracle.tokenPrices.empty()) { + return Res::Err("oracle <%s> has token prices on update", oracleId.GetHex()); + } oracle.weightage = newOracle.weightage; oracle.oracleAddress = std::move(newOracle.oracleAddress); @@ -61,42 +67,53 @@ Res COracleView::UpdateOracle(const COracleId &oracleId, COracle &&newOracle) { oracle.availablePairs = std::move(newOracle.availablePairs); // no need to update oracles list - Require(WriteBy(oracleId, oracle), - [=] { return strprintf("failed to save oracle <%s>", oracleId.GetHex()); }); + if (!WriteBy(oracleId, oracle)) { + return Res::Err("failed to save oracle <%s>", oracleId.GetHex()); + } return Res::Ok(); } Res COracleView::RemoveOracle(const COracleId &oracleId) { - Require(ExistsBy(oracleId), [=] { return strprintf("oracle <%s> not found", oracleId.GetHex()); }); + if (!ExistsBy(oracleId)) { + return Res::Err("oracle <%s> not found", oracleId.GetHex()); + } // remove oracle - Require(EraseBy(oracleId), [=] { return strprintf("failed to remove oracle <%s>", oracleId.GetHex()); }); + if (!EraseBy(oracleId)) { + return Res::Err("failed to remove oracle <%s>", oracleId.GetHex()); + } return Res::Ok(); } Res COracleView::SetOracleData(const COracleId &oracleId, int64_t timestamp, const CTokenPrices &tokenPrices) { COracle oracle; - Require(ReadBy(oracleId, oracle), - [=] { return strprintf("failed to read oracle %s from database", oracleId.GetHex()); }); + if (!ReadBy(oracleId, oracle)) { + return Res::Err("failed to read oracle %s from database", oracleId.GetHex()); + } for (const auto &tokenPrice : tokenPrices) { const auto &token = tokenPrice.first; for (const auto &price : tokenPrice.second) { const auto ¤cy = price.first; - Require(oracle.SetTokenPrice(token, currency, price.second, timestamp)); + if (auto res = oracle.SetTokenPrice(token, currency, price.second, timestamp); !res) { + return res; + } } } - Require(WriteBy(oracleId, oracle), - [=] { return strprintf("failed to store oracle %s to database", oracleId.GetHex()); }); + if (!WriteBy(oracleId, oracle)) { + return Res::Err("failed to store oracle %s to database", oracleId.GetHex()); + } return Res::Ok(); } ResVal COracleView::GetOracleData(const COracleId &oracleId) const { COracle oracle; - Require(ReadBy(oracleId, oracle), [=] { return strprintf("oracle <%s> not found", oracleId.GetHex()); }); + if (!ReadBy(oracleId, oracle)) { + return Res::Err("oracle <%s> not found", oracleId.GetHex()); + } return ResVal(oracle, Res::Ok()); } @@ -112,11 +129,11 @@ bool CFixedIntervalPrice::isLive(const CAmount deviationThreshold) const { } Res COracleView::SetFixedIntervalPrice(const CFixedIntervalPrice &fixedIntervalPrice) { - Require(WriteBy(fixedIntervalPrice.priceFeedId, fixedIntervalPrice), [=] { - return strprintf("failed to set new price feed <%s/%s>", - fixedIntervalPrice.priceFeedId.first, - fixedIntervalPrice.priceFeedId.second); - }); + if (!WriteBy(fixedIntervalPrice.priceFeedId, fixedIntervalPrice)) { + return Res::Err("failed to set new price feed <%s/%s>", + fixedIntervalPrice.priceFeedId.first, + fixedIntervalPrice.priceFeedId.second); + } LogPrint(BCLog::ORACLE, "%s(): %s/%s, active - %lld, next - %lld\n", @@ -131,10 +148,10 @@ Res COracleView::SetFixedIntervalPrice(const CFixedIntervalPrice &fixedIntervalP ResVal COracleView::GetFixedIntervalPrice(const CTokenCurrencyPair &fixedIntervalPriceId) { CFixedIntervalPrice fixedIntervalPrice; - Require(ReadBy(fixedIntervalPriceId, fixedIntervalPrice), [=] { - return strprintf( + if (!ReadBy(fixedIntervalPriceId, fixedIntervalPrice)) { + return Res::Err( "fixedIntervalPrice with id <%s/%s> not found", fixedIntervalPriceId.first, fixedIntervalPriceId.second); - }); + } DCT_ID firstID{}, secondID{}; const auto firstToken = GetTokenGuessId(fixedIntervalPriceId.first, firstID); @@ -149,7 +166,9 @@ ResVal COracleView::GetFixedIntervalPrice(const CTokenCurre loanTokens.insert(secondID.v); } - Require(!AreTokensLocked(loanTokens), [] { return "Fixed interval price currently disabled due to locked token"; }); + if (AreTokensLocked(loanTokens)) { + return Res::Err("Fixed interval price currently disabled due to locked token"); + } LogPrint(BCLog::ORACLE, "%s(): %s/%s, active - %lld, next - %lld\n", diff --git a/src/dfi/poolpairs.cpp b/src/dfi/poolpairs.cpp index 73d04e4561..c17fa287c9 100644 --- a/src/dfi/poolpairs.cpp +++ b/src/dfi/poolpairs.cpp @@ -69,12 +69,16 @@ ReturnType ReadValueAt(CPoolPairView *poolView, const PoolHeightKey &poolKey) { } Res CPoolPairView::SetPoolPair(DCT_ID const &poolId, uint32_t height, const CPoolPair &pool) { - Require(pool.idTokenA != pool.idTokenB, [] { return "Error: tokens IDs are the same."; }); + if (pool.idTokenA == pool.idTokenB) { + return Res::Err("Error: tokens IDs are the same."); + } auto poolPairByID = GetPoolPair(poolId); auto poolIdByTokens = ReadBy(ByPairKey{pool.idTokenA, pool.idTokenB}); auto mismatch = (!poolPairByID && poolIdByTokens) || (poolPairByID && !poolIdByTokens); - Require(!mismatch, [] { return "Error, there is already a poolpair with same tokens, but different poolId"; }); + if (mismatch) { + return Res::Err("Error, there is already a poolpair with same tokens, but different poolId"); + } // create new if (!poolPairByID && !poolIdByTokens) { @@ -85,7 +89,9 @@ Res CPoolPairView::SetPoolPair(DCT_ID const &poolId, uint32_t height, const CPoo return Res::Ok(); } - Require(poolId == *poolIdByTokens, [] { return "Error, PoolID is incorrect"; }); + if (poolId != *poolIdByTokens) { + return Res::Err("Error, PoolID is incorrect"); + } auto poolPairByTokens = ReadBy(poolId); assert(poolPairByTokens); @@ -116,7 +122,9 @@ Res CPoolPairView::UpdatePoolPair(DCT_ID const &poolId, const CScript &ownerAddress, const CBalances &rewards) { auto poolPair = GetPoolPair(poolId); - Require(poolPair, [=] { return strprintf("Pool with poolId %s does not exist", poolId.ToString()); }); + if (!poolPair) { + return Res::Err("Pool with poolId %s does not exist", poolId.ToString()); + } CPoolPair &pool = poolPair.value(); @@ -125,7 +133,9 @@ Res CPoolPairView::UpdatePoolPair(DCT_ID const &poolId, } if (commission >= 0) { // default/not set is -1 - Require(commission <= COIN, [] { return "commission > 100%%"; }); + if (commission > COIN) { + return Res::Err("commission > 100%%"); + } pool.commission = commission; } @@ -340,14 +350,18 @@ Res CPoolPair::AddLiquidity(CAmount amountA, std::function onMint, bool slippageProtection) { // instead of assertion due to tests - Require(amountA > 0 && amountB > 0, [] { return "amounts should be positive"; }); + if (amountA <= 0 || amountB <= 0) { + return Res::Err("amounts should be positive"); + } CAmount liquidity{0}; if (totalLiquidity == 0) { liquidity = (arith_uint256(amountA) * amountB) .sqrt() .GetLow64(); // sure this is below std::numeric_limits::max() due to sqrt natue - Require(liquidity > MINIMUM_LIQUIDITY, [] { return "liquidity too low"; }); + if (liquidity <= MINIMUM_LIQUIDITY) { + return Res::Err("liquidity too low"); + } liquidity -= MINIMUM_LIQUIDITY; // MINIMUM_LIQUIDITY is a hack for non-zero division totalLiquidity = MINIMUM_LIQUIDITY; @@ -356,23 +370,30 @@ Res CPoolPair::AddLiquidity(CAmount amountA, CAmount liqB = (arith_uint256(amountB) * arith_uint256(totalLiquidity) / reserveB).GetLow64(); liquidity = std::min(liqA, liqB); - Require(liquidity > 0, [] { return "amounts too low, zero liquidity"; }); + if (liquidity <= 0) { + return Res::Err("amounts too low, zero liquidity"); + } if (slippageProtection) { - Require((std::max(liqA, liqB) - liquidity) * 100 / liquidity < 3, - [] { return "Exceeds max ratio slippage protection of 3%%"; }); + if ((std::max(liqA, liqB) - liquidity) * 100 / liquidity >= 3) { + return Res::Err("Exceeds max ratio slippage protection of 3%%"); + } } } // increasing totalLiquidity auto resTotal = SafeAdd(totalLiquidity, liquidity); - Require(resTotal, [=] { return strprintf("can't add %d to totalLiquidity: %s", liquidity, resTotal.msg); }); + if (!resTotal) { + return Res::Err("can't add %d to totalLiquidity: %s", liquidity, resTotal.msg); + } totalLiquidity = resTotal; // increasing reserves auto resA = SafeAdd(reserveA, amountA); auto resB = SafeAdd(reserveB, amountB); - Require(resA && resB, [] { return "overflow when adding to reserves"; }); + if (!resA || !resB) { + return Res::Err("overflow when adding to reserves"); + } reserveA = resA; reserveB = resB; @@ -384,7 +405,9 @@ Res CPoolPair::RemoveLiquidity(CAmount liqAmount, std::function 0 && liqAmount < totalLiquidity, [] { return "incorrect liquidity"; }); + if (liqAmount <= 0 || liqAmount >= totalLiquidity) { + return Res::Err("incorrect liquidity"); + } CAmount resAmountA, resAmountB; resAmountA = (arith_uint256(liqAmount) * arith_uint256(reserveA) / totalLiquidity).GetLow64(); @@ -403,14 +426,16 @@ Res CPoolPair::Swap(CTokenAmount in, const std::pair &asymmetricFee, std::function onTransfer, int height) { - Require(in.nTokenId == idTokenA || in.nTokenId == idTokenB, [=] { - return strprintf("Error, input token ID (%s) doesn't match pool tokens (%s,%s)", - in.nTokenId.ToString(), - idTokenA.ToString(), - idTokenB.ToString()); - }); + if (in.nTokenId != idTokenA && in.nTokenId != idTokenB) { + return Res::Err("Error, input token ID (%s) doesn't match pool tokens (%s,%s)", + in.nTokenId.ToString(), + idTokenA.ToString(), + idTokenB.ToString()); + } - Require(status, [] { return "Pool trading is turned off!"; }); + if (!status) { + return Res::Err("Pool trading is turned off!"); + } const bool forward = in.nTokenId == idTokenA; auto &reserveF = forward ? reserveA : reserveB; @@ -418,7 +443,9 @@ Res CPoolPair::Swap(CTokenAmount in, // it is important that reserves are at least SLOPE_SWAP_RATE (1000) to be able to slide, otherwise it can lead to // underflow - Require(reserveA >= SLOPE_SWAP_RATE && reserveB >= SLOPE_SWAP_RATE, [] { return "Lack of liquidity."; }); + if (reserveA < SLOPE_SWAP_RATE || reserveB < SLOPE_SWAP_RATE) { + return Res::Err("Lack of liquidity."); + } const auto maxPrice256 = arith_uint256(maxPrice.integer) * PRECISION + maxPrice.fraction; // NOTE it has a bug prior Dakota hardfork @@ -426,7 +453,9 @@ Res CPoolPair::Swap(CTokenAmount in, ? arith_uint256(reserveT) * PRECISION / reserveF : arith_uint256(reserveF) * PRECISION / reserveT; - Require(price <= maxPrice256, [] { return "Price is higher than indicated."; }); + if (price > maxPrice256) { + return Res::Err("Price is higher than indicated."); + } // claim trading fee if (commission) { const CAmount tradeFee = MultiplyAmounts(in.nValue, commission); @@ -441,12 +470,16 @@ Res CPoolPair::Swap(CTokenAmount in, CTokenAmount dexfeeInAmount{in.nTokenId, 0}; if (dexfeeInPct > 0 && poolInFee(forward, asymmetricFee)) { - Require(dexfeeInPct <= COIN, [] { return "Dex fee input percentage over 100%%"; }); + if (dexfeeInPct > COIN) { + return Res::Err("Dex fee input percentage over 100%%"); + } dexfeeInAmount.nValue = MultiplyAmounts(in.nValue, dexfeeInPct); in.nValue -= dexfeeInAmount.nValue; } - Require(SafeAdd(reserveF, in.nValue), [] { return "Swapping will lead to pool's reserve overflow"; }); + if (!SafeAdd(reserveF, in.nValue)) { + return Res::Err("Swapping will lead to pool's reserve overflow"); + } CAmount result = slopeSwap(in.nValue, reserveF, reserveT, height); @@ -656,7 +689,9 @@ inline CAmount PoolRewardPerBlock(CAmount dailyReward, CAmount rewardPct) { } Res CPoolPairView::SetRewardPct(DCT_ID const &poolId, uint32_t height, CAmount rewardPct) { - Require(HasPoolPair(poolId), [] { return "No such pool pair"; }); + if (!HasPoolPair(poolId)) { + return Res::Err("No such pool pair"); + } WriteBy(poolId, rewardPct); if (auto dailyReward = ReadBy(DCT_ID{})) { WriteBy(PoolHeightKey{poolId, height}, PoolRewardPerBlock(*dailyReward, rewardPct)); @@ -665,7 +700,9 @@ Res CPoolPairView::SetRewardPct(DCT_ID const &poolId, uint32_t height, CAmount r } Res CPoolPairView::SetRewardLoanPct(DCT_ID const &poolId, uint32_t height, CAmount rewardLoanPct) { - Require(HasPoolPair(poolId), [] { return "No such pool pair"; }); + if (!HasPoolPair(poolId)) { + return Res::Err("No such pool pair"); + } WriteBy(poolId, rewardLoanPct); if (auto dailyReward = ReadBy(DCT_ID{})) { WriteBy(PoolHeightKey{poolId, height}, PoolRewardPerBlock(*dailyReward, rewardLoanPct)); @@ -719,7 +756,9 @@ void CPoolPairView::ForEachPoolShare(std::function= 0 && feePct <= COIN, [] { return "Token dex fee should be in percentage"; }); + if (feePct < 0 || feePct > COIN) { + return Res::Err("Token dex fee should be in percentage"); + } WriteBy(std::make_pair(poolId, tokenId), uint32_t(feePct)); return Res::Ok(); } diff --git a/src/dfi/proposals.cpp b/src/dfi/proposals.cpp index d4e7891cba..7ea8182ffc 100644 --- a/src/dfi/proposals.cpp +++ b/src/dfi/proposals.cpp @@ -110,7 +110,7 @@ Res CProposalView::UpdateProposalCycle(const CProposalId &propId, uint8_t cycle) auto key = std::make_pair(uint8_t(CProposalStatusType::Voting), propId); auto pcycle = ReadBy(key); if (!pcycle) { - Res::Err("Proposal <%s> is not in voting period", propId.GetHex()); + return Res::Err("Proposal <%s> is not in voting period", propId.GetHex()); } if (*pcycle >= cycle) { diff --git a/src/dfi/res.h b/src/dfi/res.h index c0d63d6b02..d6d526fe5b 100644 --- a/src/dfi/res.h +++ b/src/dfi/res.h @@ -104,30 +104,4 @@ struct ResVal : public Res { } }; -template -Res CheckRes(T &&res, std::tuple &&args) { - if (res) { - return Res::Ok(); - } - constexpr auto size = sizeof...(Args); - if constexpr (size == 0) { - static_assert(std::is_convertible_v); - return std::forward(res); - } else if constexpr (std:: - is_invocable_r_v>, std::string>) { - static_assert(std::is_convertible_v); - return Res::Err(std::invoke(std::get<0>(args), res.msg)); - } else if constexpr (size == 1 && - std::is_invocable_r_v>>) { - return Res::Err(std::invoke(std::get<0>(args))); - } else { - return Res::Err(args, std::make_index_sequence{}); - } -} - -#define Require(x, ...) \ - do { \ - if (auto __res = ::CheckRes(x, std::make_tuple(__VA_ARGS__)); !__res) return __res; \ - } while (0) - #endif // DEFI_DFI_RES_H diff --git a/src/dfi/rpc_oracles.cpp b/src/dfi/rpc_oracles.cpp index 911ddc1519..de243e2e73 100644 --- a/src/dfi/rpc_oracles.cpp +++ b/src/dfi/rpc_oracles.cpp @@ -916,8 +916,12 @@ ResVal GetAggregatePrice(CCustomCSView &view, }); static const uint64_t minimumLiveOracles = Params().NetworkIDString() == CBaseChainParams::REGTEST ? 1 : 2; - Require(numLiveOracles >= minimumLiveOracles, [] { return "no live oracles for specified request"; }); - Require(sumWeights > 0, [] { return "all live oracles which meet specified request, have zero weight"; }); + if (numLiveOracles < minimumLiveOracles) { + return Res::Err("no live oracles for specified request"); + } + if (sumWeights <= 0) { + return Res::Err("all live oracles which meet specified request, have zero weight"); + } ResVal res((weightedSum / arith_uint256(sumWeights)).GetLow64(), Res::Ok()); diff --git a/src/dfi/tokens.cpp b/src/dfi/tokens.cpp index 9b99af3134..93d7781a51 100644 --- a/src/dfi/tokens.cpp +++ b/src/dfi/tokens.cpp @@ -128,8 +128,9 @@ ResVal CTokensView::CreateToken(const CTokensView::CTokenImpl &token, Res CTokensView::UpdateToken(const CTokenImpl &newToken, bool isPreBayfront, const bool tokenSplitUpdate) { auto pair = GetTokenByCreationTx(newToken.creationTx); - Require(pair, - [=] { return strprintf("token with creationTx %s does not exist!", newToken.creationTx.ToString()); }); + if (!pair) { + return Res::Err("token with creationTx %s does not exist!", newToken.creationTx.ToString()); + } DCT_ID id = pair->first; CTokenImpl &oldToken = pair->second; @@ -137,7 +138,9 @@ Res CTokensView::UpdateToken(const CTokenImpl &newToken, bool isPreBayfront, con if (!isPreBayfront) { // for compatibility, in potential case when someone cheat and create finalized token with old node (and then // alter dat for ex.) - Require(!oldToken.IsFinalized(), [] { return "can't alter 'Finalized' tokens"; }); + if (oldToken.IsFinalized()) { + return Res::Err("can't alter 'Finalized' tokens"); + } } // 'name' and 'symbol' were trimmed in 'Apply' @@ -145,7 +148,9 @@ Res CTokensView::UpdateToken(const CTokenImpl &newToken, bool isPreBayfront, con // check new symbol correctness if (!tokenSplitUpdate) { - Require(newToken.IsValidSymbol()); + if (auto res = newToken.IsValidSymbol(); !res) { + return res; + } } // deal with DB symbol indexes before touching symbols/DATs: @@ -154,8 +159,9 @@ Res CTokensView::UpdateToken(const CTokenImpl &newToken, bool isPreBayfront, con // create keys with regard of new flag std::string oldSymbolKey = oldToken.CreateSymbolKey(id); std::string newSymbolKey = newToken.CreateSymbolKey(id); - Require(!GetToken(newSymbolKey), - [=] { return strprintf("token with key '%s' already exists!", newSymbolKey); }); + if (GetToken(newSymbolKey)) { + return Res::Err("token with key '%s' already exists!", newSymbolKey); + } EraseBy(oldSymbolKey); WriteBy(newSymbolKey, id); @@ -226,10 +232,14 @@ Res CTokensView::BayfrontFlagsCleanup() { Res CTokensView::AddMintedTokens(DCT_ID const &id, const CAmount &amount) { auto tokenImpl = GetToken(id); - Require(tokenImpl, [=] { return strprintf("token with id %d does not exist!", id.v); }); + if (!tokenImpl) { + return Res::Err("token with id %d does not exist!", id.v); + } auto resMinted = SafeAdd(tokenImpl->minted, amount); - Require(resMinted, [] { return "overflow when adding to minted"; }); + if (!resMinted) { + return Res::Err("overflow when adding to minted"); + } tokenImpl->minted = resMinted; @@ -239,10 +249,14 @@ Res CTokensView::AddMintedTokens(DCT_ID const &id, const CAmount &amount) { Res CTokensView::SubMintedTokens(DCT_ID const &id, const CAmount &amount) { auto tokenImpl = GetToken(id); - Require(tokenImpl, [=] { return strprintf("token with id %d does not exist!", id.v); }); + if (!tokenImpl) { + return Res::Err("token with id %d does not exist!", id.v); + } auto resMinted = tokenImpl->minted - amount; - Require(resMinted >= 0, [] { return "not enough tokens exist to subtract this amount"; }); + if (resMinted < 0) { + return Res::Err("not enough tokens exist to subtract this amount"); + } tokenImpl->minted = resMinted; diff --git a/src/dfi/validation.cpp b/src/dfi/validation.cpp index 10c8bc2b97..8870c5e052 100644 --- a/src/dfi/validation.cpp +++ b/src/dfi/validation.cpp @@ -1714,13 +1714,16 @@ static Res VaultSplits(CCustomCSView &view, }); } - Require(failedVault == CVaultId{}, - [=] { return strprintf("Failed to get vault data for: %s", failedVault.ToString()); }); + if (failedVault != CVaultId{}) { + return Res::Err("Failed to get vault data for: %s", failedVault.ToString()); + } attributes.EraseKey(CDataStructureV0{AttributeTypes::Locks, ParamIDs::TokenID, oldTokenId.v}); attributes.SetValue(CDataStructureV0{AttributeTypes::Locks, ParamIDs::TokenID, newTokenId.v}, true); - Require(attributes.Apply(view, height)); + if (auto res = attributes.Apply(view, height); !res) { + return res; + } view.SetVariable(attributes); for (const auto &[vaultId, amount] : loanTokenAmounts) { @@ -1735,7 +1738,9 @@ static Res VaultSplits(CCustomCSView &view, oldTokenAmount.ToString(), newTokenAmount.ToString()); - Require(view.AddLoanToken(vaultId, newTokenAmount)); + if (auto res = view.AddLoanToken(vaultId, newTokenAmount); !res) { + return res; + } if (const auto vault = view.GetVault(vaultId)) { VaultHistoryKey subKey{static_cast(height), vaultId, GetNextAccPosition(), vault->ownerAddress}; @@ -1751,7 +1756,9 @@ static Res VaultSplits(CCustomCSView &view, } const auto loanToken = view.GetLoanTokenByID(newTokenId); - Require(loanToken, [] { return "Failed to get loan token."; }); + if (!loanToken) { + return Res::Err("Failed to get loan token."); + } // Pre-populate to save repeated calls to get loan scheme std::map loanSchemes; @@ -1912,11 +1919,14 @@ static Res GetTokenSuffix(const CCustomCSView &view, const auto &[previousID, str] = attributes.GetValue(ascendantKey, AscendantValue{std::numeric_limits::max(), ""}); auto previousToken = view.GetToken(DCT_ID{previousID}); - Require(previousToken, [=] { return strprintf("Previous token %d not found\n", id); }); + if (!previousToken) { + return Res::Err("Previous token %d not found\n", id); + } const auto found = previousToken->symbol.find(newSuffix); - Require(found != std::string::npos, - [=] { return strprintf("Previous token name not valid: %s\n", previousToken->symbol); }); + if (found == std::string::npos) { + return Res::Err("Previous token name not valid: %s\n", previousToken->symbol); + } const auto versionNumber = previousToken->symbol.substr(found + newSuffix.size()); uint32_t previousVersion{}; diff --git a/src/dfi/vault.cpp b/src/dfi/vault.cpp index 738b29f6dd..9950276d60 100644 --- a/src/dfi/vault.cpp +++ b/src/dfi/vault.cpp @@ -23,7 +23,9 @@ Res CVaultView::StoreVault(const CVaultId &vaultId, const CVaultData &vault) { Res CVaultView::EraseVault(const CVaultId &vaultId) { auto vault = GetVault(vaultId); - Require(vault, [=] { return strprintf("Vault <%s> not found", vaultId.GetHex()); }); + if (!vault) { + return Res::Err("Vault <%s> not found", vaultId.GetHex()); + } EraseBy(vaultId); EraseBy(vaultId); @@ -37,7 +39,9 @@ std::optional CVaultView::GetVault(const CVaultId &vaultId) const { Res CVaultView::UpdateVault(const CVaultId &vaultId, const CVaultMessage &newVault) { auto vault = GetVault(vaultId); - Require(vault, [=] { return strprintf("Vault <%s> not found", vaultId.GetHex()); }); + if (!vault) { + return Res::Err("Vault <%s> not found", vaultId.GetHex()); + } EraseBy(std::make_pair(vault->ownerAddress, vaultId)); @@ -64,7 +68,9 @@ void CVaultView::ForEachVault(std::function(vaultId, amounts); - Require(amounts.Add(amount)); + if (auto res = amounts.Add(amount); !res) { + return res; + } if (!amounts.balances.empty()) { WriteBy(vaultId, amounts); } @@ -73,9 +79,12 @@ Res CVaultView::AddVaultCollateral(const CVaultId &vaultId, CTokenAmount amount) Res CVaultView::SubVaultCollateral(const CVaultId &vaultId, CTokenAmount amount) { auto amounts = GetVaultCollaterals(vaultId); - Require(amounts && amounts->Sub(amount), - [=] { return strprintf("Collateral for vault <%s> not found", vaultId.GetHex()); }); - + if (!amounts) { + return Res::Err("Collateral for vault <%s> not found", vaultId.GetHex()); + } + if (auto res = amounts->Sub(amount); !res) { + return res; + } if (amounts->balances.empty()) { EraseBy(vaultId); } else { diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp index 8174c06a5e..c355481010 100644 --- a/src/rpc/rawtransaction_util.cpp +++ b/src/rpc/rawtransaction_util.cpp @@ -61,7 +61,9 @@ ResVal GuessTokenAmount(interfaces::Chain const & chain, std::stri } catch (...) { // assuming it's token symbol, read DCT_ID from DB auto token = chain.existTokenGuessId(parsed.val->second, tokenId); - Require(token, [=]{ return strprintf("Invalid Defi token: %s", parsed.val->second); }); + if (!token) { + return Res::Err("Invalid Defi token: %s", parsed.val->second); + } return {{tokenId, parsed.val->first}, Res::Ok()}; } } diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 8b6aada766..0383fa185d 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1572,23 +1572,4 @@ BOOST_AUTO_TEST_CASE(test_Capitalize) BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff"); } -BOOST_AUTO_TEST_CASE(test_VerifyRes) -{ - auto testFunRes = []() { - Require(false, "Error"); - return Res::Ok(); - }; - auto testFunCode = []() { - Require(Res::Err("Error"), 22, "Error Code"); - return Res::Ok(); - }; - auto res = testFunRes(); - BOOST_CHECK_EQUAL(res.ok, false); - BOOST_CHECK_EQUAL(res.msg, "Error"); - auto resCode = testFunCode(); - BOOST_CHECK_EQUAL(resCode.ok, false); - BOOST_CHECK_EQUAL(resCode.code, 22u); - BOOST_CHECK_EQUAL(resCode.msg, "Error Code"); -} - BOOST_AUTO_TEST_SUITE_END()