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