Platform: Code4rena
Start Date: 13/05/2022
Pot Size: $30,000 USDC
Total HM: 8
Participants: 65
Period: 3 days
Judge: hickuphh3
Total Solo HM: 1
Id: 125
League: ETH
Rank: 17/65
Findings: 2
Award: $298.40
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: pedroais
Also found by: 0x4non, 0x52, 0xf15ers, 0xliumin, CertoraInc, Dravee, GimelSec, IllIllI, MaratCerby, StErMi, TerrierLover, WatchPug, berndartmueller, cccz, dipp, fatherOfBlocks, hake, hickuphh3, hyh, isamjay, mtz, oyc_109, p4st13r4, peritoflores, rotcivegaf, saian, simon135, sorrynotsorry, sseefried, tabish, z3s
14.8433 USDC - $14.84
In the _withdrawFromYieldPool function of the LidoVault contract, the require statement is placed after the return statement, which makes the function not check the return value of to.call, which may result in the user not receiving ether.
function _withdrawFromYieldPool( address _asset, uint256 _amount, address _to ) internal override returns (uint256) { address LIDO = _addressesProvider.getAddress('LIDO'); if (_asset == address(0)) { // Case of ETH withdraw request from user, so exchange stETH -> ETH via curve uint256 receivedETHAmount = CurveswapAdapter.swapExactTokensForTokens( _addressesProvider, _addressesProvider.getAddress('STETH_ETH_POOL'), LIDO, ETH, _amount, 200 ); // send ETH to user (bool sent, bytes memory data) = address(_to).call{value: receivedETHAmount}(''); return receivedETHAmount; require(sent, Errors.VT_COLLATERAL_WITHDRAW_INVALID);
The example contract below shows that the require statement does not take effect when the require statement comes after the return statement
pragma solidity 0.6.12; contract A{ uint256 public a; function convertA() external{ a = _test(); } function _test() internal returns (uint256) { return 1; require(false); } }
None
Put the require statement before the return statement
function _withdrawFromYieldPool( address _asset, uint256 _amount, address _to ) internal override returns (uint256) { address LIDO = _addressesProvider.getAddress('LIDO'); if (_asset == address(0)) { // Case of ETH withdraw request from user, so exchange stETH -> ETH via curve uint256 receivedETHAmount = CurveswapAdapter.swapExactTokensForTokens( _addressesProvider, _addressesProvider.getAddress('STETH_ETH_POOL'), LIDO, ETH, _amount, 200 ); // send ETH to user (bool sent, bytes memory data) = address(_to).call{value: receivedETHAmount}(''); require(sent, Errors.VT_COLLATERAL_WITHDRAW_INVALID); return receivedETHAmount;
#0 - sforman2000
2022-05-18T03:12:18Z
🌟 Selected for report: rotcivegaf
Also found by: AuditsAreUS, MaratCerby, StErMi, berndartmueller, cccz, dipp
In the depositCollateral function of the LidoVault contract, the user can choose to deposit Ether or LIDO. When the user chooses to deposit LIDO, the _depositToYieldPool function does not check msg.value == 0. When the user accidentally carries Ether in the transaction, the user will lost his Ether.
None
When user deposits LIDO, check msg.value == 0.
} else { // Case of stETH deposit from user, receive stETH from user require(_asset == LIDO && msg.value == 0, Errors.VT_COLLATERAL_DEPOSIT_INVALID); IERC20(LIDO).safeTransferFrom(msg.sender, address(this), _amount); }
#0 - sforman2000
2022-05-18T02:26:16Z