Possible division by zero depending on `TradingModule.getOraclePrice` return values
Some functions depending on `TradingModule.getOraclePrice` accept non-negative (int256 `answer`, int256 decimals) return values. In case any of those are equal to zero, division depending on `answer` or `decimals` will revert. In the worst case scenario, this will prevent the protocol from continuing operating.\\nThe function `TradingModule.getOraclePrice` properly validates that return values from Chainlink price feeds are positive.\\nNevertheless, `answer` may currently return zero, as it is calculated as `(basePrice * quoteDecimals * RATE_DECIMALS) / (quotePrice * baseDecimals);`, which can be truncated down to zero, depending on base/quote prices [1]. Additionally, `decimals` may in the future return zero, depending on changes to the protocol code, as the NatSpec states that this is a `number of `decimals` in the rate, currently hardcoded to 1e18` [2].\\nIf any of these return values are zero, calculations that use division depending on `TradingModule.getOraclePrice` will revert.\\nMore specifically:\\n[1]\\n1.1 `TradingModule.getLimitAmount`\\n```\\n        require(oraclePrice >= 0); /// @dev Chainlink rate error\\n```\\n\\nthat calls `TradingUtils._getLimitAmount`, which reverts if `oraclePrice` is `0`\\n```\\n            oraclePrice = (oracleDecimals * oracleDecimals) / oraclePrice;\\n```\\n\\n[2] 2.1 `TwoTokenPoolUtils._getOraclePairPrice`\\n```\\n            require(decimals >= 0);\\n\\n            if (uint256(decimals) != BalancerConstants.BALANCER_PRECISION) {\\n                rate = (rate * int256(BalancerConstants.BALANCER_PRECISION)) / decimals;\\n            }\\n```\\n\\n2.2 `TradingModule.getLimitAmount`\\n```\\n        require(oracleDecimals >= 0); /// @dev Chainlink decimals error\\n```\\n\\nthat calls `TradingUtils._getLimitAmount`, which reverts if `oracleDecimals` is `0`\\n```\\n            limitAmount =\\n                ((oraclePrice + \\n                    ((oraclePrice * uint256(slippageLimit)) /\\n                        Constants.SLIPPAGE_LIMIT_PRECISION)) * amount) / \\n                oracleDecimals;\\n```\\n\\n2.3 `CrossCurrencyfCashVault.convertStrategyToUnderlying`\\n```\\n        return (pvInternal * borrowTokenDecimals * rate) /\\n            (rateDecimals * int256(Constants.INTERNAL_TOKEN_PRECISION));\\n```\\n
Validate that the return values are strictly positive (instead of non-negative) in case depending function calculations may result in division by zero. This can be either done on `TradingModule.getOraclePrice` directly or on the depending functions.\\n```\\ndiff // Remove the line below\\n// Remove the line below\\ngit a/contracts/trading/TradingModule.sol b/contracts/trading/TradingModule.sol\\nindex bfc8505..70b40f2 100644\\n// Remove the line below\\n// Remove the line below\\n// Remove the line below\\n a/contracts/trading/TradingModule.sol\\n// Add the line below\\n// Add the line below\\n// Add the line below\\n b/contracts/trading/TradingModule.sol\\n@@ // Remove the line below\\n251,6 // Add the line below\\n251,9 @@ contract TradingModule is Initializable, UUPSUpgradeable, ITradingModule {\\n             (basePrice * quoteDecimals * RATE_DECIMALS) /\\n             (quotePrice * baseDecimals);\\n         decimals = RATE_DECIMALS;\\n// Add the line below\\n\\n// Add the line below\\n        require(answer > 0); /// @dev Chainlink rate error\\n// Add the line below\\n        require(decimals > 0); /// @dev Chainlink decimals error\\n     }\\n \\n     function _hasPermission(uint32 flags, uint32 flagID) private pure returns (bool) {\\n@@ // Remove the line below\\n279,9 // Add the line below\\n282,6 @@ contract TradingModule is Initializable, UUPSUpgradeable, ITradingModule {\\n         // prettier// Remove the line below\\nignore\\n         (int256 oraclePrice, int256 oracleDecimals) = getOraclePrice(sellToken, buyToken);\\n \\n// Remove the line below\\n        require(oraclePrice >= 0); /// @dev Chainlink rate error\\n// Remove the line below\\n        require(oracleDecimals >= 0); /// @dev Chainlink decimals error\\n// Remove the line below\\n\\n         limitAmount = TradingUtils._getLimitAmount({\\n             tradeType: tradeType,\\n             sellToken: sellToken,\\ndiff // Remove the line below\\n// Remove the line below\\ngit a/contracts/vaults/balancer/internal/pool/TwoTokenPoolUtils.sol b/contracts/vaults/balancer/internal/pool/TwoTokenPoolUtils.sol\\nindex 4954c59..6315c0a 100644\\n// Remove the line below\\n// Remove the line below\\n// Remove the line below\\n a/contracts/vaults/balancer/internal/pool/TwoTokenPoolUtils.sol\\n// Add the line below\\n// Add the line below\\n// Add the line below\\n b/contracts/vaults/balancer/internal/pool/TwoTokenPoolUtils.sol\\n@@ // Remove the line below\\n76,10 // Add the line below\\n76,7 @@ library TwoTokenPoolUtils {\\n         (int256 rate, int256 decimals) = tradingModule.getOraclePrice(\\n             poolContext.primaryToken, poolContext.secondaryToken\\n         );\\n// Remove the line below\\n        require(rate > 0);\\n// Remove the line below\\n        require(decimals >= 0);\\n \\n         if (uint256(decimals) != BalancerConstants.BALANCER_PRECISION) {\\n             rate = (rate * int256(BalancerConstants.BALANCER_PRECISION)) / decimals;\\n         }\\n```\\n
In the worst case, the protocol might stop operating.\\nAlbeit unlikely that `decimals` is ever zero, since currently this is a hardcoded value, it is possible that `answer` might be zero due to round-down performed by the division in `TradingModule.getOraclePrice`. This can happen if the quote token is much more expensive than the base token. In this case, `TradingModule.getLimitAmount` and depending calls, such as `TradingModule.executeTradeWithDynamicSlippage` might revert.
```\\n        require(oraclePrice >= 0); /// @dev Chainlink rate error\\n```\\n