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
Rank: 47/80
Findings: 2
Award: $32.69
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Team_FliBit
Also found by: 0x70C9, 3docSec, 8olidity, DavidGiladi, Krace, LokiThe5th, Rolezn, Sathish9098, UniversalCrypto, banpaleo5, catellatech, digitizeworx, fatherOfBlocks, hpsb, j4ld1na, josephdara, kutugu, niser93, nonseodion, oakcobalt, osmanozdemir1, pep7siup, ravikiranweb3, said, sivanesh_808
15.3494 USDC - $15.35
Title | Issue | Instances |
---|---|---|
[L-1] Array out of bounds accesses | Array out of bounds accesses | 5 |
[L-2] Burn functions must be protected with a modifier | Burn functions must be protected with a modifier | 3 |
[L-3] Missing contract-existence checks before low-level calls | Missing contract-existence checks before low-level calls | 3 |
[L-4] Local variable shadowing | Local variable shadowing | 4 |
[L-5] Missing gap Storage Variable in Upgradeable Contract | Missing gap Storage Variable in Upgradeable Contract | 2 |
[L-6] Reentrancy vulnerabilities | Reentrancy vulnerabilities | 10 |
[L-7] Restrictive casts in assignments | Restrictive casts in assignments | 3 |
Total: 7 issues
Title | Issue | Instances |
---|---|---|
[N-1] Dead-code | Dead-code | 3 |
[N-2] Duplicated require()/revert() checks should be refactored to a modifier or function | Duplicated require()/revert() checks should be refactored to a modifier or function | 9 |
[N-3] Lack of Explicit Visibility Declaration in State Variables | Lack of Explicit Visibility Declaration in State Variables | 4 |
[N-4] Inconsistent usage of require/error | Inconsistent usage of require/error | 1 |
[N-5] Max Value Optimization Replacing 2^n - 1 with type(uint n).max | Max Value Optimization Replacing 2^n - 1 with type(uint n).max | 4 |
[N-6] Token contract should have a blacklist function or modifier | Token contract should have a blacklist function or modifier | 2 |
[N-7] Missing inheritance | Missing inheritance | 3 |
[N-8] Name reused | Name reused | 1 |
[N-9] Override function arguments that are unused should have the variable name removed or commented out | Override function arguments that are unused should have the variable name removed or commented out | 2 |
[N-10] Variable names too similar | Variable names too similar | 41 |
[N-11] Single Source of Constants Ensuring Consistency and Integrity | Single Source of Constants Ensuring Consistency and Integrity | 1 |
Total: 1 issues
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>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
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
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
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
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
</details>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.
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
Line: 174 payable(msg.sender).call{value: amountOut}("")
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L174
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>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
.
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
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
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>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>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
Line: 12 interface IInitializableAToken
missing __gap storage variable
</details>Detection of shadowing using local variables.
<details> <summary> There are 4 instances of this issue: </summary>Line: 67 address[] calldata assets
shadows: - File: interfaces/IAaveIncentivesController.sol
Line: 39 function assets(address asset) external view returns ( uint128, uint128, uint256 );
(function)
Line: 87 address[] calldata assets
shadows: - File: interfaces/IAaveIncentivesController.sol
Line: 39 function assets(address asset) external view returns ( uint128, uint128, uint256 );
(function)
Line: 99 address[] calldata assets
shadows: - File: interfaces/IAaveIncentivesController.sol
Line: 39 function assets(address asset) external view returns ( uint128, uint128, uint256 );
(function)
Line: 113 address[] calldata assets
shadows: - File: interfaces/IAaveIncentivesController.sol
Line: 39 function assets(address asset) external view returns ( uint128, uint128, uint256 );
(function)
</details>Detection of the reentrancy bug.
Only report reentrancy that acts as a double call (see reentrancy-eth
, reentrancy-no-eth
).
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
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
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
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
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
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
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
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
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
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>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>Line: 370 uint decimals0 = token0.decimals()
// @audit: uint256 vs uint8
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L370
Line: 371 uint decimals1 = token1.decimals()
// @audit: uint256 vs uint8
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L371
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>Functions that are not sued.
<details> <summary> There are 3 instances of this issue: </summary>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
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
Line: 138 function validateValuesAgainstOracle(IPriceOracle oracle, address assetA, uint amountA, address assetB, uint amountB) internal view
is never used and should be removed
</details>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>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
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
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")
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" )
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
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
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
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
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>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>Line: 41 RangeManager rangeManager
State variable lacks explicit visibility. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L41
Line: 45 string _name
State variable lacks explicit visibility. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L45
Line: 46 string _symbol
State variable lacks explicit visibility. https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L46
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>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>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>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>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
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>Detect variables with names that are too similar.
<details> <summary> There are 41 instances of this issue: </summary>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
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
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
Line: 521 uint priceAssetA = oracle.getAssetPrice(assetA)
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 522 uint priceAssetB = oracle.getAssetPrice(assetB)
Line: 336 uint token0Amount
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 270 uint token1Amount
Line: 270 uint token0Amount
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 336 uint token1Amount
Line: 270 uint token0Amount
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 360 uint token1Amount
Line: 336 uint token0Amount
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 336 uint token1Amount
Line: 270 uint token0Amount
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 270 uint token1Amount
Line: 336 uint token0Amount
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 360 uint token1Amount
Line: 359 uint token0Amount
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 270 uint token1Amount
Line: 359 uint token0Amount
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 336 uint token1Amount
Line: 359 uint token0Amount
is too similar to File: contracts/PositionManager/OptionsPositionManager.sol
Line: 360 uint token1Amount
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Line: 73 uint256 feeGrowthInside0LastX128
is too similar to File: interfaces/INonfungiblePositionManager.sol
Line: 74 uint256 feeGrowthInside1LastX128
Line: 75 uint128 tokensOwed0
is too similar to File: interfaces/INonfungiblePositionManager.sol
</details>Line: 76 uint128 tokensOwed1
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>Line: 36 INonfungiblePositionManager constant public POS_MGR = INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88)
Line: 58 INonfungiblePositionManager constant public POS_MGR = INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L36
</details>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>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
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
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>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>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
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
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
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>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>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>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>Line: 41 uint256[] calldata premiums
</details>Line: 42 address initiator
#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
🌟 Selected for report: JCK
Also found by: 0xAnah, 0xhex, 0xta, DavidGiladi, K42, Rageur, Raihan, ReyAdmirado, Rolezn, SAQ, SY_S, Sathish9098, dharma09, hunter_w3b, matrix_0wl, naman1778, petrichor, wahedtalash77
17.345 USDC - $17.34
Title | Issue | Instances | Total Gas Saved |
---|---|---|---|
[G-1] Inefficient use of abi.encode() | Inefficient use of abi.encode() | 2 | 200 |
[G-2] Use assembly to emit events | Use assembly to emit events | 35 | 1330 |
[G-3] Assembly optimization for low level calls | Assembly optimization for low level calls | 3 | 744 |
[G-4] Division operations between unsigned could be unchecked | Division operations between unsigned could be unchecked | 2 | 170 |
[G-5] Modulus operations that could be unchecked | Modulus operations that could be unchecked | 3 | 255 |
[G-6] Constants Variable Should Be Private for Gas Optimization | Constants Variable Should Be Private for Gas Optimization | 6 | 20400 |
[G-7] Use of emit inside a loop | Use of emit inside a loop | 3 | 3078 |
[G-8] Identical Deployments Should be Replaced with Clone | Identical Deployments Should be Replaced with Clone | 1 | - |
[G-9] Greater or Equal Comparison Costs Less Gas than Greater Comparison | Greater or Equal Comparison Costs Less Gas than Greater Comparison | 5 | 15 |
[G-10] Inefficient Parameter Storage | Inefficient Parameter Storage | 2 | 100 |
[G-11] Inefficient Gas Usage in Solidity Smart Contracts Due to Long Error Messages | Inefficient Gas Usage in Solidity Smart Contracts Due to Long Error Messages | 1 | 18 |
[G-12] Optimal State Variable Order | Optimal State Variable Order | 1 | 5000 |
[G-13] Short-circuit rules can be used to optimize some gas usage | Short-circuit rules can be used to optimize some gas usage | 2 | 4200 |
[G-14] Safe Subtraction Should Be Unchecked | Safe Subtraction Should Be Unchecked | 7 | 595 |
[G-15] Unnecessary Casting of Variables | Unnecessary Casting of Variables | 1 | - |
[G-16] Redundant Contract Existence Check in Consecutive External Calls | Redundant Contract Existence Check in Consecutive External Calls | 15 | 1500 |
[G-17] Unused Named Return Variables | Unused Named Return Variables | 3 | - |
[G-18] Unused state variable | Unused state variable | 1 | 2900 |
[G-19] Usage of Custom Errors for Gas Efficiency | Usage of Custom Errors for Gas Efficiency | 80 | 22080 |
Total: 19 issues
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>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>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.
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
Line: 199 bytes memory params = abi.encode(1, poolId, user, collateralAsset)
use abi.encodepacked() instead.
</details>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.
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
Line: 199 bytes memory params = abi.encode(1, poolId, user, collateralAsset)
use abi.encodepacked() instead.
</details>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>Line: 103 emit SetEnabled(_isEnabled)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L103
Line: 110 emit SetTreasury(newTreasury)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L110
Line: 131 emit PushTick(tr)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L131
Line: 160 emit ShiftTick(tr)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L160
Line: 172 emit ModifyTick(tr, index)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L172
Line: 186 emit SetFee(newBaseFeeX4)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L186
Line: 193 emit SetTvlCap(newTvlCap)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L193
Line: 362 emit Rebalance(tickIndex)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L362
Line: 240 emit Withdraw(msg.sender, token, amount, liquidity)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L240
Line: 283 emit Deposit(msg.sender, token, amount, liquidity)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/GeVault.sol#L283
Line: 323 emit ClosePosition(user, debtAsset, debt, amt0, amt1)
Line: 148 emit BuyOptions(user, flashAsset, flashAmount, amount0, amount1)
Line: 455 emit Swap(msg.sender, path[0], amount, path[1], received)
Line: 106 emit LiquidatePosition(user, debtAsset, debt, amt0 - amts[0], amt1 - amts[1])
Line: 240 emit ReducedPosition(user, debtAsset, debt)
Line: 401 emit SellOptions(msg.sender, optionAddress, deposited, amount0, amount1 )
Line: 87 emit AddRange(startX10, endX10, tokenisedRanges.length - 1)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L87
Line: 132 emit Withdraw(msg.sender, address(tokenisedTicker[step]), trAmt)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L132
Line: 120 emit Withdraw(msg.sender, address(tokenisedRanges[step]), trAmt)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L120
Line: 164 emit Deposit(msg.sender, address(tr), lpAmt)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L164
Line: 50 emit DeprecatePool(poolId)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L50
Line: 78 emit AddPool(poolId, lendingPoolAddressProvider)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L78
Line: 86 emit UpdateTreasury(newTreasury)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RoeRouter.sol#L86
Line: 119 emit InitTR(address(asset0), address(asset1), startX10, endX10)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L119
Line: 162 emit Deposit(msg.sender, 1e18)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L162
Line: 214 emit ClaimFees(newFee0, newFee1)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L214
Line: 284 emit Deposit(msg.sender, lpAmt)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L284
Line: 326 emit Withdraw(msg.sender, lp)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L326
Line: 26 emit SetHardcodedPrice(_hardcodedPrice)
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/FixedOracle.sol#L26
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
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
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
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
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
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>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."
<details> <summary> There are 3 instances of this issue: </summary>// before (bool success,) = payable(receiver).call{gas: gas, value: value}(""); //after bool success; assembly { success := call(gas, receiver, value, 0, 0, 0, 0) }
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
Line: 174 payable(msg.sender).call{value: amountOut}("")
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L174
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 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.
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
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 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.
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
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
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>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.
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
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
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
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
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
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>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>Line: 148 emit BuyOptions(user, flashAsset, flashAmount, amount0, amount1)
Line: 323 emit ClosePosition(user, debtAsset, debt, amt0, amt1)
</details>Line: 106 emit LiquidatePosition(user, debtAsset, debt, amt0 - amts[0], amt1 - amts[1])
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>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>Line: 18 contract TokenisableRange is ERC20("", ""), ReentrancyGuard
original variable order (count: 17 slots)
optimized variable order (count: 16 slots)
Recomended optimizations will use 1 less slots.
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/TokenisableRange.sol#L18-L384
</details>Named return variables allow for clear and explicit naming of values to be returned from a function. However, when these variables are unused, it can lead to confusion and make the code less maintainable.
<details> <summary> There are 3 instances of this issue: </summary>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
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
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.
<details> <summary> There are 1 instances of this issue: </summary>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>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>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
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
Line: 316 amt0 = amtA - amt0
should be unchecked because there is check:<br>File: contracts/PositionManager/OptionsPositionManager.sol
Line: 315 amtA > amt0
Line: 320 amt1 = amtB - amt1
should be unchecked because there is check:<br>File: contracts/PositionManager/OptionsPositionManager.sol
Line: 319 amtB > amt1
Line: 143 valueA = valueA / 10 ** (decimalsA - decimalsB)
should be unchecked because there is check:<br>File: contracts/PositionManager/PositionManager.sol
Line: 143 decimalsA > decimalsB
Line: 144 valueB = valueB / 10 ** (decimalsB - decimalsA)
should be unchecked because there is check:<br>File: contracts/PositionManager/PositionManager.sol
Line: 144 decimalsA < decimalsB
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>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>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
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>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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Line: 69 require( address(lendingPool) == msg.sender, "OPM: Call Unallowed")
use custom error instead
Line: 91 require( address(lendingPool) == msg.sender, "OPM: Call Unallowed")
use custom error instead
Line: 137 require(sourceSwap == token0 || sourceSwap == token1, "OPM: Invalid Swap Token")
use custom error instead
Line: 167 require(options.length == amounts.length && sourceSwap.length == options.length, "OPM: Array Length Mismatch")
use custom error instead
Line: 198 require(options.length == amounts.length, "ARRAY_LEN_MISMATCH")
use custom error instead
Line: 235 require(debt > 0, "OPM: No Debt")
use custom error instead
Line: 261 require(collateralAsset == token0 || collateralAsset == token1, "OPM: Invalid Collateral Asset")
use custom error instead
Line: 344 require( (debtValue < 1e8 && tokensValue < 1e8 ) || (tokensValue > debtValue * 98 / 100 && tokensValue < debtValue * 102 / 100), "OPM: Slippage Error" )
use custom error instead
Line: 369 require(feeAmount <= IERC20(collateralAsset).balanceOf(address(this)), "OPM: Insufficient Collateral")
use custom error instead
Line: 393 require( LP.getReserveData(optionAddress).aTokenAddress != address(0x0), "OPM: Invalid Address" )
use custom error instead
Line: 420 require( LP.getReserveData(optionAddress).aTokenAddress != address(0x0), "OPM: Invalid Address" )
use custom error instead
Line: 441 require(sourceAsset == token0 || sourceAsset == token1, "OPM: Invalid Swap Asset")
use custom error instead
Line: 495 require( amountsIn[0] <= maxAmount && amountsIn[0] > 0, "OPM: Invalid Swap Amounts" )
use custom error instead
Line: 496 require( amountsIn[0] <= ERC20(path[0]).balanceOf(address(this)), "OPM: Insufficient Token Amount" )
use custom error instead
Line: 523 require ( priceAssetA > 0 && priceAssetB > 0, "OPM: Invalid Oracle Price")
use custom error instead
Line: 525 require( amountB > 0, "OPM: Target Amount Too Low")
use custom error instead
Line: 536 require(token0 == address(t0) && token1 == address(t1), "OPM: Invalid Debt Asset")
use custom error instead
Line: 30 require(roerouter != address(0x0), "Invalid address")
use custom error instead
Line: 145 require( valueA <= valueB * 101 / 100, "PM: LP Oracle Error")
use custom error instead
Line: 146 require( valueB <= valueA * 101 / 100, "PM: LP Oracle Error")
use custom error instead
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
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
Line: 66 revert("Range overlap")
use custom error instead
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/RangeManager.sol#L66
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Line: 87 require(acceptPayable, "CannotReceiveETH")
use custom error instead
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L87
Line: 91 require(acceptPayable, "CannotReceiveETH")
use custom error instead
https://github.com/code-423n4/2023-08-goodentry/blob/main/contracts/helper/V3Proxy.sol#L91
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
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
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
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
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
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
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
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
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
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
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
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>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>Line: 315 amtA > amt0
using GREATER_EQUAL/LESS_EQUAL in this case is identical therefore should be use.
Line: 319 amtB > amt1
using GREATER_EQUAL/LESS_EQUAL in this case is identical therefore should be use.
Line: 549 scale0 > scale1
using GREATER_EQUAL/LESS_EQUAL in this case is identical therefore should be use.
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
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>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.
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
Line: 66 address[] memory sourceSwap
should be declared as calldata
instead
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 ||
.
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
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