code-423n4 / 2023-03-asymmetry-findings

14 stars 12 forks source link

Price Oracle Manipulation #984

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-03-asymmetry/blob/44b5cd94ebedc187a08884a7f685e950e987261c/contracts/SafEth/derivatives/Reth.sol#L211-L216 https://github.com/code-423n4/2023-03-asymmetry/blob/44b5cd94ebedc187a08884a7f685e950e987261c/contracts/SafEth/derivatives/Reth.sol#L228-L242

Vulnerability details

Impact

Price Oracle Manipulation - pricing information for the safEth derivative's underlying assets comes from a single source for each asset, which makes the protocol vulnerable to price oracle manipulation attacks. The generally accepted best practice is to get pricing information from a decentralized oracle like Chainlink

Proof of Concept

When a user calls the stake() function in SafEth.sol in order to stake ETH and mint the safEth derivative, the function determines the value of the underlying assets by calling the ethPerDerivative function for each underlying, aggregating the results, and assigning the total value to the underlyingValue variable.

 function ethPerDerivative(uint256 _amount) public view returns (uint256) {
        if (poolCanDeposit(_amount))
            return
                RocketTokenRETHInterface(rethAddress()).getEthValue(10 ** 18);
        else return (poolPrice() * 10 ** 18) / (10 ** 18);
    }

Reth.sol For the underlying rETH (rocket pool) asset specifically, in the case that rocket pool is unable to accept new deposits, ethPerDerivative calls the poolPrice() function in the Reth.sol contract by directly querying the rETH-WETH price from the Uniswap V3 pool which effectively provides the rETH price in terms of ETH.

function poolPrice() private view returns (uint256) {
        address rocketTokenRETHAddress = RocketStorageInterface(
            ROCKET_STORAGE_ADDRESS
        ).getAddress(
                keccak256(
                    abi.encodePacked("contract.address", "rocketTokenRETH")
                )
            );
        IUniswapV3Factory factory = IUniswapV3Factory(UNI_V3_FACTORY);
        IUniswapV3Pool pool = IUniswapV3Pool(
            factory.getPool(rocketTokenRETHAddress, W_ETH_ADDRESS, 500)
        );
        (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();
        return (sqrtPriceX96 * (uint(sqrtPriceX96)) * (1e18)) >> (96 * 2);
    }

An attacker can wait for a situation where Rocket Pool is not accepting deposits, and the protocol is relying on Uniswap for the rETH price. The attacker can then manipulate the rETH-WETH price by using a flash loan or other means to obtain a large amount of rETH and drive the price of rETH down through Uniswap. Then, they have the option stake ETH into safETH and obtain a higher number of rETH than its true market value. This exposes Asymmetry to a number of risks including:

  1. Reputation risk through association with market manipulation: association with a manipulated market could damage its reputation, leading to a loss of trust from users and potential partners.
  2. Imbalanced risk exposure: If Asymmetry ends up holding a large amount of rETH due to a price manipulation, it could suffer significant losses if the price of rETH continues to fall either as a direct result of the manipulation or as a consequence of it.
  3. Inaccurate pricing information in relation to the broader market: If the rETH price is manipulated, Asymmetry may rely on inaccurate pricing information, which could lead to distorted decision-making or unexpected financial losses.

Tools Used

Manual Review

Recommended Mitigation Steps

Have a failsafe mechanism in place if a price manipulation occurs by using a decentralized Oracle like Chainlink to obtain the rETH price from multiple sources. When its time to execute the trade on Uniswap, if the price on Uniswap falls outside of a band of acceptable variability in relation to the Chainlink price, the trade can be put on hold or diverted to another pool with accurate pricing, which would mitigate the impact of a price manipulation attack. Reference - https://consensys.github.io/smart-contract-best-practices/attacks/oracle-manipulation/

liveactionllama commented 1 year ago

Marking as invalid on behalf of the Lookout.

Reason: Dupe of same warden's issue #992

liveactionllama commented 1 year ago

Since this appears to be an exact dupe, closing.

c4-sponsor commented 1 year ago

toshiSat marked the issue as sponsor disputed