code-423n4 / 2022-02-tribe-turbo-findings

1 stars 0 forks source link

Gas Optimizations #72

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

Gas Report

Table of Contents:

Summary

This code is amazingly optimized! Well done! I only have 1 suggestion: using custom errors consistently across the solution.

Recommendation

Use Custom Errors instead of Revert Strings to save Gas

Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met)

Source: https://blog.soliditylang.org/2021/04/21/custom-errors/:

Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., revert("Insufficient funds.");), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them.

Custom errors are defined using the error statement, which can be used inside and outside of contracts (including interfaces and libraries).

Instances include:

lib/solmate/ERC4626.sol:49:        require((shares = previewDeposit(amount)) != 0, "ZERO_SHARES");
lib/solmate/ERC4626.sol:106:        require((amount = previewRedeem(shares)) != 0, "ZERO_ASSETS");
src/modules/TurboClerk.sol:38:        require(newDefaultFeePercentage <= 1e18, "FEE_TOO_HIGH");
src/modules/TurboClerk.sol:72:        require(newFeePercentage <= 1e18, "FEE_TOO_HIGH");
src/modules/TurboClerk.sol:90:        require(newFeePercentage <= 1e18, "FEE_TOO_HIGH");
src/modules/TurboGibber.sol:89:        require(feiTurboCToken.repayBorrowBehalf(address(safe), feiAmount) == 0, "REPAY_FAILED");
src/modules/TurboGibber.sol:117:        require(feiTurboCToken.repayBorrowBehalf(address(safe), feiAmount) == 0, "REPAY_FAILED");
src/modules/TurboSavior.sol:77:        require(newMinDebtPercentageForSaving <= 1e18, "PERCENT_TOO_HIGH");
src/modules/TurboSavior.sol:129:        require(
src/TurboMaster.sol:208:        require(getSafeId[safe] != 0, "INVALID_SAFE");
src/TurboMaster.sol:232:        require(
src/TurboMaster.sol:258:        require(getSafeId[safe] != 0, "INVALID_SAFE");
src/TurboMaster.sol:288:        require(getSafeId[safe] != 0, "INVALID_SAFE");
src/TurboRouter.sol:38:        require(msg.sender == Auth(target).owner(), "NOT_AUTHED");
src/TurboSafe.sol:70:        require(asset != fei, "INVALID_ASSET");
src/TurboSafe.sol:79:        require(address(assetTurboCToken) != address(0), "UNSUPPORTED_ASSET");
src/TurboSafe.sol:86:        require(pool.enterMarkets(marketsToEnter)[0] == 0, "ENTER_MARKETS_FAILED");
src/TurboSafe.sol:121:                require(
src/TurboSafe.sol:140:        require(assetTurboCToken.mint(assetAmount) == 0, "MINT_FAILED");
src/TurboSafe.sol:148:        require(assetTurboCToken.redeemUnderlying(assetAmount) == 0, "REDEEM_FAILED");
src/TurboSafe.sol:173:        require(vault.asset() == fei, "NOT_FEI");
src/TurboSafe.sol:191:        require(feiTurboCToken.borrow(feiAmount) == 0, "BORROW_FAILED");
src/TurboSafe.sol:233:        if (feiAmount != 0) require(feiTurboCToken.repayBorrow(feiAmount) == 0, "REPAY_FAILED");
src/TurboSafe.sol:260:        require(getTotalFeiBoostedForVault[vault] != 0, "NO_FEI_BOOSTED");
src/TurboSafe.sol:312:        require(getTotalFeiBoostedForVault[ERC4626(address(token))] == 0 && token != assetTurboCToken, "INVALID_TOKEN");
src/TurboSafe.sol:339:        require(assetTurboCToken.redeemUnderlying(assetAmount) == 0, "REDEEM_FAILED");

I suggest replacing revert strings with custom errors.

GalloDaSballo commented 2 years ago

I've had inconsistent results with customErrors

In lack of any actual gas metrics, I'll give this report 20 points