Asymmetry contest - ast3ros'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: 67/246

Findings: 1

Award: $81.32

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Awards

81.3214 USDC - $81.32

Labels

bug
3 (High Risk)
satisfactory
upgraded by judge
duplicate-1004

External Links

Lines of code

https://github.com/code-423n4/2023-03-asymmetry/blob/0e826f307866f3b9e737a3fd7b860e1df2dd7e71/contracts/SafEth/SafEth.sol#L73 https://github.com/code-423n4/2023-03-asymmetry/blob/0e826f307866f3b9e737a3fd7b860e1df2dd7e71/contracts/SafEth/SafEth.sol#L92-L94 https://github.com/code-423n4/2023-03-asymmetry/blob/0e826f307866f3b9e737a3fd7b860e1df2dd7e71/contracts/SafEth/derivatives/Reth.sol#L212-L215

Vulnerability details

Impact

Late stakers may gain an unfair advantage compared to early stakers when staking to the SafETH contract. This can happen because ethPerDerivative may be calculated differently in underlyingValue and derivativeReceivedEthValue when depositing to Reth derivative.

Proof of Concept

When calculating the amount of SafETH to mint:

  1. The underlyingValue is calculated using the whole balance in the derivative contract as input for the ethPerDerivative function: derivatives[i].ethPerDerivative(derivatives[i].balance()).
           underlyingValue +=
                (derivatives[i].ethPerDerivative(derivatives[i].balance()) *
                    derivatives[i].balance()) /
                10 ** 18;

The input for ethPerDerivative function is whole balance in derivative contract: derivatives[i].ethPerDerivative(derivatives[i].balance())

https://github.com/code-423n4/2023-03-asymmetry/blob/0e826f307866f3b9e737a3fd7b860e1df2dd7e71/contracts/SafEth/SafEth.sol#L73

  1. The derivativeReceivedEthValue is calculated using only the depositAmount as input for the ethPerDerivative function: derivative.ethPerDerivative(depositAmount).
            uint derivativeReceivedEthValue = (derivative.ethPerDerivative(
                depositAmount
            ) * depositAmount) / 10 ** 18;

https://github.com/code-423n4/2023-03-asymmetry/blob/0e826f307866f3b9e737a3fd7b860e1df2dd7e71/contracts/SafEth/SafEth.sol#L92-L94

  1. When the derivative is Reth, depending on the amount, ethPerDerivative will be taken from either UniswapV3 or RocketTokenPool.
        if (poolCanDeposit(_amount))
            return
                RocketTokenRETHInterface(rethAddress()).getEthValue(10 ** 18);
        else return (poolPrice() * 10 ** 18) / (10 ** 18);

https://github.com/code-423n4/2023-03-asymmetry/blob/0e826f307866f3b9e737a3fd7b860e1df2dd7e71/contracts/SafEth/derivatives/Reth.sol#L212-L215

Therefore, the value of ethPerDerivative in (1) can be different from (2) because derivatives[i].balance() can be significantly different than depositAmount.

The following scenario is likely to happen:

  • derivatives[i].balance() is large, therefore ethPerDerivative is derived from UniswapV3. 1 RETH = 1.0661 WETH (price at time T 28/03).
  • depositAmount is small, therefore ethPerDerivative is derived from RocketTokenPool. 1 RETH = 1.06911 WETH (price at time T 28/03).

This leads to underlyingValue being understated or derivativeReceivedEthValue being overstated, which in turn leads to late stakers receiving more SafETH.

Tools Used

Manual

Using the same price when calculating the underlyingValue and the derivativeReceivedEthValue for RETH derivative when calculating the mintAmount to remain ratio valueETH/totalSupply. When calculating the mintAmount, it’s important to use the same price when calculating both the underlyingValue and the derivativeReceivedEthValue for RETH derivative. It helps remain underlyingValue/totalSupply.

#0 - c4-pre-sort

2023-04-04T17:46:05Z

0xSorryNotSorry marked the issue as duplicate of #1004

#1 - c4-judge

2023-04-21T14:03:53Z

Picodes marked the issue as duplicate of #1125

#2 - c4-judge

2023-04-21T14:19:09Z

Picodes marked the issue as satisfactory

#3 - c4-judge

2023-04-21T14:19:22Z

Picodes marked the issue as not a duplicate

#4 - c4-judge

2023-04-21T14:19:34Z

Picodes marked the issue as duplicate of #1004

#5 - c4-judge

2023-04-24T21:40:08Z

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