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

Findings: 2

Award: $144.58

๐ŸŒŸ Selected for report: 0

๐Ÿš€ Solo Findings: 0

Summary

Low

  1. L-1. A floating pragma is set.

Low

L-1. A floating pragma is set.

Description

The current pragma Solidity directive is ">=0.8.4". It is recommended to specify a fixed compiler version to ensure that the bytecode produced does not vary between builds. This is especially important if you rely on bytecode-level verification of the code.

Mitigation

Lock the pragma version

Lines in the code

MIMOProxy.sol#L2 MIMOProxyFactory.sol#L2 MIMOProxyRegistry.sol#L2 IMIMOProxy.sol#L2 IMIMOProxyFactory.sol#L2 IMIMOProxyRegistry.sol#L2

Index

  1. Post-increment/decrement cost more gas then pre-increment/decrement
  2. Array length should not be looked up in every loop of a for-loop
  3. Operatos <= or >= cost more gas than operators < or >
  4. != 0 is cheaper than > 0
  5. Use custom errors rather than REVERT()/REQUIRE() strings to save deployment gas
  6. Use a more recent version of solidity
  7. Using bools for storage incurs overhead
  8. ABI.ENCODE() is less efficient than ABI.ENCODEPACKED()
  9. Unchecked arithmetic when it is not possible for them to overflow
  10. Initialize variables with default values are not needed
  11. Optimize function return
  12. Move variable declaration after conditions to save gas
  13. Internal functions not called by the contrat should be removed to save deplyment gas

Details

1. Post-increment/decrement cost more gas then pre-increment/decrement

Description

++var (--var) cost less gas than var++ (var--)

Lines in the code

MIMOProxy.sol#L132

2. Array length should not be looked up in every loop of a for-loop

Description

Storage array length checks incur an extra Gwarmaccess (100 gas) per loop. Store the array length in a variable and use it in the for loop helps to save gas

Lines in the code

MIMOProxy.sol#L132

3. Operatos <= or >= cost more gas than operators < or >

Description

Change all <= / >= operators for < / > and remember to increse / decrese in consecuence to maintain the logic (example, a <= b for a < b + 1)

Lines in the code

MIMOEmptyVault.sol#L96 MIMOLeverage.sol#L130 MIMORebalance.sol#L130 MIMOAutoAction.sol#L45 MIMOAutoAction.sol#L97 MIMOManagedAction.sol#L120

4. != 0 is cheaper than > 0

Description

Replace all > 0 for != 0 to save gas.

Lines in the code

MIMOLeverage.sol#L50 MIMORebalance.sol#L135 MIMOSwap.sol#L56 MIMOProxy.sol#L92 MIMOProxy.sol#L135

5. Use custom errors rather than REVERT()/REQUIRE() strings to save deployment gas

Description

Custom errors are available from solidity version 0.8.4. The instances below match or exceed that version

Lines in the code

MIMOEmptyVault.sol#L96 MIMOLeverage.sol#L130 MIMORebalance.sol#L129 MIMOSwap.sol#L47 MIMOSwap.sol#L48 MIMOSwap.sol#L55 MIMOSwap.sol#L59 MIMOSwap.sol#L62

6. Use a more recent version of solidity

Description

Some contracts are using a different solidity version (0.8.4). Update to compile with the same version (0.8.10) what allow to have external calls skip contract existence checks if the external call has a return value

Lines in the code

IMIMOProxy.sol#L2 IMIMOProxyFactory.sol#L2 IMIMOProxyRegistry.sol#L2 MIMOProxy.sol#L2 MIMOProxyFactory.sol#L2 MIMOProxyRegistry.sol#L2

7. Using bools for storage incurs overhead

Description

Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas), and to avoid Gsset (20000 gas) when changing from 'false' to 'true', after having been 'true' in the past.

Lines in the code

IMIMOAutoAction.sol#L9 IMIMOManagedAction.sol#L13 MIMOProxy.sol#L78

8. ABI.ENCODE() is less efficient than ABI.ENCODEPACKED()

Lines in the code

MIMOEmptyVault.sol#L49 MIMOLeverage.sol#L54 MIMORebalance.sol#L49 MIMOAutoRebalance.sol#L73

9. Unchecked arithmetic when it is not possible for them to overflow

Description

The default โ€œcheckedโ€ behavior costs more gas when adding/diving/multiplying, because under-the-hood those checks are implemented as a series of opcodes that, prior to performing the actual arithmetic, check for under/overflow and revert if it is detected. if it can statically be determined there is no possible way for your arithmetic to under/overflow (such as a condition in an if statement), surrounding the arithmetic in an unchecked block will save gas.

For all for-loops in the code it is possible to change as the following example.

for (uint256 i;i < X;){ -- code -- unchecked { ++i; } }

Lines in the code

MIMOProxy.sol#L132

10. Initialize variables with default values are not needed

Description

If a variable is not set/initialized, it is assumed to have the default value (0 for uint, false for bool, address(0) for address,...). Explicitly initializing it with its default value is an anti-pattern and wastes gas.

Lines in the code

MIMOProxy.sol#L132

11. Optimize function return

Description

It's possible to refactor the return to save gas like the following sentences. Symbol - to remove the sentence Symbol + to add the sentence

MIMOManagedAction._isVaultVariationAllowed
  function _isVaultVariationAllowed( 126
    ManagedVault memory managedVault,
    uint256 rebalanceValue,
    uint256 swapResultValue
  ) internal pure returns (bool) {
    - if (swapResultValue >= rebalanceValue) {
    -   return true;
    - }
	
    - uint256 vaultVariation = (rebalanceValue - swapResultValue).wadDiv(rebalanceValue);
	
    - if (vaultVariation > managedVault.allowedVariation) {
    -   return false;
    - }
	
    - return true;
	+ return (swapResultValue >= rebalanceValue) || !(((rebalanceValue - swapResultValue).wadDiv(rebalanceValue)) > managedVault.allowedVariation);
  }
MIMOAutoAction._isVaultVariationAllowed
  function _isVaultVariationAllowed(
    AutomatedVault memory autoVault,
    uint256 rebalanceValue,
    uint256 swapResultValue
  ) internal pure returns (bool) {
    - if (swapResultValue >= rebalanceValue) {
    -   return true;
    - }

    - uint256 vaultVariation = (rebalanceValue - swapResultValue).wadDiv(rebalanceValue);

    - if (vaultVariation > autoVault.allowedVariation) {
    -   return false;
    - }

    - return true;
	+ return (swapResultValue >= rebalanceValue) || (!(((rebalanceValue - swapResultValue).wadDiv(rebalanceValue)) > autoVault.allowedVariation));
  }

Lines in the code

MIMOManagedAction.sol#L115 MIMOAutoAction.sol#L92

12. Move variable declaration after conditions to save gas

Description

In the following case it's possible to move the collateralValue variable after the IF sentence to save gas when the if condition is true.

  function _getVaultRatio(uint256 vaultId) internal view returns (uint256) {
    IAddressProvider _a = a;
    IVaultsDataProvider vaultsData = _a.vaultsData();
    IPriceFeed priceFeed = _a.priceFeed();

    uint256 collateralBalance = vaultsData.vaultCollateralBalance(vaultId);
    address collateralType = vaultsData.vaultCollateralType(vaultId);
    - uint256 collateralValue = priceFeed.convertFrom(collateralType, collateralBalance);
    uint256 vaultDebt = vaultsData.vaultDebt(vaultId);

    if (vaultDebt == 0) {
      return (type(uint256).max);
    }
	
	+ uint256 collateralValue = priceFeed.convertFrom(collateralType, collateralBalance);
    uint256 vaultRatio = collateralValue.wadDiv(vaultDebt);

    return (vaultRatio);
  }

Lines in the code

MIMOManagedAction.sol#L92

13. Internal functions not called by the contrat should be removed to save deployment gas

Lines in the code

MIMOFlashloan.sol#L51 MIMOSwap.sol#L40 MIMOAutoAction.sol#L74 MIMOAutoAction.sol#L92 MIMOManagedAction.sol#L92 MIMOManagedAction.sol#L115

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