Mimo August 2022 contest - joestakey's results

Bridging the chasm between the DeFi world and the world of regulated financial institutions.

General Information

Platform: Code4rena

Start Date: 02/08/2022

Pot Size: $50,000 USDC

Total HM: 12

Participants: 69

Period: 5 days

Judge: gzeon

Total Solo HM: 5

Id: 150

League: ETH

Mimo DeFi

Findings Distribution

Researcher Performance

Rank: 62/69

Findings: 1

Award: $49.17

🌟 Selected for report: 0

🚀 Solo Findings: 0

Gas Report

Table of Contents

Summary

Several optimizations allow to save significant amounts of gas upon deployment of contracts and function invocations. The most interesting saving is in MIMOProxy.sol, as it is will get deployed by many users, where setting a storage variable that is not modified as constant allows to save a lot of gas on deployment and on execute calls. This is the first issue detailed in this report. It is also a very simple change for the team to make Changing require statements into custom errors is also worth considering, as there is a few instances (5) in MIMOEmptyVault, and each change would yield high gas savings upon deployment.

Constant variables save storage

PROBLEM

If a variable is set to a fixed value and never modified afterwards, marking it as constant can save a storage slot.

PROOF OF CONCEPT

1 instance:

MIMOProxy.sol

  • minGasReserve is set in initialize() as 5_000 and never modified afterwards.

TOOLS USED

Manual Analysis

MITIGATION

Mark minGasReserve as constant. Instead of writing it in initialize(), hardcode it with its value.

+uint256 public constant override minGasReserve = 5_000;
-uint256 public override minGasReserve;
  • Gas costs before:
ContractMethodMinMaxAvg
MIMOProxy Deployment895092
-------------------------------------------------
MIMOProxy execute491976
  • Gas costs after:
ContractMethodMinMaxAvg
MIMOProxy Deployment893400
-------------------------------------------------
MIMOProxy execute488999

This saves 1,692 gas upon deployment for MIMOProxy.sol, and 2,977 gas per execute call

Bools for storage are expensive

IMPACT

Booleans are more expensive than uint256: each write operation emits an extra SLOAD to first read the slot's contents, replace the bits taken up by the boolean, and then write back.

PROOF OF CONCEPT

Instances:

  MIMOProxyFactory.sol:53:      _proxies[address(proxy)] = true

TOOLS USED

Manual Analysis

MITIGATION

Use uint256(2) and uint256(1) instead of true and false

-  mapping(address => bool) internal _proxies;
+  mapping(address => uint256) internal _proxies;
 

-  function isProxy(address proxy) external view override returns (bool result) {
+  function isProxy(address proxy) external view override returns (uint256 result) {

-    _proxies[address(proxy)] = true;
+    _proxies[address(proxy)] = 2;
  • Gas costs before:
ContractMethodMinMaxAvg
MIMOProxyFactory Deployment243297
  • Gas costs after:
ContractMethodMinMaxAvg
MIMOProxyFactory Deployment234703

This saves 8,594 gas on deployment for MIMOProxyFactory.sol

Constants can be private

IMPACT

Marking constants as private save gas upon deployment, as the compiler does not have to create getter functions for these variables. It is worth noting that a private variable can still be read using either the verified contract source code or the bytecode.

PROOF OF CONCEPT

MIMOProxyFactory.sol

TOOLS USED

Manual Analysis

MITIGATION

-  address public immutable mimoProxyBase;
+  address private immutable mimoProxyBase;
  • Gas costs before:
ContractMethodMinMaxAvg
MIMOProxyFactory Deployment243297
  • Gas costs after:
ContractMethodMinMaxAvg
MIMOProxyFactory Deployment232742

This saves 10,555 gas on deployment for MIMOProxyFactory.sol

Custom Errors

IMPACT

Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met) while providing the same amount of information, as explained here

Custom errors are defined using the error statement

PROOF OF CONCEPT

5 instances:

  MIMOEmptyVault.sol:95:      require(flashloanRepayAmount <= vaultCollateral.balanceOf(address(this)), Errors.CANNOT_REPAY_FLASHLOAN);
  MIMOLeverage.sol:129:      require(collateralBalanceAfter >= flashloanRepayAmount, Errors.CANNOT_REPAY_FLASHLOAN);
  MIMORebalance.sol:128:      require(
  MIMORebalance.sol:129:        a.vaultsData().vaultCollateralBalance(rbData.vaultId) >= flashloanRepayAmount,
  MIMORebalance.sol:130:        Errors.CANNOT_REPAY_FLASHLOAN,
  MIMORebalance.sol:131:      );
  MIMOSwap.sol:46:      require(proxy != address(0), Errors.INVALID_AGGREGATOR);
  MIMOSwap.sol:47:      require(router != address(0), Errors.INVALID_AGGREGATOR);

TOOLS USED

Manual Analysis

MITIGATION

Replace require and revert statements with custom errors.

For instance, in MIMOEmptyVault.sol:

- require(flashloanRepayAmount <= vaultCollateral.balanceOf(address(this)), Errors.CANNOT_REPAY_FLASHLOAN);
+     if (flashloanRepayAmount > vaultCollateral.balanceOf(address(this))) {
+         revert CustomErrors.CANNOT_REPAY_FLASHLOAN;
+     }

And define CANNOT_REPAY_FLASHLOAN as a CustomErrors.

  • Gas costs before:
ContractMethodMinMaxAvg
MIMOEmptyVaultDeployment1381499
  • Gas costs after:
ContractMethodMinMaxAvg
MIMOEmptyVaultDeployment1375408

This one require statement changed into a custom error saves 6,091 gas upon deployment for MIMOEmptyVault.sol

#0 - joestakey

2022-08-22T20:18:24Z

@gzeoneth Can you compare this report with this one ? It's not clear why this report scored less, while it details more high gas savings issues. #86 details two high gas savings issues, 2 and 7, which are both included in this report. This report even includes more instances of the require statements issue.

#1 - gzeoneth

2022-08-24T10:39:36Z

@gzeoneth Can you compare this report with this one ? It's not clear why this report scored less, while it details more high gas savings issues. #86 details two high gas savings issues, 2 and 7, which are both included in this report. This report even includes more instances of the require statements issue.

thanks I will review

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