Platform: Code4rena
Start Date: 01/08/2023
Pot Size: $91,500 USDC
Total HM: 14
Participants: 80
Period: 6 days
Judge: gzeon
Total Solo HM: 6
Id: 269
League: ETH
Rank: 21/80
Findings: 1
Award: $482.48
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: said
Also found by: 0xmuxyz, LokiThe5th, Satyam_Sharma, T1MOH, Team_FliBit, radev_sw
482.4792 USDC - $482.48
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L203 https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L368
The GeVault#poolMatchesOracle()
would always return false
due to the overflow if the sqrtPriceX96
is greater than or equal to 2^128
, which lead to reverting the transaction of rebalancing the GeVault that is called via the GeVault#rebalance()
.
Within the GeVault#rebalance()
, the GeVault#poolMatchesOracle()
would be called for the validation like this:
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L203
/// @notice Rebalance tickers /// @dev Provide the list of tickers from function rebalance() public { require(poolMatchesOracle(), "GEV: Oracle Error"); /// @audit removeFromAllTicks(); if (isEnabled) deployAssets(); }
Within the GeVault#poolMatchesOracle()
, the sqrtPriceX96
would be returned from uniswapPool.slot0()
like this:
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L368
/// @notice Checks that the pool price isn't manipulated function poolMatchesOracle() public view returns (bool matches){ (uint160 sqrtPriceX96,,,,,,) = uniswapPool.slot0(); /// @audit uint decimals0 = token0.decimals(); uint decimals1 = token1.decimals(); uint priceX8 = 10**decimals0; // Overflow if dont scale down the sqrtPrice before div 2*192 priceX8 = priceX8 * uint(sqrtPriceX96 / 2 ** 12) ** 2 * 1e8 / 2**168; /// @audit priceX8 = priceX8 / 10**decimals1; uint oraclePrice = 1e8 * oracle.getAssetPrice(address(token0)) / oracle.getAssetPrice(address(token1)); if (oraclePrice < priceX8 * 101 / 100 && oraclePrice > priceX8 * 99 / 100) matches = true; }
According to the Revert for sqrtPriceX96 >= 2^128
part in the other protocol's audit report, if the result of the sqrtPriceX96
is greater than or equal to 2^128
, an overflow
would occur like this:
Within the
SimpleManager
contract, therebalance
function includes a price calculation that triggers a revert ifsqrtPriceX96
is greater than or equal to2^128
. The calculation involves squaringsqrtPriceX96
, and if the result is larger than or equal to2^256
, an overflow occurs, leading to the revert.
Within the GeVault#poolMatchesOracle()
, the sqrtPriceX96
, which is returned from uniswapPool.slot0()
, would be used as it is for the subsequent calculation.
However, the GeVault#poolMatchesOracle()
would always return false
due to the overflow if the sqrtPriceX96
is greater than or equal to 2^128
, which lead to reverting the transaction of rebalancing the GeVault that is called via the GeVault#rebalance()
.
Because if the sqrtPriceX96
would 0
due to overflow, the priceX8
would also be 0
.
Thus, the matches
below at the final line of the GeVault#poolMatchesOracle()
would always be False
(if the sqrtPriceX96
is greater than or equal to 2^128
) and then it would be returned.
if (oraclePrice < priceX8 * 101 / 100 && oraclePrice > priceX8 * 99 / 100) matches = true;
Since the matches
, which is returned-value from the GeVault#poolMatchesOracle()
above, would always be False
(if the sqrtPriceX96
is greater than or equal to 2^128
), the transaction would always be reverted at the line of the condition in the the GeVault#rebalance()
below:
require(poolMatchesOracle(), "GEV: Oracle Error");
Remarks).
By the way, the GeVault#poolMatchesOracle()
would be called for the validation in the following functions as well.
Thus, the transaction of the following functions would also be reverted if the same situation above.
GeVault#deposit()
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L250
GeVault#withdraw()
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L215
Consider using the uniswap oracle library methodology to square the value. This will prevent reverts due to overflows.
Under/Overflow
#0 - c4-pre-sort
2023-08-09T14:27:48Z
141345 marked the issue as duplicate of #140
#1 - c4-judge
2023-08-20T17:32:22Z
gzeon-c4 changed the severity to 3 (High Risk)
#2 - c4-judge
2023-08-20T17:32:25Z
gzeon-c4 marked the issue as satisfactory