Maverick contest - IllIllI's results

DeFi infrastructure.

General Information

Platform: Code4rena

Start Date: 01/12/2022

Pot Size: $60,500 USDC

Total HM: 8

Participants: 27

Period: 11 days

Judge: kirk-baird

Total Solo HM: 6

Id: 187

League: ETH

Maverick

Findings Distribution

Researcher Performance

Rank: 7/27

Findings: 2

Award: $1,359.35

QA:
grade-a
Gas:
grade-a

🌟 Selected for report: 1

šŸš€ Solo Findings: 0

Awards

728.8818 USDC - $728.88

Labels

bug
grade-a
QA (Quality Assurance)
Q-10

External Links

Summary

Low Risk Issues

IssueInstances
[L‑01]tokenURI() does not follow EIP-7211
[L‑02]Draft imports may break in new minor versions1

Total: 2 instances over 2 issues

Non-critical Issues

IssueInstances
[N‑01]Import declarations should import specific identifiers, rather than the whole file97
[N‑02]constants should be defined rather than using magic numbers107
[N‑03]Numeric values having to do with time should use time units for readability1
[N‑04]Use bit shifts in an imutable variable rather than long bit masks of a single bit, for readability4
[N‑05]Missing event and or timelock for critical parameter change1
[N‑06]Events that mark critical parameter changes should contain both the old and the new value3
[N‑07]Use a more recent version of solidity1
[N‑08]Use a more recent version of solidity8
[N‑09]Use a more recent version of solidity1
[N‑10]Inconsistent spacing in comments28
[N‑11]Lines are too long18
[N‑12]Variable names that consist of all capital letters should be reserved for constant/immutable variables1
[N‑13]Non-library/interface files should use fixed compiler versions, not floating ones6
[N‑14]File is missing NatSpec18
[N‑15]NatSpec is incomplete9
[N‑16]Not using the named return variables anywhere in the function is confusing17
[N‑17]Duplicated require()/revert() checks should be refactored to a modifier or function3
[N‑18]Consider using delete rather than assigning zero to clear values6
[N‑19]Contracts should have full test coverage1
[N‑20]Large or complicated code bases should implement fuzzing tests1

Total: 331 instances over 20 issues

Low Risk Issues

[L‑01] tokenURI() does not follow EIP-721

The EIP states that tokenURI() "Throws if _tokenId is not a valid NFT", which the code below does not do. If the NFT has not yet been minted, tokenURI() should revert

There is 1 instance of this issue:

File: maverick-v1/contracts/models/PositionMetadata.sol

21        function tokenURI(uint256 tokenId) external view override returns (string memory) {
22            return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
23:       }

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol#L21-L23

[L‑02] Draft imports may break in new minor versions

While OpenZeppelin draft contracts are safe to use and have been audited, their 'draft' status means that the EIPs they're based on are not finalized, and thus there may be breaking changes in even minor releases. If a bug is found in this version of OpenZeppelin, and the version that you're forced to upgrade to has breaking changes in the new version, you'll encounter unnecessary delays in porting and testing replacement contracts. Ensure that you have extensive test coverage of this area so that differences can be automatically detected, and have a plan in place for how you would fully test a new version of these contracts if they do indeed change unexpectedly. Consider creating a forked version of the file rather than importing it from the package, and manually patch your fork as changes are made.

There is 1 instance of this issue:

File: router-v1/contracts/libraries/SelfPermit.sol

5:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/SelfPermit.sol#L5

Non-critical Issues

[N‑01] Import declarations should import specific identifiers, rather than the whole file

Using import declarations of the form import {<identifier_name>} from "some/file.sol" avoids polluting the symbol namespace making flattened files smaller, and speeds up compilation

There are 97 instances of this issue:

File: maverick-v1/contracts/interfaces/IFactory.sol

3:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

5:    import "../interfaces/IPool.sol";

6:    import "../interfaces/IPosition.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IFactory.sol#L3

File: maverick-v1/contracts/interfaces/IPool.sol

4:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

5:    import "./IFactory.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPool.sol#L4

File: maverick-v1/contracts/interfaces/IPosition.sol

4:    import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";

5:    import "../interfaces/IPositionMetadata.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPosition.sol#L4

File: maverick-v1/contracts/libraries/BinMap.sol

4:    import "prb-math/contracts/PRBMathSD59x18.sol";

6:    import "./BinMath.sol";

7:    import "./Constants.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMap.sol#L4

File: maverick-v1/contracts/libraries/BinMath.sol

4:    import "prb-math/contracts/PRBMathUD60x18.sol";

6:    import "./Math.sol";

7:    import "./Constants.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol#L4

File: maverick-v1/contracts/libraries/Bin.sol

4:    import "prb-math/contracts/PRBMathUD60x18.sol";

6:    import "./Math.sol";

7:    import "./BinMath.sol";

8:    import "./Delta.sol";

9:    import "./Cast.sol";

10:   import "./Constants.sol";

11:   import "../interfaces/IPool.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Bin.sol#L4

File: maverick-v1/contracts/libraries/Deployer.sol

4:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

6:    import "../models/Pool.sol";

7:    import "../interfaces/IFactory.sol";

8:    import "../interfaces/IPool.sol";

9:    import "../interfaces/IPosition.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Deployer.sol#L4

File: maverick-v1/contracts/libraries/Math.sol

3:    import "prb-math/contracts/PRBMath.sol";

5:    import "./Constants.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Math.sol#L3

File: maverick-v1/contracts/libraries/SafeERC20Min.sol

5:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

6:    import "@openzeppelin/contracts/utils/Address.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/SafeERC20Min.sol#L5

File: maverick-v1/contracts/libraries/Twa.sol

4:    import "prb-math/contracts/PRBMathSD59x18.sol";

6:    import "../interfaces/IPool.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Twa.sol#L4

File: maverick-v1/contracts/models/Factory.sol

4:    import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";

5:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

7:    import "../models/Pool.sol";

8:    import "../interfaces/IFactory.sol";

9:    import "../interfaces/IPool.sol";

10:   import "../interfaces/IPosition.sol";

11:   import "../libraries/Deployer.sol";

12:   import "../libraries/Math.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L4

File: maverick-v1/contracts/models/PoolInspector.sol

4:    import "./Pool.sol";

5:    import "../interfaces/ISwapCallback.sol";

6:    import "../libraries/Bin.sol";

7:    import "../libraries/Math.sol";

8:    import "../libraries/Constants.sol";

9:    import "../interfaces/IPool.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L4

File: maverick-v1/contracts/models/Pool.sol

4:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

6:    import "prb-math/contracts/PRBMathUD60x18.sol";

7:    import "prb-math/contracts/PRBMathSD59x18.sol";

8:    import "../libraries/Bin.sol";

9:    import "../libraries/BinMap.sol";

10:   import "../libraries/BinMath.sol";

11:   import "../libraries/Cast.sol";

12:   import "../libraries/Delta.sol";

13:   import "../libraries/Twa.sol";

14:   import "../libraries/SafeERC20Min.sol";

15:   import "../interfaces/ISwapCallback.sol";

16:   import "../interfaces/IAddLiquidityCallback.sol";

17:   import "../interfaces/IPool.sol";

18:   import "../interfaces/IPoolAdmin.sol";

19:   import "../interfaces/IFactory.sol";

20:   import "../interfaces/IPosition.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L4

File: maverick-v1/contracts/models/PositionMetadata.sol

4:    import "../interfaces/IPositionMetadata.sol";

5:    import "@openzeppelin/contracts/utils/Strings.sol";

6:    import "@openzeppelin/contracts/access/Ownable.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol#L4

File: maverick-v1/contracts/models/Position.sol

4:    import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

5:    import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";

6:    import "@openzeppelin/contracts/utils/Counters.sol";

7:    import "@openzeppelin/contracts/access/Ownable.sol";

9:    import "../interfaces/IPositionMetadata.sol";

10:   import "../interfaces/IPosition.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Position.sol#L4

File: router-v1/contracts/interfaces/external/IWETH9.sol

4:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/interfaces/external/IWETH9.sol#L4

File: router-v1/contracts/interfaces/IRouter.sol

3:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

5:    import "@maverick/contracts/contracts/interfaces/IFactory.sol";

6:    import "@maverick/contracts/contracts/interfaces/IPool.sol";

7:    import "@maverick/contracts/contracts/interfaces/IPosition.sol";

8:    import "@maverick/contracts/contracts/interfaces/ISwapCallback.sol";

9:    import "./external/IWETH9.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/interfaces/IRouter.sol#L3

File: router-v1/contracts/libraries/Multicall.sol

5:    import "../interfaces/IMulticall.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Multicall.sol#L5

File: router-v1/contracts/libraries/Path.sol

4:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

6:    import "@maverick/contracts/contracts/interfaces/IPool.sol";

8:    import "./BytesLib.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Path.sol#L4

File: router-v1/contracts/libraries/SelfPermit.sol

4:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

5:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";

7:    import "../interfaces/ISelfPermit.sol";

8:    import "../interfaces/external/IERC20PermitAllowed.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/SelfPermit.sol#L4

File: router-v1/contracts/libraries/TransferHelper.sol

4:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/TransferHelper.sol#L4

File: router-v1/contracts/Router.sol

4:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

6:    import "@maverick/contracts/contracts/interfaces/IPool.sol";

7:    import "@maverick/contracts/contracts/interfaces/IFactory.sol";

8:    import "@maverick/contracts/contracts/interfaces/IPosition.sol";

10:   import "./interfaces/IRouter.sol";

11:   import "./interfaces/external/IWETH9.sol";

12:   import "./libraries/TransferHelper.sol";

13:   import "./libraries/Path.sol";

14:   import "./libraries/Deadline.sol";

15:   import "./libraries/Multicall.sol";

16:   import "./libraries/SelfPermit.sol";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L4

[N‑02] constants should be defined rather than using magic numbers

Even assembly can benefit from using readable constants instead of hex/numeric literals

There are 107 instances of this issue:

File: maverick-v1/contracts/libraries/BinMap.sol

/// @audit 8
22:           mapIndex = tick_kinds >> 8;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMap.sol#L22

File: maverick-v1/contracts/libraries/BinMath.sol

/// @audit 0x100000000000000000000000000000000
16:               if (x >= 0x100000000000000000000000000000000) {

/// @audit 128
17:                   x >>= 128;

/// @audit 128
18:                   result += 128;

/// @audit 0x10000000000000000
20:               if (x >= 0x10000000000000000) {

/// @audit 64
21:                   x >>= 64;

/// @audit 64
22:                   result += 64;

/// @audit 0x100000000
24:               if (x >= 0x100000000) {

/// @audit 32
25:                   x >>= 32;

/// @audit 32
26:                   result += 32;

/// @audit 0x10000
28:               if (x >= 0x10000) {

/// @audit 16
29:                   x >>= 16;

/// @audit 16
30:                   result += 16;

/// @audit 0x100
32:               if (x >= 0x100) {

/// @audit 8
33:                   x >>= 8;

/// @audit 8
34:                   result += 8;

/// @audit 0x10
36:               if (x >= 0x10) {

/// @audit 4
37:                   x >>= 4;

/// @audit 4
38:                   result += 4;

/// @audit 0x4
40:               if (x >= 0x4) {

/// @audit 0x2
44:               if (x >= 0x2) result += 1;

/// @audit 255
50:               result = 255;

/// @audit 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
52:               if (x & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF > 0) {

/// @audit 128
53:                   result -= 128;

/// @audit 128
55:                   x >>= 128;

/// @audit 0xFFFFFFFFFFFFFFFF
57:               if (x & 0xFFFFFFFFFFFFFFFF > 0) {

/// @audit 64
58:                   result -= 64;

/// @audit 64
60:                   x >>= 64;

/// @audit 0xFFFFFFFF
62:               if (x & 0xFFFFFFFF > 0) {

/// @audit 32
63:                   result -= 32;

/// @audit 32
65:                   x >>= 32;

/// @audit 0xFFFF
67:               if (x & 0xFFFF > 0) {

/// @audit 16
68:                   result -= 16;

/// @audit 16
70:                   x >>= 16;

/// @audit 0xFF
72:               if (x & 0xFF > 0) {

/// @audit 8
73:                   result -= 8;

/// @audit 8
75:                   x >>= 8;

/// @audit 0xF
77:               if (x & 0xF > 0) {

/// @audit 4
78:                   result -= 4;

/// @audit 4
80:                   x >>= 4;

/// @audit 0x3
82:               if (x & 0x3 > 0) {

/// @audit 0x1
87:               if (x & 0x1 > 0) result -= 1;

/// @audit 0x1
/// @audit 0xfffcb933bd6fad9d3af5f0b9f25db4d6
/// @audit 0x100000000000000000000000000000000
96:           uint256 ratio = tick & 0x1 != 0 ? 0xfffcb933bd6fad9d3af5f0b9f25db4d6 : 0x100000000000000000000000000000000;

/// @audit 0x2
/// @audit 0xfff97272373d41fd789c8cb37ffcaa1c
/// @audit 128
97:           if (tick & 0x2 != 0) ratio = (ratio * 0xfff97272373d41fd789c8cb37ffcaa1c) >> 128;

/// @audit 0x4
/// @audit 0xfff2e50f5f656ac9229c67059486f389
/// @audit 128
98:           if (tick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656ac9229c67059486f389) >> 128;

/// @audit 0x8
/// @audit 0xffe5caca7e10e81259b3cddc7a064941
/// @audit 128
99:           if (tick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e81259b3cddc7a064941) >> 128;

/// @audit 0x10
/// @audit 0xffcb9843d60f67b19e8887e0bd251eb7
/// @audit 128
100:          if (tick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f67b19e8887e0bd251eb7) >> 128;

/// @audit 0x20
/// @audit 0xff973b41fa98cd2e57b660be99eb2c4a
/// @audit 128
101:          if (tick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98cd2e57b660be99eb2c4a) >> 128;

/// @audit 0x40
/// @audit 0xff2ea16466c9838804e327cb417cafcb
/// @audit 128
102:          if (tick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c9838804e327cb417cafcb) >> 128;

/// @audit 0x80
/// @audit 0xfe5dee046a99d51e2cc356c2f617dbe0
/// @audit 128
103:          if (tick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99d51e2cc356c2f617dbe0) >> 128;

/// @audit 0x100
/// @audit 0xfcbe86c7900aecf64236ab31f1f9dcb5
/// @audit 128
104:          if (tick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900aecf64236ab31f1f9dcb5) >> 128;

/// @audit 0x200
/// @audit 0xf987a7253ac4d9194200696907cf2e37
/// @audit 128
105:          if (tick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac4d9194200696907cf2e37) >> 128;

/// @audit 0x400
/// @audit 0xf3392b0822b88206f8abe8a3b44dd9be
/// @audit 128
106:          if (tick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b88206f8abe8a3b44dd9be) >> 128;

/// @audit 0x800
/// @audit 0xe7159475a2c578ef4f1d17b2b235d480
/// @audit 128
107:          if (tick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c578ef4f1d17b2b235d480) >> 128;

/// @audit 0x1000
/// @audit 0xd097f3bdfd254ee83bdd3f248e7e785e
/// @audit 128
108:          if (tick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd254ee83bdd3f248e7e785e) >> 128;

/// @audit 0x2000
/// @audit 0xa9f746462d8f7dd10e744d913d033333
/// @audit 128
109:          if (tick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d8f7dd10e744d913d033333) >> 128;

/// @audit 0x4000
/// @audit 0x70d869a156ddd32a39e257bc3f50aa9b
/// @audit 128
110:          if (tick & 0x4000 != 0) ratio = (ratio * 0x70d869a156ddd32a39e257bc3f50aa9b) >> 128;

/// @audit 0x8000
/// @audit 0x31be135f97da6e09a19dc367e3b6da40
/// @audit 128
111:          if (tick & 0x8000 != 0) ratio = (ratio * 0x31be135f97da6e09a19dc367e3b6da40) >> 128;

/// @audit 0x10000
/// @audit 0x9aa508b5b7e5a9780b0cc4e25d61a56
/// @audit 128
112:          if (tick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7e5a9780b0cc4e25d61a56) >> 128;

/// @audit 0x20000
/// @audit 0x5d6af8dedbcb3a6ccb7ce618d14225
/// @audit 128
113:          if (tick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedbcb3a6ccb7ce618d14225) >> 128;

/// @audit 0x40000
/// @audit 0x2216e584f630389b2052b8db590e
/// @audit 128
114:          if (tick & 0x40000 != 0) ratio = (ratio * 0x2216e584f630389b2052b8db590e) >> 128;

/// @audit 128
116:          uint256 result = (ratio * PRBMathUD60x18.SCALE) >> 128;

/// @audit 4
127:                      b + (b.mul(b) + Math.mulDiv(4 * _reserveB.mul(_reserveA), _sqrtUpperTickPrice - _sqrtLowerTickPrice, _sqrtUpperTickPrice, false)).sqrt(),

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol#L16

File: maverick-v1/contracts/models/Factory.sol

/// @audit 1e18
60:           require(_fee > 0 && _fee < 1e18, "Factory:FEE_OUT_OF_BOUNDS");

/// @audit 3600
62:           require(_lookback >= 3600 && _lookback <= uint16(type(int16).max), "Factory:LOOKBACK_OUT_OF_BOUNDS");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L60

File: maverick-v1/contracts/models/Pool.sol

/// @audit 0x1111111111111111111111111111111111111111111111111111111111111111
462:                      0x1111111111111111111111111111111111111111111111111111111111111111 * (KIND_RIGHT | KIND_BOTH)

/// @audit 0x1111111111111111111111111111111111111111111111111111111111111111
479:                      0x1111111111111111111111111111111111111111111111111111111111111111 * (KIND_LEFT | KIND_BOTH)

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L462

File: router-v1/contracts/libraries/Multicall.sol

/// @audit 68
18:                   if (result.length < 68) revert();

/// @audit 0x04
20:                       result := add(result, 0x04)

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Multicall.sol#L18

[N‑03] Numeric values having to do with time should use time units for readability

There are units for seconds, minutes, hours, days, and weeks, and since they're defined, they should be used

There is 1 instance of this issue:

File: maverick-v1/contracts/models/Factory.sol

/// @audit 3600
62:           require(_lookback >= 3600 && _lookback <= uint16(type(int16).max), "Factory:LOOKBACK_OUT_OF_BOUNDS");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L62

[N‑04] Use bit shifts in an imutable variable rather than long bit masks of a single bit, for readability

There are 4 instances of this issue:

File: maverick-v1/contracts/libraries/BinMath.sol

16:               if (x >= 0x100000000000000000000000000000000) {

20:               if (x >= 0x10000000000000000) {

24:               if (x >= 0x100000000) {

96:           uint256 ratio = tick & 0x1 != 0 ? 0xfffcb933bd6fad9d3af5f0b9f25db4d6 : 0x100000000000000000000000000000000;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol#L16

[N‑05] Missing event and or timelock for critical parameter change

Events help non-contract tools to track changes, and events prevent users from being surprised by changes

There is 1 instance of this issue:

File: maverick-v1/contracts/models/PositionMetadata.sol

17        function setBaseURI(string memory _baseURI) external onlyOwner {
18            baseURI = _baseURI;
19:       }

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol#L17-L19

[N‑06] Events that mark critical parameter changes should contain both the old and the new value

This should especially be done if the new value is not required to be different from the old value

There are 3 instances of this issue:

File: maverick-v1/contracts/models/Factory.sol

/// @audit setProtocolFeeRatio()
37:           emit SetFactoryProtocolFeeRatio(_protocolFeeRatio);

/// @audit setOwner()
43:           emit SetFactoryOwner(_owner);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L37

File: maverick-v1/contracts/models/Position.sol

/// @audit setMetadata()
25:           emit SetMetadata(metadata);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Position.sol#L25

[N‑07] Use a more recent version of solidity

Use a solidity version of at least 0.8.12 to get string.concat() to be used instead of abi.encodePacked(<str>,<str>)

There is 1 instance of this issue:

File: maverick-v1/contracts/models/PositionMetadata.sol

2:    pragma solidity ^0.8.4;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol#L2

[N‑08] Use a more recent version of solidity

Use a solidity version of at least 0.8.13 to get the ability to use using for with a list of free functions

There are 8 instances of this issue:

File: maverick-v1/contracts/libraries/BinMath.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol#L2

File: maverick-v1/contracts/libraries/Bin.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Bin.sol#L2

File: maverick-v1/contracts/libraries/SafeERC20Min.sol

3:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/SafeERC20Min.sol#L3

File: maverick-v1/contracts/libraries/Twa.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Twa.sol#L2

File: maverick-v1/contracts/models/PoolInspector.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L2

File: maverick-v1/contracts/models/Pool.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L2

File: maverick-v1/contracts/models/Position.sol

2:    pragma solidity ^0.8.4;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Position.sol#L2

File: router-v1/contracts/libraries/Path.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Path.sol#L2

[N‑09] Use a more recent version of solidity

Use a solidity version of at least 0.8.4 to get bytes.concat() instead of abi.encodePacked(<bytes>,<bytes>) Use a solidity version of at least 0.8.12 to get string.concat() instead of abi.encodePacked(<str>,<str>)

There is 1 instance of this issue:

File: router-v1/contracts/Router.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L2

[N‑10] Inconsistent spacing in comments

Some lines use // x and some use //x. The instances below point out the usages that don't follow the majority, within each file

There are 28 instances of this issue:

File: maverick-v1/contracts/interfaces/IFactory.sol

29:       //protocol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IFactory.sol#L29

File: maverick-v1/contracts/interfaces/IPoolAdmin.sol

7:        //or B protocol fee (2 or 3)

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPoolAdmin.sol#L7

File: maverick-v1/contracts/interfaces/IPool.sol

78:       //to the current bin or an absolute position

100:      //defined in Pool.sol

103:      //protocol

147:      //position of the liquidity

149:      //caller can transfer tokens

153:      //to another

163:      //and amounts

167:      //mergeId is the currrent active bin.

170:      //zero to recurse until the active bin is found.

176:      //is false or the output if exactOutput is true

179:      //exact output amount (true)

181:      //indicates no limit.  Limit is only engaged for exactOutput=false.  If the

182:      //limit is reached only part of the input amount will be swapped and the

183:      //callback will only require that amount of the swap to be paid.

185:      //caller can transfer tokens

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPool.sol#L78

File: maverick-v1/contracts/models/Pool.sol

356:      //**********************  Internal  **********************/

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L356

File: router-v1/contracts/interfaces/IRouter.sol

33:       //another token

35:       //`ExactInputSingleParams` in calldata

48:       //another along the specified path

50:       //as `ExactInputParams` in calldata

65:       //another token

67:       //`ExactOutputSingleParams` in calldata

80:       //another along the specified path (reversed)

82:       //as `ExactOutputParams` in calldata

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/interfaces/IRouter.sol#L33

File: router-v1/contracts/Router.sol

21:       //computed amount in for an exact output swap / can never actually be this

22:       //value

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L21

[N‑11] Lines are too long

Usually lines in source code are limited to 80 characters. Today's screens are much larger so it's reasonable to stretch this in some cases. Since the files will most likely reside in GitHub, and GitHub starts using a scroll bar in all cases when the length is over 164 characters, the lines below should be split when they reach that length

There are 18 instances of this issue:

File: maverick-v1/contracts/interfaces/IFactory.sol

9:        event PoolCreated(address poolAddress, uint256 fee, uint256 tickSpacing, int32 activeTick, uint32 lookback, uint16 protocolFeeRatio, IERC20 tokenA, IERC20 tokenB);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IFactory.sol#L9

File: maverick-v1/contracts/interfaces/IPool.sol

150:      function addLiquidity(uint256 tokenId, AddLiquidityParams[] calldata params, bytes calldata data) external returns (uint256 tokenAAmount, uint256 tokenBAmount, BinDelta[] memory binDeltas);

164:      function removeLiquidity(address recipient, uint256 tokenId, RemoveLiquidityParams[] calldata params) external returns (uint256 tokenAOut, uint256 tokenBOut, BinDelta[] memory binDeltas);

186:      function swap(address recipient, uint256 amount, bool tokenAIn, bool exactOutput, uint256 sqrtPriceLimit, bytes calldata data) external returns (uint256 amountIn, uint256 amountOut);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPool.sol#L150

File: maverick-v1/contracts/libraries/BinMap.sol

41:       function getKindsAtTickRange(mapping(int32 => uint256) storage binMap, int32 startTick, int32 endTick, uint256 kindMask) internal view returns (Active[] memory activeList, uint256 counter) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMap.sol#L41

File: maverick-v1/contracts/libraries/BinMath.sol

134:      function getTickSqrtPriceAndL(uint256 _reserveA, uint256 _reserveB, uint256 _sqrtLowerTickPrice, uint256 _sqrtUpperTickPrice) internal pure returns (uint256 sqrtPrice, uint256 liquidity) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol#L134

File: maverick-v1/contracts/libraries/Bin.sol

52:                   : Math.min(Math.mulDiv(deltaAOptimal, self.state.totalSupply, self.state.reserveA, false), Math.mulDiv(deltaBOptimal, self.state.totalSupply, self.state.reserveB, false));

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Bin.sol#L52

File: maverick-v1/contracts/models/Factory.sol

58:       function create(uint256 _fee, uint256 _tickSpacing, uint16 _lookback, int32 _activeTick, IERC20 _tokenA, IERC20 _tokenB) external override returns (IPool pool) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L58

File: maverick-v1/contracts/models/PoolInspector.sol

33:                   bins[activeCounter] = BinInfo({id: i + 1, kind: bin.kind, lowerTick: bin.lowerTick, reserveA: bin.reserveA, reserveB: bin.reserveB, mergeId: bin.mergeId});

107:          (sqrtPrice, liquidity) = BinMath.getTickSqrtPriceAndL(reserveA, reserveB, BinMath.tickSqrtPrice(tickSpacing, activeTick), BinMath.tickSqrtPrice(tickSpacing, activeTick + 1));

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L33

File: maverick-v1/contracts/models/Pool.sol

238:              binDeltas[i] = BinDelta({binId: param.binId, deltaA: deltaA, deltaB: deltaB, kind: bin.state.kind, isActive: isActive, lowerTick: bin.state.lowerTick, deltaLpBalance: deltaLpBalance});

260:      function swap(address recipient, uint256 amount, bool tokenAIn, bool exactOutput, uint256 sqrtPriceLimit, bytes calldata data) external returns (uint256 amountIn, uint256 amountOut) {

270:              delta.excess = (!exactOutput) ? Math.fromScale(amount, tokenAIn ? tokenAScale : tokenBScale) : Math.fromScale(amount, !tokenAIn ? tokenAScale : tokenBScale);

294:              twa.updateValue(currentState.activeTick * PRBMathSD59x18.SCALE + int256(Math.clip(delta.endSqrtPrice, delta.sqrtLowerTickPrice).div(delta.sqrtUpperTickPrice - delta.sqrtLowerTickPrice)));

516:      function _currentTickLiquidity(int32 tick) internal view returns (uint256 sqrtLowerTickPrice, uint256 sqrtUpperTickPrice, uint256 sqrtPrice, uint128[] memory binIds, SwapData memory output) {

597:      function _computeSwapExactOut(uint256 sqrtPrice, uint256 liquidity, uint256 reserveA, uint256 reserveB, uint256 amountOut, bool tokenAIn) internal view returns (Delta.Instance memory delta) {

602:          binAmountIn = Math.mulDiv(delta.deltaOutErc, tokenAIn ? sqrtPrice : sqrtPrice.inv(), (tokenAIn ? sqrtPrice.inv() : sqrtPrice) - delta.deltaOutErc.div(liquidity), true);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L238

File: router-v1/contracts/Router.sol

272:              pool = IFactory(factory).create(poolParams.fee, poolParams.tickSpacing, poolParams.lookback, poolParams.activeTick, poolParams.tokenA, poolParams.tokenB);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L272

[N‑12] Variable names that consist of all capital letters should be reserved for constant/immutable variables

If the variable needs to be different based on which class it comes from, a view/pure function should be used instead (e.g. like this).

There is 1 instance of this issue:

File: router-v1/contracts/Router.sol

48:       constructor(IFactory _factory, IPosition _position, IWETH9 _WETH9) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L48

[N‑13] Non-library/interface files should use fixed compiler versions, not floating ones

There are 6 instances of this issue:

File: maverick-v1/contracts/models/Factory.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L2

File: maverick-v1/contracts/models/PoolInspector.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L2

File: maverick-v1/contracts/models/Pool.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L2

File: maverick-v1/contracts/models/PositionMetadata.sol

2:    pragma solidity ^0.8.4;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol#L2

File: maverick-v1/contracts/models/Position.sol

2:    pragma solidity ^0.8.4;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Position.sol#L2

File: router-v1/contracts/Router.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L2

[N‑14] File is missing NatSpec

There are 18 instances of this issue:

File: maverick-v1/contracts/interfaces/IAddLiquidityCallback.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IAddLiquidityCallback.sol

File: maverick-v1/contracts/interfaces/IPositionMetadata.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPositionMetadata.sol

File: maverick-v1/contracts/interfaces/ISwapCallback.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/ISwapCallback.sol

File: maverick-v1/contracts/libraries/BinMap.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMap.sol

File: maverick-v1/contracts/libraries/BinMath.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol

File: maverick-v1/contracts/libraries/Bin.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Bin.sol

File: maverick-v1/contracts/libraries/Cast.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Cast.sol

File: maverick-v1/contracts/libraries/Constants.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Constants.sol

File: maverick-v1/contracts/libraries/Delta.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Delta.sol

File: maverick-v1/contracts/libraries/Deployer.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Deployer.sol

File: maverick-v1/contracts/libraries/Math.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Math.sol

File: maverick-v1/contracts/libraries/SafeERC20Min.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/SafeERC20Min.sol

File: maverick-v1/contracts/libraries/Twa.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Twa.sol

File: maverick-v1/contracts/models/PoolInspector.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol

File: maverick-v1/contracts/models/Pool.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol

File: maverick-v1/contracts/models/PositionMetadata.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol

File: maverick-v1/contracts/models/Position.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Position.sol

File: router-v1/contracts/libraries/Deadline.sol

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Deadline.sol

[N‑15] NatSpec is incomplete

There are 9 instances of this issue:

File: maverick-v1/contracts/interfaces/IFactory.sol

/// @audit Missing: '@return'
18        /// @param _tokenA ERC20 token
19        /// @param _tokenB ERC20 token
20:       function create(uint256 _fee, uint256 _tickSpacing, uint16 _lookback, int32 _activeTick, IERC20 _tokenA, IERC20 _tokenB) external returns (IPool);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IFactory.sol#L18-L20

File: maverick-v1/contracts/interfaces/IPool.sol

/// @audit Missing: '@return'
148       /// @param data callback function that addLiquidity will call so that the
149       //caller can transfer tokens
150:      function addLiquidity(uint256 tokenId, AddLiquidityParams[] calldata params, bytes calldata data) external returns (uint256 tokenAAmount, uint256 tokenBAmount, BinDelta[] memory binDeltas);

/// @audit Missing: '@return'
162       /// @param params array of RemoveLiquidityParams that specify the bins,
163       //and amounts
164:      function removeLiquidity(address recipient, uint256 tokenId, RemoveLiquidityParams[] calldata params) external returns (uint256 tokenAOut, uint256 tokenBOut, BinDelta[] memory binDeltas);

/// @audit Missing: '@return'
184       /// @param data callback function that swap will call so that the
185       //caller can transfer tokens
186:      function swap(address recipient, uint256 amount, bool tokenAIn, bool exactOutput, uint256 sqrtPriceLimit, bytes calldata data) external returns (uint256 amountIn, uint256 amountOut);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPool.sol#L148-L150

File: maverick-v1/contracts/models/Factory.sol

/// @audit Missing: '@return'
56        /// @param _tokenA ERC20 token
57        /// @param _tokenB ERC20 token
58:       function create(uint256 _fee, uint256 _tickSpacing, uint16 _lookback, int32 _activeTick, IERC20 _tokenA, IERC20 _tokenB) external override returns (IPool pool) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L56-L58

File: router-v1/contracts/interfaces/IRouter.sol

/// @audit Missing: '@return'
118       /// @param minTokenBAmount minimum amount of token B to add, revert if not met
119       /// @param deadline epoch timestamp in seconds
120       function getOrCreatePoolAndAddLiquidity(
121           PoolParams calldata poolParams,
122           uint256 tokenId,
123           IPool.AddLiquidityParams[] calldata addParams,
124           uint256 minTokenAAmount,
125           uint256 minTokenBAmount,
126           uint256 deadline
127:      ) external payable returns (uint256 receivingTokenId, uint256 tokenAAmount, uint256 tokenBAmount, IPool.BinDelta[] memory binDeltas);

/// @audit Missing: '@return'
134       /// @param minTokenBAmount minimum amount of token B to add, revert if not met
135       /// @param deadline epoch timestamp in seconds
136       function addLiquidityToPool(
137           IPool pool,
138           uint256 tokenId,
139           IPool.AddLiquidityParams[] calldata params,
140           uint256 minTokenAAmount,
141           uint256 minTokenBAmount,
142           uint256 deadline
143:      ) external payable returns (uint256 receivingTokenId, uint256 tokenAAmount, uint256 tokenBAmount, IPool.BinDelta[] memory binDeltas);

/// @audit Missing: '@return'
152       /// @param maxActiveTick highest activeTick (inclusive) of pool that will permit transaction to pass
153       /// @param deadline epoch timestamp in seconds
154       function addLiquidityWTickLimits(
155           IPool pool,
156           uint256 tokenId,
157           IPool.AddLiquidityParams[] calldata params,
158           uint256 minTokenAAmount,
159           uint256 minTokenBAmount,
160           int32 minActiveTick,
161           int32 maxActiveTick,
162           uint256 deadline
163:      ) external payable returns (uint256 receivingTokenId, uint256 tokenAAmount, uint256 tokenBAmount, IPool.BinDelta[] memory binDeltas);

/// @audit Missing: '@return'
179       /// @param minTokenBAmount minimum amount of token B to receive, revert if not met
180       /// @param deadline epoch timestamp in seconds
181       function removeLiquidity(
182           IPool pool,
183           address recipient,
184           uint256 tokenId,
185           IPool.RemoveLiquidityParams[] calldata params,
186           uint256 minTokenAAmount,
187           uint256 minTokenBAmount,
188           uint256 deadline
189:      ) external returns (uint256 tokenAAmount, uint256 tokenBAmount, IPool.BinDelta[] memory binDeltas);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/interfaces/IRouter.sol#L118-L127

[N‑16] Not using the named return variables anywhere in the function is confusing

Consider changing the variable to be an unnamed one

There are 17 instances of this issue:

File: maverick-v1/contracts/libraries/BinMath.sol

/// @audit _result
91:       function tickSqrtPrice(uint256 tickSpacing, int32 _tick) internal pure returns (uint256 _result) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol#L91

File: maverick-v1/contracts/libraries/Delta.sol

/// @audit edge
38:       function sqrtEdgePrice(Instance memory self) internal pure returns (uint256 edge) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Delta.sol#L38

File: maverick-v1/contracts/models/Factory.sol

/// @audit pool
46:       function lookup(uint256 _fee, uint256 _tickSpacing, uint16 _lookback, IERC20 _tokenA, IERC20 _tokenB) external view override returns (IPool pool) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L46

File: maverick-v1/contracts/models/Pool.sol

/// @audit bin
312:      function getBin(uint128 binId) external view override returns (BinState memory bin) {

/// @audit lpToken
316:      function balanceOf(uint256 tokenId, uint128 binId) external view override returns (uint256 lpToken) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L312

File: router-v1/contracts/Router.sol

/// @audit receivingTokenId
/// @audit tokenAAmount
/// @audit tokenBAmount
/// @audit binDeltas
238       function addLiquidityToPool(
239           IPool pool,
240           uint256 tokenId,
241           IPool.AddLiquidityParams[] calldata params,
242           uint256 minTokenAAmount,
243           uint256 minTokenBAmount,
244           uint256 deadline
245:      ) external payable checkDeadline(deadline) returns (uint256 receivingTokenId, uint256 tokenAAmount, uint256 tokenBAmount, IPool.BinDelta[] memory binDeltas) {

/// @audit receivingTokenId
/// @audit tokenAAmount
/// @audit tokenBAmount
/// @audit binDeltas
250       function addLiquidityWTickLimits(
251           IPool pool,
252           uint256 tokenId,
253           IPool.AddLiquidityParams[] calldata params,
254           uint256 minTokenAAmount,
255           uint256 minTokenBAmount,
256           int32 minActiveTick,
257           int32 maxActiveTick,
258           uint256 deadline
259:      ) external payable checkDeadline(deadline) returns (uint256 receivingTokenId, uint256 tokenAAmount, uint256 tokenBAmount, IPool.BinDelta[] memory binDeltas) {

/// @audit receivingTokenId
/// @audit tokenAAmount
/// @audit tokenBAmount
/// @audit binDeltas
277       function getOrCreatePoolAndAddLiquidity(
278           PoolParams calldata poolParams,
279           uint256 tokenId,
280           IPool.AddLiquidityParams[] calldata addParams,
281           uint256 minTokenAAmount,
282           uint256 minTokenBAmount,
283           uint256 deadline
284:      ) external payable checkDeadline(deadline) returns (uint256 receivingTokenId, uint256 tokenAAmount, uint256 tokenBAmount, IPool.BinDelta[] memory binDeltas) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L238-L245

[N‑17] Duplicated require()/revert() checks should be refactored to a modifier or function

The compiler will inline the function, which will avoid JUMP instructions usually associated with functions

There are 3 instances of this issue:

File: maverick-v1/contracts/models/Factory.sol

35:           require(_protocolFeeRatio <= ONE_3_DECIMAL_SCALE, "Factory:PROTOCOL_FEE_CANNOT_EXCEED_ONE");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L35

File: router-v1/contracts/Router.sol

165:          require(amountOut >= params.amountOutMinimum, "Too little received");

197:          require(amountIn <= params.amountInMaximum, "Too much requested");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L165

[N‑18] Consider using delete rather than assigning zero to clear values

The delete keyword more closely matches the semantics of what is being done, and draws more attention to the changing of state, which may lead to a more thorough audit of its associated logic

There are 6 instances of this issue:

File: maverick-v1/contracts/libraries/Delta.sol

43:           self.excess = 0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Delta.sol#L43

File: maverick-v1/contracts/models/Pool.sol

359:          binPositions[tick][kind] = 0;

382:              moveData.firstBinId = 0;

384:              moveData.mergeBinCounter = 0;

385:              moveData.totalReserveA = 0;

386:              moveData.totalReserveB = 0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L359

[N‑19] Contracts should have full test coverage

While 100% code coverage does not guarantee that there are no bugs, it often will catch easy-to-find bugs, and will ensure that there are fewer regressions when the code invariably has to be modified. Furthermore, in order to get full coverage, code authors will often have to re-organize their code so that it is more modular, so that each component can be tested separately, which reduces interdependencies between modules and layers, and makes for code that is easier to reason about and audit.

There is 1 instance of this issue:

File: maverick-v1/contracts/interfaces/IAddLiquidityCallback.sol

[N‑20] Large or complicated code bases should implement fuzzing tests

Large code bases, or code with lots of inline-assembly, complicated math, or complicated interactions between multiple contracts, should implement fuzzing tests. Fuzzers such as Echidna require the test writer to come up with invariants which should not be violated under any circumstances, and the fuzzer tests various inputs and function calls to ensure that the invariants always hold. Even code with 100% code coverage can still have bugs due to the order of the operations a user performs, and fuzzers, with properly and extensively-written invariants, can close this testing gap significantly.

There is 1 instance of this issue:

File: maverick-v1/contracts/interfaces/IAddLiquidityCallback.sol


Excluded findings

These findings are excluded from awards calculations because there are publicly-available automated tools that find them. The valid ones appear here for completeness

Summary

Non-critical Issues

IssueInstances
[N‑01]require()/revert() statements should have descriptive reason strings7
[N‑02]public functions not called by the contract should be declared external instead2
[N‑03]Event is missing indexed fields12

Total: 21 instances over 3 issues

Non-critical Issues

[N‑01] require()/revert() statements should have descriptive reason strings

There are 7 instances of this issue:

File: maverick-v1/contracts/models/Pool.sol

/// @audit (valid but excluded finding)
129:              require(param.kind < NUMBER_OF_KINDS);

/// @audit (valid but excluded finding)
333:          require(_protocolFeeRatio <= ONE_3_DECIMAL_SCALE);

/// @audit (valid but excluded finding)
342:          require(msg.sender == factory.owner());

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L129

File: router-v1/contracts/libraries/Multicall.sol

/// @audit (valid but excluded finding)
18:                   if (result.length < 68) revert();

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Multicall.sol#L18

File: router-v1/contracts/Router.sol

/// @audit (valid but excluded finding)
106:          require(msg.sender == address(pool));

/// @audit (valid but excluded finding)
205:          require(factory.isFactoryPool(IPool(msg.sender)));

/// @audit (valid but excluded finding)
206:          require(msg.sender == address(data.pool));

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L106

[N‑02] public functions not called by the contract should be declared external instead

Contracts are allowed to override their parents' functions and change the visibility from external to public.

There are 2 instances of this issue:

File: maverick-v1/contracts/models/PoolInspector.sol

/// @audit (valid but excluded finding)
45:       function getBinDepth(IPool pool, uint128 binId) public view returns (uint256 depth) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L45

File: router-v1/contracts/Router.sol

/// @audit (valid but excluded finding)
70:       function sweepToken(IERC20 token, uint256 amountMinimum, address recipient) public payable {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L70

[N‑03] Event is missing indexed fields

Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed.

There are 12 instances of this issue:

File: maverick-v1/contracts/interfaces/IFactory.sol

/// @audit (valid but excluded finding)
9:        event PoolCreated(address poolAddress, uint256 fee, uint256 tickSpacing, int32 activeTick, uint32 lookback, uint16 protocolFeeRatio, IERC20 tokenA, IERC20 tokenB);

/// @audit (valid but excluded finding)
10:       event SetFactoryProtocolFeeRatio(uint16 protocolFeeRatio);

/// @audit (valid but excluded finding)
11:       event SetFactoryOwner(address owner);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IFactory.sol#L9

File: maverick-v1/contracts/interfaces/IPool.sol

/// @audit (valid but excluded finding)
8:        event Swap(address indexed sender, address indexed recipient, bool tokenAIn, bool exactOutput, uint256 amountIn, uint256 amountOut, int32 activeTick);

/// @audit (valid but excluded finding)
10:       event AddLiquidity(address indexed sender, uint256 indexed tokenId, BinDelta[] binDeltas);

/// @audit (valid but excluded finding)
12:       event MigrateBinsUpStack(address indexed sender, uint128[] binIds, uint32 maxRecursion);

/// @audit (valid but excluded finding)
14:       event TransferLiquidity(uint256 fromTokenId, uint256 toTokenId, RemoveLiquidityParams[] params);

/// @audit (valid but excluded finding)
18:       event BinMerged(uint128 indexed binId, uint128 reserveA, uint128 reserveB, uint128 mergeId);

/// @audit (valid but excluded finding)
20:       event BinMoved(uint128 indexed binId, int128 previousTick, int128 newTick);

/// @audit (valid but excluded finding)
22:       event ProtocolFeeCollected(uint256 protocolFee, bool isTokenA);

/// @audit (valid but excluded finding)
24:       event SetProtocolFeeRatio(uint256 protocolFee);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPool.sol#L8

File: maverick-v1/contracts/interfaces/IPosition.sol

/// @audit (valid but excluded finding)
8:        event SetMetadata(IPositionMetadata metadata);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPosition.sol#L8

#0 - c4-judge

2023-01-18T22:12:56Z

kirk-baird marked the issue as grade-a

Findings Information

🌟 Selected for report: IllIllI

Also found by: 0x1f8b, 0xSmartContract, Deivitto, Mukund, RaymondFam, Rolezn, ajtra, c3phas, sakshamguruji, saneryee

Labels

bug
G (Gas Optimization)
grade-a
selected for report
G-06

Awards

630.4686 USDC - $630.47

External Links

Summary

Gas Optimizations

IssueInstancesTotal Gas Saved
[G‑01]State variables only set in the constructor should be declared immutable22097
[G‑02]Structs can be packed into fewer storage slots2-
[G‑03]Using storage instead of memory for structs/arrays saves gas14200
[G‑04]Avoid contract existence checks by using low level calls111100
[G‑05]The result of function calls should be cached rather than re-calling the function4-
[G‑06]<x> += <y> costs more gas than <x> = <x> + <y> for state variables4452
[G‑07]internal functions only called once can be inlined to save gas11220
[G‑08]Add unchecked {} for subtractions where the operands cannot underflow because of a previous require() or if-statement185
[G‑09]++i/i++ should be unchecked{++i}/unchecked{i++} when it is not possible for them to overflow, as is the case when used in for- and while-loops14840
[G‑10]require()/revert() strings longer than 32 bytes cost extra gas4-
[G‑11]Optimize names to save gas17374
[G‑12]Use a more recent version of solidity18-
[G‑13]>= costs less gas than >26
[G‑14]++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too)15
[G‑15]Splitting require() statements that use && saves gas1236
[G‑16]Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead50-
[G‑17]Inverting the condition of an if-else-statement wastes gas1-
[G‑18]require() or revert() statements that check input arguments should be at the top of the function2-
[G‑19]Functions guaranteed to revert when called by normal users can be marked payable242

Total: 159 instances over 19 issues with 9460 gas saved

Gas totals use lower bounds of ranges and count two iterations of each for-loop. All values above are runtime, not deployment, values; deployment values are listed in the individual issue descriptions. The table above as well as its gas numbers do not include any of the excluded findings.

Gas Optimizations

[G‑01] State variables only set in the constructor should be declared immutable

Avoids a Gsset (20000 gas) in the constructor, and replaces the first access in each transaction (Gcoldsload - 2100 gas) and each access thereafter (Gwarmacces - 100 gas) with a PUSH32 (3 gas).

In the example below, twa.lookback never changes, so it should be pulled out of the struct and converted to an immutable value. If you still want the struct to contain the lookback, create a private version of the twa struct, for storage purposes, that does not have the lookback, and use that to build the original twa structs on the fly, when requested, and pass the value as an argument to TWA.getTwa() when it's called. Since this is in the hot path, you'll save a lot of gas.

There are 2 instances of this issue:

File: maverick-v1/contracts/models/Pool.sol

/// @audit twa.lookback (constructor)
77:           twa.lookback = _lookback;

/// @audit twa (access)
102:          return twa;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L77

[G‑02] Structs can be packed into fewer storage slots

Each slot saved can avoid an extra Gsset (20000 gas) for the first setting of the struct. Subsequent reads as well as writes have smaller gas savings

There are 2 instances of this issue:

File: maverick-v1/contracts/libraries/Delta.sol

/// @audit Variable ordering with 10 slots instead of the current 11:
///           uint256(32):deltaInBinInternal, uint256(32):deltaInErc, uint256(32):deltaOutErc, uint256(32):excess, uint256(32):endSqrtPrice, uint256(32):sqrtPriceLimit, uint256(32):sqrtLowerTickPrice, uint256(32):sqrtUpperTickPrice, uint256(32):sqrtPrice, bool(1):tokenAIn, bool(1):exactOutput, bool(1):swappedToMaxPrice, bool(1):skipCombine, bool(1):decrementTick
5         struct Instance {
6             uint256 deltaInBinInternal;
7             uint256 deltaInErc;
8             uint256 deltaOutErc;
9             uint256 excess;
10            bool tokenAIn;
11            uint256 endSqrtPrice;
12            bool exactOutput;
13            bool swappedToMaxPrice;
14            bool skipCombine;
15            bool decrementTick;
16            uint256 sqrtPriceLimit;
17            uint256 sqrtLowerTickPrice;
18            uint256 sqrtUpperTickPrice;
19            uint256 sqrtPrice;
20:       }

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Delta.sol#L5-L20

File: maverick-v1/contracts/models/Pool.sol

/// @audit Variable ordering with 8 slots instead of the current 10:
///           uint8[2](32):kinds, user-defined[](32):activeList, uint256(32):mergeBinBalance, uint256(32):binCounter, uint256(32):mergeBinCounter, uint128[](32):mergeBins, uint128(16):firstBinId, uint128(16):totalReserveA, uint128(16):totalReserveB, int32(4):tickLimit, int32(4):shiftAmount
363       struct MoveData {
364           int32 tickLimit;
365           uint8[2] kinds;
366           int32 shiftAmount;
367           BinMap.Active[] activeList;
368           uint128 firstBinId;
369           uint256 mergeBinBalance;
370           uint128 totalReserveA;
371           uint128 totalReserveB;
372           uint256 binCounter;
373           uint256 mergeBinCounter;
374           uint128[] mergeBins;
375:      }

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L363-L375

[G‑03] Using storage instead of memory for structs/arrays saves gas

When fetching data from a storage location, assigning the data to a memory variable causes all fields of the struct/array to be read from storage, which incurs a Gcoldsload (2100 gas) for each field of the struct/array. If the fields are read from the new memory variable, they incur an additional MLOAD rather than a cheap stack read. Instead of declearing the variable with the memory keyword, declaring the variable with the storage keyword and caching any fields that need to be re-read in stack variables, will be much cheaper, only incuring the Gcoldsload for the fields actually read. The only time it makes sense to read the whole struct/array into a memory variable, is if the full struct/array is being returned by the function, is being passed to a function that requires memory, or if the array/struct is being read from another memory array/struct

There is 1 instance of this issue:

File: maverick-v1/contracts/models/PoolInspector.sol

102:              IPool.BinState memory bin = bins[i];

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L102

[G‑04] Avoid contract existence checks by using low level calls

Prior to 0.8.10 the compiler inserted extra code, including EXTCODESIZE (100 gas), to check for contract existence for external function calls. In more recent solidity versions, the compiler will not insert these checks if the external call has a return value. Similar behavior can be achieved in earlier versions by using low-level calls, since low level calls never check for contract existence

There are 11 instances of this issue:

File: maverick-v1/contracts/models/Factory.sol

/// @audit decimals()
74:               Math.scale(IERC20Metadata(address(_tokenA)).decimals()),

/// @audit decimals()
75:               Math.scale(IERC20Metadata(address(_tokenB)).decimals()),

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L74

File: maverick-v1/contracts/models/Pool.sol

/// @audit balanceOf()
502:          return IERC20(tokenA).balanceOf(address(this));

/// @audit balanceOf()
506:          return IERC20(tokenB).balanceOf(address(this));

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L502

File: router-v1/contracts/libraries/SelfPermit.sol

/// @audit allowance()
22:           if (IERC20(token).allowance(msg.sender, address(this)) < value) selfPermit(token, value, deadline, v, r, s);

/// @audit allowance()
32:           if (IERC20(token).allowance(msg.sender, address(this)) < type(uint256).max) selfPermitAllowed(token, nonce, expiry, v, r, s);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/SelfPermit.sol#L22

File: router-v1/contracts/Router.sol

/// @audit tokenOfOwnerByIndexExists()
223:              if (IPosition(position).tokenOfOwnerByIndexExists(msg.sender, 0)) {

/// @audit tokenOfOwnerByIndex()
224:                  tokenId = IPosition(position).tokenOfOwnerByIndex(msg.sender, 0);

/// @audit mint()
226:                  tokenId = IPosition(position).mint(msg.sender);

/// @audit lookup()
269:              pool = IFactory(factory).lookup(poolParams.fee, poolParams.tickSpacing, poolParams.lookback, poolParams.tokenA, poolParams.tokenB);

/// @audit create()
272:              pool = IFactory(factory).create(poolParams.fee, poolParams.tickSpacing, poolParams.lookback, poolParams.activeTick, poolParams.tokenA, poolParams.tokenB);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L223

[G‑05] The result of function calls should be cached rather than re-calling the function

The instances below point to the second+ call of the function within a single function

There are 4 instances of this issue:

File: maverick-v1/contracts/models/Pool.sol

/// @audit sqrtPrice.inv() on line 589
589:              Math.mulDiv(binAmountIn, tokenAIn ? sqrtPrice.inv() : sqrtPrice, binAmountIn.div(liquidity) + (tokenAIn ? sqrtPrice : sqrtPrice.inv()), false)

/// @audit sqrtPrice.inv() on line 589
591:          delta.endSqrtPrice = binAmountIn.div(liquidity) + (tokenAIn ? sqrtPrice : sqrtPrice.inv());

/// @audit sqrtPrice.inv() on line 602
602:          binAmountIn = Math.mulDiv(delta.deltaOutErc, tokenAIn ? sqrtPrice : sqrtPrice.inv(), (tokenAIn ? sqrtPrice.inv() : sqrtPrice) - delta.deltaOutErc.div(liquidity), true);

/// @audit sqrtPrice.inv() on line 602
603:          delta.endSqrtPrice = (tokenAIn ? sqrtPrice.inv() : sqrtPrice) - delta.deltaOutErc.div(liquidity);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L589

[G‑06] <x> += <y> costs more gas than <x> = <x> + <y> for state variables

Using the addition operator instead of plus-equals saves 113 gas

There are 4 instances of this issue:

File: maverick-v1/contracts/models/Pool.sol

161:          binBalanceA += tokenAAmount.toUint128();

162:          binBalanceB += tokenBAmount.toUint128();

288:                  binBalanceA += delta.deltaInBinInternal.toUint128();

291:                  binBalanceB += delta.deltaInBinInternal.toUint128();

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L161

[G‑07] internal functions only called once can be inlined to save gas

Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.

There are 11 instances of this issue:

File: maverick-v1/contracts/models/PoolInspector.sol

77:       function _getBinsAtTick(IPool pool, int32 tick) internal view returns (IPool.BinState[] memory bins) {

95:       function _currentTickLiquidity(IPool pool) internal view returns (uint256 sqrtPrice, uint256 liquidity, uint256 reserveA, uint256 reserveB) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L77

File: maverick-v1/contracts/models/Pool.sol

320:      function claimProtocolFees(address recipient, bool isTokenA) internal {

332:      function setProtocolFeeRatio(uint16 _protocolFeeRatio) internal {

448:      function _moveBins(int32 activeTick, int32 startingTickInitial, int32 lastTwap) internal {

486:      function _getOrCreateBin(State memory currentState, uint8 kind, int32 pos, bool isDelta) internal returns (uint128 binId, Bin.Instance storage bin) {

516:      function _currentTickLiquidity(int32 tick) internal view returns (uint256 sqrtLowerTickPrice, uint256 sqrtUpperTickPrice, uint256 sqrtPrice, uint128[] memory binIds, SwapData memory output) {

537:      function _firstKindAtTickLiquidity(int32 activeTick) internal view returns (uint256 currentReserveA, uint256 currentReserveB) {

553       function _computeSwapExactIn(
554           uint256 sqrtEdgePrice,
555           uint256 sqrtPrice,
556           uint256 liquidity,
557           uint256 reserveA,
558           uint256 reserveB,
559           uint256 amountIn,
560           bool limitInBin,
561           bool tokenAIn
562:      ) internal view returns (Delta.Instance memory delta) {

597:      function _computeSwapExactOut(uint256 sqrtPrice, uint256 liquidity, uint256 reserveA, uint256 reserveB, uint256 amountOut, bool tokenAIn) internal view returns (Delta.Instance memory delta) {

614:      function _swapTick(State memory currentState, Delta.Instance memory delta) internal returns (Delta.Instance memory newDelta) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L320

[G‑08] Add unchecked {} for subtractions where the operands cannot underflow because of a previous require() or if-statement

require(a <= b); x = b - a => require(a <= b); unchecked { x = b - a }

There is 1 instance of this issue:

File: maverick-v1/contracts/libraries/Math.sol

/// @audit if-condition on line 41
42:               return (10 ** (decimals - DEFAULT_DECIMALS)) | MAX_BIT;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Math.sol#L42

[G‑09] ++i/i++ should be unchecked{++i}/unchecked{i++} when it is not possible for them to overflow, as is the case when used in for- and while-loops

The unchecked keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas per loop

There are 14 instances of this issue:

File: maverick-v1/contracts/models/PoolInspector.sol

30:           for (uint128 i = startBinIndex; i < binCounter; i++) {

80:           for (uint8 i = 0; i < NUMBER_OF_KINDS; i++) {

101:          for (uint256 i; i < bins.length; i++) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L30

File: maverick-v1/contracts/models/Pool.sol

127:          for (uint256 i; i < params.length; i++) {

180:          for (uint256 i; i < binIds.length; i++) {

193:          for (uint256 i; i < params.length; i++) {

224:          for (uint256 i; i < params.length; i++) {

380:          for (uint256 j; j < 2; j++) {

389:              for (uint256 i; i <= moveData.binCounter; i++) {

414:              for (uint256 i; i < moveData.mergeBinCounter; i++) {

523:          for (uint256 i; i < NUMBER_OF_KINDS; i++) {

540:          for (uint256 i; i < NUMBER_OF_KINDS; i++) {

653:              for (uint256 i; i < swapData.counter; i++) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L127

File: router-v1/contracts/libraries/Multicall.sol

13:           for (uint256 i = 0; i < data.length; i++) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Multicall.sol#L13

[G‑10] require()/revert() strings longer than 32 bytes cost extra gas

Each extra memory word of bytes past the original 32 incurs an MSTORE which costs 3 gas

There are 4 instances of this issue:

File: maverick-v1/contracts/models/Factory.sol

27:           require(_protocolFeeRatio <= ONE_3_DECIMAL_SCALE, "Factory:PROTOCOL_FEE_CANNOT_EXCEED_ONE");

35:           require(_protocolFeeRatio <= ONE_3_DECIMAL_SCALE, "Factory:PROTOCOL_FEE_CANNOT_EXCEED_ONE");

59:           require(_tokenA < _tokenB, "Factory:TOKENS_MUST_BE_SORTED_BY_ADDRESS");

61:           require(_tickSpacing > 0, "Factory:TICK_SPACING_OUT_OF_BOUNDS");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L27

[G‑11] Optimize names to save gas

public/external function names and public member variable names can be optimized to save gas. See this link for an example of how it works. Below are the interfaces/abstract contracts that can be optimized so that the most frequently-called functions use the least amount of gas possible during method lookup. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted

There are 17 instances of this issue:

File: maverick-v1/contracts/interfaces/IAddLiquidityCallback.sol

/// @audit addLiquidityCallback()
4:    interface IAddLiquidityCallback {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IAddLiquidityCallback.sol#L4

File: maverick-v1/contracts/interfaces/IFactory.sol

/// @audit create(), lookup(), position(), protocolFeeRatio(), isFactoryPool()
8:    interface IFactory {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IFactory.sol#L8

File: maverick-v1/contracts/interfaces/IPoolAdmin.sol

/// @audit adminAction()
4:    interface IPoolAdmin {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPoolAdmin.sol#L4

File: maverick-v1/contracts/interfaces/IPool.sol

/// @audit fee(), tickSpacing(), tokenA(), tokenB(), factory(), binMap(), binPositions(), binBalanceA(), binBalanceB(), getTwa(), getState(), addLiquidity(), transferLiquidity(), removeLiquidity(), migrateBinsUpStack(), swap(), getBin(), balanceOf()
7:    interface IPool {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPool.sol#L7

File: maverick-v1/contracts/interfaces/IPosition.sol

/// @audit mint(), tokenOfOwnerByIndexExists()
7:    interface IPosition is IERC721Enumerable {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/IPosition.sol#L7

File: maverick-v1/contracts/interfaces/ISwapCallback.sol

/// @audit swapCallback()
4:    interface ISwapCallback {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/interfaces/ISwapCallback.sol#L4

File: maverick-v1/contracts/libraries/Deployer.sol

/// @audit deploy()
11:   library Deployer {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Deployer.sol#L11

File: maverick-v1/contracts/models/Factory.sol

/// @audit setProtocolFeeRatio(), setOwner()
14:   contract Factory is IFactory {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L14

File: maverick-v1/contracts/models/PoolInspector.sol

/// @audit getActiveBins(), getBinDepth(), calculateSwap(), getPrice()
11:   contract PoolInspector is ISwapCallback {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L11

File: maverick-v1/contracts/models/Pool.sol

/// @audit swap(), adminAction()
22:   contract Pool is IPool, IPoolAdmin {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L22

File: maverick-v1/contracts/models/PositionMetadata.sol

/// @audit setBaseURI()
8:    contract PositionMetadata is IPositionMetadata, Ownable {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol#L8

File: maverick-v1/contracts/models/Position.sol

/// @audit setMetadata(), mint(), tokenOfOwnerByIndexExists()
12:   contract Position is ERC721, ERC721Enumerable, Ownable, IPosition {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Position.sol#L12

File: router-v1/contracts/interfaces/external/IERC20PermitAllowed.sol

/// @audit permit()
6:    interface IERC20PermitAllowed {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/interfaces/external/IERC20PermitAllowed.sol#L6

File: router-v1/contracts/interfaces/IMulticall.sol

/// @audit multicall()
7:    interface IMulticall {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/interfaces/IMulticall.sol#L7

File: router-v1/contracts/interfaces/IRouter.sol

/// @audit factory(), position(), WETH9(), exactInputSingle(), exactInput(), exactOutputSingle(), exactOutput(), unwrapWETH9(), refundETH(), sweepToken(), getOrCreatePoolAndAddLiquidity(), addLiquidityToPool(), addLiquidityWTickLimits(), migrateBinsUpStack(), removeLiquidity()
11:   interface IRouter is ISwapCallback {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/interfaces/IRouter.sol#L11

File: router-v1/contracts/interfaces/ISelfPermit.sol

/// @audit selfPermit(), selfPermitIfNecessary(), selfPermitAllowed(), selfPermitAllowedIfNecessary()
6:    interface ISelfPermit {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/interfaces/ISelfPermit.sol#L6

File: router-v1/contracts/Router.sol

/// @audit sweepToken(), swapCallback(), addLiquidityCallback(), addLiquidityToPool(), addLiquidityWTickLimits(), getOrCreatePoolAndAddLiquidity(), migrateBinsUpStack(), removeLiquidity()
18:   contract Router is IRouter, Multicall, SelfPermit, Deadline {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L18

[G‑12] Use a more recent version of solidity

Use a solidity version of at least 0.8.2 to get simple compiler automatic inlining Use a solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads Use a solidity version of at least 0.8.4 to get custom errors, which are cheaper at deployment than revert()/require() strings Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value

There are 18 instances of this issue:

File: maverick-v1/contracts/libraries/BinMap.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMap.sol#L2

File: maverick-v1/contracts/libraries/BinMath.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol#L2

File: maverick-v1/contracts/libraries/Bin.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Bin.sol#L2

File: maverick-v1/contracts/libraries/Cast.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Cast.sol#L2

File: maverick-v1/contracts/libraries/Constants.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Constants.sol#L2

File: maverick-v1/contracts/libraries/Delta.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Delta.sol#L2

File: maverick-v1/contracts/libraries/Deployer.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Deployer.sol#L2

File: maverick-v1/contracts/libraries/Math.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Math.sol#L2

File: maverick-v1/contracts/libraries/SafeERC20Min.sol

3:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/SafeERC20Min.sol#L3

File: maverick-v1/contracts/libraries/Twa.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Twa.sol#L2

File: maverick-v1/contracts/models/Factory.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L2

File: maverick-v1/contracts/models/PoolInspector.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L2

File: maverick-v1/contracts/models/Pool.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L2

File: router-v1/contracts/interfaces/external/IWETH9.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/interfaces/external/IWETH9.sol#L2

File: router-v1/contracts/libraries/Deadline.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Deadline.sol#L2

File: router-v1/contracts/libraries/Multicall.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Multicall.sol#L2

File: router-v1/contracts/libraries/Path.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Path.sol#L2

File: router-v1/contracts/Router.sol

2:    pragma solidity ^0.8.0;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L2

[G‑13] >= costs less gas than >

The compiler uses opcodes GT and ISZERO for solidity code that uses >, but only requires LT for >=, which saves 3 gas

There are 2 instances of this issue:

File: maverick-v1/contracts/libraries/Math.sol

9:            return x > y ? x : y;

17:           return x > y ? x : y;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Math.sol#L9

[G‑14] ++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too)

Saves 5 gas per loop

There is 1 instance of this issue:

File: maverick-v1/contracts/models/PoolInspector.sol

85:                   binCounter--;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L85

[G‑15] Splitting require() statements that use && saves gas

See this issue which describes the fact that there is a larger deployment gas cost, but with enough runtime calls, the change ends up being cheaper by 3 gas

There are 12 instances of this issue:

File: maverick-v1/contracts/models/Factory.sol

41:           require(msg.sender == owner && _owner != address(0), "Factory:NOT_ALLOWED");

60:           require(_fee > 0 && _fee < 1e18, "Factory:FEE_OUT_OF_BOUNDS");

62:           require(_lookback >= 3600 && _lookback <= uint16(type(int16).max), "Factory:LOOKBACK_OUT_OF_BOUNDS");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L41

File: maverick-v1/contracts/models/Pool.sol

93:           require((currentState.status & LOCKED == 0) && (allowInEmergency || (currentState.status & EMERGENCY == 0)), "E");

168:          require(previousABalance + tokenAAmount <= _tokenABalance() && previousBBalance + tokenBAmount <= _tokenBBalance(), "A");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L93

File: router-v1/contracts/libraries/TransferHelper.sol

15:           require(success && (data.length == 0 || abi.decode(data, (bool))), "STF");

25:           require(success && (data.length == 0 || abi.decode(data, (bool))), "ST");

35:           require(success && (data.length == 0 || abi.decode(data, (bool))), "SA");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/TransferHelper.sol#L15

File: router-v1/contracts/Router.sol

100:          require(amountToPay > 0 && amountOut > 0, "In or Out Amount is Zero");

234:          require(tokenAAmount >= minTokenAAmount && tokenBAmount >= minTokenBAmount, "Too little added");

262:          require(activeTick >= minActiveTick && activeTick <= maxActiveTick, "activeTick not in range");

309:          require(tokenAAmount >= minTokenAAmount && tokenBAmount >= minTokenBAmount, "Too little removed");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L100

[G‑16] Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead

When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.

https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Each operation involving a uint8 costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so. Use a larger size then downcast where needed

There are 50 instances of this issue:

File: maverick-v1/contracts/libraries/BinMap.sol

/// @audit uint8 offset
21:           offset = uint8(uint32(tick_kinds));

/// @audit int32 mapIndex
22:           mapIndex = tick_kinds >> 8;

/// @audit uint16 offset
54:                   offset += bitIndex;

/// @audit uint16 offset
68:                   offset += uint16(uint32(NUMBER_OF_KINDS_32));

/// @audit int32 wordIndex
70:               wordIndex += 1;

/// @audit uint16 offset
71:               offset = 0;

/// @audit int32 tack
86:               tack = 1;

/// @audit uint16 shift
88:               shift = uint16(WORD_SIZE - offset);

/// @audit int32 tack
89:               tack = -1;

/// @audit uint16 shift
96:               shift = 0;

/// @audit uint16 subIndex
100:              subIndex = isRight ? BinMath.lsb(nextWord) + shift : BinMath.msb(nextWord) - shift;

/// @audit int32 nextTick
103:              nextTick = posFirst >> 2;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMap.sol#L21

File: maverick-v1/contracts/libraries/BinMath.sol

/// @audit uint8 result
14:               result = 0;

/// @audit uint8 result
18:                   result += 128;

/// @audit uint8 result
22:                   result += 64;

/// @audit uint8 result
26:                   result += 32;

/// @audit uint8 result
30:                   result += 16;

/// @audit uint8 result
34:                   result += 8;

/// @audit uint8 result
38:                   result += 4;

/// @audit uint8 result
42:                   result += 2;

/// @audit uint8 result
44:               if (x >= 0x2) result += 1;

/// @audit uint8 result
50:               result = 255;

/// @audit uint8 result
53:                   result -= 128;

/// @audit uint8 result
58:                   result -= 64;

/// @audit uint8 result
63:                   result -= 32;

/// @audit uint8 result
68:                   result -= 16;

/// @audit uint8 result
73:                   result -= 8;

/// @audit uint8 result
78:                   result -= 4;

/// @audit uint8 result
83:                   result -= 2;

/// @audit uint8 result
87:               if (x & 0x1 > 0) result -= 1;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol#L14

File: maverick-v1/contracts/libraries/Bin.sol

/// @audit uint128 deltaIn
61:           deltaIn = Math.mulDiv(delta.deltaInBinInternal, thisBinAmount, totalAmount, false).toUint128();

/// @audit uint128 deltaOut
63:               deltaOut = Math.mulDiv(delta.deltaOutErc, thisBinAmount, totalAmount, true).toUint128();

/// @audit uint32 maxRecursion
97:           maxRecursion = maxRecursion == 0 ? type(uint32).max : maxRecursion;

/// @audit uint32 maxRecursion
114:              maxRecursion -= 1;

/// @audit uint128 delta
122:          delta = Math.min(Math.mulDiv(tokenAmount, reserve, totalSupply, false), reserve).toUint128();

/// @audit uint128 reserveOut
123:          reserveOut = delta == 0 ? reserve : Math.clip128(reserve, delta + 1);

/// @audit uint128 deltaLpBalance128
146:              deltaLpBalance128 = Math.min(self.state.mergeBinBalance, Math.mulDiv(deltaLpBalance, self.state.mergeBinBalance, tempTotalSupply, false)).toUint128();

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Bin.sol#L61

File: maverick-v1/contracts/libraries/Cast.sol

/// @audit uint128 y
6:            require((y = uint128(x)) == x, "C");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Cast.sol#L6

File: maverick-v1/contracts/models/PoolInspector.sol

/// @audit uint128 binCounter
26:               binCounter = binCounter < endBinIndex ? binCounter : endBinIndex;

/// @audit uint128 binId
50:               binId = bin.mergeId;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L26

File: maverick-v1/contracts/models/Pool.sol

/// @audit uint128 binBalanceA
161:          binBalanceA += tokenAAmount.toUint128();

/// @audit uint128 binBalanceB
162:          binBalanceB += tokenBAmount.toUint128();

/// @audit uint128 binBalanceA
242:          binBalanceA = Math.clip128(binBalanceA, tokenAOut.toUint128());

/// @audit uint128 binBalanceB
243:          binBalanceB = Math.clip128(binBalanceB, tokenBOut.toUint128());

/// @audit uint128 binBalanceA
288:                  binBalanceA += delta.deltaInBinInternal.toUint128();

/// @audit uint128 binBalanceB
289:                  binBalanceB = Math.clip128(binBalanceB, delta.deltaOutErc.toUint128());

/// @audit uint128 binBalanceB
291:                  binBalanceB += delta.deltaInBinInternal.toUint128();

/// @audit uint128 binBalanceA
292:                  binBalanceA = Math.clip128(binBalanceA, delta.deltaOutErc.toUint128());

/// @audit uint128 binId
492:              binId = currentState.binCounter;

/// @audit int32 activeTick
622:                  activeTick = binMap.nextActive(activeTick, delta.tokenAIn);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L161

[G‑17] Inverting the condition of an if-else-statement wastes gas

Flipping the true and false blocks instead saves 3 gas

There is 1 instance of this issue:

File: maverick-v1/contracts/models/Pool.sol

270:              delta.excess = (!exactOutput) ? Math.fromScale(amount, tokenAIn ? tokenAScale : tokenBScale) : Math.fromScale(amount, !tokenAIn ? tokenAScale : tokenBScale);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L270

[G‑18] require() or revert() statements that check input arguments should be at the top of the function

Checks that involve constants should come before checks that involve state variables, function calls, and calculations. By doing these checks first, the function is able to revert before wasting a Gcoldsload (2100 gas*) in a function that may ultimately revert in the unhappy case.

There are 2 instances of this issue:

File: maverick-v1/contracts/models/Factory.sol

/// @audit expensive op on line 34
35:           require(_protocolFeeRatio <= ONE_3_DECIMAL_SCALE, "Factory:PROTOCOL_FEE_CANNOT_EXCEED_ONE");

/// @audit expensive op on line 60
61:           require(_tickSpacing > 0, "Factory:TICK_SPACING_OUT_OF_BOUNDS");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L35

[G‑19] Functions guaranteed to revert when called by normal users can be marked payable

If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are CALLVALUE(2),DUP1(3),ISZERO(3),PUSH2(3),JUMPI(10),PUSH1(3),DUP1(3),REVERT(0),JUMPDEST(1),POP(2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost

There are 2 instances of this issue:

File: maverick-v1/contracts/models/PositionMetadata.sol

17:       function setBaseURI(string memory _baseURI) external onlyOwner {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol#L17

File: maverick-v1/contracts/models/Position.sol

23:       function setMetadata(IPositionMetadata _metadata) external onlyOwner {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Position.sol#L23


Excluded findings

These findings are excluded from awards calculations because there are publicly-available automated tools that find them. The valid ones appear here for completeness

Summary

Gas Optimizations

IssueInstancesTotal Gas Saved
[G‑01]Using calldata instead of memory for read-only arguments in external functions saves gas2240
[G‑02]State variables should be cached in stack variables rather than re-reading them from storage2194
[G‑03]<array>.length should not be looked up in every loop of a for-loop618
[G‑04]Using bools for storage incurs overhead117100
[G‑05]Using > 0 costs more gas than != 0 when used on a uint in a require() statement16
[G‑06]++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too)1995
[G‑07]Use custom errors rather than revert()/require() strings to save gas38-

Total: 69 instances over 7 issues with 17653 gas saved

Gas totals use lower bounds of ranges and count two iterations of each for-loop. All values above are runtime, not deployment, values; deployment values are listed in the individual issue descriptions. The table above as well as its gas numbers do not include any of the excluded findings.

Gas Optimizations

[G‑01] Using calldata instead of memory for read-only arguments in external functions saves gas

When a function with a memory array is called externally, the abi.decode() step has to use a for-loop to copy each index of the calldata to the memory index. Each iteration of this for-loop costs at least 60 gas (i.e. 60 * <mem_array>.length). Using calldata directly, obliviates the need for such a loop in the contract code and runtime execution. Note that even if an interface defines a function as having memory arguments, it's still valid for implementation contracs to use calldata arguments instead.

If the array is passed to an internal function which passes the array to another internal function where the array is modified and therefore memory is used in the external call, it's still more gass-efficient to use calldata when the external function uses modifiers, since the modifiers may prevent the internal functions from being called. Structs have the same overhead as an array of length one

Note that I've also flagged instances where the function is public but can be marked as external since it's not called by the contract, and cases where a constructor is involved

There are 2 instances of this issue:

File: maverick-v1/contracts/models/PositionMetadata.sol

/// @audit _baseURI - (valid but excluded finding)
17:       function setBaseURI(string memory _baseURI) external onlyOwner {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol#L17

File: router-v1/contracts/Router.sol

/// @audit params - (valid but excluded finding)
143:      function exactInput(ExactInputParams memory params) external payable override checkDeadline(params.deadline) returns (uint256 amountOut) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L143

[G‑02] State variables should be cached in stack variables rather than re-reading them from storage

The instances below point to the second+ access of a state variable within a function. Caching of a state variable replaces each Gwarmaccess (100 gas) with a much cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs, or having local caches of state variable contracts/addresses.

There are 2 instances of this issue:

File: maverick-v1/contracts/models/Factory.sol

/// @audit protocolFeeRatio on line 71 - (valid but excluded finding)
80:           emit PoolCreated(address(pool), _fee, _tickSpacing, _activeTick, _lookback, protocolFeeRatio, _tokenA, _tokenB);

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L80

File: maverick-v1/contracts/models/PositionMetadata.sol

/// @audit baseURI on line 22 - (valid but excluded finding)
22:           return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PositionMetadata.sol#L22

[G‑03] <array>.length should not be looked up in every loop of a for-loop

The overheads outlined below are PER LOOP, excluding the first loop

  • storage arrays incur a Gwarmaccess (100 gas)
  • memory arrays use MLOAD (3 gas)
  • calldata arrays use CALLDATALOAD (3 gas)

Caching the length changes each of these to a DUP<N> (3 gas), and gets rid of the extra DUP<N> needed to store the stack offset

There are 6 instances of this issue:

File: maverick-v1/contracts/models/PoolInspector.sol

/// @audit (valid but excluded finding)
101:          for (uint256 i; i < bins.length; i++) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L101

File: maverick-v1/contracts/models/Pool.sol

/// @audit (valid but excluded finding)
127:          for (uint256 i; i < params.length; i++) {

/// @audit (valid but excluded finding)
180:          for (uint256 i; i < binIds.length; i++) {

/// @audit (valid but excluded finding)
193:          for (uint256 i; i < params.length; i++) {

/// @audit (valid but excluded finding)
224:          for (uint256 i; i < params.length; i++) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L127

File: router-v1/contracts/libraries/Multicall.sol

/// @audit (valid but excluded finding)
13:           for (uint256 i = 0; i < data.length; i++) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Multicall.sol#L13

[G‑04] Using bools for storage incurs overhead

    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/58f635312aa21f947cae5f8578638a85aa2519f5/contracts/security/ReentrancyGuard.sol#L23-L27 Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas) for the extra SLOAD, and to avoid Gsset (20000 gas) when changing from false to true, after having been true in the past

There is 1 instance of this issue:

File: maverick-v1/contracts/models/Factory.sol

/// @audit (valid but excluded finding)
18:       mapping(IPool => bool) public override isFactoryPool;

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L18

[G‑05] Using > 0 costs more gas than != 0 when used on a uint in a require() statement

This change saves 6 gas per instance. The optimization works until solidity version 0.8.13 where there is a regression in gas costs.

There is 1 instance of this issue:

File: maverick-v1/contracts/models/Factory.sol

/// @audit (valid but excluded finding)
61:           require(_tickSpacing > 0, "Factory:TICK_SPACING_OUT_OF_BOUNDS");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L61

[G‑06] ++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too)

Saves 5 gas per loop

There are 19 instances of this issue:

File: maverick-v1/contracts/models/PoolInspector.sol

/// @audit (valid but excluded finding)
30:           for (uint128 i = startBinIndex; i < binCounter; i++) {

/// @audit (valid but excluded finding)
34:                   activeCounter++;

/// @audit (valid but excluded finding)
49:               depth++;

/// @audit (valid but excluded finding)
80:           for (uint8 i = 0; i < NUMBER_OF_KINDS; i++) {

/// @audit (valid but excluded finding)
101:          for (uint256 i; i < bins.length; i++) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/PoolInspector.sol#L30

File: maverick-v1/contracts/models/Pool.sol

/// @audit (valid but excluded finding)
127:          for (uint256 i; i < params.length; i++) {

/// @audit (valid but excluded finding)
180:          for (uint256 i; i < binIds.length; i++) {

/// @audit (valid but excluded finding)
193:          for (uint256 i; i < params.length; i++) {

/// @audit (valid but excluded finding)
224:          for (uint256 i; i < params.length; i++) {

/// @audit (valid but excluded finding)
380:          for (uint256 j; j < 2; j++) {

/// @audit (valid but excluded finding)
389:              for (uint256 i; i <= moveData.binCounter; i++) {

/// @audit (valid but excluded finding)
396:                      moveData.mergeBinCounter++;

/// @audit (valid but excluded finding)
409:                      moveData.mergeBinCounter++;

/// @audit (valid but excluded finding)
414:              for (uint256 i; i < moveData.mergeBinCounter; i++) {

/// @audit (valid but excluded finding)
523:          for (uint256 i; i < NUMBER_OF_KINDS; i++) {

/// @audit (valid but excluded finding)
530:                  output.counter++;

/// @audit (valid but excluded finding)
540:          for (uint256 i; i < NUMBER_OF_KINDS; i++) {

/// @audit (valid but excluded finding)
653:              for (uint256 i; i < swapData.counter; i++) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L127

File: router-v1/contracts/libraries/Multicall.sol

/// @audit (valid but excluded finding)
13:           for (uint256 i = 0; i < data.length; i++) {

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Multicall.sol#L13

[G‑07] Use custom errors rather than revert()/require() strings to save gas

Custom errors are available from solidity version 0.8.4. Custom errors save ~50 gas each time they're hit by avoiding having to allocate and store the revert string. Not defining the strings also save deployment gas

There are 38 instances of this issue:

File: maverick-v1/contracts/libraries/BinMath.sol

/// @audit (valid but excluded finding)
94:           require(tick <= MAX_TICK, "X");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/BinMath.sol#L94

File: maverick-v1/contracts/libraries/Bin.sol

/// @audit (valid but excluded finding)
85:           require(deltaLpToken != 0, "L");

/// @audit (valid but excluded finding)
140:              require(activeBin.state.mergeId == 0, "N");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Bin.sol#L85

File: maverick-v1/contracts/libraries/Cast.sol

/// @audit (valid but excluded finding)
6:            require((y = uint128(x)) == x, "C");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/Cast.sol#L6

File: maverick-v1/contracts/libraries/SafeERC20Min.sol

/// @audit (valid but excluded finding)
18:               require(abi.decode(returndata, (bool)), "T");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/libraries/SafeERC20Min.sol#L18

File: maverick-v1/contracts/models/Factory.sol

/// @audit (valid but excluded finding)
27:           require(_protocolFeeRatio <= ONE_3_DECIMAL_SCALE, "Factory:PROTOCOL_FEE_CANNOT_EXCEED_ONE");

/// @audit (valid but excluded finding)
34:           require(msg.sender == owner, "Factory:NOT_ALLOWED");

/// @audit (valid but excluded finding)
35:           require(_protocolFeeRatio <= ONE_3_DECIMAL_SCALE, "Factory:PROTOCOL_FEE_CANNOT_EXCEED_ONE");

/// @audit (valid but excluded finding)
41:           require(msg.sender == owner && _owner != address(0), "Factory:NOT_ALLOWED");

/// @audit (valid but excluded finding)
59:           require(_tokenA < _tokenB, "Factory:TOKENS_MUST_BE_SORTED_BY_ADDRESS");

/// @audit (valid but excluded finding)
60:           require(_fee > 0 && _fee < 1e18, "Factory:FEE_OUT_OF_BOUNDS");

/// @audit (valid but excluded finding)
61:           require(_tickSpacing > 0, "Factory:TICK_SPACING_OUT_OF_BOUNDS");

/// @audit (valid but excluded finding)
62:           require(_lookback >= 3600 && _lookback <= uint16(type(int16).max), "Factory:LOOKBACK_OUT_OF_BOUNDS");

/// @audit (valid but excluded finding)
64:           require(pools[_fee][_tickSpacing][_lookback][_tokenA][_tokenB] == IPool(address(0)), "Factory:POOL_ALREADY_EXISTS");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Factory.sol#L27

File: maverick-v1/contracts/models/Pool.sol

/// @audit (valid but excluded finding)
87:           require(msg.sender == position.ownerOf(tokenId) || msg.sender == position.getApproved(tokenId), "P");

/// @audit (valid but excluded finding)
93:           require((currentState.status & LOCKED == 0) && (allowInEmergency || (currentState.status & EMERGENCY == 0)), "E");

/// @audit (valid but excluded finding)
168:          require(previousABalance + tokenAAmount <= _tokenABalance() && previousBBalance + tokenBAmount <= _tokenBBalance(), "A");

/// @audit (valid but excluded finding)
303:          require(previousBalance + amountIn <= (tokenAIn ? _tokenABalance() : _tokenBBalance()), "S");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Pool.sol#L87

File: maverick-v1/contracts/models/Position.sol

/// @audit (valid but excluded finding)
43:           require(_exists(tokenId), "Invalid Token ID");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/maverick-v1/contracts/models/Position.sol#L43

File: router-v1/contracts/libraries/Deadline.sol

/// @audit (valid but excluded finding)
6:            require(block.timestamp <= deadline, "Transaction too old");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/Deadline.sol#L6

File: router-v1/contracts/libraries/TransferHelper.sol

/// @audit (valid but excluded finding)
15:           require(success && (data.length == 0 || abi.decode(data, (bool))), "STF");

/// @audit (valid but excluded finding)
25:           require(success && (data.length == 0 || abi.decode(data, (bool))), "ST");

/// @audit (valid but excluded finding)
35:           require(success && (data.length == 0 || abi.decode(data, (bool))), "SA");

/// @audit (valid but excluded finding)
44:           require(success, "STE");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/libraries/TransferHelper.sol#L15

File: router-v1/contracts/Router.sol

/// @audit (valid but excluded finding)
55:           require(IWETH9(msg.sender) == WETH9, "Not WETH9");

/// @audit (valid but excluded finding)
61:           require(balanceWETH9 >= amountMinimum, "Insufficient WETH9");

/// @audit (valid but excluded finding)
72:           require(balanceToken >= amountMinimum, "Insufficient token");

/// @audit (valid but excluded finding)
100:          require(amountToPay > 0 && amountOut > 0, "In or Out Amount is Zero");

/// @audit (valid but excluded finding)
101:          require(factory.isFactoryPool(IPool(msg.sender)), "Must call from a Factory Pool");

/// @audit (valid but excluded finding)
139:          require(amountOut >= params.amountOutMinimum, "Too little received");

/// @audit (valid but excluded finding)
165:          require(amountOut >= params.amountOutMinimum, "Too little received");

/// @audit (valid but excluded finding)
177:          require(amountOutReceived == amountOut, "Requested amount not available");

/// @audit (valid but excluded finding)
188:          require(amountIn <= params.amountInMaximum, "Too much requested");

/// @audit (valid but excluded finding)
197:          require(amountIn <= params.amountInMaximum, "Too much requested");

/// @audit (valid but excluded finding)
234:          require(tokenAAmount >= minTokenAAmount && tokenBAmount >= minTokenBAmount, "Too little added");

/// @audit (valid but excluded finding)
262:          require(activeTick >= minActiveTick && activeTick <= maxActiveTick, "activeTick not in range");

/// @audit (valid but excluded finding)
304:          require(msg.sender == position.ownerOf(tokenId), "P");

/// @audit (valid but excluded finding)
309:          require(tokenAAmount >= minTokenAAmount && tokenBAmount >= minTokenBAmount, "Too little removed");

https://github.com/code-423n4/2022-12-Stealth-Project/blob/fc8589d7d8c1d8488fd97ccc46e1ff11c8426ac2/router-v1/contracts/Router.sol#L55

#0 - c4-judge

2023-01-18T21:52:57Z

kirk-baird marked the issue as grade-a

#1 - c4-judge

2023-01-23T23:29:11Z

kirk-baird marked the issue as selected for report

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