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
Rank: 54/246
Findings: 4
Award: $98.95
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: adriro
Also found by: 0xMirce, 0xRajkumar, 0xepley, BPZ, Bahurum, Bauer, Co0nan, Emmanuel, Franfran, HollaDieWaldfee, IgorZuk, MiloTruck, NoamYakov, RedTiger, Ruhum, T1MOH, Tricko, ad3sh_, auditor0517, bin2chen, carrotsmuggler, eyexploit, handsomegiraffe, igingu, jasonxiale, koxuan, lukris02, monrel, nadin, peanuts, rbserver, rvierdiiev, shaka, sinarette, tnevler, y1cunhui
4.5426 USDC - $4.54
The purpose of the ethPerDerivative function with-in the WstEth contract is to get the price of the derivative in terms of ETH. However the implementation of this function does not do that; this function will actually return the "amount of stETH tokens corresponding to one wstETH" (cited from the Lido Finance documentation for wstETH). This is problematic because the price of stETH in terms of ETH is not equal to 1, for example the current conversion 1 stETH = 0.992 ETH. The implications of this is that the protocol will misrepresent the underlying value in terms of ETH that has been allocated to the Lido-based derivative (WstEth contract). The direct impact of this misrepresentation of underlying ETH on the users can be seen with-in the stake function of the SafEth contract. This function will miscalculate the current underlying value of the Lido-based derivative and, additionally, miscalculate the amount the user is now staking, ultimately, over-valuing or under-valuing the user's position by minting an incorrect amount of SafEth tokens to the user.
The ethPerDerivative function implemented in the WstEth contract will not get the price of the derivative in terms of ETH:
function ethPerDerivative(uint256 _amount) public view returns (uint256) { return IWStETH(WST_ETH).getStETHByWstETH(10 ** 18); }
This function will, instead, return the amount of stETH tokens representing one wstETH. For additional reference, please see the Lido Finance documentation on the getStETHByWstETH method.
Manual Audit Review
It is recommended to refactor the ethPerDerivative function with-in the WstEth contract so that the resulting amount of stETH tokens representing one wstETH is then directly converted to ETH. This can be done by utilizing the get_dy method of the implemented stETH/ETH Curve Pool:
function ethPerDerivative(uint256 _amount) public view returns (uint256) { uint256 stETHPerWstETH = IWStETH(WST_ETH).getStETHByWstETH(10 ** 18); return IStEthEthPool(LIDO_CRV_POOL).get_dy(1, 0, stETHPerWstETH); }
#0 - c4-pre-sort
2023-04-04T17:16:39Z
0xSorryNotSorry marked the issue as duplicate of #588
#1 - c4-judge
2023-04-21T17:11:33Z
Picodes marked the issue as satisfactory
#2 - c4-judge
2023-04-23T11:07:04Z
Picodes changed the severity to 3 (High Risk)
🌟 Selected for report: brgltd
Also found by: 0xbepresent, 0xepley, 0xnev, BPZ, Breeje, Polaris_tow, SadBase, SaeedAlipoor01988, eyexploit, ladboy233, latt1ce, peanuts, rbserver
40.6368 USDC - $40.64
https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/Reth.sol#L91
To execute the swap function, its needed to define necessary swap data for ExactInputSingleParams struct.
Source : https://docs.uniswap.org/contracts/v3/reference/periphery/interfaces/ISwapRouter
Source : https://docs.uniswap.org/contracts/v3/guides/swaps/single-swaps
177 uint256 amountSwapped = swapExactInputSingleHop( 178 W_ETH_ADDRESS, 179 rethAddress(), 180 500, 181 msg.value, 182 minOut 183 );
91 ISwapRouter.ExactInputSingleParams memory params = ISwapRouter 92 .ExactInputSingleParams({ 93 tokenIn: _tokenIn, 94 tokenOut: _tokenOut, 95 fee: _poolFee, 96 recipient: address(this), 97 amountIn: _amountIn, 98 amountOutMinimum: _minOut, 99 sqrtPriceLimitX96: 0 100 }); 101 amountOut = ISwapRouter(UNISWAP_ROUTER).exactInputSingle(params);
Here you can see that deadline parameter has not been defined so that it could finally revert the swap.
Manual Auditing
Add the deadline: block.timestamp as shown below.
91 ISwapRouter.ExactInputSingleParams memory params = ISwapRouter 92 .ExactInputSingleParams({ 93 tokenIn: _tokenIn, 94 tokenOut: _tokenOut, 95 fee: _poolFee, 96 recipient: address(this), + deadline: block.timestamp, 97 amountIn: _amountIn, 98 amountOutMinimum: _minOut, 99 sqrtPriceLimitX96: 0 100 }); 101 amountOut = ISwapRouter(UNISWAP_ROUTER).exactInputSingle(params);
Also its needed to change the ISwapRouter interface ExactInputSingleParams struct accordingly. Add the deadline: block.timestamp as shown below.
5 struct ExactInputSingleParams { 6 address tokenIn; 7 address tokenOut; 8 uint24 fee; 9 address recipient; + deadline: block.timestamp, 10 uint amountIn; 11 uint amountOutMinimum; 12 uint160 sqrtPriceLimitX96; 13 }
#0 - c4-pre-sort
2023-04-04T14:49:34Z
0xSorryNotSorry marked the issue as duplicate of #1087
#1 - c4-judge
2023-04-22T10:18:34Z
Picodes marked the issue as satisfactory
🌟 Selected for report: RaymondFam
Also found by: 0xepley, BPZ, Franfran, Parad0x, RedTiger, d3e4, fyvgsk, handsomegiraffe, ladboy233, rbserver, silviaxyz, whoismatthewmc1, yac
40.6368 USDC - $40.64
WstEth.sol has a hardcoded maxSlipage as 1%. It could revert the withdraw function during sudden price crashes.
35 maxSlippage = (1 * 10 ** 16); // 1%
60 uint256 minOut = (stEthBal * (10 ** 18 - maxSlippage)) / 10 ** 18;
Due to hard coded maxSlippage owner unable to define minOut so that its a constant (relative to the input parameter amount) , eventually Owner unable to perform the withdraw function during price crash conditions.
Manual Auditing
Remove the hard coded maxSlippage & let owner to determine the maximum slippage he's willing to take with the current market condition as a input parameter for the withdraw function.
#0 - c4-pre-sort
2023-04-04T15:22:22Z
0xSorryNotSorry marked the issue as duplicate of #814
#1 - c4-judge
2023-04-23T11:12:24Z
Picodes marked the issue as duplicate of #588
#2 - c4-judge
2023-04-24T21:10:52Z
Picodes marked the issue as satisfactory
#3 - c4-judge
2023-04-24T21:13:14Z
Picodes marked the issue as not a duplicate
#4 - c4-judge
2023-04-24T21:13:39Z
Picodes marked the issue as duplicate of #150