Asymmetry contest - 0xl51'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: 156/246

Findings: 2

Award: $13.27

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/SafEth.sol#L91 https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/SafEth.sol#L92 https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/Reth.sol#L228

Vulnerability details

Impact

The probability of the following events are theoretically possible, but considered as low. Although the impact is of a high importance.

Proof of Concept

In function stake(https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/SafEth.sol#L91) in SafEth.sol contract Bob decides to stake e.g. 2k ETH. This case scenario is possible due to the fact that the owner can set maxDeposit to be an integer as high as MAX_UINT. maxSlippage doesn't have any range in which could be set, so in a scenario in which the max slippage is set to e.g. 0.5e18(50%) for Reth. The weights for each derivative doesn't have any particular range in which could be set so the weight of the Reth in the index can variable from 0 - maxUint. When Bob stakes his 2k ETH if the weight of Reth at that moment is e.g. 50%, Bob is highly likely to hit the cap of the rocketDepositPool with the deposit of 1k ETH and poolCanDeposit fn to return false because rocketDepositPool.getBalance() + _amount <= rocketDAOProtocolSettingsDeposit.getMaximumDepositPoolSize(). This will lead to the swap in https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/Reth.sol#L177, where the fee tier for the pool is statically typed:

Reth.sol

``` uint256 amountSwapped = swapExactInputSingleHop( W_ETH_ADDRESS, rethAddress(), 500, msg.value, minOut );` ```

Then after the deposit function in Reth.sol has completed, the new spot price will be extracted again with the deposit amount left after the swap: SafEth.sol

``` uint derivativeReceivedEthValue = (derivative.ethPerDerivative( depositAmount ) * depositAmount) / 10 ** 18; ```

Reth.sol ...

``` 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); } ```

After derivativeReceivedEthValue is calculated with the new price Bob will be then minted more tokens because of the inflated price of rETH in the pool with fee tier of 500.

``` totalStakeValueEth += derivativeReceivedEthValue; uint256 mintAmount = (totalStakeValueEth * 10 ** 18) / preDepositPrice; ```

Tools Used

_

Use TWAP oracle implementation from Uniswap V3.

#0 - c4-pre-sort

2023-04-03T07:02:45Z

0xSorryNotSorry marked the issue as low quality report

#1 - c4-pre-sort

2023-04-04T11:49:33Z

0xSorryNotSorry marked the issue as duplicate of #601

#2 - c4-judge

2023-04-21T16:11:44Z

Picodes marked the issue as duplicate of #1125

#3 - c4-judge

2023-04-21T16:13:50Z

Picodes marked the issue as satisfactory

#4 - c4-judge

2023-04-24T21:46:36Z

Picodes changed the severity to 3 (High Risk)

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