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: 26/65
Findings: 3
Award: $88.60
π 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
the require statement in the _withdrawFromYieldPool function is never checked since it is after the return statement
/2022-05-sturdy/smart-contracts/LidoVault.sol 140: (bool sent, bytes memory data) = address(_to).call{value: receivedETHAmount}(''); 141: return receivedETHAmount; 142: require(sent, Errors.VT_COLLATERAL_WITHDRAW_INVALID);
since the _to address is an user controlled parameter, it is possible that if the user inputs a bad address the transfer will fail silently and cause the user to lose funds
#0 - sforman2000
2022-05-18T03:12:24Z
π Selected for report: IllIllI
Also found by: 0x1f8b, 0x4non, 0xNazgul, 0xf15ers, 0xkatana, 0xliumin, AlleyCat, BouSalman, Dravee, Funen, GimelSec, Hawkeye, MaratCerby, Picodes, StErMi, TerrierLover, WatchPug, Waze, berndartmueller, bobirichman, cryptphi, csanuragjain, defsec, delfin454000, dipp, fatherOfBlocks, hake, hickuphh3, hyh, joestakey, kebabsec, mics, mtz, oyc_109, p4st13r4, p_crypt0, robee, rotcivegaf, sikorico, simon135, sorrynotsorry, tintin
49.399 USDC - $49.40
the function addCollateralAsset does not check if invalid addresses are added to a vault, eg zero address checks
Checking addresses against zero-address during initialization or during setting is a security best-practice.
/2022-05-sturdy/smart-contracts/CollateralAdapter.sol 43: function addCollateralAsset( 44: address _externalAsset, 45: address _internalAsset, 46: address _acceptVault 47: ) external onlyAdmin { 48: _assetToVaults[_externalAsset] = _acceptVault; 49: _collateralAssets[_externalAsset] = _internalAsset; 50: } 51:
/2022-05-sturdy/smart-contracts/YieldManager.sol 60: function initialize(ILendingPoolAddressesProvider _provider) public initializer { 61: _addressesProvider = _provider; 62: }
Use of hard-coded addresses may cause errors: Each contract needs contract addresses in order to be integrated into other protocols and systems. These addresses are currently hard-coded, which may cause errors and result in the codebaseβs deployment with an incorrect asset. Using hard-coded values instead of deployer-provided values makes these contracts incredibly difficult to test.
Recommendation: set addresses when contracts are created rather than using hard-coded values. This practice will facilitate testing and reused across networks
/2022-05-sturdy/smart-contracts/ConvexCurveLPVault.sol 40: convexBooster = 0xF403C135812408BFbE8713b5A23a04b3D48AAE31;
The function _depositToYieldPool() takes in an address parameter _asset.
/2022-05-sturdy/smart-contracts/ConvexCurveLPVault.sol 131: function _depositToYieldPool(address _asset, uint256 _amount)
This parameter is not used within the function except in the require statement
/2022-05-sturdy/smart-contracts/ConvexCurveLPVault.sol 137: require(_asset == curveLPToken, Errors.VT_COLLATERAL_DEPOSIT_INVALID);
therefore this parameter can be removed from the function
this also applies to
/2022-05-sturdy/smart-contracts/ConvexCurveLPVault.sol 154: function _getWithdrawalAmount(address _asset, uint256 _amount) 178: function withdrawOnLiquidation(address _asset, uint256 _amount) 192: function _withdrawFromYieldPool( 193: address _asset,
the function _depositToYieldPool may deposit ETH however it does not have the payable modifier
/2022-05-sturdy/smart-contracts/LidoVault.sol 79: function _depositToYieldPool(address _asset, uint256 _amount) 80: internal 81: override 82: returns (address, uint256)
#0 - HickupHH3
2022-06-06T02:37:04Z
Low issues: NC issues: unnecessary parameter, hard coded addresses, missing zero address checks Invalid: payable modifier
π Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0xNazgul, 0xf15ers, 0xkatana, 0xliumin, Cityscape, Dravee, Fitraldys, Funen, GimelSec, Hawkeye, JC, MaratCerby, SooYa, StErMi, Tomio, WatchPug, Waze, bobirichman, defsec, delfin454000, fatherOfBlocks, hake, hansfriese, hickuphh3, ignacio, joestakey, kebabsec, mics, mtz, oyc_109, robee, rotcivegaf, samruna, sikorico, simon135, z3s
24.3601 USDC - $24.36
for variables only used once, changing it to inline saves gas
/2022-05-sturdy/smart-contracts/ConvexCurveLPVault.sol 62: IConvexBooster.PoolInfo memory poolInfo = IConvexBooster(convexBooster).poolInfo(convexPoolId); 76: uint256 treasuryAmount = _processTreasury(_asset, yieldAmount); 81: address yieldManager = _addressesProvider.getAddress('YIELD_MANAGER'); 107: address _extraReward = IConvexBaseRewardPool(baseRewardPool).extraRewards(i); 108: address _rewardToken = IRewards(_extraReward).rewardToken();
/2022-05-sturdy/smart-contracts/GeneralVault.sol 119: uint256 withdrawAmount = _withdrawFromYieldPool(_asset, _amountToWithdraw, _to); 122: uint256 decimal = IERC20Detailed(_asset).decimals();
/2022-05-sturdy/smart-contracts/LidoVault.sol 37: uint256 treasuryStETH = _processTreasury(yieldStETH);
The code can be optimized by minimising the number of SLOADs. SLOADs are expensive (100 gas) compared to MLOADs/MSTOREs (3 gas).
/2022-05-sturdy/smart-contracts/YieldManager.sol 130: for (uint256 i = 0; i < assetYields.length; i++) {
Prefix increments are cheaper than postfix increments, eg ++i rather than i++
/2022-05-sturdy/smart-contracts/ConvexCurveLPVault.sol 106: for (uint256 i = 0; i < extraRewardsLength; i++) {
/2022-05-sturdy/smart-contracts/GeneralVault.sol 218: for (uint256 i = 0; i < length; i++) {
/2022-05-sturdy/smart-contracts/YieldManager.sol 120: for (uint256 i = 0; i < _count; i++) { 130: for (uint256 i = 0; i < assetYields.length; i++) { 156: for (uint256 i = 0; i < length; i++) {
Uninitialized variables are assigned with the types default value.
Explicitly initializing a variable with it's default value costs unnecesary gas.
/2022-05-sturdy/smart-contracts/ConvexCurveLPVault.sol 106: for (uint256 i = 0; i < extraRewardsLength; i++) {
/2022-05-sturdy/smart-contracts/GeneralVault.sol 218: for (uint256 i = 0; i < length; i++) {
/2022-05-sturdy/smart-contracts/YieldManager.sol 120: for (uint256 i = 0; i < _count; i++) { 130: for (uint256 i = 0; i < assetYields.length; i++) { 156: for (uint256 i = 0; i < length; i++) {