Platform: Code4rena
Start Date: 16/02/2023
Pot Size: $144,750 USDC
Total HM: 17
Participants: 154
Period: 19 days
Judge: Trust
Total Solo HM: 5
Id: 216
League: ETH
Rank: 138/154
Findings: 1
Award: $42.07
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: c3phas
Also found by: 0x3b, 0x6980, 0x73696d616f, 0xSmartContract, 0xackermann, 0xhacksmithh, 0xsomeone, Bnke0x0, Bough, Budaghyan, Darshan, DeFiHackLabs, Deivitto, GalloDaSballo, JCN, LethL, Madalad, MiniGlome, Morraez, P-384, PaludoX0, Phantasmagoria, Praise, RHaO-sec, Rageur, RaymondFam, ReyAdmirado, Rickard, Rolezn, SaeedAlipoor01988, Saintcode_, Sathish9098, TheSavageTeddy, Tomio, Viktor_Cortess, abiih, arialblack14, atharvasama, banky, codeislight, cryptonue, ddimitrov22, dec3ntraliz3d, descharre, dharma09, emmac002, favelanky, hl_, hunter_w3b, kaden, kodyvim, matrix_0wl, oyc_109, pavankv, scokaf, seeu, yamapyblack
42.0697 USDC - $42.07
Incorrect use of storage variable in _harvestCore() function of ReaperStrategyGranarySupplyOnly
contract .
The current implementation of the function uses the storage keyword to create a pointer to an array in the contract's storage. However, this is unnecessary and will lead to higher gas costs . Using memory instead of storage would be more appropriate and efficient.
Code changes:
for (uint256 i = 0; i < numSteps; i = i.uncheckedInc()) { address[2] storage step = steps[i]; // Should be memory variable IERC20Upgradeable startToken = IERC20Upgradeable(step[0]); uint256 amount = startToken.balanceOf(address(this)); if (amount == 0) { continue; } _swapVelo(step[0], step[1], amount, VELO_ROUTER); } }
should be changed to:
for (uint256 i = 0; i < numSteps; i = i.uncheckedInc()) { // Changed to memory since this storage pointer is not used to update value address[2] memory step = steps[i]; IERC20Upgradeable startToken = IERC20Upgradeable(step[0]); uint256 amount = startToken.balanceOf(address(this)); if (amount == 0) { continue; } _swapVelo(step[0], step[1], amount, VELO_ROUTER); }
The _cascadingAccessRoles()
function in ReaperVaultV2.sol
can be optimized by changing its state mutability from view
to pure
since the function does not access any storage variables. This change will not only make the function more efficient but also reduce gas costs.
function _cascadingAccessRoles() internal view override returns (bytes32[] memory) { bytes32[] memory cascadingAccessRoles = new bytes32[](5); cascadingAccessRoles[0] = DEFAULT_ADMIN_ROLE; cascadingAccessRoles[1] = ADMIN; cascadingAccessRoles[2] = GUARDIAN; cascadingAccessRoles[3] = STRATEGIST; cascadingAccessRoles[4] = DEPOSITOR; return cascadingAccessRoles; }
change the function header to
function _cascadingAccessRoles() internal pure override returns (bytes32[] memory) { bytes32[] memory cascadingAccessRoles = new bytes32[](5); cascadingAccessRoles[0] = DEFAULT_ADMIN_ROLE; cascadingAccessRoles[1] = ADMIN; cascadingAccessRoles[2] = GUARDIAN; cascadingAccessRoles[3] = STRATEGIST; cascadingAccessRoles[4] = DEPOSITOR; return cascadingAccessRoles; }
In the setAddresses()
function of ActivePool.sol, an SLOAD
can be saved by using a function parameter. When calling the getAllowedCollaterals()
function, use _collateralConfigAddress
instead of collateralConfigAddress
, and hence save an SLOAD
.
Link to the code on github Current code
collateralConfigAddress = _collateralConfigAddress; // omitted .. address[] memory collaterals = ICollateralConfig(collateralConfigAddress).getAllowedCollaterals();
Change to
collateralConfigAddress = _collateralConfigAddress; // omitted .. address[] memory collaterals = ICollateralConfig(_collateralConfigAddress).getAllowedCollaterals();
#0 - c4-judge
2023-03-09T18:52:52Z
trust1995 marked the issue as grade-b