Platform: Code4rena
Start Date: 28/04/2022
Pot Size: $50,000 USDC
Total HM: 7
Participants: 43
Period: 5 days
Judge: gzeon
Total Solo HM: 2
Id: 115
League: ETH
Rank: 42/43
Findings: 1
Award: $59.06
🌟 Selected for report: 0
🚀 Solo Findings: 0
59.0559 USDC - $59.06
saves gas
File: InceptionVaultsCore.sol 218: uint256 insuranceAmount = 0;
caching variables that are used multiple times in memory saves gas
DexAddressProvider.sol:16: for (uint256 i; i < dexes.length; i++) { //@audit cache dexes.length
using prefix increments save gas
DexAddressProvider.sol:16: for (uint256 i; i < dexes.length; i++) { //@audit use ++i AdminInceptionVault.sol:108: for (uint8 i = 1; i < _collateralCount + 1; i++) {
Use calldata instead of memory for function parameters saves gas
DexAddressProvider.sol:13: constructor(IAddressProvider a, Dex[] memory dexes) public {
for variables only used once, changing it to inline saves gas
AdminInceptionVault.sol:100: IERC20 asset = IERC20(_a.vaultsData().vaultCollateralType(_vaultId));
File: AdminInceptionVault.sol 138: IERC20 par = IERC20(address(_a.stablex()));
File: InceptionVaultFactory.sol 108: uint256 newId = ++_inceptionVaultCount;
File: InceptionVaultsCore.sol 80: uint256 vaultId = _inceptionVaultsData.vaultId(msg.sender); 137: IERC20 stablex = IERC20(_a.stablex()); 151: uint256 newBaseDebt = _a.ratesManager().calculateBaseDebt(newDebt, _cumulativeRate); 155: uint256 collateralValue = _inceptionPriceFeed.convertFrom(v.collateralBalance); 156: uint256 newVaultDebt = _inceptionVaultsData.vaultDebt(_vaultId); 158: bool isHealthy = _a.liquidationManager().isHealthy(collateralValue, newVaultDebt, _vaultConfig.minCollateralRatio); 185: IERC20 stablex = IERC20(_a.stablex()); 290: uint256 newCollateralValue = _inceptionPriceFeed.convertFrom(newCollateralBalance); 326: uint256 currentVaultDebt = _inceptionVaultsData.vaultDebt(_vaultId); 332: uint256 newBaseDebt = _a.ratesManager().calculateBaseDebt(remainder, _cumulativeRate);
File: InceptionVaultsDataProvider.sol 78: uint256 increase = _newBaseDebt.sub(_vault.baseDebt); 81: uint256 decrease = _vault.baseDebt.sub(_newBaseDebt);
File: ChainlinkInceptionPriceFeed.sol 46: uint256 price = getAssetPrice(); 47: uint8 collateralDecimals = ERC20(_inceptionCollateral).decimals(); 48: uint8 parDecimals = ERC20(address(_a.stablex())).decimals(); // Needs re-casting because ISTABLEX does not expose decimals() 49: uint8 oracleDecimals = _assetOracle.decimals(); 50: uint256 parAccuracy = MathPow.pow(10, parDecimals); 51: uint256 collateralAccuracy = MathPow.pow(10, oracleDecimals.add(collateralDecimals)); 60: uint256 price = getAssetPrice(); 61: uint8 collateralDecimals = ERC20(_inceptionCollateral).decimals(); 62: uint8 parDecimals = ERC20(address(_a.stablex())).decimals(); // Needs re-casting because ISTABLEX does not expose decimals() 63: uint8 oracleDecimals = _assetOracle.decimals(); 64: uint256 parAccuracy = MathPow.pow(10, parDecimals); 65: uint256 collateralAccuracy = MathPow.pow(10, oracleDecimals.add(collateralDecimals)); 82: uint8 eurDecimals = _eurOracle.decimals(); 83: uint256 eurAccuracy = MathPow.pow(10, eurDecimals);
File: GenericMinerV2.sol 236: uint256 multiplier = _getBoostMultiplier(_user); 267: uint256 mimoReward = currentMimoBalance.sub(_mimoBalanceTracker); 268: uint256 parReward = currentParBalance.sub(_parBalanceTracker); 284: uint256 currentBalance = _a.mimo().balanceOf(address(this)); 285: uint256 reward = currentBalance.sub(_mimoBalanceTracker); 298: uint256 currentBalance = _par.balanceOf(address(this)); 299: uint256 reward = currentBalance.sub(_parBalanceTracker); 300: uint256 accParAmountPerShare = _accParAmountPerShare.add(reward.rayDiv(_totalStakeWithBoost));
File: PARMinerV2.sol 118: uint256 parBalanceBefore = _par.balanceOf(address(this)); 202: uint256 currentBalance = _par.balanceOf(address(this)).sub(_totalStake); 203: uint256 reward = currentBalance.sub(_parBalanceTracker); 204: uint256 accParAmountPerShare = _accParAmountPerShare.add(reward.rayDiv(_totalStakeWithBoost)); 336: uint256 multiplier = _getBoostMultiplier(_user); 365: uint256 parReward = currentParBalance.sub(_parBalanceTracker); 379: uint256 currentBalance = _a.mimo().balanceOf(address(this)); 380: uint256 reward = currentBalance.sub(_mimoBalanceTracker);
Due to how constant variables are implemented (replacements at compile-time), an expression assigned to a constant variable is recomputed each time that the variable is used, which wastes some gas.
Consequences: each usage of a "constant" costs ~100gas more on each access (it is still a little better than storing the result in storage, but not much..). since these are not real constants, they can't be referenced from a real constant environment (e.g. from assembly, or from another library )
File: InceptionVaultsCore.sol 23: uint256 internal constant _MAX_INT = 2**256 - 1; //@audit use type(uint).max) instead
moving the require statement to the top of the function will save gas in the case where requre statement fails
File: InceptionVaultsCore.sol 285: require(_amount <= v.collateralBalance, "IV101");
File: GenericMinerV2.sol 58: require(boostConfig.a >= 1 && boostConfig.d > 0 && boostConfig.maxBoost >= 1, "LM004");