Asymmetry contest - nowonder92'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: 243/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#L156-L204 https://github.com/code-423n4/2023-03-asymmetry/blob/44b5cd94ebedc187a08884a7f685e950e987261c/contracts/SafEth/derivatives/Reth.sol#L211-L216

Vulnerability details

Impact

Deposits are exposed to unnecessary risk by using Uni v3 Weth/Reth Pool as an oracle. It is also possible for staking to be inoperable due to over/underflow.

Proof of Concept

In the event of !poolCanDeposit(msg.value) in Reth.sol deposit(), this derivative uses a singular hard-coded pool to retrieve a price from uniswap v3. In the case of a single volatile event in that pool, a user will receive far less SafEth than expected in return. These calculations are also exposed to "non divisible by 0" occurrences due the spot price.

Get the TWAP Price or use an external oracle like Chainlink.

Example TWAP:

function consult(address pool, uint32 secondsAgo) external view returns (int24 arithmeticMeanTick, uint128 harmonicMeanLiquidity) { require(secondsAgo != 0, 'BP'); uint32[] memory secondsAgos = new uint32[](2); secondsAgos[0] = secondsAgo; secondsAgos[1] = 0; (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s) = IUniswapV3Pool(pool).observe(secondsAgos); int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0]; uint160 secondsPerLiquidityCumulativesDelta = secondsPerLiquidityCumulativeX128s[1] - secondsPerLiquidityCumulativeX128s[0]; arithmeticMeanTick = int24(tickCumulativesDelta / int56(int32(secondsAgo))); // Always round to negative infinity if (tickCumulativesDelta < 0 && (tickCumulativesDelta % int56(int32(secondsAgo)) != 0)) arithmeticMeanTick--; // We are multiplying here instead of shifting to ensure that harmonicMeanLiquidity doesn't overflow uint128 uint192 secondsAgoX160 = uint192(secondsAgo) * type(uint160).max; harmonicMeanLiquidity = uint128(secondsAgoX160 / (uint192(secondsPerLiquidityCumulativesDelta) << 32)); } function getQuoteAtTick( int24 tick, uint128 baseAmount, address baseToken, address quoteToken ) external pure returns (uint256 quoteAmount) { uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick); // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself if (sqrtRatioX96 <= type(uint128).max) { uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96; quoteAmount = baseToken < quoteToken ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192) : FullMath.mulDiv(1 << 192, baseAmount, ratioX192); } else { uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64); quoteAmount = baseToken < quoteToken ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128) : FullMath.mulDiv(1 << 128, baseAmount, ratioX128); } }

#0 - c4-pre-sort

2023-03-31T09:53:58Z

0xSorryNotSorry marked the issue as low quality report

#1 - c4-pre-sort

2023-04-04T11:16:38Z

0xSorryNotSorry marked the issue as duplicate of #601

#2 - c4-judge

2023-04-21T16:11:43Z

Picodes marked the issue as satisfactory

#3 - c4-judge

2023-04-21T16:15:39Z

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