#pragma once #include #include #include #include namespace AmountUtil { inline bool IsValidMoney(const CAmount amount) noexcept { return MoneyRange(amount); } inline bool IsValidAmountRange(const CAmount amount) noexcept { return amount >= -MAX_MONEY && amount <= MAX_MONEY; } inline void ValidateMoney(const CAmount amount) { if (!IsValidMoney(amount)) { ThrowValidation(EConsensusError::AMOUNT_OUT_OF_RANGE); } } inline void ValidateAmountRange(const CAmount amount) { if (!IsValidAmountRange(amount)) { ThrowValidation(EConsensusError::AMOUNT_OUT_OF_RANGE); } } inline boost::optional TrySafeAdd(const CAmount lhs, const CAmount rhs) noexcept { if ((rhs > 0 && lhs > std::numeric_limits::max() - rhs) || (rhs < 0 && lhs < std::numeric_limits::min() - rhs)) { return boost::none; } return lhs + rhs; } inline CAmount SafeAdd(const CAmount lhs, const CAmount rhs) { const auto sum = TrySafeAdd(lhs, rhs); if (!sum) { ThrowValidation(EConsensusError::AMOUNT_OUT_OF_RANGE); } return *sum; } inline boost::optional TrySafeSubtract(const CAmount lhs, const CAmount rhs) noexcept { if ((rhs > 0 && lhs < std::numeric_limits::min() + rhs) || (rhs < 0 && lhs > std::numeric_limits::max() + rhs)) { return boost::none; } return lhs - rhs; } inline CAmount SafeSubtract(const CAmount lhs, const CAmount rhs) { const auto difference = TrySafeSubtract(lhs, rhs); if (!difference) { ThrowValidation(EConsensusError::AMOUNT_OUT_OF_RANGE); } return *difference; } inline uint64_t UnsignedAbs(const CAmount amount) { return amount >= 0 ? static_cast(amount) : static_cast(-(amount + 1)) + 1; } } // namespace AmountUtil