Ethos Reserve contest - dec3ntraliz3d's results

A CDP-backed stablecoin platform designed to generate yield on underlying assets to establish a sustainable DeFi stable interest rate.

General Information

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

Ethos Reserve

Findings Distribution

Researcher Performance

Rank: 138/154

Findings: 1

Award: $42.07

Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Gas report

G-01

Incorrect use of storage variable in _harvestCore() function of ReaperStrategyGranarySupplyOnly contract .

Link to the code on github

Summary:

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);
        }

G-02

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.

Link to the code on github

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;
 }

G-03

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

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter