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
Rank: 31/69
Findings: 2
Award: $118.83
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0xDjango, 0xNazgul, 0xc0ffEE, 8olidity, Bnke0x0, Chom, CodingNameKiki, Deivitto, Dravee, Funen, JC, JohnSmith, NoamYakov, ReyAdmirado, Rohan16, Rolezn, Sm4rty, SooYa, TomFrenchBlockchain, TomJ, Waze, __141345__, ajtra, ak1, aysha, bin2chen, bobirichman, brgltd, bulej93, c3phas, delfin454000, durianSausage, erictee, fatherOfBlocks, gogo, horsefacts, hyh, ladboy233, mics, natzuu, nxrblsrpr, oyc_109, rbserver, samruna, sikorico, simon135, tofunmi, wagmi
69.6581 USDC - $69.66
public
functions not called by the contract should be declared external
insteadThere are 4 instances of this issue:
File: contracts/proxy/MIMOProxy.sol 54: function execute(address target, bytes calldata data) public payable override returns (bytes memory response) { 104: function setPermission(
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxy.sol
File: contracts/proxy/MIMOProxyFactory.sol 45: function deployFor(address owner) public override returns (IMIMOProxy proxy) {
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxyFactory.sol
File: contracts/proxy/MIMOProxyRegistry.sol 45: function deployFor(address owner) public override returns (IMIMOProxy proxy) {
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxyRegistry.sol
receive()
/fallback()
functionsThere are 1 instances of this issue:
File: contracts/proxy/MIMOProxy.sol 38: receive() external payable {}
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxy.sol
There are 3 instances of this issue:
File: contracts/proxy/MIMOProxy.sol 2: pragma solidity >=0.8.4;
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxy.sol
File: contracts/proxy/MIMOProxyFactory.sol 2: pragma solidity >=0.8.4;
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxyFactory.sol
File: contracts/proxy/MIMOProxyRegistry.sol 2: pragma solidity >=0.8.4;
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxyRegistry.sol
There are 11 instances of this issue:
indexed
fieldsThere are 2 instances of this issue:
File: contracts/proxy/interfaces/IMIMOProxy.sol event Execute(address indexed target, bytes data, bytes response)
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/interfaces/IMIMOProxy.sol
File: contracts/proxy/interfaces/IMIMOProxyFactory.sol event DeployProxy(address indexed deployer, address indexed owner, address proxy)
There are 13 instances of this issue:
File: contracts/actions/automated/interfaces/IMIMOAutoRebalance.sol 4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
File: contracts/actions/interfaces/IMIMOFlashloan.sol 4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 7: import "./IMIMOProxyAction.sol"; 8: import "../../core/interfaces/IAddressProvider.sol";
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/interfaces/IMIMOFlashloan.sol
File: contracts/actions/interfaces/IMIMOSwap.sol 4: import "../../core/dex/interfaces/IDexAddressProvider.sol";
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/interfaces/IMIMOSwap.sol
File: contracts/actions/managed/interfaces/IMIMOManagedAction.sol 4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 8: import "../../../core/dex/interfaces/IDexAddressProvider.sol";
File: contracts/actions/managed/interfaces/IMIMOManagedRebalance.sol 4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
File: contracts/actions/MIMOEmptyVault.sol 6: import "./interfaces/IMIMOEmptyVault.sol";
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/MIMOEmptyVault.sol
File: contracts/actions/MIMOFlashloan.sol 10: import "../core/interfaces/IAddressProvider.sol"; 11: import "../proxy/interfaces/IMIMOProxyRegistry.sol";
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/MIMOFlashloan.sol
File: contracts/proxy/MIMOProxyRegistry.sol 7: import "../core/interfaces/IAddressProvider.sol"; 8: import "../core/interfaces/IAccessController.sol";
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxyRegistry.sol
🌟 Selected for report: Dravee
Also found by: 0x040, 0x1f8b, 0xDjango, 0xNazgul, 0xSmartContract, 0xc0ffEE, Aymen0909, Bnke0x0, Chom, CodingNameKiki, Deivitto, Fitraldys, Funen, IllIllI, JC, JohnSmith, NoamYakov, ReyAdmirado, Rolezn, TomJ, Waze, ajtra, bearonbike, bobirichman, brgltd, c3phas, durianSausage, fatherOfBlocks, gogo, ignacio, jag, joestakey, ladboy233, mics, oyc_109, rbserver, samruna, sikorico, simon135
49.1659 USDC - $49.17
++i
will cost less gas than i++
. The same change can be applied to i--
as well.This change would save up to 6 gas per instance/loop.
There are 1 instances of this issue:
File: contracts/proxy/MIMOProxy.sol 132: for (uint256 i = 0; i < targets.length; i++) {
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxy.sol
The instances below point to the second+ access of a state variable within a function. Caching of a state variable replace each Gwarmaccess (100 gas) with a much cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs, or having local caches of state variable contracts/addresses.
There are 4 instances of this issue:
File: contracts/actions/MIMOVaultActions.sol /// @audit Cache `core`. Used 2 times in `deposit` 49: collateral.safeIncreaseAllowance(address(core), amount); 50: core.deposit(address(collateral), amount);
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/MIMOVaultActions.sol
File: contracts/proxy/MIMOProxy.sol /// @audit Cache `owner`. Used 2 times in `execute` 56: if (owner != msg.sender) { 62: revert CustomErrors.EXECUTION_NOT_AUTHORIZED(owner, msg.sender, target, selector); /// @audit Cache `owner`. Used 2 times in `setPermission` 110: if (owner != msg.sender) { 111: revert CustomErrors.NOT_OWNER(owner, msg.sender); /// @audit Cache `owner`. Used 2 times in `multicall` 128: if (msg.sender != owner) { 129: revert CustomErrors.NOT_OWNER(owner, msg.sender);
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxy.sol
constant
/non-immutable
variables to zero than to let the default of zero be appliedNot overwriting the default for stack variables saves 8 gas. Storage and memory variables have larger savings
There are 1 instances of this issue:
File: contracts/proxy/MIMOProxy.sol 132: for (uint256 i = 0; i < targets.length; i++) {
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxy.sol
private
rather than public
for constants, saves gasIf needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table
There are 1 instances of this issue:
File: contracts/proxy/MIMOProxyFactory.sol 19: uint256 public constant override VERSION = 1;
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxyFactory.sol
++i
/i++
should be unchecked{++I}
/unchecked{I++}
in for
-loopsWhen an increment or any arithmetic operation is not possible to overflow it should be placed in unchecked{}
block. \This is because of the default compiler overflow and underflow safety checks since Solidity version 0.8.0. \In for-loops it saves around 30-40 gas per loop
There are 1 instances of this issue:
File: contracts/proxy/MIMOProxy.sol 132: for (uint256 i = 0; i < targets.length; i++) {
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxy.sol
calldata
instead of memory
for function parametersIf a reference type function parameter is read-only, it is cheaper in gas to use calldata instead of memory. Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory. Try to use calldata as a data location because it will avoid copies and also makes sure that the data cannot be modified.
There are 12 instances of this issue:
File: contracts/actions/automated/MIMOAutoAction.sol 93: AutomatedVault memory autoVault,
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/automated/MIMOAutoAction.sol
File: contracts/actions/automated/MIMOAutoRebalance.sol 166: AutomatedVault memory autoVault, 167: VaultState memory vaultState, 205: AutomatedVault memory autoVault, 206: VaultState memory vaultState, 237: AutomatedVault memory autoVault, 263: AutomatedVault memory autoVault,
File: contracts/actions/managed/MIMOManagedAction.sol 116: ManagedVault memory managedVault,
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/managed/MIMOManagedAction.sol
File: contracts/actions/managed/MIMOManagedRebalance.sol 143: ManagedVault memory managedVault, 180: ManagedVault memory managedVault,
File: contracts/actions/MIMOFlashloan.sol /// @audit Store `flData` in calldata. 51: function _takeFlashLoan(FlashLoanData memory flData, bytes memory params) internal { /// @audit Store `params` in calldata. 51: function _takeFlashLoan(FlashLoanData memory flData, bytes memory params) internal {
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/MIMOFlashloan.sol
x <= y
with x < y + 1
, and x >= y
with x > y - 1
In the EVM, there is no opcode for >=
or <=
. When using greater than or equal, two operations are performed: >
and =
. Using strict comparison operators hence saves gas
There are 6 instances of this issue:
File: contracts/actions/automated/MIMOAutoAction.sol 45: if (autoParams.varFee >= maxVarFee) { 97: if (swapResultValue >= rebalanceValue) {
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/automated/MIMOAutoAction.sol
File: contracts/actions/managed/MIMOManagedAction.sol 120: if (swapResultValue >= rebalanceValue) {
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/managed/MIMOManagedAction.sol
File: contracts/actions/MIMOEmptyVault.sol 96: require(flashloanRepayAmount <= vaultCollateral.balanceOf(address(this)), Errors.CANNOT_REPAY_FLASHLOAN);
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/MIMOEmptyVault.sol
File: contracts/actions/MIMOLeverage.sol 130: require(collateralBalanceAfter >= flashloanRepayAmount, Errors.CANNOT_REPAY_FLASHLOAN);
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/MIMOLeverage.sol
File: contracts/actions/MIMORebalance.sol 130: a.vaultsData().vaultCollateralBalance(rbData.vaultId) >= flashloanRepayAmount,
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/actions/MIMORebalance.sol
immutable
& constant
for state variables that do not change their valueThere are 1 instances of this issue:
File: contracts/proxy/MIMOProxyRegistry.sol 16: IMIMOProxyFactory public override factory;
https://github.com/code-423n4/2022-08-mimo/tree/main/contracts/proxy/MIMOProxyRegistry.sol