Closed c4-submissions closed 1 year ago
@toshiSat Im thinking another solution could be to lock down votiumStrategy so only afEth can interact with it
0xleastwood marked the issue as selected for report
0xleastwood marked the issue as not selected for report
0xleastwood marked the issue as primary issue
https://github.com/asymmetryfinance/afeth/pull/169
we went with locking it down so only afEth deposit or withdraw from votium strategy
0xleastwood marked the issue as selected for report
0xleastwood marked the issue as duplicate of #23
0xleastwood marked the issue as not selected for report
0xleastwood marked the issue as partial-50
Only giving 50% credit because it misses the depositRewards()
edge case.
Giving full credit as paired with #41, it covers all cases outlined in the primary issue.
0xleastwood marked the issue as full credit
0xleastwood marked the issue as satisfactory
Lines of code
https://github.com/code-423n4/2023-09-asymmetry/blob/main/contracts/strategies/votium/VotiumStrategy.sol#L39 https://github.com/code-423n4/2023-09-asymmetry/blob/main/contracts/strategies/votium/VotiumStrategy.sol#L109
Vulnerability details
Summary
Direct deposits and withdrawals within VotiumStrategy lack any slippage controls, which opens up the possibility of sandwich attacks and Miner Extractable Value (MEV) exploits.
Impact
Interactions in the AfEth protocol often require the exchange of ETH for other assets. Users deposit ETH, and the protocol needs to convert it to other LSD tokens while staking in SafEth, and also to CVX tokens while depositing in the VotiumStrategy. Similarly, during withdrawals, the protocol converts those assets back to ETH.
While the AfEth contract implements slippage control in
deposit()
andwithdraw()
through a_minout
parameter to ensure the return of a minimum number of assets after execution, the same is not true for theVotiumStrategy
contract, which can be used in a standalone fashion.The
deposit()
function in VotiumStrategy simple takes the received ETH amount and swaps it to CVX usingbuyCvx()
:https://github.com/code-423n4/2023-09-asymmetry/blob/main/contracts/strategies/votium/VotiumStrategy.sol#L39-L46
https://github.com/code-423n4/2023-09-asymmetry/blob/main/contracts/strategies/votium/VotiumStrategyCore.sol#L227-L243
In the previous snippet of code, line 239, we can see that the last argument to
exchange_underlying()
is zero, which is the minimum output amount. The comment reads "this is handled at the afEth level" which is partially true: it is only checked when being used from AfEth, but not for direct depositors of the VotiumStrategy.The
withdraw()
function has the same issue when swapping CVX for ETH insellCvx()
:https://github.com/code-423n4/2023-09-asymmetry/blob/main/contracts/strategies/votium/VotiumStrategy.sol#L109-L29
https://github.com/code-423n4/2023-09-asymmetry/blob/main/contracts/strategies/votium/VotiumStrategyCore.sol#L250-L265
Again, in line 262 we see the same issue as before, the minimum output is configured to zero.
We can see that there is no slippage control at any level, the swap output amount is configured to zero, and there is no check of the number of minted tokens or the amount of ETH sent back to the user.
This implies that direct deposits or withdrawals in the VotiumStrategy contract are susceptible to arbitrary sandwich attacks by MEV bots, which could potentially result in a loss of funds for the user. In the case of a sandwiched deposit, there will be a reduced issuance of VotiumStrategy tokens, as the swap may yield fewer CVX tokens than anticipated. Similarly, a sandwiched withdrawal may lead to a reduced amount of ETH being returned to the user.
Proof of Concept
Recommendation
Add a minimum output parameter to both
deposit()
andwithdraw()
in the VotiumStrategy contract.The AfEth contract can still set these arguments as zero, since it already has slippage control, while allowing direct users of the VotiumStrategy contract to protect against MEV attacks.
Assessed type
MEV