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: 28/69
Findings: 2
Award: $127.67
🌟 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
67.7324 USDC - $67.73
 
High privilege account such as admin / owner is changed with only single process. This can be a concern since an admin / owner role has a high privilege in the contract and mistakenly setting a new admin to an incorrect address will end up losing that privilege.
Total of 1 issue found.
This can be fixed by implementing 2-step process. We can do this by following. First make the setAdmin function approve a new address as a pending admin. Next that pending admin has to claim the ownership in a separate transaction to be a new admin.
 
I recommend adding check of 0-address for input validation of critical address parameters. Not doing so might lead to non-functional contract and have to redeploy the contract, when it is updated to 0-address accidentally.
Total of 1 issue found.
Add 0-address check for above addresses.
 
Each event should have 3 indexed fields if there are 3 or more fields.
Total of 5 issues found.
./proxy/interfaces/IMIMOProxy.sol:9: event Execute(address indexed target, bytes data, bytes response); ./proxy/interfaces/IMIMOProxyFactory.sol:11: event DeployProxy(address indexed deployer, address indexed owner, address proxy); ./actions/managed/interfaces/IMIMOManagedAction.sol:22: event ManagerSet(address manager, bool isManager); ./actions/managed/interfaces/IMIMOManagedAction.sol:23: event ManagementSet(uint256 vaultId, ManagedVault managedVault); ./actions/automated/interfaces/IMIMOAutoAction.sol:25: event AutomationSet(uint256 vaultId, AutomatedVault autoVault);
Add up to 3 indexed fields when possible.
 
🌟 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
59.9447 USDC - $59.94
 
Since Solidity 0.8.0, all arithmetic operations revert on overflow and underflow by default. However in places where overflow and underflow is not possible, it is better to use unchecked block to reduce the gas usage. Reference: https://docs.soliditylang.org/en/v0.8.15/control-structures.html#checked-or-unchecked-arithmetic
Total of 2 issues found.
Wrap line 133 and 134 with unchecked since underflow is not possible due to line 132 check 132: if (collateralBalanceAfter > flashloanRepayAmount) { 133: token.safeIncreaseAllowance(address(core), collateralBalanceAfter - flashloanRepayAmount); 134: core.deposit(address(token), collateralBalanceAfter - flashloanRepayAmount);
https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/MIMOLeverage.sol#L132-L134
Wrap the code with uncheck like described in above PoC.
 
SLOADs cost 100 gas where MLOADs/MSTOREs cost only 3 gas. Whenever function reads storage value more than once, it should be cached to save gas.
Total of 2 issue found.
Cache owner of setPermission() of MIMOProxy.sol 2 SLOADs to 1 SLOAD, 1 MSTORE and 2 MLOAD https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/proxy/MIMOProxy.sol#L110-L111
Cache owner of multicall() of MIMOProxy.sol 2 SLOADs to 1 SLOAD, 1 MSTORE and 2 MLOAD https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/proxy/MIMOProxy.sol#L128-L129
When certain state variable is read more than once, cache it to local variable to save gas.
 
Below has redundant use of variables. Instead of defining a new variable, emit the event first and then update the variable.
Total of 1 issue found.
function transferOwnership(address newOwner) external override { if (owner != msg.sender) { revert CustomErrors.NOT_OWNER(oldOwner, msg.sender); } emit TransferOwnership(owner, newOwner); owner = newOwner; }
Instead of defining a new variable, emit the event first and then update the variable like shown in above PoC.
 
In some function return statement are used even though named returns is set. This is redundant because return statement is not needed when using named returns and named returns is not needed when using return statement. Removing unused named returns variable in below code can save gas and improve code readability.
Total of 3 issues found.
Remove unused named returns variable as mentioned in above PoC.
 
State variable that is only set in the constructor/initializer and can't be changed afterwards, should be declared as immutable.
Total of 2 issues found.
minGasReserve variable of MIMOProxy.sol https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxy.sol#L19
factory variable of MIMOProxyRegistry.sol https://github.com/code-423n4/2022-08-mimo/blob/eb1a5016b69f72bc1e4fd3600a65e908bd228f13/contracts/proxy/MIMOProxyRegistry.sol#L16
 
If the function is not called internally, it is cheaper to set your function visibility to external instead of public.
Total of 1 issue found.
MIMOProxy.sol:setPermission() https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/proxy/MIMOProxy.sol#L104-L114
104: function setPermission( 105: address envoy, 106: address target, 107: bytes4 selector, 108: bool permission 109: ) public override {
Change the function visibility to external.
 
Certain function is defined even though it is called only once. Inline it instead to where it is called to avoid usage of extra gas.
Total of 6 issues found.
_isVaultVariationAllowed() of MIMOManagedAction.sol Called only once at line 195 of MIMOManagedRebalance.sol https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/managed/MIMOManagedAction.sol#L115-L122 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/managed/MIMOManagedRebalance.sol#L195
_isVaultVariationAllowed() of MIMOAutoAction.sol Called only once at line 227 of MIMOAutoRebalance.sol https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/automated/MIMOAutoAction.sol#L92-L99 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/automated/MIMOAutoRebalance.sol#L277
_preRebalanceChecks() of MIMOManagedRebalance.sol Called only once at line 58 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/managed/MIMOManagedRebalance.sol#L142-L166 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/managed/MIMOManagedRebalance.sol#L58
_preRebalanceChecks() of /MIMOAutoRebalance.sol Called only once at line 59 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/automated/MIMOAutoRebalance.sol#L236-L250 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/automated/MIMOAutoRebalance.sol#L59
_postRebalanceChecks() of MIMOManagedRebalance.sol Called only once at line 67 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/managed/MIMOManagedRebalance.sol#L179-L211 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/managed/MIMOManagedRebalance.sol#L67
_postRebalanceChecks() of MIMOAutoRebalance.sol Called only once at line 74 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/automated/MIMOAutoRebalance.sol#L262-L286 https://github.com/code-423n4/2022-08-mimo/blob/main/contracts/actions/automated/MIMOAutoRebalance.sol#L74
I recommend to not define above functions and instead inline it at place it is called.
 
When variable is not initialized, it will have its default values. For example, 0 for uint, false for bool and address(0) for address. Reference: https://docs.soliditylang.org/en/v0.8.15/control-structures.html#scoping-and-declarations
Total of 1 issue found.
./proxy/MIMOProxy.sol:132: for (uint256 i = 0; i < targets.length; i++) {
I suggest removing default value initialization. For example,
- for (uint256 i; i < targets.length; i++) {
 
Prefix increments/decrements (++i or --i) costs cheaper gas than postfix increment/decrements (i++ or i--).
Total of 1 issue found.
./proxy/MIMOProxy.sol:132: for (uint256 i = 0; i < targets.length; i++) {
Change it to postfix increments/decrements. It saves 6 gas per loop. For example,
for (uint256 i = 0; i < targets.length; ++i) {
 
There are function with empty blocks. These should do something like emit an event or reverting. If not it should be removed from the contract.
Total of 2 issues found.
./proxy/MIMOProxy.sol:38: receive() external payable {} ./actions/MIMOFlashloan.sol:44: ) external virtual override returns (bool) {}
Add emit or revert in the function block.