Mimo August 2022 contest - IllIllI'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: 14/69

Findings: 2

Award: $889.68

🌟 Selected for report: 1

šŸš€ Solo Findings: 0

Summary

Low Risk Issues

IssueInstances
[L‑01]Use of msg.value in functions available to batches1
[L‑02]Unused/empty receive()/fallback() function1
[L‑03]Missing checks for address(0x0) when assigning values to address state variables2

Total: 4 instances over 3 issues

Non-critical Issues

IssueInstances
[N‑01]Missing initializer modifier on constructor1
[N‑02]override function arguments that are unused should have the variable name removed or commented out to avoid compiler warnings5
[N‑03]constants should be defined rather than using magic numbers2
[N‑04]Use a more recent version of solidity11
[N‑05]Constant redefined elsewhere7
[N‑06]Lines are too long1
[N‑07]Typos12
[N‑08]File is missing NatSpec11
[N‑09]NatSpec is incomplete23
[N‑10]Event is missing indexed fields5
[N‑11]Not using the named return variables anywhere in the function is confusing3

Total: 81 instances over 11 issues

Low Risk Issues

[L‑01] Use of msg.value in functions available to batches

The contract extends BoringBatchable, which warns to ensure msg.value isn't able to be used in a batchable call. MIMOVaultActions.depositETH() and MIMOVaultActions.depositETHAndBorrow() both use msg.value but aren't currently exploitable due to the fact that it has to be executed by the owner or an envoy, needs to be allow-listed, and even then the functions would require latent funds.

There is 1 instance of this issue:

File: /contracts/proxy/MIMOProxy.sol

54:    function execute(address target, bytes calldata data) public payable override returns (bytes memory response) {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L54

[L‑02] Unused/empty receive()/fallback() function

If the intention is for the Ether to be used, the function should call another function, otherwise it should revert (e.g. require(msg.sender == address(weth)))

There is 1 instance of this issue:

File: contracts/proxy/MIMOProxy.sol

38:     receive() external payable {}

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L38

[L‑03] Missing checks for address(0x0) when assigning values to address state variables

There are 2 instances of this issue:

File: contracts/proxy/MIMOProxyFactory.sol

27:       mimoProxyBase = _mimoProxyBase;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxyFactory.sol#L27

File: contracts/proxy/MIMOProxy.sol

122:      owner = newOwner;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L122

Non-critical Issues

[N‑01] Missing initializer modifier on constructor

OpenZeppelin recommends that the initializer modifier be applied to constructors in order to avoid potential griefs, social engineering, or exploits. Ensure that the modifier is applied to the implementation contract. If the default constructor is currently being used, it should be changed to be an explicit one with the modifier applied.

There is 1 instance of this issue:

File: contracts/proxy/MIMOProxy.sol

12:   contract MIMOProxy is IMIMOProxy, Initializable, BoringBatchable {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L12

[N‑02] override function arguments that are unused should have the variable name removed or commented out to avoid compiler warnings

There are 5 instances of this issue:

File: contracts/actions/MIMOFlashloan.sol

39:       address[] calldata assets,

40:       uint256[] calldata amounts,

41:       uint256[] calldata premiums,

42:       address initiator,

43:       bytes calldata params

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOFlashloan.sol#L39

[N‑03] constants should be defined rather than using magic numbers

Even assembly can benefit from using readable constants instead of hex/numeric literals

There are 2 instances of this issue:

File: contracts/actions/automated/MIMOAutoRebalance.sol

/// @audit 1e15
180:      uint256 targetRatio = autoVault.targetRatio + 1e15; // add 0.1% to account for rounding

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/MIMOAutoRebalance.sol#L180

File: contracts/proxy/MIMOProxy.sol

/// @audit 5_000
30:       minGasReserve = 5_000;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L30

[N‑04] Use a more recent version of solidity

Use a solidity version of at least 0.8.13 to get the ability to use using for with a list of free functions

There are 11 instances of this issue:

File: contracts/actions/automated/MIMOAutoAction.sol

2:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/MIMOAutoAction.sol#L2

File: contracts/actions/automated/MIMOAutoRebalance.sol

2:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/MIMOAutoRebalance.sol#L2

File: contracts/actions/managed/MIMOManagedAction.sol

2:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedAction.sol#L2

File: contracts/actions/managed/MIMOManagedRebalance.sol

2:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedRebalance.sol#L2

File: contracts/actions/MIMOEmptyVault.sol

2:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOEmptyVault.sol#L2

File: contracts/actions/MIMOFlashloan.sol

2:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOFlashloan.sol#L2

File: contracts/actions/MIMOLeverage.sol

2:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOLeverage.sol#L2

File: contracts/actions/MIMORebalance.sol

2:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMORebalance.sol#L2

File: contracts/actions/MIMOSwap.sol

2:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOSwap.sol#L2

File: contracts/actions/MIMOVaultActions.sol

3:    pragma solidity 0.8.10;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOVaultActions.sol#L3

File: contracts/proxy/MIMOProxyFactory.sol

2:    pragma solidity >=0.8.4;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxyFactory.sol#L2

[N‑05] Constant redefined elsewhere

Consider defining in only one contract so that values cannot become out of sync when only one location is updated. A cheap way to store constants in a single location is to create an internal constant in a library. If the variable is a local cache of another contract's value, consider making the cache variable internal or private, which will require external users to query the contract with the source of truth, so that callers don't get out of sync.

There are 7 instances of this issue:

File: contracts/actions/managed/MIMOManagedAction.sol

/// @audit seen in contracts/actions/automated/MIMOAutoAction.sol 
12:     IAddressProvider public immutable a;

/// @audit seen in contracts/actions/automated/MIMOAutoAction.sol 
13:     IMIMOProxyRegistry public immutable proxyRegistry;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedAction.sol#L12

File: contracts/actions/managed/MIMOManagedRebalance.sol

/// @audit seen in contracts/actions/automated/MIMOAutoRebalance.sol 
20:     address public immutable mimoRebalance;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedRebalance.sol#L20

File: contracts/actions/MIMOEmptyVault.sol

/// @audit seen in contracts/actions/managed/MIMOManagedAction.sol 
17:     IMIMOProxyRegistry public immutable proxyRegistry;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOEmptyVault.sol#L17

File: contracts/actions/MIMOLeverage.sol

/// @audit seen in contracts/actions/MIMOEmptyVault.sol 
17:     IMIMOProxyRegistry public immutable proxyRegistry;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOLeverage.sol#L17

File: contracts/actions/MIMORebalance.sol

/// @audit seen in contracts/actions/MIMOLeverage.sol 
17:     IMIMOProxyRegistry public immutable proxyRegistry;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMORebalance.sol#L17

File: contracts/actions/MIMOSwap.sol

/// @audit seen in contracts/actions/managed/MIMOManagedAction.sol 
19:     IAddressProvider public immutable a;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOSwap.sol#L19

[N‑06] Lines are too long

Usually lines in source code are limited to 80 characters. Today's screens are much larger so it's reasonable to stretch this in some cases. Since the files will most likely reside in GitHub, and GitHub starts using a scroll bar in all cases when the length is over 164 characters, the lines below should be split when they reach that length

There is 1 instance of this issue:

File: contracts/actions/managed/MIMOManagedRebalance.sol

14:   @notice This contract only serves to change the access control and enforce the `managedRebalance` configuration; the actual rebalance logic is done through the `MIMORebalance` contract through a `delegateCall` from a `MIMOProxy` clone

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedRebalance.sol#L14

[N‑07] Typos

There are 12 instances of this issue:

File: contracts/actions/automated/MIMOAutoRebalance.sol

/// @audit aggegator
52:       @param swapData SwapData struct containing aggegator swap parameters

/// @audit reblanced
84:       @param assets Address array with one element corresponding to the address of the reblanced asset

/// @audit rebalnce
157:      @notice Helper function calculating the amount to rebalance from vault A and to mint from vault B with rebalnce formula

/// @audit og
159:      @param vaultState VaultState struct og the vault to rebalance

/// @audit allowedVaration
254:      @dev Checks that change in global vault value (vault A + B) is below allowedVaration and vault A ratio equal or above targetRatio

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/MIMOAutoRebalance.sol#L52

File: contracts/actions/managed/MIMOManagedRebalance.sol

/// @audit aggegator
48:       @param swapData SwapData struct containing aggegator swap parameters

/// @audit reblanced
85:       @param assets Address array with one element corresponding to the address of the reblanced asset

/// @audit allowedVaration
170:      @dev Checks that change in global vault value (vault A + B) is below allowedVaration and vault A & B ratios are at least targetRatios

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedRebalance.sol#L48

File: contracts/actions/MIMOLeverage.sol

/// @audit FlashloanDat
/// @audit struc
42:       @param _calldata Bytes containing depositAmount, stablex swapAmount, struct FlashloanDat data and struc SwapData

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOLeverage.sol#L42

File: contracts/actions/MIMORebalance.sol

/// @audit reblanced
57:       @param assets Address array with one element corresponding to the address of the reblanced asset

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMORebalance.sol#L57

File: contracts/proxy/interfaces/IMIMOProxyFactory.sol

/// @audit PRBProxy
19:     /// @notice The release version of PRBProxy.

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/interfaces/IMIMOProxyFactory.sol#L19

[N‑08] File is missing NatSpec

There are 11 instances of this issue:

File: contracts/actions/automated/interfaces/IMIMOAutoAction.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/interfaces/IMIMOAutoAction.sol

File: contracts/actions/automated/interfaces/IMIMOAutoRebalance.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/interfaces/IMIMOAutoRebalance.sol

File: contracts/actions/interfaces/IMIMOEmptyVault.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOEmptyVault.sol

File: contracts/actions/interfaces/IMIMOFlashloan.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOFlashloan.sol

File: contracts/actions/interfaces/IMIMOLeverage.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOLeverage.sol

File: contracts/actions/interfaces/IMIMOProxyAction.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOProxyAction.sol

File: contracts/actions/interfaces/IMIMORebalance.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMORebalance.sol

File: contracts/actions/interfaces/IMIMOSwap.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOSwap.sol

File: contracts/actions/interfaces/IMIMOVaultActions.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOVaultActions.sol

File: contracts/actions/managed/interfaces/IMIMOManagedAction.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/interfaces/IMIMOManagedAction.sol

File: contracts/actions/managed/interfaces/IMIMOManagedRebalance.sol

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/interfaces/IMIMOManagedRebalance.sol

[N‑09] NatSpec is incomplete

There are 23 instances of this issue:

File: contracts/actions/automated/MIMOAutoAction.sol

/// @audit Missing: '@param vaultId'
54      /**
55        @return AutomatedVault struct of a specific vault id
56       */
57:     function getAutomatedVault(uint256 vaultId) external view override returns (AutomatedVault memory) {

/// @audit Missing: '@param vaultId'
61      /**
62        @return Timestamp of the last performed operation
63       */
64:     function getOperationTracker(uint256 vaultId) external view override returns (uint256) {

/// @audit Missing: '@param autoVault'
/// @audit Missing: '@param rebalanceValue'
/// @audit Missing: '@param swapResultValue'
88      /**
89        @notice Helper function determining if a vault value variation is within vault's management parameters
90        @return True if value change is below allowedVariation and false if it is above
91       */
92      function _isVaultVariationAllowed(
93        AutomatedVault memory autoVault,
94        uint256 rebalanceValue,
95        uint256 swapResultValue
96:     ) internal pure returns (bool) {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/MIMOAutoAction.sol#L54-L57

File: contracts/actions/automated/MIMOAutoRebalance.sol

/// @audit Missing: '@return'
88        @param params Bytes sent by this contract containing MIMOProxy owner, RebalanceData struct and SwapData struct
89       */
90      function executeOperation(
91        address[] calldata assets,
92        uint256[] calldata amounts,
93        uint256[] calldata premiums,
94        address initiator,
95        bytes calldata params
96:     ) external override returns (bool) {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/MIMOAutoRebalance.sol#L88-L96

File: contracts/actions/managed/MIMOManagedAction.sol

/// @audit Missing: '@param vaultId'
67      /**
68        @return ManagedVault struct of a specific vault id
69       */
70:     function getManagedVault(uint256 vaultId) external view override returns (ManagedVault memory) {

/// @audit Missing: '@param vaultId'
74      /**
75        @return Timestamp of the last performed operation
76       */
77:     function getOperationTracker(uint256 vaultId) external view override returns (uint256) {

/// @audit Missing: '@param manager'
81      /**
82        @return Bool value indicating if an address is allowed to manage user vaults or not
83       */
84:     function getManager(address manager) external view override returns (bool) {

/// @audit Missing: '@param vaultId'
88      /**
89        @notice Helper function calculating LTV ratio
90        @return Vault collateral value / vault debt
91       */
92:     function _getVaultRatio(uint256 vaultId) internal view returns (uint256) {

/// @audit Missing: '@param managedVault'
/// @audit Missing: '@param rebalanceValue'
/// @audit Missing: '@param swapResultValue'
111     /**
112       @notice Helper function determining if a vault value variation is within vault's management parameters
113       @return True if value change is below allowedVariation and false if it is above
114      */
115     function _isVaultVariationAllowed(
116       ManagedVault memory managedVault,
117       uint256 rebalanceValue,
118       uint256 swapResultValue
119:    ) internal pure returns (bool) {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedAction.sol#L67-L70

File: contracts/actions/managed/MIMOManagedRebalance.sol

/// @audit Missing: '@return'
89        @param params Bytes sent by this contract containing MIMOProxy owner, RebalanceData struct and SwapData struct
90       */
91      function executeOperation(
92        address[] calldata assets,
93        uint256[] calldata amounts,
94        uint256[] calldata premiums,
95        address initiator,
96        bytes calldata params
97:     ) external override returns (bool) {

/// @audit Missing: '@param rebalanceAmount'
135     /**
136       @notice Helper function performing pre rebalance operation sanity checks
137       @dev Checks that vault is managed, that rebalance was called by manager, and maximum daily operation was not reached 
138       @param managedVault ManagedVault struct of the vault to rebalance
139       @param rbData RebalanceData struct of the vault to rebalance
140       @param vaultsData Cached VaultsDataProvider interface for gas saving
141      */
142     function _preRebalanceChecks(
143       ManagedVault memory managedVault,
144       IMIMORebalance.RebalanceData calldata rbData,
145       IVaultsDataProvider vaultsData,
146:      uint256 rebalanceAmount

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedRebalance.sol#L89-L97

File: contracts/actions/MIMOEmptyVault.sol

/// @audit Missing: '@return'
61        @param params Bytes sent by this contract containing MIMOProxy owner, target vault id, SwapData struct
62       */
63      function executeOperation(
64        address[] calldata assets,
65        uint256[] calldata amounts,
66        uint256[] calldata premiums,
67        address initiator,
68        bytes calldata params
69:     ) external override returns (bool) {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOEmptyVault.sol#L61-L69

File: contracts/actions/MIMOFlashloan.sol

/// @audit Missing: '@return'
36        @param params Bytes sent in the _takeFlashLoan calls that encode any additional needed information to complete the transaction 
37       */
38      function executeOperation(
39        address[] calldata assets,
40        uint256[] calldata amounts,
41        uint256[] calldata premiums,
42        address initiator,
43        bytes calldata params
44:     ) external virtual override returns (bool) {}

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOFlashloan.sol#L36-L44

File: contracts/actions/MIMOLeverage.sol

/// @audit Missing: '@return'
66        @param params Bytes sent by this contract containing MIMOProxy owner, stablex swap amount and swap data
67       */
68      function executeOperation(
69        address[] calldata assets,
70        uint256[] calldata amounts,
71        uint256[] calldata premiums,
72        address initiator,
73        bytes calldata params
74:     ) external override returns (bool) {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOLeverage.sol#L66-L74

File: contracts/actions/MIMORebalance.sol

/// @audit Missing: '@return'
61        @param params Bytes sent by this contract containing MIMOProxy owner, RebalanceData struct and SwapData struct
62       */
63      function executeOperation(
64        address[] calldata assets,
65        uint256[] calldata amounts,
66        uint256[] calldata premiums,
67        address initiator,
68        bytes calldata params
69:     ) external override returns (bool) {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMORebalance.sol#L61-L69

File: contracts/proxy/interfaces/IMIMOProxyFactory.sol

/// @audit Missing: '@return'
15      /// @notice Mapping to track all deployed proxies.
16      /// @param proxy The address of the proxy to make the check for.
17:     function isProxy(address proxy) external view returns (bool result);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/interfaces/IMIMOProxyFactory.sol#L15-L17

File: contracts/proxy/interfaces/IMIMOProxyRegistry.sol

/// @audit Missing: '@return'
16      /// @notice Gets the current proxy of the given owner.
17      /// @param owner The address of the owner of the current proxy.
18:     function getCurrentProxy(address owner) external view returns (IMIMOProxy proxy);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/interfaces/IMIMOProxyRegistry.sol#L16-L18

File: contracts/proxy/interfaces/IMIMOProxy.sol

/// @audit Missing: '@return'
22      /// @param selector The selector of the method of the target contract called by the envoy
23      /// contract and function selector.
24      function getPermission(
25        address envoy,
26        address target,
27        bytes4 selector
28:     ) external view returns (bool);

/// @audit Missing: '@return'
77      /// @param targets An array of contract addresses to call 
78      /// @param data The bytes for each batched function call 
79:     function multicall(address[] calldata targets, bytes[] calldata data) external returns (bytes[] memory);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/interfaces/IMIMOProxy.sol#L22-L28

[N‑10] Event is missing indexed fields

Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (threefields). Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed.

There are 5 instances of this issue:

File: contracts/actions/automated/interfaces/IMIMOAutoAction.sol

25:     event AutomationSet(uint256 vaultId, AutomatedVault autoVault);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/interfaces/IMIMOAutoAction.sol#L25

File: contracts/actions/managed/interfaces/IMIMOManagedAction.sol

22:     event ManagerSet(address manager, bool isManager);

23:     event ManagementSet(uint256 vaultId, ManagedVault managedVault);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/interfaces/IMIMOManagedAction.sol#L22

File: contracts/proxy/interfaces/IMIMOProxyFactory.sol

11:     event DeployProxy(address indexed deployer, address indexed owner, address proxy);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/interfaces/IMIMOProxyFactory.sol#L11

File: contracts/proxy/interfaces/IMIMOProxy.sol

9:      event Execute(address indexed target, bytes data, bytes response);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/interfaces/IMIMOProxy.sol#L9

[N‑11] Not using the named return variables anywhere in the function is confusing

Consider changing the variable to be an unnamed one

There are 3 instances of this issue:

File: contracts/actions/automated/MIMOAutoRebalance.sol

/// @audit rebalanceAmount
/// @audit mintAmount
/// @audit autoFee
142     function getAmounts(uint256 vaultId, address toCollateral)
143       external
144       view
145       override
146       returns (
147         uint256 rebalanceAmount,
148         uint256 mintAmount,
149:        uint256 autoFee

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/MIMOAutoRebalance.sol#L142-L149

#0 - m19

2022-08-18T08:10:21Z

This is an outstanding QA report

#1 - liveactionllama

2022-09-06T16:50:16Z

Per @gzeoneth (judge), they agree with the severities outlined above by the warden.

Awards

229.1011 USDC - $229.10

Labels

bug
G (Gas Optimization)
old-submission-method

External Links

Summary

Gas Optimizations

IssueInstances
[G‑01]Multiple address/ID mappings can be combined into a single mapping of an address/ID to a struct, where appropriate2
[G‑02]State variables only set in the constructor should be declared immutable2
[G‑03]State variables should be cached in stack variables rather than re-reading them from storage5
[G‑04]internal functions only called once can be inlined to save gas5
[G‑05]Add unchecked {} for subtractions where the operands cannot underflow because of a previous require() or if-statement4
[G‑06]Optimize names to save gas15
[G‑07]Using bools for storage incurs overhead3
[G‑08]++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too)1
[G‑09]Empty blocks should be removed or emit something1
[G‑10]Use custom errors rather than revert()/require() strings to save gas5

Total: 43 instances over 10 issues

Gas Optimizations

[G‑01] Multiple address/ID mappings can be combined into a single mapping of an address/ID to a struct, where appropriate

Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot. Finally, if both fields are accessed in the same function, can save ~42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operations.

There are 2 instances of this issue:

File: contracts/actions/automated/MIMOAutoAction.sol

15      mapping(uint256 => AutomatedVault) internal _automatedVaults;
16:     mapping(uint256 => uint256) internal _operationTracker;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/MIMOAutoAction.sol#L15-L16

File: contracts/actions/managed/MIMOManagedAction.sol

15      mapping(uint256 => ManagedVault) internal _managedVaults;
16:     mapping(uint256 => uint256) internal _operationTracker;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedAction.sol#L15-L16

[G‑02] State variables only set in the constructor should be declared immutable

Avoids a Gsset (20000 gas) in the constructor, and replaces the first access in each transaction (Gcoldsload - 2100 gas) and each access thereafter (Gwarmacces - 100 gas) with a PUSH32 (3 gas).

There are 2 instances of this issue:

File: contracts/proxy/MIMOProxyRegistry.sol

/// @audit factory (constructor)
27:       factory = factory_;

/// @audit factory (access)
54:       proxy = factory.deployFor(owner);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxyRegistry.sol#L27

[G‑03] State variables should be cached in stack variables rather than re-reading them from storage

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 5 instances of this issue:

File: contracts/proxy/MIMOProxy.sol

/// @audit owner on line 56
62:           revert CustomErrors.EXECUTION_NOT_AUTHORIZED(owner, msg.sender, target, selector);

/// @audit owner on line 62
72:       address owner_ = owner;

/// @audit owner on line 82
83:         revert CustomErrors.OWNER_CHANGED(owner_, owner);

/// @audit owner on line 110
111:        revert CustomErrors.NOT_OWNER(owner, msg.sender);

/// @audit owner on line 128
129:        revert CustomErrors.NOT_OWNER(owner, msg.sender);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L62

[G‑04] internal functions only called once can be inlined to save gas

Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.

There are 5 instances of this issue:

File: contracts/actions/automated/MIMOAutoRebalance.sol

204     function _getRebalanceParams(
205       AutomatedVault memory autoVault,
206       VaultState memory vaultState,
207       IERC20 toCollateral,
208       uint256 vaultId
209     )
210       internal
211       view
212       returns (
213         IMIMORebalance.RebalanceData memory rbData,
214         FlashLoanData memory flData,
215:        uint256 autoFee

236     function _preRebalanceChecks(
237       AutomatedVault memory autoVault,
238       uint256 vaultId,
239:      uint256 vaultARatio

262     function _postRebalanceChecks(
263       AutomatedVault memory autoVault,
264       uint256 rebalanceAmount,
265       uint256 vaultBBalanceBefore,
266       uint256 vaultId,
267       address vaultOwner,
268:      IVaultsDataProvider vaultsData

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/MIMOAutoRebalance.sol#L204-L215

File: contracts/actions/managed/MIMOManagedRebalance.sol

142     function _preRebalanceChecks(
143       ManagedVault memory managedVault,
144       IMIMORebalance.RebalanceData calldata rbData,
145       IVaultsDataProvider vaultsData,
146:      uint256 rebalanceAmount

179     function _postRebalanceChecks(
180       ManagedVault memory managedVault,
181       uint256 rebalanceAmount,
182       uint256 vaultBBalanceBefore,
183       uint256 vaultId,
184       address vaultOwner,
185       address toCollateral,
186:      IVaultsDataProvider vaultsData

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedRebalance.sol#L142-L146

[G‑05] Add unchecked {} for subtractions where the operands cannot underflow because of a previous require() or if-statement

require(a <= b); x = b - a => require(a <= b); unchecked { x = b - a }

There are 4 instances of this issue:

File: contracts/actions/MIMOLeverage.sol

/// @audit require() on line 130
133:        token.safeIncreaseAllowance(address(core), collateralBalanceAfter - flashloanRepayAmount);

/// @audit require() on line 130
134:        core.deposit(address(token), collateralBalanceAfter - flashloanRepayAmount);

/// @audit if-condition on line 132
133:        token.safeIncreaseAllowance(address(core), collateralBalanceAfter - flashloanRepayAmount);

/// @audit if-condition on line 132
134:        core.deposit(address(token), collateralBalanceAfter - flashloanRepayAmount);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOLeverage.sol#L133

[G‑06] Optimize names to save gas

public/external function names and public member variable names can be optimized to save gas. See this link for an example of how it works. Below are the interfaces/abstract contracts that can be optimized so that the most frequently-called functions use the least amount of gas possible during method lookup. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted

There are 15 instances of this issue:

File: contracts/actions/automated/interfaces/IMIMOAutoAction.sol

/// @audit setAutomation(), a(), proxyRegistry(), getAutomatedVault(), getOperationTracker()
7:    interface IMIMOAutoAction {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/interfaces/IMIMOAutoAction.sol#L7

File: contracts/actions/automated/interfaces/IMIMOAutoRebalance.sol

/// @audit rebalance(), getAmounts()
9:    interface IMIMOAutoRebalance is IMIMOAutoAction {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/automated/interfaces/IMIMOAutoRebalance.sol#L9

File: contracts/actions/interfaces/IMIMOEmptyVault.sol

/// @audit emptyVaultOperation()
7:    interface IMIMOEmtpyVault is IMIMOProxyAction, IMIMOSwap {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOEmptyVault.sol#L7

File: contracts/actions/interfaces/IMIMOFlashloan.sol

/// @audit executeOperation(), lendingPool()
10:   interface IMIMOFlashloan {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOFlashloan.sol#L10

File: contracts/actions/interfaces/IMIMOLeverage.sol

/// @audit leverageOperation()
9:    interface IMIMOLeverage is IMIMOSwap, IMIMOProxyAction {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOLeverage.sol#L9

File: contracts/actions/interfaces/IMIMOProxyAction.sol

/// @audit executeAction()
4:    interface IMIMOProxyAction {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOProxyAction.sol#L4

File: contracts/actions/interfaces/IMIMORebalance.sol

/// @audit rebalanceOperation()
7:    interface IMIMORebalance is IMIMOProxyAction, IMIMOSwap {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMORebalance.sol#L7

File: contracts/actions/interfaces/IMIMOVaultActions.sol

/// @audit deposit(), depositETH(), depositAndBorrow(), depositETHAndBorrow(), withdraw(), withdrawETH(), borrow(), core(), vaultsData(), stablex()
8:    interface IMIMOVaultActions {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/interfaces/IMIMOVaultActions.sol#L8

File: contracts/actions/managed/interfaces/IMIMOManagedAction.sol

/// @audit setManagement(), setManager(), a(), proxyRegistry(), getManagedVault(), getOperationTracker(), getManager()
11:   interface IMIMOManagedAction {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/interfaces/IMIMOManagedAction.sol#L11

File: contracts/actions/managed/interfaces/IMIMOManagedRebalance.sol

/// @audit rebalance()
11:   interface IMIMOManagedRebalance is IMIMOManagedAction {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/interfaces/IMIMOManagedRebalance.sol#L11

File: contracts/actions/MIMOEmptyVault.sol

/// @audit emptyVaultOperation()
14:   contract MIMOEmptyVault is MIMOSwap, MIMOFlashloan, IMIMOEmtpyVault {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOEmptyVault.sol#L14

File: contracts/proxy/interfaces/IMIMOProxyFactory.sol

/// @audit isProxy(), VERSION(), deploy(), deployFor()
8:    interface IMIMOProxyFactory {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/interfaces/IMIMOProxyFactory.sol#L8

File: contracts/proxy/interfaces/IMIMOProxyRegistry.sol

/// @audit factory(), getCurrentProxy(), deploy(), deployFor()
10:   interface IMIMOProxyRegistry {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/interfaces/IMIMOProxyRegistry.sol#L10

File: contracts/proxy/interfaces/IMIMOProxy.sol

/// @audit initialize(), getPermission(), minGasReserve(), execute(), setPermission(), multicall()
6:    interface IMIMOProxy {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/interfaces/IMIMOProxy.sol#L6

File: contracts/proxy/MIMOProxy.sol

/// @audit initialize()
12:   contract MIMOProxy is IMIMOProxy, Initializable, BoringBatchable {

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L12

[G‑07] Using bools for storage incurs overhead

    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because 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. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/58f635312aa21f947cae5f8578638a85aa2519f5/contracts/security/ReentrancyGuard.sol#L23-L27 Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas) for the extra SLOAD, and to avoid Gsset (20000 gas) when changing from false to true, after having been true in the past

There are 3 instances of this issue:

File: contracts/actions/managed/MIMOManagedAction.sol

17:     mapping(address => bool) internal _managers;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/managed/MIMOManagedAction.sol#L17

File: contracts/proxy/MIMOProxyFactory.sol

24:     mapping(address => bool) internal _proxies;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxyFactory.sol#L24

File: contracts/proxy/MIMOProxy.sol

24:     mapping(address => mapping(address => mapping(bytes4 => bool))) internal _permissions;

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L24

[G‑08] ++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too)

Saves 5 gas per loop

There is 1 instance 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/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L132

[G‑09] Empty blocks should be removed or emit something

The code should be refactored such that they no longer exist, or the block should do something useful, such as emitting an event or reverting. If the contract is meant to be extended, the contract should be abstract and the function signatures be added without any default implementation. If the block is an empty if-statement block to avoid doing subsequent checks in the else-if/else conditions, the else-if/else conditions should be nested under the negation of the if-statement, because they involve different classes of checks, which may lead to the introduction of errors when the code is later modified (if(x){}else if(y){...}else{...} => if(!x){if(y){...}else{...}}). Empty receive()/fallback() payable functions that are not used, can be removed to save deployment gas.

There is 1 instance of this issue:

File: contracts/proxy/MIMOProxy.sol

38:     receive() external payable {}

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L38

[G‑10] Use custom errors rather than revert()/require() strings to save gas

Custom errors are available from solidity version 0.8.4. Custom errors save ~50 gas each time they're hit by avoiding having to allocate and store the revert string. Not defining the strings also save deployment gas

There are 5 instances of this issue:

File: contracts/actions/MIMOEmptyVault.sol

96:       require(flashloanRepayAmount <= vaultCollateral.balanceOf(address(this)), Errors.CANNOT_REPAY_FLASHLOAN);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOEmptyVault.sol#L96

File: contracts/actions/MIMOLeverage.sol

130:      require(collateralBalanceAfter >= flashloanRepayAmount, Errors.CANNOT_REPAY_FLASHLOAN);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOLeverage.sol#L130

File: contracts/actions/MIMORebalance.sol

129       require(
130         a.vaultsData().vaultCollateralBalance(rbData.vaultId) >= flashloanRepayAmount,
131         Errors.CANNOT_REPAY_FLASHLOAN
132:      );

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMORebalance.sol#L129-L132

File: contracts/actions/MIMOSwap.sol

47:       require(proxy != address(0), Errors.INVALID_AGGREGATOR);

48:       require(router != address(0), Errors.INVALID_AGGREGATOR);

https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/actions/MIMOSwap.sol#L47

#0 - m19

2022-08-18T07:57:57Z

We found this gas report really outstanding

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