Asymmetry contest - fs0c'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: 233/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/main/contracts/SafEth/derivatives/Reth.sol#L173 https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/SfrxEth.sol#L74

Vulnerability details

Impact

A user when staking might actually get less tokens in return from the derivatives and might loose tokens due to sandwich attacks.

POC

In the deposit function in Reth derivative contract, consider the following if condition:

if (!poolCanDeposit(msg.value)) {
            uint rethPerEth = (10 ** 36) / poolPrice(); //@audit sandwich possible?

            uint256 minOut = ((((rethPerEth * msg.value) / 10 ** 18) *
                ((10 ** 18 - maxSlippage))) / 10 ** 18);

            IWETH(W_ETH_ADDRESS).deposit{value: msg.value}();
            uint256 amountSwapped = swapExactInputSingleHop(
                W_ETH_ADDRESS,
                rethAddress(),
                500,
                msg.value,
                minOut
            );

            return amountSwapped;

The poolPrice is calculated as follows:

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

Consider the following scenario for a sandwich attack:

  1. Legit user starts a transaction to deposit tokens, which if are landed into the following condition if the deposit amount is high enough will swap from WETH to RETH using uniswap pool.
  2. When an attacker sees the transaction coming through, they sandwich the transaction and as the minOut depends on the current price, the value of minOut will be decreased in case of the attack, and hence it will have no effect on protecting against slippage.

Tools used.

Manual Analysis

Recommendation

minOut can be taken as an input from user.

#0 - c4-pre-sort

2023-04-04T11:43:59Z

0xSorryNotSorry marked the issue as duplicate of #601

#1 - c4-judge

2023-04-21T16:11:16Z

Picodes marked the issue as duplicate of #1125

#2 - c4-judge

2023-04-21T16:14:06Z

Picodes marked the issue as satisfactory

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