Good Entry - DavidGiladi's results

The best day trading platform to make every trade entry a Good Entry.

General Information

Platform: Code4rena

Start Date: 01/08/2023

Pot Size: $91,500 USDC

Total HM: 14

Participants: 80

Period: 6 days

Judge: gzeon

Total Solo HM: 6

Id: 269

League: ETH

Good Entry

Findings Distribution

Researcher Performance

Rank: 47/80

Findings: 2

Award: $32.69

QA:
grade-b
Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

15.3494 USDC - $15.35

Labels

bug
disagree with severity
grade-b
high quality report
QA (Quality Assurance)
sponsor acknowledged
Q-18

External Links

Low Issues

TitleIssueInstances
[L-1] Array out of bounds accessesArray out of bounds accesses5
[L-2] Burn functions must be protected with a modifierBurn functions must be protected with a modifier3
[L-3] Missing contract-existence checks before low-level callsMissing contract-existence checks before low-level calls3
[L-4] Local variable shadowingLocal variable shadowing4
[L-5] Missing gap Storage Variable in Upgradeable ContractMissing gap Storage Variable in Upgradeable Contract2
[L-6] Reentrancy vulnerabilitiesReentrancy vulnerabilities10
[L-7] Restrictive casts in assignmentsRestrictive casts in assignments3

Total: 7 issues

Non-Critical Issues

TitleIssueInstances
[N-1] Dead-codeDead-code3
[N-2] Duplicated require()/revert() checks should be refactored to a modifier or functionDuplicated require()/revert() checks should be refactored to a modifier or function9
[N-3] Lack of Explicit Visibility Declaration in State VariablesLack of Explicit Visibility Declaration in State Variables4
[N-4] Inconsistent usage of require/errorInconsistent usage of require/error1
[N-5] Max Value Optimization Replacing 2^n - 1 with type(uint n).maxMax Value Optimization Replacing 2^n - 1 with type(uint n).max4
[N-6] Token contract should have a blacklist function or modifierToken contract should have a blacklist function or modifier2
[N-7] Missing inheritanceMissing inheritance3
[N-8] Name reusedName reused1
[N-9] Override function arguments that are unused should have the variable name removed or commented outOverride function arguments that are unused should have the variable name removed or commented out2
[N-10] Variable names too similarVariable names too similar41
[N-11] Single Source of Constants Ensuring Consistency and IntegritySingle Source of Constants Ensuring Consistency and Integrity1

Total: 1 issues

Array out of bounds accesses

  • Severity: Low
  • Confidence: Medium

Description

If the lengths of arrays are not checked before they're accessed, user operations may not be executed properly due to the potential issue of accessing an array out of its bounds. In Solidity, accessing an array beyond its boundaries can cause a runtime error known as an out-of-bounds exception. This error arises when attempting to read or write to an element of an array that does not exist. Therefore, it is critical to avoid out-of-bounds exceptions while accessing arrays in Solidity code to prevent unexpected halts and possible loss of funds.

<details> <summary> There are 5 instances of this issue: </summary>
  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 64 uint256[] calldata amounts

is accessed on File: contracts/PositionManager/OptionsPositionManager.sol

Line: 73 uint amount = amounts[k]

index that might be out-of-bounds

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L64

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 66 address[] memory sourceSwap

is accessed on File: contracts/PositionManager/OptionsPositionManager.sol

Line: 74 withdrawOptionAssets(poolId, asset, amount, sourceSwap[k], user)

index that might be out-of-bounds

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L66

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 86 uint256[] calldata amounts

is accessed on File: contracts/PositionManager/OptionsPositionManager.sol

Line: 97 uint amount = amounts[k]

index that might be out-of-bounds

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L86

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 470 address[] memory path

is accessed on File: contracts/PositionManager/OptionsPositionManager.sol

Line: 474 checkSetAllowance(path[0], address(ammRouter), amount)

index that might be out-of-bounds

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L470

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 491 address[] memory path

is accessed on File: contracts/PositionManager/OptionsPositionManager.sol

Line: 492 checkSetAllowance(path[0], address(ammRouter), maxAmount)

index that might be out-of-bounds

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L491

</details>

Missing contract-existence checks before low-level calls

  • Severity: Low
  • Confidence: High

Description

Low-level calls return success if there is no code present at the specified address. In addition to the zero-address checks, add a check to verify that <address>.code.length > 0 or use the extcodesize assembly operation to verify the presence of contract code at the specified address. Both these methods ensure the existence of a contract before making a low-level call.

<details> <summary> There are 3 instances of this issue: </summary>
  • File: contracts/helper/V3Proxy.sol
Line: 156 msg.sender.call{value: msg.value - amounts[0]}("")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L156

  • File: contracts/helper/V3Proxy.sol
Line: 174 payable(msg.sender).call{value: amountOut}("")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L174

  • File: contracts/helper/V3Proxy.sol
Line: 192 payable(msg.sender).call{value: amounts[1]}("")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L192

</details>

Burn functions must be protected with a modifier

  • Severity: Low
  • Confidence: High

Description

If burn functions are not protected by a modifier, any address may be able to burn tokens, potentially leading to financial loss. A common modifier to use is onlyOwner.

<details> <summary> There are 3 instances of this issue: </summary>
  • File: interfaces/IAToken.sol
Line: 61 function burn( address user, address receiverOfUnderlying, uint256 amount, uint256 index ) external;

Burn function without a protective modifier. https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IAToken.sol#L61-L66

  • File: interfaces/IUniswapV2Pair.sol
Line: 46 function burn(address to) external returns (uint amount0, uint amount1);

Burn function without a protective modifier. https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IUniswapV2Pair.sol#L46

  • File: interfaces/INonfungiblePositionManager.sol
Line: 179 function burn(uint256 tokenId) external payable;

Burn function without a protective modifier. https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/INonfungiblePositionManager.sol#L179

</details>

Missing gap Storage Variable in Upgradeable Contract

  • Severity: Low
  • Confidence: High

Description

upgradeable contracts that are missing a '__gap' storage variable. In upgradeable contracts, it is important to reserve storage slots for future versions to introduce new storage variables. The '__gap' storage variable acts as a placeholder, allowing for seamless upgrades without affecting existing storage layout.When a contract is not designed with a '__gap' storage variable, adding new storage variables in subsequent versions becomes problematic. It can lead to storage collisions or layout incompatibilities, making it difficult to upgrade the contract without requiring costly data migrations or redeployments.

<details> <summary> There are 2 instances of this issue: </summary>
  • File: interfaces/IAToken.sol
Line: 9 interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken

missing __gap storage variable

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IAToken.sol#L9-L112

  • File: interfaces/IInitializableAToken.sol
Line: 12 interface IInitializableAToken

missing __gap storage variable

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IInitializableAToken.sol#L12-L55

</details>

Local variable shadowing

  • Severity: Low
  • Confidence: High

Description

Detection of shadowing using local variables.

<details> <summary> There are 4 instances of this issue: </summary>
  • File: interfaces/IAaveIncentivesController.sol
Line: 67 address[] calldata assets

shadows: - File: interfaces/IAaveIncentivesController.sol

Line: 39 function assets(address asset) external view returns ( uint128, uint128, uint256 );

(function)

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IAaveIncentivesController.sol#L67

  • File: interfaces/IAaveIncentivesController.sol
Line: 87 address[] calldata assets

shadows: - File: interfaces/IAaveIncentivesController.sol

Line: 39 function assets(address asset) external view returns ( uint128, uint128, uint256 );

(function)

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IAaveIncentivesController.sol#L87

  • File: interfaces/IAaveIncentivesController.sol
Line: 99 address[] calldata assets

shadows: - File: interfaces/IAaveIncentivesController.sol

Line: 39 function assets(address asset) external view returns ( uint128, uint128, uint256 );

(function)

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IAaveIncentivesController.sol#L99

  • File: interfaces/IAaveIncentivesController.sol
Line: 113 address[] calldata assets

shadows: - File: interfaces/IAaveIncentivesController.sol

Line: 39 function assets(address asset) external view returns ( uint128, uint128, uint256 );

(function)

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IAaveIncentivesController.sol#L113

</details>

Reentrancy vulnerabilities

  • Severity: Low
  • Confidence: Medium

Description

Detection of the reentrancy bug. Only report reentrancy that acts as a double call (see reentrancy-eth, reentrancy-no-eth).

<details> <summary> There are 10 instances of this issue: </summary>
  • Reentrancy in File: contracts/RangeManager.sol
Line: 75 function generateRange(uint128 startX10, uint128 endX10, string memory startName, string memory endName, address beacon) external onlyOwner

: External calls: - File: contracts/RangeManager.sol

Line: 79 BeaconProxy trbp = new BeaconProxy(beacon, "")
State variables written after the call(s): - File: contracts/RangeManager.sol
Line: 80 tokenisedRanges.push( TokenisableRange(address(trbp)) )

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L75-L88

  • Reentrancy in File: contracts/RangeManager.sol
Line: 75 function generateRange(uint128 startX10, uint128 endX10, string memory startName, string memory endName, address beacon) external onlyOwner

: External calls: - File: contracts/RangeManager.sol

Line: 79 BeaconProxy trbp = new BeaconProxy(beacon, "")
- File: contracts/RangeManager.sol
Line: 81 trbp = new BeaconProxy(beacon, "")
State variables written after the call(s): - File: contracts/RangeManager.sol
Line: 82 tokenisedTicker.push( TokenisableRange(address(trbp)) )

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L75-L88

  • Reentrancy in File: contracts/TokenisableRange.sol
Line: 167 function claimFee() public

: External calls: - File: contracts/TokenisableRange.sol

Line: 168 (uint256 newFee0, uint256 newFee1) = POS_MGR.collect( INonfungiblePositionManager.CollectParams({ tokenId: tokenId, recipient: address(this), amount0Max: type(uint128).max, amount1Max: type(uint128).max }) )
- File: contracts/TokenisableRange.sol
Line: 180 TOKEN0.token.safeTransfer(treasury, tf0)
- File: contracts/TokenisableRange.sol
Line: 181 TOKEN1.token.safeTransfer(treasury, tf1)
State variables written after the call(s): - File: contracts/TokenisableRange.sol
Line: 183 fee0 = fee0 + newFee0 - tf0
- File: contracts/TokenisableRange.sol
Line: 184 fee1 = fee1 + newFee1 - tf1

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L167-L215

  • Reentrancy in File: contracts/TokenisableRange.sol
Line: 134 function init(uint n0, uint n1) external

: External calls: - File: contracts/TokenisableRange.sol

Line: 138 TOKEN0.token.safeTransferFrom(msg.sender, address(this), n0)
- File: contracts/TokenisableRange.sol
Line: 139 TOKEN1.token.safeTransferFrom(msg.sender, address(this), n1)
- File: contracts/TokenisableRange.sol
Line: 140 TOKEN0.token.safeIncreaseAllowance(address(POS_MGR), n0)
- File: contracts/TokenisableRange.sol
Line: 141 TOKEN1.token.safeIncreaseAllowance(address(POS_MGR), n1)
- File: contracts/TokenisableRange.sol
Line: 142 (tokenId, liquidity, , ) = POS_MGR.mint( INonfungiblePositionManager.MintParams({ token0: address(TOKEN0.token), token1: address(TOKEN1.token), fee: feeTier * 100, tickLower: lowerTick, tickUpper: upperTick, amount0Desired: n0, amount1Desired: n1, amount0Min: n0 * 95 / 100, amount1Min: n1 * 95 / 100, recipient: address(this), deadline: block.timestamp }) )
State variables written after the call(s): - File: contracts/TokenisableRange.sol
Line: 142 (tokenId, liquidity, , ) = POS_MGR.mint( INonfungiblePositionManager.MintParams({ token0: address(TOKEN0.token), token1: address(TOKEN1.token), fee: feeTier * 100, tickLower: lowerTick, tickUpper: upperTick, amount0Desired: n0, amount1Desired: n1, amount0Min: n0 * 95 / 100, amount1Min: n1 * 95 / 100, recipient: address(this), deadline: block.timestamp }) )
- File: contracts/TokenisableRange.sol
Line: 142 (tokenId, liquidity, , ) = POS_MGR.mint( INonfungiblePositionManager.MintParams({ token0: address(TOKEN0.token), token1: address(TOKEN1.token), fee: feeTier * 100, tickLower: lowerTick, tickUpper: upperTick, amount0Desired: n0, amount1Desired: n1, amount0Min: n0 * 95 / 100, amount1Min: n1 * 95 / 100, recipient: address(this), deadline: block.timestamp }) )

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L134-L163

  • Reentrancy in File: contracts/helper/V3Proxy.sol
Line: 147 function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) payable external returns (uint[] memory amounts)

: External calls: - File: contracts/helper/V3Proxy.sol

Line: 151 amounts[0] = ROUTER.exactOutputSingle{value: msg.value}(ISwapRouter.ExactOutputSingleParams(path[0], path[1], feeTier, msg.sender, deadline, amountOut, msg.value, 0))
State variables written after the call(s): - File: contracts/helper/V3Proxy.sol
Line: 153 acceptPayable = true

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L147-L158

  • Reentrancy in File: contracts/helper/V3Proxy.sol
Line: 147 function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) payable external returns (uint[] memory amounts)

: External calls: - File: contracts/helper/V3Proxy.sol

Line: 151 amounts[0] = ROUTER.exactOutputSingle{value: msg.value}(ISwapRouter.ExactOutputSingleParams(path[0], path[1], feeTier, msg.sender, deadline, amountOut, msg.value, 0))
- File: contracts/helper/V3Proxy.sol
Line: 154 ROUTER.refundETH()
External calls sending eth: - File: contracts/helper/V3Proxy.sol
Line: 151 amounts[0] = ROUTER.exactOutputSingle{value: msg.value}(ISwapRouter.ExactOutputSingleParams(path[0], path[1], feeTier, msg.sender, deadline, amountOut, msg.value, 0))
State variables written after the call(s): - File: contracts/helper/V3Proxy.sol
Line: 155 acceptPayable = false

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L147-L158

  • Reentrancy in File: contracts/helper/V3Proxy.sol
Line: 178 function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) payable external returns (uint[] memory amounts)

: External calls: - File: contracts/helper/V3Proxy.sol

Line: 182 ogInAsset.safeTransferFrom(msg.sender, address(this), amountIn)
- File: contracts/helper/V3Proxy.sol
Line: 183 ogInAsset.safeApprove(address(ROUTER), amountIn)
- File: contracts/helper/V3Proxy.sol
Line: 186 amounts[1] = ROUTER.exactInputSingle(ISwapRouter.ExactInputSingleParams(path[0], path[1], feeTier, address(this), deadline, amountIn, amountOutMin, 0))
- File: contracts/helper/V3Proxy.sol
Line: 187 ogInAsset.safeApprove(address(ROUTER), 0)
State variables written after the call(s): - File: contracts/helper/V3Proxy.sol
Line: 189 acceptPayable = true

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L178-L194

  • Reentrancy in File: contracts/helper/V3Proxy.sol
Line: 178 function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) payable external returns (uint[] memory amounts)

: External calls: - File: contracts/helper/V3Proxy.sol

Line: 182 ogInAsset.safeTransferFrom(msg.sender, address(this), amountIn)
- File: contracts/helper/V3Proxy.sol
Line: 183 ogInAsset.safeApprove(address(ROUTER), amountIn)
- File: contracts/helper/V3Proxy.sol
Line: 186 amounts[1] = ROUTER.exactInputSingle(ISwapRouter.ExactInputSingleParams(path[0], path[1], feeTier, address(this), deadline, amountIn, amountOutMin, 0))
- File: contracts/helper/V3Proxy.sol
Line: 187 ogInAsset.safeApprove(address(ROUTER), 0)
- File: contracts/helper/V3Proxy.sol
Line: 190 weth.withdraw(amounts[1])
State variables written after the call(s): - File: contracts/helper/V3Proxy.sol
Line: 191 acceptPayable = false

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L178-L194

  • Reentrancy in File: contracts/helper/V3Proxy.sol
Line: 160 function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) payable external returns (uint[] memory amounts)

: External calls: - File: contracts/helper/V3Proxy.sol

Line: 164 ogInAsset.safeTransferFrom(msg.sender, address(this), amountInMax)
- File: contracts/helper/V3Proxy.sol
Line: 165 ogInAsset.safeApprove(address(ROUTER), amountInMax)
- File: contracts/helper/V3Proxy.sol
Line: 167 amounts[0] = ROUTER.exactOutputSingle(ISwapRouter.ExactOutputSingleParams(path[0], path[1], feeTier, address(this), deadline, amountOut, amountInMax, 0))
- File: contracts/helper/V3Proxy.sol
Line: 169 ogInAsset.safeApprove(address(ROUTER), 0)
State variables written after the call(s): - File: contracts/helper/V3Proxy.sol
Line: 171 acceptPayable = true

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L160-L176

  • Reentrancy in File: contracts/helper/V3Proxy.sol
Line: 160 function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) payable external returns (uint[] memory amounts)

: External calls: - File: contracts/helper/V3Proxy.sol

Line: 164 ogInAsset.safeTransferFrom(msg.sender, address(this), amountInMax)
- File: contracts/helper/V3Proxy.sol
Line: 165 ogInAsset.safeApprove(address(ROUTER), amountInMax)
- File: contracts/helper/V3Proxy.sol
Line: 167 amounts[0] = ROUTER.exactOutputSingle(ISwapRouter.ExactOutputSingleParams(path[0], path[1], feeTier, address(this), deadline, amountOut, amountInMax, 0))
- File: contracts/helper/V3Proxy.sol
Line: 169 ogInAsset.safeApprove(address(ROUTER), 0)
- File: contracts/helper/V3Proxy.sol
Line: 172 weth.withdraw(amountOut)
State variables written after the call(s): - File: contracts/helper/V3Proxy.sol
Line: 173 acceptPayable = false

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L160-L176

</details>

Restrictive casts in assignments

  • Severity: Low
  • Confidence: Medium

Description

This detector flags the instances where a restrictive cast is being used in an assignment. For example, if an address variable 'foo' is used in an expression like 'IERC20 token = FooToken(foo)', the specific cast to 'FooToken' is unnecessary as the compiler only checks that 'FooToken' extends 'IERC20' and does not check any function signatures. In such cases, it would be more appropriate to use 'IERC20 token = IERC20(foo)' or even better, 'FooToken token = FooToken(foo)'. The former allows the file in which it's used to possibly remove the import for 'FooToken', leading to cleaner and more efficient code.

<details> <summary> There are 3 instances of this issue: </summary>
  • File: contracts/GeVault.sol
Line: 370 uint decimals0 = token0.decimals()
// @audit: uint256 vs uint8

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L370

  • File: contracts/GeVault.sol
Line: 371 uint decimals1 = token1.decimals()
// @audit: uint256 vs uint8

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L371

  • File: contracts/TokenisableRange.sol
Line: 274 feeLiquidity = newLiquidity * ( (fee0 * TOKEN0_PRICE / 10 ** TOKEN0.decimals) + (fee1 * TOKEN1_PRICE / 10 ** TOKEN1.decimals) ) / ( (added0 * TOKEN0_PRICE / 10 ** TOKEN0.decimals) + (added1 * TOKEN1_PRICE / 10 ** TOKEN1.decimals) )
// @audit: uint256 vs uint128

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L274-L275

</details>

Dead-code

  • Severity: Non-Critical
  • Confidence: Medium

Description

Functions that are not sued.

<details> <summary> There are 3 instances of this issue: </summary>
  • File: interfaces/PoolAddress.sol
Line: 33 function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool)

is never used and should be removed

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/PoolAddress.sol#L33-L49

  • File: interfaces/PoolAddress.sol
Line: 20 function getPoolKey( address tokenA, address tokenB, uint24 fee ) internal pure returns (PoolKey memory)

is never used and should be removed

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/PoolAddress.sol#L20-L27

  • File: contracts/PositionManager/PositionManager.sol
Line: 138 function validateValuesAgainstOracle(IPriceOracle oracle, address assetA, uint amountA, address assetB, uint amountB) internal view

is never used and should be removed

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/PositionManager.sol#L138-L147

</details>

Duplicated require()/revert() checks should be refactored to a modifier or function

  • Severity: Non-Critical
  • Confidence: High

Description

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.

<details> <summary> There are 9 instances of this issue: </summary>
  • File: contracts/GeVault.sol
Line: 120 require(t0 == token0 && t1 == token1, "GEV: Invalid TR")

Has duplicate:<br>File: contracts/GeVault.sol

Line: 141 require(t0 == token0 && t1 == token1, "GEV: Invalid TR")

File: contracts/GeVault.sol

Line: 170 require(t0 == token0 && t1 == token1, "GEV: Invalid TR")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L120

  • File: contracts/GeVault.sol
Line: 203 require(poolMatchesOracle(), "GEV: Oracle Error")

Has duplicate:<br>File: contracts/GeVault.sol

Line: 215 require(poolMatchesOracle(), "GEV: Oracle Error")

File: contracts/GeVault.sol

Line: 250 require(poolMatchesOracle(), "GEV: Oracle Error")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L203

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 69 require( address(lendingPool) == msg.sender, "OPM: Call Unallowed")

Has duplicate:<br>File: contracts/PositionManager/OptionsPositionManager.sol

Line: 91 require( address(lendingPool) == msg.sender, "OPM: Call Unallowed")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L69

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 393 require( LP.getReserveData(optionAddress).aTokenAddress != address(0x0), "OPM: Invalid Address" )

Has duplicate:<br>File: contracts/PositionManager/OptionsPositionManager.sol

Line: 420 require( LP.getReserveData(optionAddress).aTokenAddress != address(0x0), "OPM: Invalid Address" )

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L393

  • File: contracts/helper/LPOracle.sol
Line: 63 require(timeStamp > 0, "Round not complete")

Has duplicate:<br>File: contracts/helper/OracleConvert.sol

Line: 44 require(timeStamp > 0, "Round not complete")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/LPOracle.sol#L63

  • File: contracts/helper/V3Proxy.sol
Line: 87 require(acceptPayable, "CannotReceiveETH")

Has duplicate:<br>File: contracts/helper/V3Proxy.sol

Line: 91 require(acceptPayable, "CannotReceiveETH")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L87

  • File: contracts/helper/V3Proxy.sol
Line: 99 require(path.length == 2, "Direct swap only")

Has duplicate:<br>File: contracts/helper/V3Proxy.sol

Line: 106 require(path.length == 2, "Direct swap only")

File: contracts/helper/V3Proxy.sol

Line: 113 require(path.length == 2, "Direct swap only")

File: contracts/helper/V3Proxy.sol

Line: 125 require(path.length == 2, "Direct swap only")

File: contracts/helper/V3Proxy.sol

Line: 138 require(path.length == 2, "Direct swap only")

File: contracts/helper/V3Proxy.sol

Line: 148 require(path.length == 2, "Direct swap only")

File: contracts/helper/V3Proxy.sol

Line: 161 require(path.length == 2, "Direct swap only")

File: contracts/helper/V3Proxy.sol

Line: 179 require(path.length == 2, "Direct swap only")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L99

  • File: contracts/helper/V3Proxy.sol
Line: 139 require(path[0] == ROUTER.WETH9(), "Invalid path")

Has duplicate:<br>File: contracts/helper/V3Proxy.sol

Line: 149 require(path[0] == ROUTER.WETH9(), "Invalid path")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L139

  • File: contracts/helper/V3Proxy.sol
Line: 162 require(path[1] == ROUTER.WETH9(), "Invalid path")

Has duplicate:<br>File: contracts/helper/V3Proxy.sol

Line: 180 require(path[1] == ROUTER.WETH9(), "Invalid path")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L162

</details>

Lack of Explicit Visibility Declaration in State Variables

  • Severity: Non-Critical
  • Confidence: High

Description

This detector identifies state variables that are missing explicit visibility declarations. By default, without explicit declaration, the visibility of such variables is set to 'internal'. While this does not necessarily lead to vulnerabilities, explicitly declaring the visibility of each state variable can improve code readability and maintainability. Therefore, it is recommended to always specify the visibility, even when it's the default 'internal'.

<details> <summary> There are 4 instances of this issue: </summary>
  • File: contracts/GeVault.sol
Line: 41 RangeManager rangeManager

State variable lacks explicit visibility. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L41

  • File: contracts/TokenisableRange.sol
Line: 45 string _name

State variable lacks explicit visibility. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L45

  • File: contracts/TokenisableRange.sol
Line: 46 string _symbol

State variable lacks explicit visibility. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L46

  • File: contracts/helper/V3Proxy.sol
Line: 65 bool acceptPayable

State variable lacks explicit visibility. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L65

</details>

Inconsistent usage of require/error

  • Severity: Non-Critical
  • Confidence: High

Description

Some parts of the codebase use require statements, while others use custom errors. Consider refactoring the code to use the same approach: the following findings represent the minority of require vs error, and they show one occurrence in each contract, for brevity.

<details> <summary> There are 1 instances of this issue: </summary>
  • File: contracts/RangeManager.sol
Line: 25 contract RangeManager is ReentrancyGuard, Ownable

File: contracts/RangeManager.sol

Line: 66 revert("Range overlap")

The contract RangeManager uses both require and custom revert for error handling.

There are 5 require statement(s) and 1 custom revert statement(s).

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L25-L215

</details>

Token contract should have a blacklist function or modifier

  • Severity: Non-Critical
  • Confidence: Medium

Description

NFT thefts have increased recently, so with the addition of stolen NFTs to the platform, NFTs can be converted into liquidity. To prevent this, we recommend adding a blacklist function.

<details> <summary> There are 2 instances of this issue: </summary>
  • File: contracts/GeVault.sol
Line: 27 contract GeVault is ERC20, Ownable, ReentrancyGuard

Token contract does not contain a blacklist. Consider adding one for increased security. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L27-L466

  • File: contracts/TokenisableRange.sol
Line: 18 contract TokenisableRange is ERC20("", ""), ReentrancyGuard

Token contract does not contain a blacklist. Consider adding one for increased security. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L18-L384

</details>

Variable names too similar

  • Severity: Non-Critical
  • Confidence: Medium

Description

Detect variables with names that are too similar.

<details> <summary> There are 41 instances of this issue: </summary>
  • Variable File: interfaces/IUniswapV2Router01.sol
Line: 13 uint256 amountADesired

is too similar to File: interfaces/IUniswapV2Router01.sol

Line: 14 uint256 amountBDesired

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IUniswapV2Router01.sol#L13

  • Variable File: interfaces/IUniswapV3SwapCallback.sol
Line: 17 int256 amount0Delta

is too similar to File: interfaces/IUniswapV3SwapCallback.sol

Line: 18 int256 amount1Delta

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/IUniswapV3SwapCallback.sol#L17

  • Variable File: contracts/GeVault.sol
Line: 339 uint availToken0 = token0.balanceOf(address(this))

is too similar to File: contracts/GeVault.sol

Line: 340 uint availToken1 = token1.balanceOf(address(this))

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L339

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 521 uint priceAssetA = oracle.getAssetPrice(assetA)

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 522 uint priceAssetB = oracle.getAssetPrice(assetB)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L521

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 336 uint token0Amount

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 270 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L336

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 270 uint token0Amount

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 336 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L270

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 270 uint token0Amount

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 360 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L270

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 336 uint token0Amount

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 336 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L336

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 270 uint token0Amount

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 270 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L270

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 336 uint token0Amount

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 360 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L336

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 359 uint token0Amount

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 270 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L359

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 359 uint token0Amount

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 336 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L359

  • Variable File: contracts/PositionManager/OptionsPositionManager.sol
Line: 359 uint token0Amount

is too similar to File: contracts/PositionManager/OptionsPositionManager.sol

Line: 360 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L359

  • Variable File: contracts/TokenisableRange.sol
Line: 269 uint256 TOKEN0_PRICE = ORACLE.getAssetPrice(address(TOKEN0.token))

is too similar to File: contracts/TokenisableRange.sol

Line: 270 uint256 TOKEN1_PRICE = ORACLE.getAssetPrice(address(TOKEN1.token))

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L269

  • Variable File: contracts/TokenisableRange.sol
Line: 352 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 270 uint256 TOKEN1_PRICE = ORACLE.getAssetPrice(address(TOKEN1.token))

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L352

  • Variable File: contracts/TokenisableRange.sol
Line: 343 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 270 uint256 TOKEN1_PRICE = ORACLE.getAssetPrice(address(TOKEN1.token))

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L343

  • Variable File: contracts/TokenisableRange.sol
Line: 333 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 270 uint256 TOKEN1_PRICE = ORACLE.getAssetPrice(address(TOKEN1.token))

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L333

  • Variable File: contracts/TokenisableRange.sol
Line: 269 uint256 TOKEN0_PRICE = ORACLE.getAssetPrice(address(TOKEN0.token))

is too similar to File: contracts/TokenisableRange.sol

Line: 352 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L269

  • Variable File: contracts/TokenisableRange.sol
Line: 352 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 352 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L352

  • Variable File: contracts/TokenisableRange.sol
Line: 343 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 352 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L343

  • Variable File: contracts/TokenisableRange.sol
Line: 333 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 352 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L333

  • Variable File: contracts/TokenisableRange.sol
Line: 343 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 343 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L343

  • Variable File: contracts/TokenisableRange.sol
Line: 343 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 333 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L343

  • Variable File: contracts/TokenisableRange.sol
Line: 352 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 333 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L352

  • Variable File: contracts/TokenisableRange.sol
Line: 269 uint256 TOKEN0_PRICE = ORACLE.getAssetPrice(address(TOKEN0.token))

is too similar to File: contracts/TokenisableRange.sol

Line: 343 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L269

  • Variable File: contracts/TokenisableRange.sol
Line: 333 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 333 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L333

  • Variable File: contracts/TokenisableRange.sol
Line: 269 uint256 TOKEN0_PRICE = ORACLE.getAssetPrice(address(TOKEN0.token))

is too similar to File: contracts/TokenisableRange.sol

Line: 333 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L269

  • Variable File: contracts/TokenisableRange.sol
Line: 352 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 343 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L352

  • Variable File: contracts/TokenisableRange.sol
Line: 333 uint TOKEN0_PRICE

is too similar to File: contracts/TokenisableRange.sol

Line: 343 uint TOKEN1_PRICE

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L333

  • Variable File: contracts/TokenisableRange.sol
Line: 240 uint256 token0Amount

is too similar to File: contracts/TokenisableRange.sol

Line: 368 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L240

  • Variable File: contracts/TokenisableRange.sol
Line: 368 uint token0Amount

is too similar to File: contracts/TokenisableRange.sol

Line: 368 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L368

  • Variable File: contracts/TokenisableRange.sol
Line: 240 uint256 token0Amount

is too similar to File: contracts/TokenisableRange.sol

Line: 377 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L240

  • Variable File: contracts/TokenisableRange.sol
Line: 240 uint256 token0Amount

is too similar to File: contracts/TokenisableRange.sol

Line: 240 uint256 token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L240

  • Variable File: contracts/TokenisableRange.sol
Line: 377 uint token0Amount

is too similar to File: contracts/TokenisableRange.sol

Line: 377 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L377

  • Variable File: contracts/TokenisableRange.sol
Line: 368 uint token0Amount

is too similar to File: contracts/TokenisableRange.sol

Line: 377 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L368

  • Variable File: contracts/TokenisableRange.sol
Line: 368 uint token0Amount

is too similar to File: contracts/TokenisableRange.sol

Line: 240 uint256 token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L368

  • Variable File: contracts/TokenisableRange.sol
Line: 377 uint token0Amount

is too similar to File: contracts/TokenisableRange.sol

Line: 368 uint token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L377

  • Variable File: contracts/TokenisableRange.sol
Line: 377 uint token0Amount

is too similar to File: contracts/TokenisableRange.sol

Line: 240 uint256 token1Amount

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L377

  • Variable File: contracts/TokenisableRange.sol
Line: 204 uint token0Price = ORACLE.getAssetPrice(address(TOKEN0.token))

is too similar to File: contracts/TokenisableRange.sol

Line: 205 uint token1Price = ORACLE.getAssetPrice(address(TOKEN1.token))

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L204

  • Variable File: interfaces/INonfungiblePositionManager.sol
Line: 73 uint256 feeGrowthInside0LastX128

is too similar to File: interfaces/INonfungiblePositionManager.sol

Line: 74 uint256 feeGrowthInside1LastX128

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/INonfungiblePositionManager.sol#L73

  • Variable File: interfaces/INonfungiblePositionManager.sol
Line: 75 uint128 tokensOwed0

is too similar to File: interfaces/INonfungiblePositionManager.sol

Line: 76 uint128 tokensOwed1

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/INonfungiblePositionManager.sol#L75

</details>

Single Source of Constants Ensuring Consistency and Integrity

  • Severity: Non-Critical
  • Confidence: High

Description

It suggests that constants should be defined in only one contract to prevent values from becoming out of sync when updates are made in different locations.

Consider consolidating constant definitions in a single contract or using a centralized approach, such as creating an internal constant in a library. This ensures that all references to the constant retrieve the same value, eliminating inconsistencies and the potential for errors caused by mismatched values.

Additionally, if a variable is used as a local cache of another contract's value, it is recommended to make the cache variable internal or private. By doing so, external users are required to query the contract with the source of truth, ensuring that callers always obtain the most up-to-date and accurate information.

<details> <summary> There are 1 instances of this issue: </summary>
  • INonfungiblePositionManager constant public POS_MGR = INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88) is redefines:
  • File: contracts/RangeManager.sol
Line: 36 INonfungiblePositionManager constant public POS_MGR = INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88)
  • File: contracts/TokenisableRange.sol
Line: 58 INonfungiblePositionManager constant public POS_MGR = INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L36

</details>

Missing inheritance

  • Severity: Non-Critical
  • Confidence: High

Description

This detector identifies instances where a contract defines functions that match an interface's signature, but does not explicitly inherit from the interface. Explicitly declaring inheritance relationships can improve code readability and maintainability, and ensures that the contract adheres to the defined interface.

<details> <summary> There are 3 instances of this issue: </summary>
  • File: contracts/helper/LPOracle.sol
Line: 17 contract LPOracle

should inherit from File: contracts/helper/LPOracle.sol

Line: 13 interface IERC20

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/LPOracle.sol#L17-L105

  • File: contracts/helper/OracleConvert.sol
Line: 15 contract OracleConvert

should inherit from File: contracts/helper/LPOracle.sol

Line: 13 interface IERC20

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/OracleConvert.sol#L15-L81

  • File: contracts/helper/V3Proxy.sol
Line: 60 contract V3Proxy is ReentrancyGuard, Ownable

should inherit from File: contracts/PositionManager/OptionsPositionManager.sol

Line: 7 interface AmountsRouter

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L60-L196

</details>

Max Value Optimization Replacing 2^n - 1 with type(uint n).max

  • Severity: Non-Critical
  • Confidence: High

Description

In Solidity, 2**<n> - 1 is commonly used to represent the maximum value for an unsigned integer of n bits. However, this expression can be replaced with type(uint<n>).max, which provides a more explicit and self-explanatory representation of the maximum value.If the -1 adjustment is not present, you can still use type(uint<n>).max and add 1 to obtain the correct maximum value.

<details> <summary> There are 4 instances of this issue: </summary>
  • File: contracts/GeVault.sol
Line: 374 priceX8 = priceX8 * uint(sqrtPriceX96 / 2 ** 12) ** 2 * 1e8 / 2**168

should use max() instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L374

  • File: contracts/TokenisableRange.sol
Line: 99 int24 _upperTick = TickMath.getTickAtSqrtRatio( uint160( 2**48 * sqrt( (2 ** 96 * (10 ** TOKEN1.decimals)) * 1e10 / (uint256(startX10) * 10 ** TOKEN0.decimals) ) ) )

should use max() instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L99

  • File: contracts/TokenisableRange.sol
Line: 100 int24 _lowerTick = TickMath.getTickAtSqrtRatio( uint160( 2**48 * sqrt( (2 ** 96 * (10 ** TOKEN1.decimals)) * 1e10 / (uint256(endX10 ) * 10 ** TOKEN0.decimals) ) ) )

should use max() instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L100

  • File: contracts/TokenisableRange.sol
Line: 338 (amt0, amt1) = LiquidityAmounts.getAmountsForLiquidity( uint160( sqrt( (2 ** 192 * ((TOKEN0_PRICE * 10 ** TOKEN1.decimals) / TOKEN1_PRICE)) / ( 10 ** TOKEN0.decimals ) ) ), TickMath.getSqrtRatioAtTick(lowerTick), TickMath.getSqrtRatioAtTick(upperTick), liquidity)

should use max() instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L338

</details>

Name reused

  • Severity: Non-Critical
  • Confidence: High

Description

If a codebase has two contracts the similar names, the compilation artifacts will not contain one of the contracts with the duplicate name.

<details> <summary> There are 1 instances of this issue: </summary>
  • ISwapRouter is re-used:
    • File: contracts/helper/V3Proxy.sol
Line: 9 interface ISwapRouter
- File: interfaces/ISwapRouter.sol
Line: 9 interface ISwapRouter is IUniswapV3SwapCallback

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L9-L35

</details>

Override function arguments that are unused should have the variable name removed or commented out

  • Severity: Non-Critical
  • Confidence: High

Description

Unused arguments in overridden functions can lead to compiler warnings andcan make the code less readable. It is a good practice to remove or comment outunused arguments in these cases.

<details> <summary> There are 2 instances of this issue: </summary>
  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 41 uint256[] calldata premiums

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L41

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 42 address initiator

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L42

</details>

#0 - c4-pre-sort

2023-08-10T17:12:26Z

141345 marked the issue as high quality report

#1 - c4-sponsor

2023-08-15T05:52:53Z

Keref marked the issue as sponsor acknowledged

#2 - Keref

2023-08-15T05:53:00Z

Respect the hustle but that's trash automated chatGPT-level unchecked kind of report... 90% useless or non sensical content "Variable name too similar" for token0 and token1, blacklist stolen NFTs function...

4 valid feedback (not bug, just readability improvement): L7, N2, N3, N4

#3 - c4-sponsor

2023-08-15T05:53:22Z

Keref marked the issue as disagree with severity

#4 - c4-judge

2023-08-20T16:33:48Z

gzeon-c4 marked the issue as grade-a

#5 - c4-judge

2023-08-20T16:47:54Z

gzeon-c4 marked the issue as grade-b

Findings Information

Awards

17.345 USDC - $17.34

Labels

bug
G (Gas Optimization)
grade-b
G-16

External Links

Gas Optimization Issues

TitleIssueInstancesTotal Gas Saved
[G-1] Inefficient use of abi.encode()Inefficient use of abi.encode()2200
[G-2] Use assembly to emit eventsUse assembly to emit events351330
[G-3] Assembly optimization for low level callsAssembly optimization for low level calls3744
[G-4] Division operations between unsigned could be uncheckedDivision operations between unsigned could be unchecked2170
[G-5] Modulus operations that could be uncheckedModulus operations that could be unchecked3255
[G-6] Constants Variable Should Be Private for Gas OptimizationConstants Variable Should Be Private for Gas Optimization620400
[G-7] Use of emit inside a loopUse of emit inside a loop33078
[G-8] Identical Deployments Should be Replaced with CloneIdentical Deployments Should be Replaced with Clone1-
[G-9] Greater or Equal Comparison Costs Less Gas than Greater ComparisonGreater or Equal Comparison Costs Less Gas than Greater Comparison515
[G-10] Inefficient Parameter StorageInefficient Parameter Storage2100
[G-11] Inefficient Gas Usage in Solidity Smart Contracts Due to Long Error MessagesInefficient Gas Usage in Solidity Smart Contracts Due to Long Error Messages118
[G-12] Optimal State Variable OrderOptimal State Variable Order15000
[G-13] Short-circuit rules can be used to optimize some gas usageShort-circuit rules can be used to optimize some gas usage24200
[G-14] Safe Subtraction Should Be UncheckedSafe Subtraction Should Be Unchecked7595
[G-15] Unnecessary Casting of VariablesUnnecessary Casting of Variables1-
[G-16] Redundant Contract Existence Check in Consecutive External CallsRedundant Contract Existence Check in Consecutive External Calls151500
[G-17] Unused Named Return VariablesUnused Named Return Variables3-
[G-18] Unused state variableUnused state variable12900
[G-19] Usage of Custom Errors for Gas EfficiencyUsage of Custom Errors for Gas Efficiency8022080

Total: 19 issues

Inefficient Gas Usage in Solidity Smart Contracts Due to Long Error Messages

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 18

Description

If the string parameter of a require() or revert() function is longer than 32 bytes, it can lead to inefficiencies. This is because each extra memory word of bytes past the original 32 incurs an MSTORE operation, which costs 3 gas.

<details> <summary> There are 1 instances of this issue: </summary>
  • File: contracts/helper/FixedOracle.sol
Line: 11 require(msg.sender == owner, "Only the owner can call this function.")

make the message shorter than 32 bytes

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/FixedOracle.sol#L11

</details>

Inefficient use of abi.encode()

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 200

Description

The abi.encode() function is less gas efficient than abi.encodePacked(), especially when encoding only static types. This detector identifies instances where abi.encode() is used and all arguments are static, suggesting that abi.encodePacked() could potentially be used instead for better gas efficiency. Note: abi.encodePacked() should not be used if any of the arguments are dynamic types, as it could lead to hash collisions.

<details> <summary> There are 2 instances of this issue: </summary>
  • File: interfaces/PoolAddress.sol
Line: 35 pool = address( uint160( uint256( keccak256( abi.encodePacked( hex'ff', factory, keccak256(abi.encode(key.token0, key.token1, key.fee)), POOL_INIT_CODE_HASH ) ) ) ) )

use abi.encodepacked() instead.

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/PoolAddress.sol#L35-L48

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 199 bytes memory params = abi.encode(1, poolId, user, collateralAsset)

use abi.encodepacked() instead.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L199

</details>

Inefficient use of abi.encode()

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 200

Description

The abi.encode() function is less gas efficient than abi.encodePacked(), especially when encoding only static types. This detector identifies instances where abi.encode() is used and all arguments are static, suggesting that abi.encodePacked() could potentially be used instead for better gas efficiency. Note: abi.encodePacked() should not be used if any of the arguments are dynamic types, as it could lead to hash collisions.

<details> <summary> There are 2 instances of this issue: </summary>
  • File: interfaces/PoolAddress.sol
Line: 35 pool = address( uint160( uint256( keccak256( abi.encodePacked( hex'ff', factory, keccak256(abi.encode(key.token0, key.token1, key.fee)), POOL_INIT_CODE_HASH ) ) ) ) )

use abi.encodepacked() instead.

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/PoolAddress.sol#L35-L48

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 199 bytes memory params = abi.encode(1, poolId, user, collateralAsset)

use abi.encodepacked() instead.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L199

</details>

Use assembly to emit events

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 1330

Description

This detector checks for instances where a contract uses assembly code to emit events. While it's technically possible to emit events using inline assembly in Solidity, it's generally discouraged due to readability concerns and potential for errors. Events should usually be emitted using higher-level Solidity constructs.

<details> <summary> There are 35 instances of this issue: </summary>
  • File: contracts/GeVault.sol
Line: 103 emit SetEnabled(_isEnabled)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L103

  • File: contracts/GeVault.sol
Line: 110 emit SetTreasury(newTreasury)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L110

  • File: contracts/GeVault.sol
Line: 131 emit PushTick(tr)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L131

  • File: contracts/GeVault.sol
Line: 160 emit ShiftTick(tr)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L160

  • File: contracts/GeVault.sol
Line: 172 emit ModifyTick(tr, index)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L172

  • File: contracts/GeVault.sol
Line: 186 emit SetFee(newBaseFeeX4)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L186

  • File: contracts/GeVault.sol
Line: 193 emit SetTvlCap(newTvlCap)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L193

  • File: contracts/GeVault.sol
Line: 362 emit Rebalance(tickIndex)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L362

  • File: contracts/GeVault.sol
Line: 240 emit Withdraw(msg.sender, token, amount, liquidity)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L240

  • File: contracts/GeVault.sol
Line: 283 emit Deposit(msg.sender, token, amount, liquidity)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L283

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 323 emit ClosePosition(user, debtAsset, debt, amt0, amt1)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L323

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 148 emit BuyOptions(user, flashAsset, flashAmount, amount0, amount1)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L148

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 455 emit Swap(msg.sender, path[0], amount, path[1], received)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L455

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 106 emit LiquidatePosition(user, debtAsset, debt, amt0 - amts[0], amt1 - amts[1])

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L106

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 240 emit ReducedPosition(user, debtAsset, debt)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L240

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 401 emit SellOptions(msg.sender, optionAddress, deposited, amount0, amount1 )

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L401

  • File: contracts/RangeManager.sol
Line: 87 emit AddRange(startX10, endX10, tokenisedRanges.length - 1)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L87

  • File: contracts/RangeManager.sol
Line: 132 emit Withdraw(msg.sender, address(tokenisedTicker[step]), trAmt)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L132

  • File: contracts/RangeManager.sol
Line: 120 emit Withdraw(msg.sender, address(tokenisedRanges[step]), trAmt)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L120

  • File: contracts/RangeManager.sol
Line: 164 emit Deposit(msg.sender, address(tr), lpAmt)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L164

  • File: contracts/RoeRouter.sol
Line: 50 emit DeprecatePool(poolId)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L50

  • File: contracts/RoeRouter.sol
Line: 78 emit AddPool(poolId, lendingPoolAddressProvider)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L78

  • File: contracts/RoeRouter.sol
Line: 86 emit UpdateTreasury(newTreasury)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L86

  • File: contracts/TokenisableRange.sol
Line: 119 emit InitTR(address(asset0), address(asset1), startX10, endX10)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L119

  • File: contracts/TokenisableRange.sol
Line: 162 emit Deposit(msg.sender, 1e18)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L162

  • File: contracts/TokenisableRange.sol
Line: 214 emit ClaimFees(newFee0, newFee1)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L214

  • File: contracts/TokenisableRange.sol
Line: 284 emit Deposit(msg.sender, lpAmt)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L284

  • File: contracts/TokenisableRange.sol
Line: 326 emit Withdraw(msg.sender, lp)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L326

  • File: contracts/helper/FixedOracle.sol
Line: 26 emit SetHardcodedPrice(_hardcodedPrice)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/FixedOracle.sol#L26

  • File: contracts/helper/V3Proxy.sol
Line: 121 emit Swap(msg.sender, path[0], path[1], amounts[0], amounts[1])

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L121

  • File: contracts/helper/V3Proxy.sol
Line: 134 emit Swap(msg.sender, path[0], path[1], amounts[0], amounts[1])

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L134

  • File: contracts/helper/V3Proxy.sol
Line: 143 emit Swap(msg.sender, path[0], path[1], amounts[0], amounts[1])

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L143

  • File: contracts/helper/V3Proxy.sol
Line: 157 emit Swap(msg.sender, path[0], path[1], amounts[0], amounts[1])

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L157

  • File: contracts/helper/V3Proxy.sol
Line: 175 emit Swap(msg.sender, path[0], path[1], amounts[0], amounts[1])

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L175

  • File: contracts/helper/V3Proxy.sol
Line: 193 emit Swap(msg.sender, path[0], path[1], amounts[0], amounts[1])

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L193

</details>

Assembly optimization for low level calls

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 744

Description

Identifies situations where returnData is copied to memory even if the variable is not utilized. In such cases, a low level assembly call could be a more efficient approach."

// before
(bool success,) = payable(receiver).call{gas: gas, value: value}("");

//after
bool success;
assembly {
    success := call(gas, receiver, value, 0, 0, 0, 0)
}
<details> <summary> There are 3 instances of this issue: </summary>
  • File: contracts/helper/V3Proxy.sol
Line: 156 msg.sender.call{value: msg.value - amounts[0]}("")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L156

  • File: contracts/helper/V3Proxy.sol
Line: 174 payable(msg.sender).call{value: amountOut}("")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L174

  • File: contracts/helper/V3Proxy.sol
Line: 192 payable(msg.sender).call{value: amounts[1]}("")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L192

</details>

Division operations between unsigned could be unchecked

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 170

Description

Division operations on unsigned integers should be unchecked to save gas since they cannot overflow or underflow. Because unsigned integers cannot have negative values, execution of division operations outside unchecked blocks adds nothing but overhead. Saves about 85 gas.

<details> <summary> There are 2 instances of this issue: </summary>
  • File: contracts/TokenisableRange.sol
Line: 71 z = (x / z + z) / 2

Should be unchecked - x / z. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L71

  • File: contracts/helper/LPOracle.sol
Line: 49 z = (x / z + z) / 2

Should be unchecked - x / z. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/LPOracle.sol#L49

</details>

Modulus operations that could be unchecked

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 255

Description

Modulus operations should be unchecked to save gas since they cannot overflow or underflow. Execution of modulus operations outside unchecked blocks adds nothing but overhead. Saves about 30 gas.

<details> <summary> There are 3 instances of this issue: </summary>
  • File: contracts/TokenisableRange.sol
Line: 112 (_lowerTick + int24(feeTier)) % int24(feeTier * 2)

should be unchecked

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L112

  • File: contracts/TokenisableRange.sol
Line: 113 (_upperTick + int24(feeTier)) % int24(feeTier * 2)

should be unchecked

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L113

  • File: contracts/TokenisableRange.sol
Line: 106 (midleTick + int24(feeTier)) % int24(feeTier * 2)

should be unchecked

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L106

</details>

Constants Variable Should Be Private for Gas Optimization

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 20400

Description

This detector flags contracts that inefficiently use public for constant variables. 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.

<details> <summary> There are 6 instances of this issue: </summary>
  • File: contracts/GeVault.sol
Line: 62 uint public constant nearbyRanges = 2

nearbyRanges is a public. Consider making it private to save gas.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L62

  • File: contracts/RangeManager.sol
Line: 36 INonfungiblePositionManager constant public POS_MGR = INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88)

POS_MGR is a public. Consider making it private to save gas.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L36

  • File: contracts/TokenisableRange.sol
Line: 58 INonfungiblePositionManager constant public POS_MGR = INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88)

POS_MGR is a public. Consider making it private to save gas.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L58

  • File: contracts/TokenisableRange.sol
Line: 59 IUniswapV3Factory constant public V3_FACTORY = IUniswapV3Factory(0x1F98431c8aD98523631AE4a59f267346ea31F984)

V3_FACTORY is a public. Consider making it private to save gas.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L59

  • File: contracts/TokenisableRange.sol
Line: 60 address constant public treasury = 0x22Cc3f665ba4C898226353B672c5123c58751692

treasury is a public. Consider making it private to save gas.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L60

  • File: contracts/TokenisableRange.sol
Line: 61 uint constant public treasuryFee = 20

treasuryFee is a public. Consider making it private to save gas.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L61

</details>

Use of emit inside a loop

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 3078

Description

Emitting an event inside a loop performs a LOG op N times, where N is the loop length. This can lead to significant gas costs.

<details> <summary> There are 3 instances of this issue: </summary>
  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 148 emit BuyOptions(user, flashAsset, flashAmount, amount0, amount1)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L148

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 323 emit ClosePosition(user, debtAsset, debt, amt0, amt1)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L323

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 106 emit LiquidatePosition(user, debtAsset, debt, amt0 - amts[0], amt1 - amts[1])

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L106

</details>

Identical Deployments Should be Replaced with Clone

  • Severity: Gas Optimization
  • Confidence: High

Description

Detects instances where the same contract is deployed multiple times. Such cases might benefit from the clone factory pattern (EIP-1167), which can significantly reduce deployment gas costs.

<details> <summary> There are 1 instances of this issue: </summary>
  • - BeaconProxy is deployed in multiple functions:

File: contracts/RangeManager.sol

Line: 79 BeaconProxy trbp = new BeaconProxy(beacon, "")

File: contracts/RangeManager.sol

Line: 81 trbp = new BeaconProxy(beacon, "")

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L79

</details>

Optimal State Variable Order

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 5000

Description

Detects optimal variable order in contract storage layouts to decrease the number of storage slots used. Each storage slot used can cost at least 5,000 gas for each write operation, and potentially up to 20,000 gas if you're turning a zero value into a non-zero value. Hence, optimizing storage usage can result in significant gas savings. The real-world savings could vary depending on your contract's specific logic and the state of the Ethereum network.

<details> <summary> There are 1 instances of this issue: </summary>
  • Optimization opportunity in storage variable layout of contract File: contracts/TokenisableRange.sol
Line: 18 contract TokenisableRange is ERC20("", ""), ReentrancyGuard
  • original variable order (count: 17 slots)

    • int24 lowerTick
    • int24 upperTick
    • uint24 feeTier
    • uint256 tokenId
    • uint256 fee0
    • uint256 fee1
    • TokenisableRange.ASSET TOKEN0
    • TokenisableRange.ASSET TOKEN1
    • IAaveOracle ORACLE
    • string _name
    • string _symbol
    • TokenisableRange.ProxyState status
    • address creator
    • uint128 liquidity
    • address TREASURY_DEPRECATED
    • uint256 treasuryFee_deprecated
    • INonfungiblePositionManager POS_MGR
    • IUniswapV3Factory V3_FACTORY
    • address treasury
    • uint256 treasuryFee
  • optimized variable order (count: 16 slots)

    • IAaveOracle ORACLE
    • int24 lowerTick
    • int24 upperTick
    • uint24 feeTier
    • TokenisableRange.ProxyState status
    • address creator
    • address TREASURY_DEPRECATED
    • INonfungiblePositionManager POS_MGR
    • IUniswapV3Factory V3_FACTORY
    • address treasury
    • uint128 liquidity
    • uint256 tokenId
    • uint256 fee0
    • uint256 fee1
    • TokenisableRange.ASSET TOKEN0
    • TokenisableRange.ASSET TOKEN1
    • string _name
    • string _symbol
    • uint256 treasuryFee_deprecated
    • uint256 treasuryFee

Recomended optimizations will use 1 less slots.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L18-L384

</details>

Unused Named Return Variables

  • Severity: Gas Optimization
  • Confidence: High

Description

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 3 instances of this issue: </summary>
  • File: contracts/TokenisableRange.sol
Line: 352 function getValuePerLPAtPrice(uint TOKEN0_PRICE, uint TOKEN1_PRICE) public view returns (uint256 priceX1e8)

there is not use of this variables: @ priceX1e8

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L352-L357

  • File: contracts/TokenisableRange.sol
Line: 361 function latestAnswer() public view returns (uint256 priceX1e8)

there is not use of this variables: @ priceX1e8

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L361-L363

  • File: contracts/helper/OracleConvert.sol
Line: 78 function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)

there is not use of this variables: @ roundId @ answer @ startedAt @ updatedAt @ answeredInRound

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/OracleConvert.sol#L78-L80

</details>

Unused state variable

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 2900

Description

Unused state variable.

<details> <summary> There are 1 instances of this issue: </summary>
  • File: contracts/GeVault.sol
Line: 41 RangeManager rangeManager

is never used in File: contracts/GeVault.sol

Line: 27 contract GeVault is ERC20, Ownable, ReentrancyGuard

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L41

</details>

Safe Subtraction Should Be Unchecked

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 595

Description

This detector identifies subtraction operations where the subtraction could safely be unchecked. This occurs when a prior if-statement or require() function ensures that the first operand (minuend) is greater than or equal to the second operand (subtrahend). In these cases, an unchecked subtraction would not result in an underflow error, and can save gas by skipping the redundant check.

<details> <summary> There are 7 instances of this issue: </summary>
  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 298 swapTokensForExactTokens(ammRouter, token0Amount - amtA, amtB, path)

should be unchecked because there is check:<br>File: contracts/PositionManager/OptionsPositionManager.sol

Line: 295 amtA < token0Amount

<br><br> https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L298

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 303 swapTokensForExactTokens(ammRouter, token1Amount - amtB, amtA, path)

should be unchecked because there is check:<br>File: contracts/PositionManager/OptionsPositionManager.sol

Line: 300 amtB < token1Amount

<br><br> https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L303

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 316 amt0 = amtA - amt0

should be unchecked because there is check:<br>File: contracts/PositionManager/OptionsPositionManager.sol

Line: 315 amtA > amt0

<br><br> https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L316

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 320 amt1 = amtB - amt1

should be unchecked because there is check:<br>File: contracts/PositionManager/OptionsPositionManager.sol

Line: 319 amtB > amt1

<br><br> https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L320

  • File: contracts/PositionManager/PositionManager.sol
Line: 143 valueA = valueA / 10 ** (decimalsA - decimalsB)

should be unchecked because there is check:<br>File: contracts/PositionManager/PositionManager.sol

Line: 143 decimalsA > decimalsB

<br><br> https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/PositionManager.sol#L143

  • File: contracts/PositionManager/PositionManager.sol
Line: 144 valueB = valueB / 10 ** (decimalsB - decimalsA)

should be unchecked because there is check:<br>File: contracts/PositionManager/PositionManager.sol

Line: 144 decimalsA < decimalsB

<br><br> https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/PositionManager.sol#L144

  • File: contracts/helper/LPOracle.sol
Line: 90 norm_b = sqrt( a * b * priceA * 10**(decimalsB-decimalsA) / priceB )

should be unchecked because there is check:<br>File: contracts/helper/LPOracle.sol

Line: 89 decimalsB >= decimalsA

<br><br> https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/LPOracle.sol#L90

</details>

Unnecessary Casting of Variables

  • Severity: Gas Optimization
  • Confidence: High

Description

This detector scans for instances 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 1 instances of this issue: </summary>
  • File: contracts/RangeManager.sol
Line: 83 IAaveOracle oracle = IAaveOracle(ILendingPoolAddressesProvider( LENDING_POOL.getAddressesProvider() ).getPriceOracle())

Unnecessary cast: ILendingPoolAddressesProvider( LENDING_POOL.getAddressesProvider() ) it cast to the same type.<br> https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L83

</details>

Usage of Custom Errors for Gas Efficiency

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 22080

Description

This detector flags functions that use revert()/require() strings, which are less gas efficient than custom errors. Custom errors, available from Solidity version 0.8.4, save approximately 50 gas each time they're used by avoiding the need to allocate and store the revert string.

<details> <summary> There are 80 instances of this issue: </summary>
  • File: contracts/GeVault.sol
Line: 79 require(_treasury != address(0x0), "GEV: Invalid Treasury")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L79

  • File: contracts/GeVault.sol
Line: 80 require(_uniswapPool != address(0x0), "GEV: Invalid Pool")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L80

  • File: contracts/GeVault.sol
Line: 81 require(weth != address(0x0), "GEV: Invalid WETH")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L81

  • File: contracts/GeVault.sol
Line: 120 require(t0 == token0 && t1 == token1, "GEV: Invalid TR")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L120

  • File: contracts/GeVault.sol
Line: 125 require( t.lowerTick() > ticks[ticks.length-1].upperTick(), "GEV: Push Tick Overlap")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L125

  • File: contracts/GeVault.sol
Line: 127 require( t.upperTick() < ticks[ticks.length-1].lowerTick(), "GEV: Push Tick Overlap")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L127

  • File: contracts/GeVault.sol
Line: 141 require(t0 == token0 && t1 == token1, "GEV: Invalid TR")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L141

  • File: contracts/GeVault.sol
Line: 146 require( t.lowerTick() > ticks[0].upperTick(), "GEV: Shift Tick Overlap")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L146

  • File: contracts/GeVault.sol
Line: 148 require( t.upperTick() < ticks[0].lowerTick(), "GEV: Shift Tick Overlap")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L148

  • File: contracts/GeVault.sol
Line: 170 require(t0 == token0 && t1 == token1, "GEV: Invalid TR")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L170

  • File: contracts/GeVault.sol
Line: 184 require(newBaseFeeX4 < 1e4, "GEV: Invalid Base Fee")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L184

  • File: contracts/GeVault.sol
Line: 203 require(poolMatchesOracle(), "GEV: Oracle Error")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L203

  • File: contracts/GeVault.sol
Line: 215 require(poolMatchesOracle(), "GEV: Oracle Error")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L215

  • File: contracts/GeVault.sol
Line: 217 require(liquidity <= balanceOf(msg.sender), "GEV: Insufficient Balance")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L217

  • File: contracts/GeVault.sol
Line: 218 require(liquidity > 0, "GEV: Withdraw Zero")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L218

  • File: contracts/GeVault.sol
Line: 249 require(isEnabled, "GEV: Pool Disabled")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L249

  • File: contracts/GeVault.sol
Line: 250 require(poolMatchesOracle(), "GEV: Oracle Error")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L250

  • File: contracts/GeVault.sol
Line: 251 require(token == address(token0) || token == address(token1), "GEV: Invalid Token")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L251

  • File: contracts/GeVault.sol
Line: 252 require(amount > 0 || msg.value > 0, "GEV: Deposit Zero")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L252

  • File: contracts/GeVault.sol
Line: 256 require(token == address(WETH), "GEV: Invalid Weth")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L256

  • File: contracts/GeVault.sol
Line: 269 require(tvlCap > valueX8 + getTVL(), "GEV: Max Cap Reached")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L269

  • File: contracts/GeVault.sol
Line: 281 require(liquidity > 0, "GEV: No Liquidity Added")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L281

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 69 require( address(lendingPool) == msg.sender, "OPM: Call Unallowed")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L69

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 91 require( address(lendingPool) == msg.sender, "OPM: Call Unallowed")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L91

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 137 require(sourceSwap == token0 || sourceSwap == token1, "OPM: Invalid Swap Token")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L137

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 167 require(options.length == amounts.length && sourceSwap.length == options.length, "OPM: Array Length Mismatch")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L167

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 198 require(options.length == amounts.length, "ARRAY_LEN_MISMATCH")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L198

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 235 require(debt > 0, "OPM: No Debt")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L235

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 261 require(collateralAsset == token0 || collateralAsset == token1, "OPM: Invalid Collateral Asset")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L261

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 344 require( (debtValue < 1e8 && tokensValue < 1e8 ) || (tokensValue > debtValue * 98 / 100 && tokensValue < debtValue * 102 / 100), "OPM: Slippage Error" )

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L344-L348

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 369 require(feeAmount <= IERC20(collateralAsset).balanceOf(address(this)), "OPM: Insufficient Collateral")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L369

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 393 require( LP.getReserveData(optionAddress).aTokenAddress != address(0x0), "OPM: Invalid Address" )

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L393

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 420 require( LP.getReserveData(optionAddress).aTokenAddress != address(0x0), "OPM: Invalid Address" )

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L420

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 441 require(sourceAsset == token0 || sourceAsset == token1, "OPM: Invalid Swap Asset")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L441

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 495 require( amountsIn[0] <= maxAmount && amountsIn[0] > 0, "OPM: Invalid Swap Amounts" )

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L495

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 496 require( amountsIn[0] <= ERC20(path[0]).balanceOf(address(this)), "OPM: Insufficient Token Amount" )

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L496

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 523 require ( priceAssetA > 0 && priceAssetB > 0, "OPM: Invalid Oracle Price")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L523

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 525 require( amountB > 0, "OPM: Target Amount Too Low")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L525

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 536 require(token0 == address(t0) && token1 == address(t1), "OPM: Invalid Debt Asset")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L536

  • File: contracts/PositionManager/PositionManager.sol
Line: 30 require(roerouter != address(0x0), "Invalid address")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/PositionManager.sol#L30

  • File: contracts/PositionManager/PositionManager.sol
Line: 145 require( valueA <= valueB * 101 / 100, "PM: LP Oracle Error")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/PositionManager.sol#L145

  • File: contracts/PositionManager/PositionManager.sol
Line: 146 require( valueB <= valueA * 101 / 100, "PM: LP Oracle Error")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/PositionManager.sol#L146

  • File: contracts/RangeManager.sol
Line: 49 require( address(lendingPool) != address(0x0), "Invalid address" )

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L49

  • File: contracts/RangeManager.sol
Line: 60 require(start < end, "Range invalid")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L60

  • File: contracts/RangeManager.sol
Line: 66 revert("Range overlap")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L66

  • File: contracts/RangeManager.sol
Line: 76 require(beacon != address(0x0), "Invalid beacon")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L76

  • File: contracts/RangeManager.sol
Line: 108 require(step < tokenisedRanges.length && step < tokenisedTicker.length, "Invalid step")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L108

  • File: contracts/RangeManager.sol
Line: 206 require(hf > 1.01e18, "Health factor is too low")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L206

  • File: contracts/RoeRouter.sol
Line: 34 require(treasury_ != address(0x0), "Invalid address")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L34

  • File: contracts/RoeRouter.sol
Line: 68 require ( lendingPoolAddressProvider != address(0x0) && token0 != address(0x0) && token1 != address(0x0) && ammRouter != address(0x0), "Invalid Address" )

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L68-L74

  • File: contracts/RoeRouter.sol
Line: 75 require(token0 < token1, "Invalid Order")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L75

  • File: contracts/RoeRouter.sol
Line: 84 require(newTreasury != address(0x0), "Invalid address")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L84

  • File: contracts/TokenisableRange.sol
Line: 86 require(address(_oracle) != address(0x0), "Invalid oracle")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L86

  • File: contracts/TokenisableRange.sol
Line: 87 require(status == ProxyState.INIT_PROXY, "!InitProxy")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L87

  • File: contracts/TokenisableRange.sol
Line: 135 require(status == ProxyState.INIT_LP, "!InitLP")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L135

  • File: contracts/TokenisableRange.sol
Line: 136 require(msg.sender == creator, "Unallowed call")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L136

  • File: contracts/TokenisableRange.sol
Line: 209 require(addedValue > liquidityValue * 95 / 100 && liquidityValue > addedValue * 95 / 100, "TR: Claim Fee Slippage")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L209

  • File: contracts/TokenisableRange.sol
Line: 225 require(totalSupply() > 0, "TR Closed")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L225

  • File: contracts/TokenisableRange.sol
Line: 271 require (TOKEN0_PRICE > 0 && TOKEN1_PRICE > 0, "Invalid Oracle Price")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L271

  • File: contracts/helper/FixedOracle.sol
Line: 11 require(msg.sender == owner, "Only the owner can call this function.")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/FixedOracle.sol#L11

  • File: contracts/helper/LPOracle.sol
Line: 29 require(lpToken != address(0x0) && clToken0 != address(0x0) && clToken1 != address(0x0), "Invalid address")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/LPOracle.sol#L29

  • File: contracts/helper/LPOracle.sol
Line: 63 require(timeStamp > 0, "Round not complete")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/LPOracle.sol#L63

  • File: contracts/helper/LPOracle.sol
Line: 101 require(decimalsA <= 18 && decimalsB <= 18, "Incorrect tokens")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/LPOracle.sol#L101

  • File: contracts/helper/OracleConvert.sol
Line: 23 require(clToken0 != address(0x0) && clToken1 != address(0x0), "Invalid address")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/OracleConvert.sol#L23

  • File: contracts/helper/OracleConvert.sol
Line: 26 require(CL_TOKENA.decimals() + CL_TOKENB.decimals() >= 16, "Decimals error")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/OracleConvert.sol#L26

  • File: contracts/helper/OracleConvert.sol
Line: 44 require(timeStamp > 0, "Round not complete")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/OracleConvert.sol#L44

  • File: contracts/helper/V3Proxy.sol
Line: 87 require(acceptPayable, "CannotReceiveETH")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L87

  • File: contracts/helper/V3Proxy.sol
Line: 91 require(acceptPayable, "CannotReceiveETH")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L91

  • File: contracts/helper/V3Proxy.sol
Line: 99 require(path.length == 2, "Direct swap only")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L99

  • File: contracts/helper/V3Proxy.sol
Line: 106 require(path.length == 2, "Direct swap only")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L106

  • File: contracts/helper/V3Proxy.sol
Line: 113 require(path.length == 2, "Direct swap only")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L113

  • File: contracts/helper/V3Proxy.sol
Line: 125 require(path.length == 2, "Direct swap only")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L125

  • File: contracts/helper/V3Proxy.sol
Line: 138 require(path.length == 2, "Direct swap only")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L138

  • File: contracts/helper/V3Proxy.sol
Line: 139 require(path[0] == ROUTER.WETH9(), "Invalid path")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L139

  • File: contracts/helper/V3Proxy.sol
Line: 148 require(path.length == 2, "Direct swap only")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L148

  • File: contracts/helper/V3Proxy.sol
Line: 149 require(path[0] == ROUTER.WETH9(), "Invalid path")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L149

  • File: contracts/helper/V3Proxy.sol
Line: 161 require(path.length == 2, "Direct swap only")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L161

  • File: contracts/helper/V3Proxy.sol
Line: 162 require(path[1] == ROUTER.WETH9(), "Invalid path")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L162

  • File: contracts/helper/V3Proxy.sol
Line: 179 require(path.length == 2, "Direct swap only")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L179

  • File: contracts/helper/V3Proxy.sol
Line: 180 require(path[1] == ROUTER.WETH9(), "Invalid path")

use custom error instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L180

</details>

Greater or Equal Comparison Costs Less Gas than Greater Comparison

  • Severity: Gas Optimization
  • Confidence: High
  • Total Gas Saved: 15

Description

In Solidity, the >= operator costs less gas than the > operator. This is because the Solidity compiler uses the LT opcode for >= comparisons, which requires less gas than the combination of GT and ISZERO opcodes used for > comparisons. Therefore, replacing > with >= when possible can reduce the gas cost of your contract.

<details> <summary> There are 5 instances of this issue: </summary>
  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 315 amtA > amt0

using GREATER_EQUAL/LESS_EQUAL in this case is identical therefore should be use.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L315

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 319 amtB > amt1

using GREATER_EQUAL/LESS_EQUAL in this case is identical therefore should be use.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L319

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 549 scale0 > scale1

using GREATER_EQUAL/LESS_EQUAL in this case is identical therefore should be use.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L549

  • File: contracts/RangeManager.sol
Line: 51 ASSET_0 = _asset0 < _asset1 ? _asset0 : _asset1

using GREATER_EQUAL/LESS_EQUAL in this case is identical therefore should be use.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L51

  • File: contracts/RangeManager.sol
Line: 52 ASSET_1 = _asset0 < _asset1 ? _asset1 : _asset0

using GREATER_EQUAL/LESS_EQUAL in this case is identical therefore should be use.

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L52

</details>

Inefficient Parameter Storage

  • Severity: Gas Optimization
  • Confidence: Medium
  • Total Gas Saved: 100

Description

When passing function parameters, using the calldata area instead of memory can improve gas efficiency. Calldata is a read-only area where function arguments and external function calls' parameters are stored.

By using calldata for function parameters, you avoid unnecessary gas costs associated with copying data from calldata to memory. This is particularly beneficial when the parameter is read-only and doesn't require modification within the contract.

Using calldata for function parameters can help optimize gas usage, especially when making external function calls or when the parameter values are provided externally and don't need to be stored persistently within the contract.

<details> <summary> There are 2 instances of this issue: </summary>
  • File: interfaces/PoolAddress.sol
Line: 33 PoolKey memory key

should be declared as calldata instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/interfaces/PoolAddress.sol#L33

  • File: contracts/PositionManager/OptionsPositionManager.sol
Line: 66 address[] memory sourceSwap

should be declared as calldata instead

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/PositionManager/OptionsPositionManager.sol#L66

</details>

Short-circuit rules can be used to optimize some gas usage

  • Severity: Gas Optimization
  • Confidence: Medium
  • Total Gas Saved: 4200

Description

Some conditions may be reordered to save an SLOAD (2100 gas), as we avoid reading state variables when the first part of the condition fails (with &&), or succeeds (with ||). For instance, consider a scenario where you have a stateVariable (a variable stored in contract storage) and a localVariable (a variable in memory).

If you have a condition like stateVariable > 0 && localVariable > 0, if localVariable > 0 is false, the Solidity runtime will still execute stateVariable > 0, which costs an SLOAD operation (2100 gas). However, if you reorder the condition to localVariable > 0 && stateVariable > 0, the stateVariable > 0 check won't happen if localVariable > 0 is false, saving you the SLOAD gas cost.

Similarly, for the || operator, if you have a condition like stateVariable > 0 || localVariable > 0, and stateVariable > 0 is true, the Solidity runtime will still execute localVariable > 0. But if you reorder the condition to localVariable > 0 || stateVariable > 0, and localVariable > 0 is true, the stateVariable > 0 check won't happen, again saving you the SLOAD gas cost.

This detector checks for such conditions in the contract and reports if any condition could be optimized by taking advantage of the short-circuiting behavior of && and ||.

<details> <summary> There are 2 instances of this issue: </summary>
  • File: contracts/TokenisableRange.sol
Line: 237 fee0+fee1 > 0 && ( n0 > 0 || fee0 == 0) && ( n1 > 0 || fee1 == 0 )
// @audit: Switch (n0 > 0 || fee0 == 0) && fee0 + fee1 > 0

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L237

  • File: contracts/TokenisableRange.sol
Line: 237 fee0+fee1 > 0 && ( n0 > 0 || fee0 == 0) && ( n1 > 0 || fee1 == 0 )
// @audit: Switch (n1 > 0 || fee1 == 0) && fee0 + fee1 > 0 && (n0 > 0 || fee0 == 0)

https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L237

</details>

#0 - c4-judge

2023-08-20T17:03:35Z

gzeon-c4 marked the issue as grade-b

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