Platform: Code4rena
Start Date: 30/05/2023
Pot Size: $300,500 USDC
Total HM: 79
Participants: 101
Period: about 1 month
Judge: Trust
Total Solo HM: 36
Id: 242
League: ETH
Rank: 89/101
Findings: 2
Award: $62.33
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Raihan
Also found by: 0x11singh99, 0xAnah, 0xSmartContract, 0xn006e7, Aymen0909, DavidGiladi, IllIllI, JCN, Jorgect, MohammedRizwan, Rageur, ReyAdmirado, Rickard, Rolezn, SAQ, SM3_SS, Sathish9098, TheSavageTeddy, hunter_w3b, kaveyjoe, lsaudit, matrix_0wl, naman1778, petrichor, shamsulhaq123, wahedtalash77
62.3314 USDC - $62.33
Detect optimal variable order in struct definitions to decrease the number of slots used.
<details> <summary> There are 5 instances of this issue: </summary>Line: 105 struct Proposal { /// @notice Unique id for looking up a proposal uint256 id; /// @notice Creator of the proposal address proposer; /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds uint256 eta; /// @notice the ordered list of target addresses for calls to be made address[] targets; /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made uint256[] values; /// @notice The ordered list of function signatures to be called string[] signatures; /// @notice The ordered list of calldata to be passed to each call bytes[] calldatas; /// @notice The block at which voting begins: holders must delegate their votes prior to this block uint256 startBlock; /// @notice The block at which voting ends: votes must be cast prior to this block uint256 endBlock; /// @notice Current number of votes in favor of this proposal uint256 forVotes; /// @notice Current number of votes in opposition to this proposal uint256 againstVotes; /// @notice Current number of votes for abstaining for this proposal uint256 abstainVotes; /// @notice Flag marking whether the proposal has been canceled bool canceled; /// @notice Flag marking whether the proposal has been executed bool executed; /// @notice Receipts of ballots for the entire set of voters mapping(address => Receipt) receipts; }
original variable order (count: 14 slots)
optimized variable order (count: 13 slots)
Recomended optimizations will use 1 less slots.
Line: 26 struct DepositInput { //Deposit Info address hToken; //Input Local hTokens Address. address token; //Input Native / underlying Token Address. uint256 amount; //Amount of Local hTokens deposited for interaction. uint256 deposit; //Amount of native tokens deposited for interaction. uint24 toChain; //Destination chain for interaction. }
original variable order (count: 5 slots)
optimized variable order (count: 4 slots)
Line: 73 struct DepositMultipleParams { //Deposit Info uint8 numberOfAssets; //Number of assets to deposit. uint32 depositNonce; //Deposit nonce. address[] hTokens; //Input Local hTokens Address. address[] tokens; //Input Native / underlying Token Address. uint256[] amounts; //Amount of Local hTokens deposited for interaction. uint256[] deposits; //Amount of native tokens deposited for interaction. uint24 toChain; //Destination chain for interaction. }
original variable order (count: 6 slots)
optimized variable order (count: 5 slots)
Line: 63 struct DepositParams { //Deposit Info uint32 depositNonce; //Deposit nonce. address hToken; //Input Local hTokens Address. address token; //Input Native / underlying Token Address. uint256 amount; //Amount of Local hTokens deposited for interaction. uint256 deposit; //Amount of native tokens deposited for interaction. uint24 toChain; //Destination chain for interaction. }
original variable order (count: 5 slots)
optimized variable order (count: 4 slots)
Recomended optimizations will use 4 less slots.
Line: 55 struct DepositMultipleParams { //Deposit Info uint8 numberOfAssets; //Number of assets to deposit. uint32 depositNonce; //Deposit nonce. address[] hTokens; //Input Local hTokens Address. address[] tokens; //Input Native / underlying Token Address. uint256[] amounts; //Amount of Local hTokens deposited for interaction. uint256[] deposits; //Amount of native tokens deposited for interaction. uint24 toChain; //Destination chain for interaction. uint128 depositedGas; //BRanch chain gas token amount sent with request. }
original variable order (count: 6 slots)
optimized variable order (count: 5 slots)
Recomended optimizations will use 2 less slots.
</details>Detect optimal variable order in contract storage layouts to decrease the number of slots used.
<details> <summary> There are 3 instances of this issue: </summary>Line: 58 contract BranchBridgeAgent is IBranchBridgeAgent
original variable order (count: 17 slots)
optimized variable order (count: 16 slots)
Recomended optimizations will use 1 less slots.
Line: 90 contract RootBridgeAgent is IRootBridgeAgent
original variable order (count: 21 slots)
optimized variable order (count: 19 slots)
Recomended optimizations will use 2 less slots.
Line: 20 contract RootPort is Ownable, IRootPort
original variable order (count: 22 slots)
optimized variable order (count: 21 slots)
Recomended optimizations will use 1 less slots.
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootPort.sol#L20-L532
</details>Where a variable is casted to its own type. This is unnecessary and can be safely removed to improve code readability.
<details> <summary> There are 25 instances of this issue: </summary>Line: 100 rewardToken.safeTransferFrom(address(flywheelRewards), user, accrued)
Unnecessary cast: address(flywheelRewards)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/base/FlywheelCore.sol#L100
Line: 126 uint256 oldRewardBalance = rewardToken.balanceOf(address(flywheelRewards))
Unnecessary cast: address(flywheelRewards)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/base/FlywheelCore.sol#L126
Line: 128 rewardToken.safeTransferFrom(address(flywheelRewards), address(newFlywheelRewards), oldRewardBalance)
Unnecessary cast: address(flywheelRewards)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/base/FlywheelCore.sol#L128
Line: 128 rewardToken.safeTransferFrom(address(flywheelRewards), address(newFlywheelRewards), oldRewardBalance)
Unnecessary cast: address(newFlywheelRewards)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/base/FlywheelCore.sol#L128
Line: 133 emit FlywheelRewardsUpdate(address(newFlywheelRewards))
Unnecessary cast: address(newFlywheelRewards)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/base/FlywheelCore.sol#L133
Line: 132 address flyWheelRewards = address(bribeFlywheel.flywheelRewards())
Unnecessary cast: address(bribeFlywheel.flywheelRewards())
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/gauges/BaseV2Gauge.sol#L132
Line: 244 ERC20MultiVotes(partnerGovernance).mint(address(this), amount * bHermesRate)
Unnecessary cast: ERC20MultiVotes(partnerGovernance)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/maia/tokens/ERC4626PartnerManager.sol#L244
Line: 41 msg.sender != address(rewardsContract)
Unnecessary cast: address(rewardsContract)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/depots/SingleRewardsDepot.sol#L41
Line: 261 uint128 liquidityToDecrease = uint128((liquidity * shares) / totalSupply)
Unnecessary cast: uint128((liquidity * shares) / totalSupply)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/base/TalosBaseStrategy.sol#L261
Line: 40 address(ulysses.asset()).safeApprove(address(ulysses), type(uint256).max)
Unnecessary cast: address(ulysses.asset())
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesRouter.sol#L40
Line: 74 address(getUlyssesLP(routes[0].from).asset()).safeTransferFrom(msg.sender, address(this), amount)
Unnecessary cast: address(getUlyssesLP(routes[0].from).asset())
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesRouter.sol#L74
Line: 92 address(getUlyssesLP(routes[length].to).asset()).safeTransfer(msg.sender, amount)
Unnecessary cast: address(getUlyssesLP(routes[length].to).asset())
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesRouter.sol#L92
Line: 13 ERC20(string(string.concat("Hermes - ", _name)), string(string.concat("h-", _symbol)), 18)
Unnecessary cast: string(string.concat("h-", _symbol))
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/token/ERC20hTokenBranch.sol#L13
Line: 13 ERC20(string(string.concat("Hermes - ", _name)), string(string.concat("h-", _symbol)), 18)
Unnecessary cast: string(string.concat("Hermes - ", _name))
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/token/ERC20hTokenBranch.sol#L13
Line: 64 bridgeAgentAddress = payable(_bridgeAgentAddress)
Unnecessary cast: payable(_bridgeAgentAddress)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/CoreRootRouter.sol#L64
Line: 77 bridgeAgentAddress = payable(_bridgeAgentAddress)
Unnecessary cast: payable(_bridgeAgentAddress)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/MulticallRootRouter.sol#L77
Line: 44 ERC20(string(string.concat("Hermes ", _name)), string(string.concat("h-", _symbol)), 18)
Unnecessary cast: string(string.concat("h-", _symbol))
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/token/ERC20hTokenRoot.sol#L44
Line: 364 i < uint256(uint8(numOfAssets))
Unnecessary cast: uint8(numOfAssets)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgentExecutor.sol#L364
Line: 651 address(data.tokenIn).safeTransfer(msg.sender, uint256(amount0 > 0 ? amount0 : amount1))
Unnecessary cast: address(data.tokenIn)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L651
Line: 160 _setOwner(address(_owner))
Unnecessary cast: address(_owner)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootPort.sol#L160
Line: 44 ERC20(string(string.concat("Hermes ", _name)), string(string.concat("h-", _symbol)), 18)
Unnecessary cast: string(string.concat("Hermes ", _name))
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/token/ERC20hTokenRoot.sol#L44
Line: 315 secondsInsideX128 = RewardMath.computeBoostedSecondsInsideX128( stakedDuration, liquidity, uint128(boostAmount), uint128(boostTotalSupply), secondsPerLiquidityInsideInitialX128, secondsPerLiquidityInsideX128 )
Unnecessary cast: uint128(boostAmount)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L315-L322
Line: 315 secondsInsideX128 = RewardMath.computeBoostedSecondsInsideX128( stakedDuration, liquidity, uint128(boostAmount), uint128(boostTotalSupply), secondsPerLiquidityInsideInitialX128, secondsPerLiquidityInsideX128 )
Unnecessary cast: uint128(boostTotalSupply)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L315-L322
Line: 416 secondsInsideX128 = RewardMath.computeBoostedSecondsInsideX128( stakedDuration, liquidity, uint128(boostAmount), uint128(boostTotalSupply), secondsPerLiquidityInsideInitialX128, secondsPerLiquidityInsideX128 )
Unnecessary cast: uint128(boostAmount)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L416-L423
Line: 416 secondsInsideX128 = RewardMath.computeBoostedSecondsInsideX128( stakedDuration, liquidity, uint128(boostAmount), uint128(boostTotalSupply), secondsPerLiquidityInsideInitialX128, secondsPerLiquidityInsideX128 )
Unnecessary cast: uint128(boostTotalSupply)
it cast to the same type.<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L416-L423
Instead of using operator && in a a single require clause split into multiple clauses to save gas.
<details> <summary> There are 11 instances of this issue: </summary>Line: 67 require( votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD, "GovernorBravo::initialize: invalid voting period" )
split the condition
Line: 71 require( votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY, "GovernorBravo::initialize: invalid voting delay" )
split the condition
Line: 75 require( proposalThreshold_ >= MIN_PROPOSAL_THRESHOLD && proposalThreshold_ <= MAX_PROPOSAL_THRESHOLD, "GovernorBravo::initialize: invalid proposal threshold" )
split the condition
Line: 119 require( targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, "GovernorBravo::propose: proposal function information arity mismatch" )
split the condition
Line: 237 require( (govToken.getPriorVotes(proposal.proposer, sub256(block.number, 1)) < getProposalThresholdAmount()) && msg.sender == whitelistGuardian, "GovernorBravo::cancel: whitelisted proposer" )
split the condition
Line: 298 require( proposalCount >= proposalId && proposalId > initialProposalId, "GovernorBravo::state: invalid proposal id" )
split the condition
Line: 399 require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, "GovernorBravo::_setVotingDelay: invalid voting delay" )
split the condition
Line: 415 require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, "GovernorBravo::_setVotingPeriod: invalid voting period" )
split the condition
Line: 432 require( newProposalThreshold >= MIN_PROPOSAL_THRESHOLD && newProposalThreshold <= MAX_PROPOSAL_THRESHOLD, "GovernorBravo::_setProposalThreshold: invalid proposal threshold" )
split the condition
Line: 507 require( msg.sender == pendingAdmin && msg.sender != address(0), "GovernorBravo:_acceptAdmin: pending admin only" );
split the condition:
Line: 408 require(balance0 >= amount0 && balance1 >= amount1)
split the condition
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/base/TalosBaseStrategy.sol#L408
</details>This detector checks for instances where a non-negative number is compared to 0 using the ">/<" comparison. It suggests replacing this with the "!="/"==" comparison as it could potentially save a small amount of gas.
<details> <summary> There are 68 instances of this issue: </summary>Line: 85 partnerVault != address(0) && address(gaugeBoost).balanceOf(address(this)) > 0
Replace address(gaugeBoost).balanceOf(address(this)) > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/maia/PartnerUtilityManager.sol#L85
Line: 95 partnerVault != address(0) && address(governance).balanceOf(address(this)) > 0
Replace address(governance).balanceOf(address(this)) > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/maia/PartnerUtilityManager.sol#L95
Line: 75 partnerVault != address(0) && address(gaugeWeight).balanceOf(address(this)) > 0
Replace address(gaugeWeight).balanceOf(address(this)) > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/maia/PartnerUtilityManager.sol#L75
v Line: 158 reward <= 0
Replace reward <= 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L158
Line: 271 reward > 0
Replace reward > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L271
Line: 139 _liquidity > 0
Replace _liquidity > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosStrategyVanilla.sol#L139
Line: 409 amount0 > 0
Replace amount0 > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/base/TalosBaseStrategy.sol#L409
Line: 410 amount1 > 0
Replace amount1 > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/base/TalosBaseStrategy.sol#L410
Line: 153 claimed > 0
Replace claimed > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L153
Line: 282 leftOverBandwidth > 0
Replace leftOverBandwidth > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L282
Line: 926 if gt(positiveFee, 0) { output := add(output, positiveFee) }
Replace positiveFee > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L926
Line: 968 if gt(updateAmount, 0) { output := add(output, updateAmount) }
Replace updateAmount > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L968
Line: 991 gt(_positiveFee, 0)
Replace _positiveFee > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L991
Line: 111 j != i && weights[i][j] > 0
Replace weights[i_scope_0][j] > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/factories/UlyssesFactory.sol#L111
Line: 191 oldBandwidth > 0
Replace oldBandwidth > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L191
Line: 272 oldBandwidth > 0
Replace oldBandwidth_scope_1 > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L272
Line: 256 oldBandwidth > 0
Replace oldBandwidth > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L256
Line: 911 updateAmount > 0
Replace updateAmount > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L911
Line: 981 gt(_positiveFee, 0)
Replace _positiveFee > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L981
Line: 1048 updateAmount > 0
Replace updateAmount > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L1048
Line: 47 require(_weight > 0)
Replace _weight > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesToken.sol#L47
Line: 52 require(_weights[i] > 0)
Replace _weights[i] > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-4626/ERC4626MultiToken.sol#L52
Line: 979 _amount - _deposit > 0
Replace _amount - _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L979
Line: 517 (uint128 gasToBridgeOut, bool isRemote) = (remoteCallDepositedGas > 0 ? (_gasToBridgeOut, true) : (msg.value.toUint128(), false))
Replace remoteCallDepositedGas > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L517-L518
Line: 623 _amounts[i] - _deposits[i] > 0
Replace _amounts[i] - _deposits[i] > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L623
Line: 160 gasRemaining > 0
Replace gasRemaining > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/ArbitrumBranchBridgeAgent.sol#L160
Line: 123 _amount - _deposit > 0
Replace _amount - _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/ArbitrumBranchPort.sol#L123
Line: 118 _deposit > 0
Replace _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/ArbitrumBranchPort.sol#L118
Line: 144 _amounts[i] - _deposits[i] > 0
Replace _amounts[i] - _deposits[i] > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/ArbitrumBranchPort.sol#L144
Line: 137 _deposits[i] > 0
Replace _deposits[i] > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/ArbitrumBranchPort.sol#L137
Line: 495 (uint128 gasToBridgeOut, bool isRemote) = (remoteCallDepositedGas > 0 ? (_gasToBridgeOut, true) : (msg.value.toUint128(), false))
Replace remoteCallDepositedGas > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L495-L496
Line: 521 !isRemote && gasToBridgeOut > 0
Replace gasToBridgeOut > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L521
Line: 627 _deposits[i] > 0
Replace _deposits[i] > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L627
Line: 248 _amount - _deposit > 0
Replace _amount - _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchPort.sol#L248
Line: 268 _deposits[i] > 0
Replace _deposits[i] > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchPort.sol#L268
Line: 474 !isRemote && gasToBridgeOut > 0
Replace gasToBridgeOut > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L474
Line: 499 !isRemote && gasToBridgeOut > 0
Replace gasToBridgeOut > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L499
Line: 539 (uint128 gasToBridgeOut, bool isRemote) = (remoteCallDepositedGas > 0 ? (_gasToBridgeOut, true) : (msg.value.toUint128(), false))
Replace remoteCallDepositedGas > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L539-L540
Line: 983 _deposit > 0
Replace _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L983
Line: 470 (uint128 gasToBridgeOut, bool isRemote) = (remoteCallDepositedGas > 0 ? (_gasToBridgeOut, true) : (msg.value.toUint128(), false))
Replace remoteCallDepositedGas > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L470-L471
Line: 543 !isRemote && gasToBridgeOut > 0
Replace gasToBridgeOut > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L543
Line: 1328 executionBudget > 0
Replace executionBudget > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L1328
Line: 252 _deposit > 0
Replace _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchPort.sol#L252
Line: 275 _amounts[i] - _deposits[i] > 0
Replace _amounts[i] - _deposits[i] > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchPort.sol#L275
Line: 56 (_dParams.amount < _dParams.deposit) //Deposit can't be greater than amount. || (_dParams.amount > 0 && !IPort(_localPortAddress).isLocalToken(_dParams.hToken, _fromChain)) //Check local exists. || (_dParams.deposit > 0 && !IPort(_localPortAddress).isUnderlyingToken(_dParams.token, _fromChain))
Replace _dParams.amount > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L56-L58
Line: 750 _initialGas > 0
Replace _initialGas > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L750
Line: 457 _deposit > 0
Replace _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L457
Line: 451 _amount - _deposit > 0
Replace _amount - _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L451
Line: 347 hTokens[i] == address(0) || (tokens[i] == address(0) && _deposits[i] > 0)
Replace _deposits[i] > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L347
Line: 1161 initialGas > 0
Replace initialGas > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L1161
Line: 56 (_dParams.amount < _dParams.deposit) //Deposit can't be greater than amount. || (_dParams.amount > 0 && !IPort(_localPortAddress).isLocalToken(_dParams.hToken, _fromChain)) //Check local exists. || (_dParams.deposit > 0 && !IPort(_localPortAddress).isUnderlyingToken(_dParams.token, _fromChain))
Replace _dParams.deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L56-L58
Line: 750 _initialGas > 0
Replace _initialGas > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L750
Line: 757 _initialGas > 0
Replace _initialGas > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L757
Line: 451 _amount - _deposit > 0
Replace _amount - _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L451
Line: 301 localAddress == address(0) || (underlyingAddress == address(0) && _deposit > 0)
Replace _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L301
Line: 1240 executionBudget > 0
Replace executionBudget > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L1240
Line: 1171 initialGas > 0
Replace initialGas > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L1171
Line: 282 _amount - _deposit > 0
Replace _amount - _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootPort.sol#L282
Line: 283 _deposit > 0
Replace _deposit > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootPort.sol#L283
Line: 417 weight > 0
Replace weight > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-20/ERC20Gauges.sol#L417
Line: 441 weight > 0
Replace weight > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-20/ERC20Gauges.sol#L441
Line: 250 pos > 0 && ckpts[pos - 1].fromBlock == block.number
Replace pos > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-20/ERC20MultiVotes.sol#L250
Line: 162 strategyRewardsAccrued > 0
Replace strategyRewardsAccrued > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/base/FlywheelCore.sol#L162
Line: 127 oldRewardBalance > 0
Replace oldRewardBalance > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/base/FlywheelCore.sol#L127
Line: 234 accruedRewards > 0
Replace accruedRewards > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/rewards/FlywheelGaugeRewards.sol#L234
Line: 138 reward <= 0
Replace reward <= 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L138
Line: 199 incentive.numberOfStakes > 0
Replace incentive.numberOfStakes > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L199
Line: 281 reward > 0
Replace reward > 0
with ==
/!=
https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L281
The expressions 'x * 2' and 'x / 2' can be optimized for gas efficiency by utilizing bitwise operations. In Solidity, you can achieve the same results by using bitwise left shift (x << 1) for multiplication and bitwise right shift (x >> 1) for division.
Using bitwise shift operations (SHL and SHR) instead of multiplication (MUL) and division (DIV) opcodes can lead to significant gas savings. The MUL and DIV opcodes cost 5 gas, while the SHL and SHR opcodes incur a lower cost of only 3 gas.
By leveraging these more efficient bitwise operations, you can reduce the gas consumption of your smart contracts and enhance their overall performance.
I reported issues that were overlooked by the winning bot. Specifically, the bot missed opportunities for optimization in the cases of multiplication and division operations performed inside assembly blocks. These operations could potentially be replaced by more efficient bitwise shift operations (shl
and shr
). I reported only on instances that were missed by the winning bot.
It's important to mention that I've merged the issues of multiplication and division into one, considering they are conceptually similar and can be addressed using the same optimization approach. Hence, please take this consolidation into account when evaluating the reported issues
<details> <summary> There are 7 instances of this issue: </summary>Line: 47 uint24 private constant protocolFee = 2 * 1e5
instead 2
use bit shifting 1
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosStrategyVanilla.sol#L47
Line: 396 let slot := sload(add(bandwidthStateListStart, mul(i, 2)))
instead 2
use bit shifting 1
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L396
Line: 490 let weight := shr(248, sload(add(bandwidthStateListStart, mul(i, 2))))
instead 2
use bit shifting 1
like this shl(1, i)
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L490
Line: 424 mstore(add(diffs, add(mul(i, 0x20), 0x20)), diff)
instead 32
use bit shifting 5
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L424
Line: 522 mstore(add(bandwidthUpdateAmounts, add(mul(i, 0x20), 0x20)), bandwidthUpdate)
instead 32
use bit shifting 5
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L522
Line: 464 let diff := mload(add(diffs, add(mul(i, 0x20), 0x20)))
instead 32
use bit shifting 5
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L464
Line: 436 mstore(add(diffs, add(mul(i, 0x20), 0x20)), diff)
instead 32
use bit shifting 5
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L436
</details>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.
I reported issues that were overlooked by the winning bot. I reported only on instances that were missed.
It's important to highlight that I didn't report on cases of empty functions overriding others, as these are often intentional design choices in contract inheritance and do not constitute inefficiencies or errors.
<details> <summary> There are 6 instances of this issue: </summary>Line: 96 try strategy.pool().checkDeviation(optimizer. maxTwapDeviation(), optimizer.twapDuration()) {} catch { ... }
contains an empty block. https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosManager.sol#L96-L99
Line: 177 try nonfungiblePositionManager.safeTransferFrom(address(this), address(boostAggregator), _tokenId) { ... } catch {}
contains an empty block. https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosStrategyStaked.sol#L177-L179
Line: 221 if (incompleteCycle) { // If current cycle queue incomplete, do nothing to current cycle rewards or accrued } else { ... }
contains an empty block. https://github.com/code-423n4/2023-05-maia/blob/main/src/rewards/rewards/FlywheelGaugeRewards.sol#L221-L226
Line: 1328 if (executionBudget > 0) try anycallConfig.withdraw(executionBudget) {} catch {}
contains an empty block. https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L1328
Line: 1328 try anycallConfig.withdraw(executionBudget) {} catch {}
contains an empty block. https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L1328
Line: 1240 try anycallConfig.withdraw(executionBudget) {} catch {}
contains an empty block. https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L1240
</details>Using private
for constant variables is cheaper in terms of gas usage. If the value of the constant variable is needed, it can be accessed via a getter function. In case of multiple constant variables, a single getter function could be used to return a tuple of the values of all currently-private constants.
Line: 9 string public constant name = "vMaia Governor Bravo"
name
is a public constant variable. Consider making it private to save gas.
https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoDelegateMaia.sol#L9
Line: 12 uint256 public constant MIN_PROPOSAL_THRESHOLD = 0.005 ether
MIN_PROPOSAL_THRESHOLD
is a public constant variable. Consider making it private to save gas.
Line: 15 uint256 public constant MAX_PROPOSAL_THRESHOLD = 0.05 ether
MAX_PROPOSAL_THRESHOLD
is a public constant variable. Consider making it private to save gas.
Line: 18 uint256 public constant MIN_VOTING_PERIOD = 80640
MIN_VOTING_PERIOD
is a public constant variable. Consider making it private to save gas.
Line: 21 uint256 public constant MAX_VOTING_PERIOD = 161280
MAX_VOTING_PERIOD
is a public constant variable. Consider making it private to save gas.
Line: 24 uint256 public constant MIN_VOTING_DELAY = 40320
MIN_VOTING_DELAY
is a public constant variable. Consider making it private to save gas.
Line: 27 uint256 public constant MAX_VOTING_DELAY = 80640
MAX_VOTING_DELAY
is a public constant variable. Consider making it private to save gas.
Line: 30 uint256 public constant quorumVotes = 0.35 ether
quorumVotes
is a public constant variable. Consider making it private to save gas.
Line: 33 uint256 public constant proposalMaxOperations = 10
proposalMaxOperations
is a public constant variable. Consider making it private to save gas.
Line: 36 uint256 public constant DIVISIONER = 1 ether
DIVISIONER
is a public constant variable. Consider making it private to save gas.
Line: 42 bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)")
DOMAIN_TYPEHASH
is a public constant variable. Consider making it private to save gas.
Line: 46 bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)")
BALLOT_TYPEHASH
is a public constant variable. Consider making it private to save gas.
Line: 360 bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)")
DELEGATION_TYPEHASH
is a public constant variable. Consider making it private to save gas.
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-20/ERC20MultiVotes.sol#L360-L361
</details>Named return variables allow for clear and explicit naming of values to be returned from a function. However, when these variables are unused, it can lead to confusion and make the code less maintainable.
<details> <summary> There are 16 instances of this issue: </summary>Line: 188 function incrementGauge(address gauge, uint112 weight) external nonReentrant returns (uint112 newUserWeight)
there is not use of this variables: @ newUserWeight
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-20/ERC20Gauges.sol#L188-L192
Line: 245 function incrementGauges(address[] calldata gaugeList, uint112[] calldata weights) external nonReentrant returns (uint256 newUserWeight)
there is not use of this variables: @ newUserWeight
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-20/ERC20Gauges.sol#L245-L270
Line: 273 function decrementGauge(address gauge, uint112 weight) external nonReentrant returns (uint112 newUserWeight)
there is not use of this variables: @ newUserWeight
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-20/ERC20Gauges.sol#L273-L282
Line: 322 function decrementGauges(address[] calldata gaugeList, uint112[] calldata weights) external nonReentrant returns (uint112 newUserWeight)
there is not use of this variables: @ newUserWeight
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-20/ERC20Gauges.sol#L322-L352
Line: 268 function getActions(uint256 proposalId) external view returns ( address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas )
there is not use of this variables: @ targets @ values @ signatures @ calldatas
Line: 32 function getRewards() external override onlyFlywheelRewards returns (uint256 balance)
there is not use of this variables: @ balance
Line: 39 function totalAssets() public view override returns (uint256 _totalAssets)
there is not use of this variables: @ _totalAssets
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesToken.sol#L39-L41
Line: 1227 function anyFallback(bytes calldata data) external virtual requiresExecutor returns (bool success, bytes memory result)
there is not use of this variables: @ success @ result
Line: 112 function anyExecuteNoSettlement(bytes calldata _data) external override requiresAgentExecutor returns (bool success, bytes memory result)
there is not use of this variables: @ success @ result
Line: 101 function anyExecuteNoSettlement(bytes calldata) external virtual requiresAgentExecutor returns (bool success, bytes memory result)
there is not use of this variables: @ success @ result
Line: 112 function anyExecuteSettlement(bytes calldata, SettlementParams memory) external virtual requiresAgentExecutor returns (bool success, bytes memory result)
there is not use of this variables: @ success @ result
Line: 123 function anyExecuteSettlementMultiple(bytes calldata, SettlementMultipleParams memory) external virtual requiresAgentExecutor returns (bool success, bytes memory result)
there is not use of this variables: @ success @ result
Line: 229 function anyExecuteNoSettlement(bytes calldata _data) external virtual override requiresAgentExecutor returns (bool success, bytes memory result)
there is not use of this variables: @ success @ result
Line: 345 function anyExecuteSignedDepositSingle( bytes1 funcId, bytes calldata encodedData, DepositParams calldata, address userAccount, uint24 ) external payable override requiresExecutor lock returns (bool success, bytes memory result)
there is not use of this variables: @ success @ result
Line: 421 function anyExecuteSignedDepositMultiple( bytes1 funcId, bytes memory encodedData, DepositMultipleParams calldata, address userAccount, uint24 ) external payable requiresExecutor lock returns (bool success, bytes memory result)
there is not use of this variables: @ success @ result
Line: 1177 function anyFallback(bytes calldata data) external virtual requiresExecutor returns (bool success, bytes memory result)
there is not use of this variables: @ success @ result
</details>State variables that are not updated following deployment should be declared immutable to save gas.
<details> <summary> There are 27 instances of this issue: </summary>Line: 32 uint256 public totalWeights
should be immutable
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-4626/ERC4626MultiToken.sol#L32
Line: 44 MultiRewardsDepot public override multiRewardsDepot
should be immutable
https://github.com/code-423n4/2023-05-maia/blob/main/src/gauges/BaseV2Gauge.sol#L44
Line: 41 address public override strategy
should be immutable
https://github.com/code-423n4/2023-05-maia/blob/main/src/gauges/BaseV2Gauge.sol#L41
Line: 62 address public admin
should be immutable
https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L62
Line: 20 address public partnerVault
should be immutable
https://github.com/code-423n4/2023-05-maia/blob/main/src/maia/PartnerUtilityManager.sol#L20
Line: 18 UlyssesFactory public ulyssesFactory
should be immutable
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesRouter.sol#L18
Line: 112 address public bridgeAgentExecutorAddress
should be immutable
Line: 22 uint24 public localChainId
should be immutable
Line: 25 address public rootPortAddress
should be immutable
Line: 23 address public localPortAddress
should be immutable
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/VirtualAccount.sol#L23
Line: 21 address public hTokenFactoryAddress
should be immutable
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/CoreBranchRouter.sol#L21
Line: 24 address public localPortAddress
should be immutable
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/CoreBranchRouter.sol#L24
Line: 25 address public factoryAddress
should be immutable
Line: 16 uint256 public localChainId
should be immutable
Line: 19 address public rootPortAddress
should be immutable
Line: 97 GovTokenInterface public govToken
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L97
Line: 88 uint256 public initialProposalId
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L88
Line: 91 uint256 public proposalCount
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L91
Line: 85 uint256 public proposalThreshold
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L85
Line: 94 TimelockInterface public timelock
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L94
Line: 79 uint256 public votingDelay
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L79
Line: 82 uint256 public votingPeriod
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L82
Line: 166 address public whitelistGuardian
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L166
Line: 62 address public admin
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L62
Line: 68 address public implementation
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L68
Line: 65 address public pendingAdmin
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/governance/GovernorBravoInterfaces.sol#L65
Line: 22 address public localBranchPortAddress
should be immutable https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/token/ERC20hTokenRoot.sol#L22
</details>Assignment operations that involve calculations, like add-assigment (+=
), for state variables, should be replaced with the appropriate calculation operation, like add (+
), followed by an assignment operation (=
), to save gas. Avoids a Gwarmaccess
(100 gas).
I reported issues that were overlooked by the winning bot. I reported only on instances that were missed.
<details> <summary> There are 7 instances of this issue: </summary>Line: 157 protocolFees0 += collect0
should use the appropriate calculation operation (+
), followed by an assignment operation (=
)
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosStrategyStaked.sol#L157
Line: 158 protocolFees1 += collect1
should use the appropriate calculation operation (+
), followed by an assignment operation (=
)
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosStrategyStaked.sol#L158
Line: 122 protocolFees0 += earnedProtocolFees0
should use the appropriate calculation operation (+
), followed by an assignment operation (=
)
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosStrategyVanilla.sol#L122
Line: 123 protocolFees1 += earnedProtocolFees1
should use the appropriate calculation operation (+
), followed by an assignment operation (=
)
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosStrategyVanilla.sol#L123
Line: 151 liquidity += liquidityDifference
should use the appropriate calculation operation (+
), followed by an assignment operation (=
)
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosStrategyVanilla.sol#L151
Line: 52 totalWeights += _weight
should use the appropriate calculation operation (+
), followed by an assignment operation (=
)
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesToken.sol#L52
Line: 68 totalWeights -= weights[assetIndex]
should use the appropriate calculation operation (-
), followed by an assignment operation (=
)
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesToken.sol#L68
</details>This detector identifies instances of computations being performed inside loops that could be performed outside the loop to save gas.
Unnecessary computation inside loops:
Any computation performed inside a loop that doesn't change with each iteration can be moved outside the loop to save gas.This detector identifies instances where the following unnecessary computations are performed inside loops:
1 Local variables are read inside loops but never modified within the same loop, indicating they could be cached outside the loop.
2 Computations involving constant expressions (literals) which result in the same output in every loop iteration.
By addressing these issues, gas usage can be optimized.
<details> <summary> There are 1 instances of this issue: </summary>Line: 282 leftOverBandwidth > 0
The following computations can be cached outside of loops for gas optimization leftOverBandwidth > 0
<br>.
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L282
This detector identifies instances where there are consecutive external calls to the same contract, where the subsequent calls could use a low-level call to save gas.
Note: This detector only triggers if the function call does not return any value.
Prior to 0.8.10, the compiler inserted extra code, including EXTCODESIZE (100 gas), to check for contract existence for external function calls. In more recent Solidity versions the compiler will not insert these checks if the external call has a return value. Similar behavior can be achieved in earlier versions by using low-level calls, since low-level calls never check for contract existence.
<details> <summary> There are 13 instances of this issue: </summary>Line: 196 address(gaugeBoost).safeApprove(oldPartnerVault, 0)
This call could be replaced with a low-level call because the contract SafeTransferLib
has already been checked in <br>Line: 195 address(gaugeWeight).safeApprove(oldPartnerVault, 0)
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/maia/tokens/ERC4626PartnerManager.sol#L196
Line: 126 address(_token1).safeTransferFrom(msg.sender, address(this), amount1Desired)
This call could be replaced with a low-level call because the contract SafeTransferLib
has already been checked in <br>Line: 125 address(_token0).safeTransferFrom(msg.sender, address(this), amount0Desired)
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/base/TalosBaseStrategy.sol#L126
Line: 197 address(_token1).safeTransferFrom(msg.sender, address(this), amount1Desired)
This call could be replaced with a low-level call because the contract SafeTransferLib
has already been checked in <br>Line: 196 address(_token0).safeTransferFrom(msg.sender, address(this), amount0Desired)
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/base/TalosBaseStrategy.sol#L197
Line: 407 uint256 balance1 = _token1.balanceOf(address(this))
This call could be replaced with a low-level call because the contract ERC20
has already been checked in <br>Line: 406 uint256 balance0 = _token0.balanceOf(address(this))
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/base/TalosBaseStrategy.sol#L407
Line: 135 uniswapV3Staker.withdrawToken(tokenId, user, "")
This call could be replaced with a low-level call because the contract UniswapV3Staker
has already been checked in <br>Line: 114 uniswapV3Staker.unstakeToken(tokenId)
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/boost-aggregator/BoostAggregator.sol#L135
Line: 168 address(hermesGaugeBoost).safeTransfer(to, hermesGaugeBoost.balanceOf(address(this)))
This call could be replaced with a low-level call because the contract bHermesBoost
has already been checked in <br>Line: 167 hermesGaugeBoost.decrementAllGaugesAllBoost()
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/boost-aggregator/BoostAggregator.sol#L168
Line: 175 hermesGaugeBoost.updateUserBoost(address(this))
This call could be replaced with a low-level call because the contract bHermesBoost
has already been checked in <br>Line: 174 hermesGaugeBoost.decrementAllGaugesBoost(amount)
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/boost-aggregator/BoostAggregator.sol#L175
Line: 131 uint256 balance1 = token1.balanceOf(address(this)) - protocolFees1
This call could be replaced with a low-level call because the contract ERC20
has already been checked in <br>Line: 130 uint256 balance0 = token0.balanceOf(address(this)) - protocolFees0
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/talos/TalosStrategyVanilla.sol#L131
Line: 92 address(getUlyssesLP(routes[length].to).asset()).safeTransfer(msg.sender, amount)
This call could be replaced with a low-level call because the contract UlyssesPool
has already been checked in <br>Line: 74 address(getUlyssesLP(routes[0].from).asset()).safeTransferFrom(msg.sender, address(this), amount)
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesRouter.sol#L92
Line: 92 address(getUlyssesLP(routes[length].to).asset()).safeTransfer(msg.sender, amount)
This call could be replaced with a low-level call because the contract SafeTransferLib
has already been checked in <br>Line: 74 address(getUlyssesLP(routes[0].from).asset()).safeTransferFrom(msg.sender, address(this), amount)
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesRouter.sol#L92
Line: 50 string memory symbol = ERC20(_underlyingAddress).symbol()
This call could be replaced with a low-level call because the contract ERC20
has already been checked in <br>Line: 49 string memory name = ERC20(_underlyingAddress).name()
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/ArbitrumCoreBranchRouter.sol#L50
Line: 66 string memory symbol = ERC20(_underlyingAddress).symbol()
This call could be replaced with a low-level call because the contract ERC20
has already been checked in <br>Line: 65 string memory name = ERC20(_underlyingAddress).name()
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/CoreBranchRouter.sol#L66
Line: 1042 IPort(localPortAddress).toggleVirtualAccountApproved(userAccount, localRouterAddress)
This call could be replaced with a low-level call because the contract IRootPort
has already been checked in <br>Line: 1029 IPort(localPortAddress).toggleVirtualAccountApproved(userAccount, localRouterAddress)
<br>
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L1042
This detector checks for instances where the same require() or revert() condition is repeated in multiple places within the same contract. Such duplicate checks can often be refactored into a modifier or function, reducing code redundancy and increasing maintainability.
I reported issues that were overlooked by the winning bot. I reported only on instances that were missed.
<details> <summary> There are 5 instances of this issue: </summary>Line: 191 require(_userGauges[msg.sender].remove(gauge))
Has duplicate:<br>File: src/erc-20/ERC20Boost.sol
Line: 213 require(_userGauges[msg.sender].remove(gauge))
File: src/erc-20/ERC20Boost.sol
Line: 239 require(_userGauges[msg.sender].remove(gauge))
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-20/ERC20Boost.sol#L191
Line: 34 require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES")
Has duplicate:<br>File: src/erc-4626/ERC4626DepositOnly.sol
Line: 34 require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES")
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-4626/ERC4626.sol#L34
Line: 91 require(_id != 0)
Has duplicate:<br>File: src/ulysses-amm/UlyssesToken.sol
Line: 30 require(_id != 0)
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesPool.sol#L91
Line: 1367 require(_unlocked == 1)
Has duplicate:<br>File: src/ulysses-omnichain/BranchPort.sol
Line: 424 require(_unlocked == 1)
Line: 129 require(_setup, "Setup ended.")
Has duplicate:<br>File: src/ulysses-omnichain/RootPort.sol
Line: 145 require(_setup, "Setup ended.")
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootPort.sol#L129
</details>This detector identifies instances of repeated external calls within loops. By moving the first external call outside of the loop and using low-level calls inside the loop, it is possible to save gas by avoiding repeated EXTCODESIZE opcodes, as there is no need to check again if the contract exists.
Note: This detector only triggers if the function call does not return any value.
Prior to 0.8.10, the compiler inserted extra code, including EXTCODESIZE (100 gas), to check for contract existence for external function calls. In more recent Solidity versions the compiler will not insert these checks if the external call has a return value. Similar behavior can be achieved in earlier versions by using low-level calls, since low-level calls never check for contract existence.
<details> <summary> There are 26 instances of this issue: </summary>Line: 51 require(ERC20(_assets[i]).decimals() == 18)
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-4626/ERC4626MultiToken.sol#L51
Line: 69 assets[i].safeTransferFrom(msg.sender, address(this), assetsAmounts[i])
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-4626/ERC4626MultiToken.sol#L69
Line: 80 assets[i].safeTransfer(receiver, assetsAmounts[i])
https://github.com/code-423n4/2023-05-maia/blob/main/src/erc-4626/ERC4626MultiToken.sol#L80
Line: 78 _gauges[i].newEpoch()
https://github.com/code-423n4/2023-05-maia/blob/main/src/gauges/factories/BaseV2GaugeFactory.sol#L78
Line: 94 _gauges[i].newEpoch()
https://github.com/code-423n4/2023-05-maia/blob/main/src/gauges/factories/BaseV2GaugeFactory.sol#L94
Line: 65 _gaugeFactories[i].newEpoch()
https://github.com/code-423n4/2023-05-maia/blob/main/src/gauges/factories/BaseV2GaugeManager.sol#L65
Line: 81 _gaugeFactories[i].newEpoch()
https://github.com/code-423n4/2023-05-maia/blob/main/src/gauges/factories/BaseV2GaugeManager.sol#L81
Line: 252 timelock.cancelTransaction( proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta )
Line: 116 assets[i].safeTransfer(msg.sender, assetBalance - newAssetBalance)
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesToken.sol#L116
Line: 118 assets[i].safeTransferFrom(msg.sender, address(this), newAssetBalance - assetBalance)
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-amm/UlyssesToken.sol#L118
Line: 124 pools[poolIds[i]].transferOwnership(owner)
Line: 102 IRootPort(rootPortAddress).bridgeToLocalBranchFromRoot(_recipient, _localAddresses[i], _amounts[i])
Line: 138 _underlyingAddresses[i].safeTransferFrom( _depositor, address(this), _denormalizeDecimals(_deposits[i], ERC20(_underlyingAddresses[i]).decimals()) )
Line: 145 IRootPort(rootPortAddress).bridgeToRootFromLocalBranch( _depositor, _localAddresses[i], _amounts[i] - _deposits[i] )
Line: 284 _deposits[i] = _normalizeDecimals(_dParams.deposits[i], ERC20(_dParams.tokens[i]).decimals())
Line: 624 IPort(localPortAddress).bridgeIn(_recipient, _hTokens[i], _amounts[i] - _deposits[i])
Line: 628 IPort(localPortAddress).withdraw(_recipient, _tokens[i], _deposits[i])
Line: 720 deposits[i] = _normalizeDecimals(_dParams.deposits[i], ERC20(_dParams.tokens[i]).decimals())
Line: 1355 deposits[i] = _normalizeDecimals(_deposits[i], ERC20(_tokens[i]).decimals())
Line: 269 _underlyingAddresses[i].safeTransferFrom( _depositor, address(this), _denormalizeDecimals(_deposits[i], ERC20(_underlyingAddresses[i]).decimals()) )
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchPort.sol#L269-L273
Line: 276 _localAddresses[i].safeTransferFrom(_depositor, address(this), _amounts[i] - _deposits[i])
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchPort.sol#L276
Line: 277 ERC20hTokenBranch(_localAddresses[i]).burn(_amounts[i] - _deposits[i])
https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchPort.sol#L277
Line: 312 IVirtualAccount(userAccount).withdrawERC20(outputParams.outputTokens[i], outputParams.amountsOut[i])
Line: 388 IVirtualAccount(userAccount).withdrawERC20(outputParams.outputTokens[i], outputParams.amountsOut[i])
Line: 464 IVirtualAccount(userAccount).withdrawERC20(outputParams.outputTokens[i], outputParams.amountsOut[i])
</details>Line: 600 IPort(localPortAddress).bridgeToRoot( msg.sender, IPort(localPortAddress).getGlobalTokenFromLocal(settlement.hTokens[i], settlement.toChain), settlement.amounts[i], settlement.deposits[i], settlement.toChain )
#0 - c4-judge
2023-07-09T16:00:26Z
trust1995 marked the issue as grade-b