Asymmetry contest - ak1'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: 159/246

Findings: 1

Award: $13.13

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Reth.sol :

QA-1

deposit() would revert for rocket derivative due to hard coded pool fee (500 is set)

if (!poolCanDeposit(msg.value)) { uint rethPerEth = (10 ** 36) / poolPrice(); 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, --------------------------------> audit observation - hardcoded fee value. msg.value, minOut );

When fee values are increased, one of the derivative would revert. And due to this, all staking would revert.

QA-2

Use storge gap since the contracts are upgradable.

There are more chances for storage slot Collison when new variable is added at the end of the SafEthStorage

Lets look at the SafEthStorage contract,

contract SafEthStorage { bool public pauseStaking; // true if staking is paused bool public pauseUnstaking; // true if unstaking is pause uint256 public derivativeCount; // amount of derivatives added to contract uint256 public totalWeight; // total weight of all derivatives (used to calculate percentage of derivative) uint256 public minAmount; // minimum amount to stake uint256 public maxAmount; // maximum amount to stake mapping(uint256 => IDerivative) public derivatives; // derivatives in the system mapping(uint256 => uint256) public weights; // weights for each derivative

The parameter maxAmount would be last one and any new variable can be added next to this maxAmount.

Lets look one of the contracts, WstEth.sol

contract WstEth is IDerivative, Initializable, OwnableUpgradeable { address public constant WST_ETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; address public constant LIDO_CRV_POOL = 0xDC24316b9AE028F1497c275EB9192a3Ea0f67022; address public constant STETH_TOKEN = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; uint256 public maxSlippage; // As recommended by https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); }

First three variables are constant so they will not occupy any storage slot. but the maxSlippage would be assgined in storage slot since it is a state variable.

Any new value added in SafEthStorage would affect the maxSlippage value.

Recommendation : use storage gap. Follow Open zeppalin recommendation

#0 - c4-pre-sort

2023-03-31T12:05:13Z

0xSorryNotSorry marked the issue as low quality report

#1 - c4-sponsor

2023-04-07T21:40:56Z

toshiSat marked the issue as sponsor acknowledged

#2 - c4-judge

2023-04-24T17:04:06Z

Picodes marked the issue as grade-b

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