Asymmetry contest - skidog's results

A protocol to help diversify and decentralize liquid staking derivatives.

General Information

Platform: Code4rena

Start Date: 24/03/2023

Pot Size: $49,200 USDC

Total HM: 20

Participants: 246

Period: 6 days

Judge: Picodes

Total Solo HM: 1

Id: 226

League: ETH

Asymmetry Finance

Findings Distribution

Researcher Performance

Rank: 236/246

Findings: 1

Award: $0.14

🌟 Selected for report: 0

🚀 Solo Findings: 0

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: Asymmetry's 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

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/

#0 - c4-pre-sort

2023-04-04T11:23:49Z

0xSorryNotSorry marked the issue as duplicate of #601

#1 - c4-judge

2023-04-21T16:14:47Z

Picodes marked the issue as satisfactory

#2 - c4-judge

2023-04-21T16:15:26Z

Picodes marked the issue as duplicate of #1125

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter