Skip to content

Instantly share code, notes, and snippets.

@code423n4
Created November 28, 2023 17:38
Show Gist options
  • Save code423n4/7dcb6a2255ec949b54664c8c8c12b879 to your computer and use it in GitHub Desktop.
Save code423n4/7dcb6a2255ec949b54664c8c8c12b879 to your computer and use it in GitHub Desktop.
Best bot finding from 2023-11-panoptic-bot-findings

Winning bot race submission

This is the top-ranked automated findings report, from IllIllI-bot bot. All findings in this report will be considered known issues for the purposes of your C4 audit.

Note: There is a section for disputed findings below the usual findings sections

Summary

Issue Instances Gas Savings
[L-01] Addition/multiplication in unchecked block is unsafe 2 0
[L-02] Code does not follow the best practice of check-effects-interaction 4 0
[L-03] Consider implementing two-step procedure for updating protocol addresses 1 0
[L-04] External calls in an un-bounded for-loop may result in a DOS 11 0
[L-05] File allows a version of solidity that is susceptible to an assembly optimizer bug 1 0
[L-06] Functions calling tokens with transfer hooks are missing reentrancy guards 2 0
[L-07] Loss of precision 1 0
[L-08] Missing contract-existence checks before yul call() 1 0
[L-09] Solidity version 0.8.20 may not work on other chains due to PUSH0 11 0
[L-10] Subtraction in unchecked block is unsafe 7 0
[L-11] Subtraction may underflow if multiplication is too large 1 0
[L-12] Unsafe downcast 8 0
[G-01] do-while is cheaper than for-loops when the initial check can be skipped 6 0
[G-02] Assembly: Check msg.sender using xor and the scratch space 2 0
[G-03] Use uint256(1)/uint256(2) instead of true/false to save gas for changes 1 8550
[G-04] Avoid updating storage when the value hasn't changed 1 800
[G-05] Assembly: Use scratch space for building calldata 3 660
[G-06] Avoid contract existence checks by using low-level calls 7 700
[G-07] Avoid transferring amounts of zero in order to save gas 3 300
[G-08] Using bools for storage incurs overhead 1 100
[G-09] Combine mappings referenced in the same function by the same key 4 168
[G-10] Enable IR-based code generation 1 0
[G-11] Multiple accesses of a mapping/array should use a local variable cache 1 42
[G-12] Assigning state variables directly with named struct constructors wastes gas 1 28
[G-13] Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead 13 286
[G-14] Optimize names to save gas 1 22
[G-15] Constructors can be marked payable 1 21
[G-16] internal/private functions only called once can be inlined to save gas 12 240
[G-17] Division by powers of two should use bit shifting 1 20
[G-18] Assembly: Use scratch space when building emitted events with two data arguments 3 45
[G-19] Consider using solady's FixedPointMathLib 3 0
[G-20] Multiple address/ID mappings can be combined into a single mapping of an address/ID to a struct 3 0
[G-21] Nesting if-statements is cheaper than using && 3 18
[G-22] Reduce deployment costs by tweaking contracts' metadata 1 0
[G-23] Reduce gas usage by moving to Solidity 0.8.19 or later 13 0
[G-24] Using > 0 costs more gas than != 0 when used on a uint in a require() statement 1 6
[G-25] Stack variable is only used once 24 72
[G-26] >= costs less gas than > 21 63
[G-27] A memory array's length should not be looked up in every iteration of a for/while-loop 1 3
[G-28] Split revert checks to save gas 9 18
[G-29] Using private rather than public, saves gas 2 0
[N-01] 2**<n> - 1 should be re-written as type(uint<n>).max 21 0
[N-02] constants should be defined rather than using magic numbers 164 0
[N-03] else-block not required 1 0
[N-04] if-statement can be converted to a ternary 1 0
[N-05] public functions not called by the contract should be declared external instead 7 0
[N-06] require()/revert() statements should have descriptive reason strings 6 0
[N-07] Add inline comments for unnamed variables 3 0
[N-08] Adding a return statement when the function defines a named return variable, is redundant 1 0
[N-09] Assembly block creates dirty bits 1 0
[N-10] Assembly blocks should have extensive comments 21 0
[N-11] Complex casting 25 0
[N-12] Consider adding a block/deny-list 2 0
[N-13] Consider adding formal verification proofs 1 0
[N-14] Consider bounding input array length 1 0
[N-15] Consider defining system-wide constants in a single file 3 0
[N-16] Consider making contracts Upgradeable 1 0
[N-17] Consider moving msg.sender checks to a common authorization modifier 3 0
[N-18] Consider returning a struct rather than having multiple return values 5 0
[N-19] Consider splitting long calculations 17 0
[N-20] Consider using delete rather than assigning zero/false to clear values 3 0
[N-21] Consider using a struct rather than having many function input parameters 4 0
[N-22] Consider using descriptive constants when passing zero as a function argument 3 0
[N-23] Constants in comparisons should appear on the left side 60 0
[N-24] Contract should expose an interface 16 0
[N-25] Contract uses both require()/revert() as well as custom errors 1 0
[N-26] Contracts should have full test coverage 1 0
[N-27] Critical system parameter changes should be behind a timelock 1 0
[N-28] Custom error has no error details 16 0
[N-29] Custom errors should be used rather than revert()/require() 6 0
[N-30] Duplicated require()/revert() checks should be refactored to a modifier or function 2 0
[N-31] Events are missing sender information 1 0
[N-32] Events that mark critical parameter changes should contain both the old and the new value 1 0
[N-33] Expressions for constant values should use immutable rather than constant 2 0
[N-34] High cyclomatic complexity 2 0
[N-35] Inconsistent method of specifying a floating pragma 2 0
[N-36] Inconsistent spacing in comments 4 0
[N-37] Invalid NatSpec comment style 7 0
[N-38] Large numeric literals should use underscores for readability 8 0
[N-39] Large or complicated code bases should implement invariant tests 1 0
[N-40] Libraries should be defined in separate files from their usage 3 0
[N-41] Local variable shadows state variable 2 0
[N-42] Long functions should be refactored into multiple, smaller, functions 16 0
[N-43] Multiple address/ID mappings can be combined into a single mapping of an address/ID to a struct, for readability 3 0
[N-44] NatSpec: Contract declarations should have @dev tags 7 0
[N-45] NatSpec: Contract declarations should have @title tags 1 0
[N-46] NatSpec: Error declarations should have descriptions 2 0
[N-47] NatSpec: Event @param tag is missing 20 0
[N-48] NatSpec: File is missing NatSpec 1 0
[N-49] NatSpec: Function @param tag is missing 11 0
[N-50] NatSpec: Function @return tag is missing 3 0
[N-51] NatSpec: Non-public state variable declarations should use @dev tags 16 0
[N-52] Non-library/interface files should use fixed compiler versions, not floating ones 1 0
[N-53] Not using the named return variables anywhere in the function is confusing 5 0
[N-54] Polymorphic functions make security audits more time-consuming and error-prone 10 0
[N-55] Setters should prevent re-setting of the same value 1 0
[N-56] Style guide: Contract does not follow the Solidity style guide's suggested layout ordering 2 0
[N-57] Style guide: Control structures do not follow the Solidity Style Guide 12 0
[N-58] Style guide: Function ordering does not follow the Solidity style guide 3 0
[N-59] Style guide: Lines are too long 162 0
[N-60] Style guide: Modifier names should use lowerCamelCase 1 0
[N-61] Style guide: Non-external/public function names should begin with an underscore 8 0
[N-62] Style guide: Non-external/public variable names should begin with an underscore 22 0
[N-63] Typos 8 0
[N-64] Unnecessary cast 13 0
[N-65] Unsafe conversion from unsigned to signed values 6 0
[N-66] Unused error definition 1 0
[N-67] Unused contract variables 1 0
[N-68] Unused import 1 0
[N-69] Use bit shifts in an imutable variable rather than long bit masks of a single bit, for readability 2 0
[N-70] Use of override is unnecessary 2 0
[N-71] Variables need not be initialized to false 1 0
[N-72] Variables need not be initialized to zero 7 0
[D-01] abi.encodePacked() should not be used with dynamic types when passing the result to a hash function such as keccak256() 9 0
[D-02] else-block not required 3 0
[D-03] if-statement can be converted to a ternary 1 0
[D-04] internal functions not called by the contract should be removed 48 0
[D-05] internal functions not called by the contract should be removed 2 0
[D-06] internal functions not called by the contract should be removed 2 0
[D-07] internal functions not called by the contract should be removed 50 0
[D-08] keccak256() should only need to be called on a specific string literal once 1 0
[D-09] payable function does not transfer Eth 1 0
[D-10] require() / revert() statements should have descriptive reason strings 34 0
[D-11] safeTransfer function does not check for contract existence 1 0
[D-12] unchecked {} can be used on the division of two uints in order to save gas 3 0
[D-13] A calldata array's length should not be looked up in every iteration of a for/while-loop 1 0
[D-14] Adding a return statement when the function defines a named return variable, is redundant 5 0
[D-15] All interfaces used within a project should be imported 12 0
[D-16] Array lengths not checked 1 0
[D-17] Assembly blocks should have comments 9 0
[D-18] Assembly: Check msg.sender using xor and the scratch space 4 0
[D-19] Assembly: Checks for address(0x0) are more efficient in assembly 2 0
[D-20] Avoid fetching a low-level call's return data by using assembly 1 0
[D-21] Bad bot rules 1 0
[D-22] Cast to bytes or bytes32 for clearer semantic meaning 9 0
[D-23] Change public function visibility to external to save gas 5 0
[D-24] Consider adding a block/deny-list 1 0
[D-25] Contract implements a payable multicall and has payable functions 1 0
[D-26] Contract should expose an interface 1 0
[D-27] Contracts are vulnerable to rebasing accounting-related issues 2 0
[D-28] Control structures do not follow the Solidity Style Guide 53 0
[D-29] Default bool values are manually reset 2 0
[D-30] Dependence on external protocols 34 0
[D-31] Division by zero not prevented 2 0
[D-32] Do not use UNDERSCORE in struct elements names 2 0
[D-33] Duplicated require()/revert() checks should be refactored to a modifier or function 6 0
[D-34] Duplicated require()/revert() checks should be refactored to a modifier Or function to save gas 2 0
[D-35] Event names should use CamelCase 6 0
[D-36] Events that mark critical parameter changes should contain both the old and the new value 7 0
[D-37] Function doesn't perform any updates 11 0
[D-38] Functions which are either private or internal should have a preceding _ in their name 66 0
[D-39] Getter for public state variables are redundant 1 0
[D-40] Inconsistent comment spacing 5 0
[D-41] Inline modifiers that are only used once, to save gas 1 0
[D-42] Input array lengths may differ 2 0
[D-43] It is standard for all external and public functions to be override from an interface 2 0
[D-44] It's not standard to end and begin a code object on the same line 34 0
[D-45] Lack of unchecked in loops 2 0
[D-46] Loss of precision 1 0
[D-47] Loss of precision 2 0
[D-48] Low level calls with Solidity before 0.8.14 result in an optimiser bug 28 0
[D-49] Missing checks for state variable assignments 13 0
[D-50] Missing contract-existence checks before low-level calls 1 0
[D-51] Modulus operations that could be unchecked 15 0
[D-52] Must approve or increase allowance first 3 0
[D-53] NatSpec: Contract declarations should have @notice tags 13 0
[D-54] NatSpec: Function declarations should have @notice tags 18 0
[D-55] NatSpec: Modifier declarations should have @notice tags 1 0
[D-56] Nesting if-statements is cheaper than using && 1 0
[D-57] NFT contract redefines _mint()/_safeMint(), but not both 1 0
[D-58] Non-assembly method available 1 0
[D-59] Non-library/interface files should use fixed compiler versions, not floating ones 10 0
[D-60] Not initializing local variables to zero saves gas 7 0
[D-61] Numbers downcast to addresses may result in collisions 1 0
[D-62] Open TODOs 2 0
[D-63] Optimal State Variable Order 5 0
[D-64] Optimize Gas Usage by Combining Mappings into a Struct 8 0
[D-65] Overflows in unchecked blocks 7 0
[D-66] Overly complicated arithmetic 2 0
[D-67] Public functions not used internally can be marked as external to save gas 7 0
[D-68] Redundant Contract Existence Check in Consecutive External Calls 22 0
[D-69] Return values of transfer()/transferFrom() not checked 4 0
[D-70] Revert on transfer to the zero address 3 0
[D-71] safeMint should be used in place of mint 1 0
[D-72] Same cast is done multiple times 1 0
[D-73] SPDX identifier should be the in the first line of a solidity file 13 0
[D-74] State variable read in a loop 14 0
[D-75] Storage Write Removal Bug On Conditional Early Termination 30 0
[D-76] Style guide: constant/immutable variable names should use capital letters and underscores 7 0
[D-77] Style guide: Contract does not follow the Solidity style guide's suggested layout ordering 11 0
[D-78] Style guide: Function Names Not in mixedCase 8 0
[D-79] Style guide: Function names should use lowerCamelCase 3 0
[D-80] Subtraction in unchecked block is unsafe 4 0
[D-81] Subtraction may underflow if multiplication is too large 6 0
[D-82] The result of function calls should be cached rather than re-calling the function 1 0
[D-83] Top level pragma declarations should be separated by two blank lines 13 0
[D-84] Trade-offs Between Modifiers and Internal Functions 2 0
[D-85] Unchecked return value of low-level call()/delegatecall() 1 0
[D-86] Unnecessary cast wastes gas 13 0
[D-87] Unnecessary look up in if condition 14 0
[D-88] Unsafe downcast 51 0
[D-89] Unused error definition 14 0
[D-90] Unused struct definition 2 0
[D-91] Unused contract variables 21 0
[D-92] Unused function parameter 14 0
[D-93] Unused import 33 0
[D-94] Unused local variable 5 0
[D-95] Unused named return variables without optimizer waste gas 5 0
[D-96] Unusual loop variable 2 0
[D-97] Unusual loop variable 4 0
[D-98] Use != 0 instead of > 0 for unsigned integer comparison 18 0
[D-99] Use _safeMint instead of _mint for ERC721 4 0
[D-100] Use @inheritdoc rather than using a non-standard annotation 2 0
[D-101] Use bytes.concat() on bytes instead of abi.encodePacked() for clearer semantic meaning 9 0
[D-102] Use a single file for all system-wide constants 12 0
[D-103] Use assembly for small keccak256 hashes, in order to save gas 1 0
[D-104] Use assembly to emit events, in order to save gas 5 0
[D-105] Use constants instead of type(uintx).max 5 0
[D-106] Use delete instead of setting mapping/state variable to zero, to save gas 2 0
[D-107] Use multiple require() and if statements instead of && 4 0
[D-108] Using bools for storage incurs overhead 2 0

Note: There is a section for disputed findings below the usual findings sections

Low Risk Issues

[L-01] Addition/multiplication in unchecked block is unsafe

The additions/multiplications may silently overflow because they're in unchecked blocks with no preceding value checks, which may lead to unexpected results

There are 2 instance(s) of this issue:

File: contracts/libraries/Math.sol

260:             uint256 inv = (3 * denominator) ^ 2;

GitHub : 260

File: contracts/types/LeftRight.sol

57:              return self + uint256(int256(right));

GitHub : 57

[L-02] Code does not follow the best practice of check-effects-interaction

Code should follow the best-practice of check-effects-interaction, where state variables are updated before any external calls are made. Doing so prevents a large class of reentrancy bugs.

There are 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit tickSpacing() called prior to this assignment
626:             s_accountLiquidity[positionKey_to] = fromLiq;

/// @audit tickSpacing() called prior to this assignment
627:             s_accountLiquidity[positionKey_from] = 0;

/// @audit tickSpacing() called prior to this assignment
629:             s_accountFeesBase[positionKey_to] = fromBase;

/// @audit tickSpacing() called prior to this assignment
630:             s_accountFeesBase[positionKey_from] = 0;

GitHub : 626,627,629,630

[L-03] Consider implementing two-step procedure for updating protocol addresses

A copy-paste error or a typo may end up bricking protocol functionality, or sending tokens to an address with no known private key. Consider implementing a two-step procedure for updating protocol addresses, where the recipient is set as pending, and must 'accept' the assignment by making an affirmative call. A straight forward way of doing this would be to have the target contracts implement EIP-165, and to have the 'set' functions ensure that the recipient is of the right interface type.

There are 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

/// @audit isApprovedForAll:  setApprovalForAll()
77       function setApprovalForAll(address operator, bool approved) public {
78           isApprovedForAll[msg.sender][operator] = approved;
79   
80           emit ApprovalForAll(msg.sender, operator, approved);
81:      }

GitHub : 77

[L-04] External calls in an un-bounded for-loop may result in a DOS

Consider limiting the number of iterations in for-loops that make external calls

There are 11 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit tickSpacing() : 
583          for (uint256 leg = 0; leg < numLegs; ) {
584              // for this leg index: extract the liquidity chunk: a 256bit word containing the liquidity amount and upper/lower tick
585              // @dev see `contracts/types/LiquidityChunk.sol`
586              uint256 liquidityChunk = PanopticMath.getLiquidityChunk(
587                  id,
588                  leg,
589                  uint128(amount),
590                  univ3pool.tickSpacing()
591              );
592  
593              //construct the positionKey for the from and to addresses
594              bytes32 positionKey_from = keccak256(
595                  abi.encodePacked(
596                      address(univ3pool),
597                      from,
598                      id.tokenType(leg),
599                      liquidityChunk.tickLower(),
600                      liquidityChunk.tickUpper()
601                  )
602              );
603              bytes32 positionKey_to = keccak256(
604                  abi.encodePacked(
605                      address(univ3pool),
606                      to,
607                      id.tokenType(leg),
608                      liquidityChunk.tickLower(),
609                      liquidityChunk.tickUpper()
610                  )
611              );
612  
613              // Revert if recipient already has that position
614              if (
615                  (s_accountLiquidity[positionKey_to] != 0) ||
616                  (s_accountFeesBase[positionKey_to] != 0)
617              ) revert Errors.TransferFailed();
618  
619              // Revert if not all balance is transferred
620              uint256 fromLiq = s_accountLiquidity[positionKey_from];
621              if (fromLiq.rightSlot() != liquidityChunk.liquidity()) revert Errors.TransferFailed();
622  
623              int256 fromBase = s_accountFeesBase[positionKey_from];
624  
625              //update+store liquidity and fee values between accounts
626              s_accountLiquidity[positionKey_to] = fromLiq;
627              s_accountLiquidity[positionKey_from] = 0;
628  
629              s_accountFeesBase[positionKey_to] = fromBase;
630              s_accountFeesBase[positionKey_from] = 0;
631              unchecked {
632                  ++leg;
633              }
634:         }

/// @audit positions() :  _getFeesBase(), _createLegInAMM()
/// @audit positions() :  _getFeesBase(), _collectAndWritePositionData(), _createLegInAMM()
/// @audit tickSpacing() : 
/// @audit mint() :  _mintLiquidity(), _createLegInAMM()
/// @audit fee() :  _mintLiquidity(), _createLegInAMM()
/// @audit token1() :  _mintLiquidity(), _createLegInAMM()
/// @audit token0() :  _mintLiquidity(), _createLegInAMM()
/// @audit burn() :  _burnLiquidity(), _createLegInAMM()
/// @audit collect() :  _collectAndWritePositionData(), _createLegInAMM()
860          for (uint256 leg = 0; leg < numLegs; ) {
861              int256 _moved;
862              int256 _itmAmounts;
863              int256 _totalCollected;
864  
865              {
866                  // cache the univ3pool, tokenId, isBurn, and _positionSize variables to get rid of stack too deep error
867                  IUniswapV3Pool _univ3pool = univ3pool;
868                  uint256 _tokenId = tokenId;
869                  bool _isBurn = isBurn;
870                  uint128 _positionSize = positionSize;
871                  uint256 _leg;
872  
873                  unchecked {
874                      // Reverse the order of the legs if this call is burning a position (LIFO)
875                      // We loop in reverse order if burning a position so that any dependent long liquidity is returned to the pool first,
876                      // allowing the corresponding short liquidity to be removed
877                      _leg = _isBurn ? numLegs - leg - 1 : leg;
878                  }
879  
880                  // for this _leg index: extract the liquidity chunk: a 256bit word containing the liquidity amount and upper/lower tick
881                  // @dev see `contracts/types/LiquidityChunk.sol`
882                  uint256 liquidityChunk = PanopticMath.getLiquidityChunk(
883                      _tokenId,
884                      _leg,
885                      _positionSize,
886                      _univ3pool.tickSpacing()
887                  );
888  
889                  (_moved, _itmAmounts, _totalCollected) = _createLegInAMM(
890                      _univ3pool,
891                      _tokenId,
892                      _leg,
893                      liquidityChunk,
894                      _isBurn
895                  );
896  
897                  unchecked {
898                      // increment accumulators of the upper bound on tokens contained across all legs of the position at any given tick
899                      amount0 += Math.getAmount0ForLiquidity(liquidityChunk);
900  
901                      amount1 += Math.getAmount1ForLiquidity(liquidityChunk);
902                  }
903              }
904  
905              totalMoved = totalMoved.add(_moved);
906              itmAmounts = itmAmounts.add(_itmAmounts);
907              totalCollected = totalCollected.add(_totalCollected);
908  
909              unchecked {
910                  ++leg;
911              }
912:         }

GitHub : 583,860,860,860,860,860,860,860,860,860

File: contracts/multicall/Multicall.sol

/// @audit delegatecall() : 
14           for (uint256 i = 0; i < data.length; ) {
15               (bool success, bytes memory result) = address(this).delegatecall(data[i]);
16   
17               if (!success) {
18                   // Bubble up the revert reason
19                   // The bytes type is ABI encoded as a length-prefixed byte array
20                   // So we simply need to add 32 to the pointer to get the start of the data
21                   // And then revert with the size loaded from the first 32 bytes
22                   // Other solutions will do work to differentiate the revert reasons and provide paranthetical information
23                   // However, we have chosen to simply replicate the the normal behavior of the call
24                   // NOTE: memory-safe because it reads from memory already allocated by solidity (the bytes memory result)
25                   assembly ("memory-safe") {
26                       revert(add(result, 32), mload(result))
27                   }
28               }
29   
30               results[i] = result;
31   
32               unchecked {
33                   ++i;
34               }
35:          }

GitHub : 14

[L-05] File allows a version of solidity that is susceptible to an assembly optimizer bug

In solidity versions 0.8.13 and 0.8.14, there is an optimizer bug where, if the use of a variable is in a separate assembly block from the block in which it was stored, the mstore operation is optimized out, leading to uninitialized memory. The code currently does not have such a pattern of execution, but it does use mstores in assembly blocks, so it is a risk for future changes. The affected solidity versions should be avoided if at all possible.

There are 1 instance(s) of this issue:

File: contracts/libraries/SafeTransferLib.sol

19           assembly ("memory-safe") {
20               // Get free memory pointer - we will store our calldata in scratch space starting at the offset specified here.
21               let p := mload(0x40)
22   
23               // Write the abi-encoded calldata into memory, beginning with the function selector.
24               mstore(p, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
25               mstore(add(4, p), from) // Append the "from" argument.
26               mstore(add(36, p), to) // Append the "to" argument.
27               mstore(add(68, p), amount) // Append the "amount" argument.
28   
29               success := and(
30                   // Set success to whether the call reverted, if not we check it either
31                   // returned exactly 1 (can't just be non-zero data), or had no return data.
32                   or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
33                   // We use 100 because that's the total length of our calldata (4 + 32 * 3)
34                   // Counterintuitively, this call() must be positioned after the or() in the
35                   // surrounding and() because and() evaluates its arguments from right to left.
36                   call(gas(), token, 0, p, 100, 0, 32)
37               )
38:          }

GitHub : 19

[L-06] Functions calling tokens with transfer hooks are missing reentrancy guards

Even if the function follows the best practice of check-effects-interaction, not using a reentrancy guard when there may be transfer hooks will open the users of this protocol up to read-only reentrancies with no way to protect against it, except by block-listing the whole protocol.

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit safeTransferFrom() :  uniswapV3MintCallback()
407      function uniswapV3MintCallback(
408          uint256 amount0Owed,
409          uint256 amount1Owed,
410          bytes calldata data
411      ) external {
412          // Decode the mint callback data
413          CallbackLib.CallbackData memory decoded = abi.decode(data, (CallbackLib.CallbackData));
414          // Validate caller to ensure we got called from the AMM pool
415          CallbackLib.validateCallback(msg.sender, address(FACTORY), decoded.poolFeatures);
416          // Sends the amount0Owed and amount1Owed quantities provided
417          if (amount0Owed > 0)
418              SafeTransferLib.safeTransferFrom(
419                  decoded.poolFeatures.token0,
420                  decoded.payer,
421                  msg.sender,
422                  amount0Owed
423              );
424          if (amount1Owed > 0)
425              SafeTransferLib.safeTransferFrom(
426                  decoded.poolFeatures.token1,
427                  decoded.payer,
428                  msg.sender,
429                  amount1Owed
430              );
431:     }

/// @audit safeTransferFrom() :  uniswapV3SwapCallback()
441      function uniswapV3SwapCallback(
442          int256 amount0Delta,
443          int256 amount1Delta,
444          bytes calldata data
445      ) external {
446          // Decode the swap callback data, checks that the UniswapV3Pool has the correct address.
447          CallbackLib.CallbackData memory decoded = abi.decode(data, (CallbackLib.CallbackData));
448          // Validate caller to ensure we got called from the AMM pool
449          CallbackLib.validateCallback(msg.sender, address(FACTORY), decoded.poolFeatures);
450  
451          // Extract the address of the token to be sent (amount0 -> token0, amount1 -> token1)
452          address token = amount0Delta > 0
453              ? address(decoded.poolFeatures.token0)
454              : address(decoded.poolFeatures.token1);
455  
456          // Transform the amount to pay to uint256 (take positive one from amount0 and amount1)
457          uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);
458  
459          // Pay the required token from the payer to the caller of this contract
460          SafeTransferLib.safeTransferFrom(token, decoded.payer, msg.sender, amountToPay);
461:     }

GitHub : 407,441

[L-07] Loss of precision

Division by large numbers may result in the result being zero, due to solidity not supporting fractions. Consider requiring a minimum amount for the numerator to ensure that it is always larger than the denominator

There are 1 instance(s) of this issue:

File: contracts/libraries/Math.sol

/// @audit division by lowPriceX96
108                  mulDiv(
109                      uint256(liquidityChunk.liquidity()) << 96,
110                      highPriceX96 - lowPriceX96,
111                      highPriceX96
112:                 ) / lowPriceX96;

GitHub : 108

[L-08] Missing contract-existence checks before yul call()

Low-level calls return success if there is no code present at the specified address. In addition to the zero-address checks, add a check to verify that extcodesize() is non-zero.

There are 1 instance(s) of this issue:

File: contracts/libraries/SafeTransferLib.sol

19           assembly ("memory-safe") {
20               // Get free memory pointer - we will store our calldata in scratch space starting at the offset specified here.
21               let p := mload(0x40)
22   
23               // Write the abi-encoded calldata into memory, beginning with the function selector.
24               mstore(p, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
25               mstore(add(4, p), from) // Append the "from" argument.
26               mstore(add(36, p), to) // Append the "to" argument.
27               mstore(add(68, p), amount) // Append the "amount" argument.
28   
29               success := and(
30                   // Set success to whether the call reverted, if not we check it either
31                   // returned exactly 1 (can't just be non-zero data), or had no return data.
32                   or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
33                   // We use 100 because that's the total length of our calldata (4 + 32 * 3)
34                   // Counterintuitively, this call() must be positioned after the or() in the
35                   // surrounding and() because and() evaluates its arguments from right to left.
36                   call(gas(), token, 0, p, 100, 0, 32)
37               )
38:          }

GitHub : 19

[L-09] Solidity version 0.8.20 may not work on other chains due to PUSH0

The compiler for Solidity 0.8.20 switches the default target EVM version to Shanghai, which includes the new PUSH0 op code. This op code may not yet be implemented on all L2s, so deployment on these chains will fail. To work around this issue, use an earlier EVM version. While the project itself may or may not compile with 0.8.20, other projects with which it integrates, or which extend this project may, and those projects will have problems deploying these contracts/libraries.

There are 11 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/Constants.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/Errors.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/FeesCalc.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/Math.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/PanopticMath.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/SafeTransferLib.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/tokens/ERC1155Minimal.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/types/LeftRight.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/types/LiquidityChunk.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/types/TokenId.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

[L-10] Subtraction in unchecked block is unsafe

The subtraction may silently underflow because it's in an unchecked block with no preceding value checks, which may lead to unexpected results

There are 7 instance(s) of this issue:

File: contracts/libraries/FeesCalc.sol

125:                 feeGrowthInside0X128 = lowerOut0 - upperOut0; // fee growth inside the chunk

126:                 feeGrowthInside1X128 = lowerOut1 - upperOut1;

142:                 feeGrowthInside0X128 = upperOut0 - lowerOut0;

143:                 feeGrowthInside1X128 = upperOut1 - lowerOut1;

GitHub : 125,126,142,143

File: contracts/types/LeftRight.sol

179:             int256 left256 = int256(x.leftSlot()) - y.leftSlot();

182:             int256 right256 = int256(x.rightSlot()) - y.rightSlot();

GitHub : 179,182

File: contracts/types/TokenId.sol

391:             (legLowerTick, legUpperTick) = (selfStrike - oneSidedRange, selfStrike + oneSidedRange);

GitHub : 391

[L-11] Subtraction may underflow if multiplication is too large

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1313                     uint256 numerator = totalLiquidity ** 2 -
1314                         totalLiquidity *
1315:                        removedLiquidity +

GitHub : 1313

[L-12] Unsafe downcast

When a type is downcast to a smaller type, the higher order bits are truncated, effectively applying a modulo to the original value. Without any other checks, this wrapping will lead to unexpected behavior and bugs

There are 8 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit uint64
1469:         poolId = uint64(s_AddrToPoolIdData[univ3pool]);

GitHub : 1469

File: contracts/libraries/PanopticMath.sol

/// @audit uint64
39:           return uint64(uint160(univ3pool) >> 96);

/// @audit uint64 -> uint256
57:                   (uint64(uint256(keccak256(abi.encodePacked(token0, token1, fee)))) >> 32);

GitHub : 39,57

File: contracts/types/TokenId.sol

/// @audit uint256 self -> uint64
82:               return uint64(self);

/// @audit int24 -> int256
/// @audit int256
151:              return int24(int256(self >> (64 + legIndex * 48 + 12)));

/// @audit int24 -> int256
/// @audit int256
162:              return int24(int256((self >> (64 + legIndex * 48 + 36)) % 4096));

GitHub : 82,151,151,162,162

Gas Risk Issues

[G-01] do-while is cheaper than for-loops when the initial check can be skipped

for (uint256 i; i < len; ++i){ ... } -> do { ...; ++i } while (i < len);

There are 6 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

550:         for (uint256 i = 0; i < ids.length; ) {

583:         for (uint256 leg = 0; leg < numLegs; ) {

860:         for (uint256 leg = 0; leg < numLegs; ) {

GitHub : 550,583,860

File: contracts/multicall/Multicall.sol

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

GitHub : 14

File: contracts/tokens/ERC1155Minimal.sol

141:         for (uint256 i = 0; i < ids.length; ) {

187:             for (uint256 i = 0; i < owners.length; ++i) {

GitHub : 141,187

[G-02] Assembly: Check msg.sender using xor and the scratch space

See this prior finding for details on the conversion

There are 2 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

97:          if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

135:         if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

GitHub : 97,135

[G-03] Use uint256(1)/uint256(2) instead of true/false to save gas for changes

Avoids a Gsset (20000 gas) when changing from false to true, after having been true in the past. Since most of the bools aren't changed twice in one transaction, I've counted the amount of gas as half of the full amount, for each variable. Note that public state variables can be re-written to be private and use uint256, but have public getters returning bools.

There are 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

/// @audit reset in: setApprovalForAll()
67       mapping(address owner => mapping(address operator => bool approvedForAll))
68:          public isApprovedForAll;

GitHub : 67

[G-04] Avoid updating storage when the value hasn't changed

If the old value is equal to the new value, not re-storing the value will avoid a Gsreset (2900 gas), potentially at the expense of a Gcoldsload (2100 gas) or a Gwarmaccess (100 gas)

There are 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

/// @audit isApprovedForAll:  setApprovalForAll()
77       function setApprovalForAll(address operator, bool approved) public {
78           isApprovedForAll[msg.sender][operator] = approved;
79   
80           emit ApprovalForAll(msg.sender, operator, approved);
81:      }

GitHub : 77

[G-05] Assembly: Use scratch space for building calldata

If an external call's calldata can fit into two or fewer words, use the scratch space to build the calldata, rather than allowing Solidity to do a memory expansion.

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1102         (, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = univ3pool
1103             .positions(
1104                 keccak256(
1105                     abi.encodePacked(
1106                         address(this),
1107                         liquidityChunk.tickLower(),
1108                         liquidityChunk.tickUpper()
1109                     )
1110                 )
1111:            );

GitHub : 1102

File: contracts/libraries/FeesCalc.sol

101:         (, , uint256 lowerOut0, uint256 lowerOut1, , , , ) = univ3pool.ticks(tickLower);

102:         (, , uint256 upperOut0, uint256 upperOut1, , , , ) = univ3pool.ticks(tickUpper);

GitHub : 101,102

[G-06] 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. Note that it still saves gas, even if the return value is not directly used.

There are 7 instance(s) of this issue:

File: contracts/libraries/FeesCalc.sol

101:         (, , uint256 lowerOut0, uint256 lowerOut1, , , , ) = univ3pool.ticks(tickLower);

102:         (, , uint256 upperOut0, uint256 upperOut1, , , , ) = univ3pool.ticks(tickUpper);

163:                 feeGrowthInside0X128 = univ3pool.feeGrowthGlobal0X128() - lowerOut0 - upperOut0;

164:                 feeGrowthInside1X128 = univ3pool.feeGrowthGlobal1X128() - lowerOut1 - upperOut1;

GitHub : 101,102,163,164

File: contracts/tokens/ERC1155Minimal.sol

112:                 ERC1155Holder(to).onERC1155Received(msg.sender, from, id, amount, data) !=

165:                 ERC1155Holder(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) !=

224:                 ERC1155Holder(to).onERC1155Received(msg.sender, address(0), id, amount, "") !=

GitHub : 112,165,224

[G-07] Avoid transferring amounts of zero in order to save gas

Skipping the external call when nothing will be transferred, will save at least 100 gas

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

418              SafeTransferLib.safeTransferFrom(
419                  decoded.poolFeatures.token0,
420                  decoded.payer,
421                  msg.sender,
422                  amount0Owed
423:             );

425              SafeTransferLib.safeTransferFrom(
426                  decoded.poolFeatures.token1,
427                  decoded.payer,
428                  msg.sender,
429                  amount1Owed
430:             );

460:         SafeTransferLib.safeTransferFrom(token, decoded.payer, msg.sender, amountToPay);

GitHub : 418,425,460

[G-08] 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(0) and uint256(1) for true/false to avoid a Gwarmaccess (100 gas) for the extra SLOAD

There are 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

67       mapping(address owner => mapping(address operator => bool approvedForAll))
68:          public isApprovedForAll;

GitHub : 67

[G-09] Combine mappings referenced in the same function by the same key

Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot. Even if the values can't be packed, if both fields are accessed in the same function (as is the case for these instances), combining them can save ~42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operations.

There are 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit combine: s_accountFeesBase,s_accountLiquidity
578      function registerTokenTransfer(address from, address to, uint256 id, uint256 amount) internal {
579          // Extract univ3pool from the poolId map to Uniswap Pool
580          IUniswapV3Pool univ3pool = s_poolContext[id.validate()].pool;
581  
582          uint256 numLegs = id.countLegs();
583          for (uint256 leg = 0; leg < numLegs; ) {
584              // for this leg index: extract the liquidity chunk: a 256bit word containing the liquidity amount and upper/lower tick
585              // @dev see `contracts/types/LiquidityChunk.sol`
586              uint256 liquidityChunk = PanopticMath.getLiquidityChunk(
587                  id,
588                  leg,
589                  uint128(amount),
590                  univ3pool.tickSpacing()
591              );
592  
593              //construct the positionKey for the from and to addresses
594              bytes32 positionKey_from = keccak256(
595                  abi.encodePacked(
596                      address(univ3pool),
597                      from,
598                      id.tokenType(leg),
599                      liquidityChunk.tickLower(),
600                      liquidityChunk.tickUpper()
601                  )
602              );
603              bytes32 positionKey_to = keccak256(
604                  abi.encodePacked(
605                      address(univ3pool),
606                      to,
607                      id.tokenType(leg),
608                      liquidityChunk.tickLower(),
609                      liquidityChunk.tickUpper()
610                  )
611              );
612  
613              // Revert if recipient already has that position
614              if (
615                  (s_accountLiquidity[positionKey_to] != 0) ||
616                  (s_accountFeesBase[positionKey_to] != 0)
617              ) revert Errors.TransferFailed();
618  
619              // Revert if not all balance is transferred
620              uint256 fromLiq = s_accountLiquidity[positionKey_from];
621              if (fromLiq.rightSlot() != liquidityChunk.liquidity()) revert Errors.TransferFailed();
622  
623              int256 fromBase = s_accountFeesBase[positionKey_from];
624  
625              //update+store liquidity and fee values between accounts
626              s_accountLiquidity[positionKey_to] = fromLiq;
627              s_accountLiquidity[positionKey_from] = 0;
628  
629              s_accountFeesBase[positionKey_to] = fromBase;
630              s_accountFeesBase[positionKey_from] = 0;
631              unchecked {
632                  ++leg;
633              }
634          }
635:     }

/// @audit combine: s_accountFeesBase,s_accountLiquidity
936      function _createLegInAMM(
937          IUniswapV3Pool _univ3pool,
938          uint256 _tokenId,
939          uint256 _leg,
940          uint256 _liquidityChunk,
941          bool _isBurn
942      ) internal returns (int256 _moved, int256 _itmAmounts, int256 _totalCollected) {
943          uint256 _tokenType = TokenId.tokenType(_tokenId, _leg);
944          // unique key to identify the liquidity chunk in this uniswap pool
945          bytes32 positionKey = keccak256(
946              abi.encodePacked(
947                  address(_univ3pool),
948                  msg.sender,
949                  _tokenType,
950                  _liquidityChunk.tickLower(),
951                  _liquidityChunk.tickUpper()
952              )
953          );
954  
955          // update our internal bookkeeping of how much liquidity we have deployed in the AMM
956          // for example: if this _leg is short, we add liquidity to the amm, make sure to add that to our tracking
957          uint128 updatedLiquidity;
958          uint256 isLong = TokenId.isLong(_tokenId, _leg);
959          uint256 currentLiquidity = s_accountLiquidity[positionKey]; //cache
960  
961          unchecked {
962              // did we have liquidity already deployed in Uniswap for this chunk range from some past mint?
963  
964              // s_accountLiquidity is a LeftRight. The right slot represents the liquidity currently sold (added) in the AMM owned by the user
965              // the left slot represents the amount of liquidity currently bought (removed) that has been removed from the AMM - the user owes it to a seller
966              // the reason why it is called "removedLiquidity" is because long options are created by removing -ie.short selling LP positions
967              uint128 startingLiquidity = currentLiquidity.rightSlot();
968              uint128 removedLiquidity = currentLiquidity.leftSlot();
969              uint128 chunkLiquidity = _liquidityChunk.liquidity();
970  
971              if (isLong == 0) {
972                  // selling/short: so move from msg.sender *to* uniswap
973                  // we're minting more liquidity in uniswap: so add the incoming liquidity chunk to the existing liquidity chunk
974                  updatedLiquidity = startingLiquidity + chunkLiquidity;
975  
976                  /// @dev If the isLong flag is 0=short but the position was burnt, then this is closing a long position
977                  /// @dev so the amount of short liquidity should decrease.
978                  if (_isBurn) {
979                      removedLiquidity -= chunkLiquidity;
980                  }
981              } else {
982                  // the _leg is long (buying: moving *from* uniswap to msg.sender)
983                  // so we seek to move the incoming liquidity chunk *out* of uniswap - but was there sufficient liquidity sitting in uniswap
984                  // in the first place?
985                  if (startingLiquidity < chunkLiquidity) {
986                      // the amount we want to move (liquidityChunk.legLiquidity()) out of uniswap is greater than
987                      // what the account that owns the liquidity in uniswap has (startingLiquidity)
988                      // we must ensure that an account can only move its own liquidity out of uniswap
989                      // so we revert in this case
990                      revert Errors.NotEnoughLiquidity();
991                  } else {
992                      // we want to move less than what already sits in uniswap, no problem:
993                      updatedLiquidity = startingLiquidity - chunkLiquidity;
994                  }
995  
996                  /// @dev If the isLong flag is 1=long and the position is minted, then this is opening a long position
997                  /// @dev so the amount of short liquidity should increase.
998                  if (!_isBurn) {
999                      removedLiquidity += chunkLiquidity;
1000                 }
1001             }
1002 
1003             // update the starting liquidity for this position for next time around
1004             s_accountLiquidity[positionKey] = uint256(0).toLeftSlot(removedLiquidity).toRightSlot(
1005                 updatedLiquidity
1006             );
1007         }
1008 
1009         // track how much liquidity we need to collect from uniswap
1010         // add the fees that accumulated in uniswap within the liquidityChunk:
1011         {
1012             /** if the position is NOT long (selling a put or a call), then _mintLiquidity to move liquidity
1013                 from the msg.sender to the uniswap v3 pool:
1014                 Selling(isLong=0): Mint chunk of liquidity in Uniswap (defined by upper tick, lower tick, and amount)
1015                        ┌─────────────────────────────────┐
1016                 ▲     ┌▼┐ liquidityChunk                 │
1017                 │  ┌──┴─┴──┐                         ┌───┴──┐
1018                 │  │       │                         │      │
1019                 └──┴───────┴──►                      └──────┘
1020                    Uniswap v3                      msg.sender
1021             
1022              else: the position is long (buying a put or a call), then _burnLiquidity to remove liquidity from univ3
1023                 Buying(isLong=1): Burn in Uniswap
1024                        ┌─────────────────┐
1025                 ▲     ┌┼┐                │
1026                 │  ┌──┴─┴──┐         ┌───▼──┐
1027                 │  │       │         │      │
1028                 └──┴───────┴──►      └──────┘
1029                     Uniswap v3      msg.sender 
1030             */
1031             _moved = isLong == 0
1032                 ? _mintLiquidity(_liquidityChunk, _univ3pool)
1033                 : _burnLiquidity(_liquidityChunk, _univ3pool); // from msg.sender to Uniswap
1034             // add the moved liquidity chunk to amount we need to collect from uniswap:
1035 
1036             // Is this _leg ITM?
1037             // if tokenType is 1, and we transacted some token0: then this leg is ITM!
1038             if (_tokenType == 1) {
1039                 // extract amount moved out of UniswapV3 pool
1040                 _itmAmounts = _itmAmounts.toRightSlot(_moved.rightSlot());
1041             }
1042             // if tokenType is 0, and we transacted some token1: then this leg is ITM
1043             if (_tokenType == 0) {
1044                 // Add this in-the-money amount transacted.
1045                 _itmAmounts = _itmAmounts.toLeftSlot(_moved.leftSlot());
1046             }
1047         }
1048 
1049         // if there was liquidity at that tick before the transaction, collect any accumulated fees
1050         if (currentLiquidity.rightSlot() > 0) {
1051             _totalCollected = _collectAndWritePositionData(
1052                 _liquidityChunk,
1053                 _univ3pool,
1054                 currentLiquidity,
1055                 positionKey,
1056                 _moved,
1057                 isLong
1058             );
1059         }
1060 
1061         // position has been touched, update s_accountFeesBase with the latest values from the pool.positions
1062         s_accountFeesBase[positionKey] = _getFeesBase(
1063             _univ3pool,
1064             updatedLiquidity,
1065             _liquidityChunk
1066         );
1067:    }

/// @audit combine: s_accountPremiumGross,s_accountPremiumOwed
1073     function _updateStoredPremia(
1074         bytes32 positionKey,
1075         uint256 currentLiquidity,
1076         int256 collectedAmounts
1077     ) private {
1078         (uint256 deltaPremiumOwed, uint256 deltaPremiumGross) = _getPremiaDeltas(
1079             currentLiquidity,
1080             collectedAmounts
1081         );
1082 
1083         s_accountPremiumOwed[positionKey] = s_accountPremiumOwed[positionKey].add(deltaPremiumOwed);
1084         s_accountPremiumGross[positionKey] = s_accountPremiumGross[positionKey].add(
1085             deltaPremiumGross
1086         );
1087:    }

/// @audit combine: s_accountFeesBase,s_accountLiquidity,s_accountPremiumGross,s_accountPremiumOwed
1371     function getAccountPremium(
1372         address univ3pool,
1373         address owner,
1374         uint256 tokenType,
1375         int24 tickLower,
1376         int24 tickUpper,
1377         int24 atTick,
1378         uint256 isLong
1379     ) external view returns (uint128 premiumToken0, uint128 premiumToken1) {
1380         bytes32 positionKey = keccak256(
1381             abi.encodePacked(address(univ3pool), owner, tokenType, tickLower, tickUpper)
1382         );
1383 
1384         // Extract the account liquidity for a given uniswap pool, owner, token type, and ticks
1385         uint256 acctPremia = isLong == 1
1386             ? s_accountPremiumOwed[positionKey]
1387             : s_accountPremiumGross[positionKey];
1388 
1389         // Compute the premium up to the current block (ie. after last touch until now). Do not proceed if atTick == type(int24).max = 8388608
1390         if (atTick < type(int24).max) {
1391             // unique key to identify the liquidity chunk in this uniswap pool
1392             uint256 accountLiquidities = s_accountLiquidity[positionKey];
1393             uint128 netLiquidity = accountLiquidities.rightSlot();
1394             if (netLiquidity != 0) {
1395                 int256 amountToCollect;
1396                 {
1397                     IUniswapV3Pool _univ3pool = IUniswapV3Pool(univ3pool);
1398                     uint256 tempChunk = uint256(0).createChunk(tickLower, tickUpper, 0);
1399                     // how much fees have been accumulated within the liquidity chunk since last time we updated this chunk?
1400                     // Compute (currentFeesGrowth - oldFeesGrowth), the amount to collect
1401                     // currentFeesGrowth (calculated from FeesCalc.calculateAMMSwapFeesLiquidityChunk) is (ammFeesCollectedPerLiquidity * liquidityChunk.liquidity())
1402                     // oldFeesGrowth is the last stored update of fee growth within the position range in the past (feeGrowthRange*liquidityChunk.liquidity()) (s_accountFeesBase[positionKey])
1403                     int256 feesBase = FeesCalc.calculateAMMSwapFeesLiquidityChunk(
1404                         _univ3pool,
1405                         atTick,
1406                         netLiquidity,
1407                         tempChunk
1408                     );
1409                     amountToCollect = feesBase.sub(s_accountFeesBase[positionKey]);
1410                 }
1411 
1412                 (uint256 deltaPremiumOwed, uint256 deltaPremiumGross) = _getPremiaDeltas(
1413                     accountLiquidities,
1414                     amountToCollect
1415                 );
1416                 // Extract the account liquidity for a given uniswap pool, owner, token type, and ticks
1417                 acctPremia = isLong == 1
1418                     ? acctPremia.add(deltaPremiumOwed)
1419                     : acctPremia.add(deltaPremiumGross);
1420             }
1421         }
1422 
1423         premiumToken0 = acctPremia.rightSlot();
1424         premiumToken1 = acctPremia.leftSlot();
1425:    }

GitHub : 578,936,1073,1371

[G-10] Enable IR-based code generation

By using --via-ir or {"viaIR": true}, the compiler is able to use more advanced multi-function optimizations, for extra gas savings.

There are 1 instance(s) of this issue:

File: Various Files

GitHub : various

[G-11] Multiple accesses of a mapping/array should use a local variable cache

The instances below point to the second+ access of a value inside a mapping/array, within a function. Caching a mapping's value in a local storage or calldata variable when the value is accessed multiple times, saves ~42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operations. Caching an array's struct avoids recalculating the array offsets into memory/calldata

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit s_poolContext[poolId] on line 323
326:          s_poolContext[poolId].locked = true;

GitHub : 326

[G-12] Assigning state variables directly with named struct constructors wastes gas

Using named arguments for struct means that the compiler needs to organize the fields in memory before doing the assignment, which wastes gas. Set each field directly in storage (use dot-notation), or use the unnamed version of the constructor.

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

375          s_poolContext[poolId] = PoolAddressAndLock({
376              pool: IUniswapV3Pool(univ3pool),
377              locked: false
378:         });

GitHub : 375

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

When using elements that are smaller than 32 bytes, your contracts 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 13 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1280                 premium0X64_base = Math
1281                     .mulDiv(collected0, totalLiquidity * 2 ** 64, netLiquidity ** 2)
1282:                    .toUint128();

1283                 premium1X64_base = Math
1284                     .mulDiv(collected1, totalLiquidity * 2 ** 64, netLiquidity ** 2)
1285:                    .toUint128();

1295                     premium0X64_owed = Math
1296                         .mulDiv(premium0X64_base, numerator, totalLiquidity)
1297:                        .toUint128();

1298                     premium1X64_owed = Math
1299                         .mulDiv(premium1X64_base, numerator, totalLiquidity)
1300:                        .toUint128();

1317                     premium0X64_gross = Math
1318                         .mulDiv(premium0X64_base, numerator, totalLiquidity ** 2)
1319:                        .toUint128();

1320                     premium1X64_gross = Math
1321                         .mulDiv(premium1X64_base, numerator, totalLiquidity ** 2)
1322:                        .toUint128();

1469:        poolId = uint64(s_AddrToPoolIdData[univ3pool]);

GitHub : 1280,1283,1295,1298,1317,1320,1469

File: contracts/libraries/Math.sol

89:              sqrtPriceX96 = uint160((sqrtR >> 32) + (sqrtR % (1 << 32) == 0 ? 0 : 1));

173:         if ((downcastedInt = uint128(toDowncast)) != toDowncast) revert Errors.CastingError();

GitHub : 89,173

File: contracts/libraries/PanopticMath.sol

121              legLiquidity = Math.getLiquidityForAmount0(
122                  uint256(0).addTickLower(tickLower).addTickUpper(tickUpper),
123                  amount
124:             );

126              legLiquidity = Math.getLiquidityForAmount1(
127                  uint256(0).addTickLower(tickLower).addTickUpper(tickUpper),
128                  amount
129:             );

GitHub : 121,126

File: contracts/types/LeftRight.sol

199:         if (!((selfAsInt128 = int128(self)) == self)) revert Errors.CastingError();

206:         if (!((selfAsUint128 = uint128(self)) == self)) revert Errors.CastingError();

GitHub : 199,206

[G-14] 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 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit initializeAMMPool(), uniswapV3MintCallback(), uniswapV3SwapCallback(), burnTokenizedPosition(), mintTokenizedPosition(), getAccountLiquidity(), getAccountPremium(), getAccountFeesBase(), getUniswapV3PoolFromId(), getPoolId()
72:   contract SemiFungiblePositionManager is ERC1155, Multicall {

GitHub : 72

[G-15] Constructors can be marked payable

Payable functions cost less gas to execute, since the compiler does not have to add extra checks to ensure that a payment wasn't provided. A constructor can safely be marked as payable, since only the deployer would be able to pass funds, and the project itself would not pass any funds.

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

342:      constructor(IUniswapV3Factory _factory) {

GitHub : 342

[G-16] internal/private 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. The inliner can do it only for 'simple' cases:

Now to get back to the point why we require the routine to be simple: As soon as you do more complicated things like for example branching, calling external contracts, the Common Subexpression Eliminator cannot re-construct the code anymore or does not do full symbolic evaluation of the expressions.

https://soliditylang.org/blog/2021/03/02/saving-gas-with-simple-inliner/

Therefore, the instances below contain branching or use op-codes with side-effects

There are 12 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

321:     function beginReentrancyLock(uint64 poolId) internal {

331:     function endReentrancyLock(uint64 poolId) internal {

544      function afterTokenTransfer(
545          address from,
546          address to,
547          uint256[] memory ids,
548          uint256[] memory amounts
549:     ) internal override {

743      function swapInAMM(
744          IUniswapV3Pool univ3pool,
745          int256 itmAmounts
746:     ) internal returns (int256 totalSwapped) {

848      function _createPositionInAMM(
849          IUniswapV3Pool univ3pool,
850          uint256 tokenId,
851          uint128 positionSize,
852          bool isBurn
853:     ) internal returns (int256 totalMoved, int256 totalCollected, int256 itmAmounts) {

936      function _createLegInAMM(
937          IUniswapV3Pool _univ3pool,
938          uint256 _tokenId,
939          uint256 _leg,
940          uint256 _liquidityChunk,
941          bool _isBurn
942:     ) internal returns (int256 _moved, int256 _itmAmounts, int256 _totalCollected) {

1073     function _updateStoredPremia(
1074         bytes32 positionKey,
1075         uint256 currentLiquidity,
1076         int256 collectedAmounts
1077:    ) private {

1129     function _mintLiquidity(
1130         uint256 liquidityChunk,
1131         IUniswapV3Pool univ3pool
1132:    ) internal returns (int256 movedAmounts) {

1169     function _burnLiquidity(
1170         uint256 liquidityChunk,
1171         IUniswapV3Pool univ3pool
1172:    ) internal returns (int256 movedAmounts) {

1200     function _collectAndWritePositionData(
1201         uint256 liquidityChunk,
1202         IUniswapV3Pool univ3pool,
1203         uint256 currentLiquidity,
1204         bytes32 positionKey,
1205         int256 movedInLeg,
1206         uint256 isLong
1207:    ) internal returns (int256 collectedOut) {

GitHub : 321,331,544,743,848,936,1073,1129,1169,1200

File: contracts/tokens/ERC1155Minimal.sol

214:     function _mint(address to, uint256 id, uint256 amount) internal {

236:     function _burn(address from, uint256 id, uint256 amount) internal {

GitHub : 214,236

[G-17] Division by powers of two should use bit shifting

<x> / 2 is the same as <x> >> 1. While the compiler uses the SHR opcode to accomplish both, the version that uses division incurs an overhead of 20 gas due to JUMPs to and from a compiler utility function that introduces checks which can be avoided by using unchecked {} around the division by two.

There are 1 instance(s) of this issue:

File: contracts/types/TokenId.sol

389:             int24 oneSidedRange = (selfWidth * tickSpacing) / 2;

GitHub : 389

[G-18] Assembly: Use scratch space when building emitted events with two data arguments

Using the scratch space for more than one, but at most two words worth of data (non-indexed arguments) will save gas over needing Solidity's abi memory expansion used for emitting normally.

There are 3 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

108:         emit TransferSingle(msg.sender, from, to, id, amount);

220:         emit TransferSingle(msg.sender, address(0), to, id, amount);

239:         emit TransferSingle(msg.sender, from, address(0), id, amount);

GitHub : 108,220,239

[G-19] Consider using solady's FixedPointMathLib

Saves gas, and works to avoid unnecessary overflows.

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1316:                        ((removedLiquidity ** 2) / 2 ** (VEGOID));

GitHub : 1316

File: contracts/libraries/Math.sol

108                  mulDiv(
109                      uint256(liquidityChunk.liquidity()) << 96,
110                      highPriceX96 - lowPriceX96,
111                      highPriceX96
112:                 ) / lowPriceX96;

GitHub : 108

File: contracts/types/TokenId.sol

389:             int24 oneSidedRange = (selfWidth * tickSpacing) / 2;

GitHub : 389

[G-20] Multiple address/ID mappings can be combined into a single mapping of an address/ID to a struct

Saves a storage slot for each of the removed mappings. The instances below refer to both mappings using the same key in the same function, so the mappings are related.

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit combine: s_accountFeesBase,s_accountLiquidity
/// @audit combine: s_accountFeesBase,s_accountLiquidity,s_accountPremiumGross,s_accountPremiumOwed
/// @audit combine: s_accountPremiumGross,s_accountPremiumOwed
72   contract SemiFungiblePositionManager is ERC1155, Multicall {
73       /*//////////////////////////////////////////////////////////////
74                                   EVENTS
75       //////////////////////////////////////////////////////////////*/
76   
77       /// @notice Emitted when a UniswapV3Pool is initialized.
78:      /// @param uniswapPool Address of the underlying Uniswap v3 pool

GitHub : 72,72,72

[G-21] Nesting if-statements is cheaper than using &&

Nesting if-statements avoids the stack operations of setting up and using an extra jumpdest, and saves 6 gas

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

706          if ((itmAmounts != 0) && (swapAtMint)) {
707              totalMoved = swapInAMM(univ3pool, itmAmounts).add(totalMoved);
708:         }

GitHub : 706

File: contracts/types/TokenId.sol

512                      if ((isLong == isLongP) && (tokenType == tokenTypeP))
513:                         revert Errors.InvalidTokenIdParameter(4);

517                      if ((isLong != isLongP) && (tokenType != tokenTypeP))
518:                         revert Errors.InvalidTokenIdParameter(5);

GitHub : 512,517

[G-22] Reduce deployment costs by tweaking contracts' metadata

See this link, at its bottom, for full details

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

72   contract SemiFungiblePositionManager is ERC1155, Multicall {
73       /*//////////////////////////////////////////////////////////////
74                                   EVENTS
75       //////////////////////////////////////////////////////////////*/
76   
77       /// @notice Emitted when a UniswapV3Pool is initialized.
78:      /// @param uniswapPool Address of the underlying Uniswap v3 pool

GitHub : 72

[G-23] Reduce gas usage by moving to Solidity 0.8.19 or later

See this link for the full details. Additionally, every new release has new optimizations, which will save gas.

There are 13 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

2:   pragma solidity =0.8.18;

GitHub : 2

File: contracts/libraries/CallbackLib.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/Constants.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/Errors.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/FeesCalc.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/Math.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/PanopticMath.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/SafeTransferLib.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/multicall/Multicall.sol

2:   pragma solidity =0.8.18;

GitHub : 2

File: contracts/tokens/ERC1155Minimal.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/types/LeftRight.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/types/LiquidityChunk.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/types/TokenId.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

[G-24] 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 are 1 instance(s) of this issue:

File: contracts/libraries/Math.sol

207:                  require(denominator > 0);

GitHub : 207

[G-25] Stack variable is only used once

If the variable is only accessed once, it's cheaper to use the assigned value directly that one time, and save the 3 gas the extra stack assignment would spend

There are 24 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

452          address token = amount0Delta > 0
453              ? address(decoded.poolFeatures.token0)
454:             : address(decoded.poolFeatures.token1);

457:         uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);

775:                 (uint160 sqrtPriceX96, , , , , , ) = _univ3pool.slot0();

824              (int256 swap0, int256 swap1) = _univ3pool.swap(
825                  msg.sender,
826                  zeroForOne,
827                  swapAmount,
828                  zeroForOne
829                      ? Constants.MIN_V3POOL_SQRT_RATIO + 1
830                      : Constants.MAX_V3POOL_SQRT_RATIO - 1,
831                  data
832:             );

1078         (uint256 deltaPremiumOwed, uint256 deltaPremiumGross) = _getPremiaDeltas(
1079             currentLiquidity,
1080             collectedAmounts
1081:        );

1102         (, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = univ3pool
1103             .positions(
1104                 keccak256(
1105                     abi.encodePacked(
1106                         address(this),
1107                         liquidityChunk.tickLower(),
1108                         liquidityChunk.tickUpper()
1109                     )
1110                 )
1111:            );

1134         bytes memory mintdata = abi.encode(
1135             CallbackLib.CallbackData({ // compute by reading values from univ3pool every time
1136                     poolFeatures: CallbackLib.PoolFeatures({
1137                         token0: univ3pool.token0(),
1138                         token1: univ3pool.token1(),
1139                         fee: univ3pool.fee()
1140                     }),
1141                     payer: msg.sender
1142                 })
1143:        );

1147         (uint256 amount0, uint256 amount1) = univ3pool.mint(
1148             address(this),
1149             liquidityChunk.tickLower(),
1150             liquidityChunk.tickUpper(),
1151             liquidityChunk.liquidity(),
1152             mintdata
1153:        );

1175         (uint256 amount0, uint256 amount1) = univ3pool.burn(
1176             liquidityChunk.tickLower(),
1177             liquidityChunk.tickUpper(),
1178             liquidityChunk.liquidity()
1179:        );

1208:        uint128 startingLiquidity = currentLiquidity.rightSlot();

1276:                uint128 collected0 = uint128(collectedAmounts.rightSlot());

1277:                uint128 collected1 = uint128(collectedAmounts.leftSlot());

1397:                    IUniswapV3Pool _univ3pool = IUniswapV3Pool(univ3pool);

1398:                    uint256 tempChunk = uint256(0).createChunk(tickLower, tickUpper, 0);

1403                     int256 feesBase = FeesCalc.calculateAMMSwapFeesLiquidityChunk(
1404                         _univ3pool,
1405                         atTick,
1406                         netLiquidity,
1407                         tempChunk
1408:                    );

1412                 (uint256 deltaPremiumOwed, uint256 deltaPremiumGross) = _getPremiaDeltas(
1413                     accountLiquidities,
1414                     amountToCollect
1415:                );

GitHub : 452,457,775,824,1078,1102,1134,1147,1175,1208,1276,1277,1397,1398,1403,1412

File: contracts/libraries/FeesCalc.sol

62           (
63               uint256 ammFeesPerLiqToken0X128,
64               uint256 ammFeesPerLiqToken1X128
65           ) = _getAMMSwapFeesPerLiquidityCollected(
66                   univ3pool,
67                   currentTick,
68                   liquidityChunk.tickLower(),
69                   liquidityChunk.tickUpper()
70:              );

GitHub : 62

File: contracts/libraries/Math.sol

122:         uint160 lowPriceX96 = getSqrtRatioAtTick(liquidityChunk.tickLower());

123:         uint160 highPriceX96 = getSqrtRatioAtTick(liquidityChunk.tickUpper());

158:         uint160 lowPriceX96 = getSqrtRatioAtTick(liquidityChunk.tickLower());

159:         uint160 highPriceX96 = getSqrtRatioAtTick(liquidityChunk.tickUpper());

GitHub : 122,123,158,159

File: contracts/types/TokenId.sol

380:             int24 selfWidth = self.width(legIndex);

385:             int24 minTick = (Constants.MIN_V3POOL_TICK / tickSpacing) * tickSpacing;

386:             int24 maxTick = (Constants.MAX_V3POOL_TICK / tickSpacing) * tickSpacing;

GitHub : 380,385,386

[G-26] >= 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. If < is being used, the condition can be inverted.

There are 21 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

417          if (amount0Owed > 0)
418              SafeTransferLib.safeTransferFrom(
419                  decoded.poolFeatures.token0,
420                  decoded.payer,
421                  msg.sender,
422                  amount0Owed
423:             );

424          if (amount1Owed > 0)
425              SafeTransferLib.safeTransferFrom(
426                  decoded.poolFeatures.token1,
427                  decoded.payer,
428                  msg.sender,
429                  amount1Owed
430:             );

687              if (tickLimitLow > tickLimitHigh) {
688                  swapAtMint = true;
689                  (tickLimitLow, tickLimitHigh) = (tickLimitHigh, tickLimitLow);
690:             }

985                  if (startingLiquidity < chunkLiquidity) {
986                      // the amount we want to move (liquidityChunk.legLiquidity()) out of uniswap is greater than
987                      // what the account that owns the liquidity in uniswap has (startingLiquidity)
988                      // we must ensure that an account can only move its own liquidity out of uniswap
989                      // so we revert in this case
990                      revert Errors.NotEnoughLiquidity();
991                  } else {
992                      // we want to move less than what already sits in uniswap, no problem:
993                      updatedLiquidity = startingLiquidity - chunkLiquidity;
994:                 }

1050         if (currentLiquidity.rightSlot() > 0) {
1051             _totalCollected = _collectAndWritePositionData(
1052                 _liquidityChunk,
1053                 _univ3pool,
1054                 currentLiquidity,
1055                 positionKey,
1056                 _moved,
1057                 isLong
1058             );
1059:        }

1390         if (atTick < type(int24).max) {
1391             // unique key to identify the liquidity chunk in this uniswap pool
1392             uint256 accountLiquidities = s_accountLiquidity[positionKey];
1393             uint128 netLiquidity = accountLiquidities.rightSlot();
1394             if (netLiquidity != 0) {
1395                 int256 amountToCollect;
1396                 {
1397                     IUniswapV3Pool _univ3pool = IUniswapV3Pool(univ3pool);
1398                     uint256 tempChunk = uint256(0).createChunk(tickLower, tickUpper, 0);
1399                     // how much fees have been accumulated within the liquidity chunk since last time we updated this chunk?
1400                     // Compute (currentFeesGrowth - oldFeesGrowth), the amount to collect
1401                     // currentFeesGrowth (calculated from FeesCalc.calculateAMMSwapFeesLiquidityChunk) is (ammFeesCollectedPerLiquidity * liquidityChunk.liquidity())
1402                     // oldFeesGrowth is the last stored update of fee growth within the position range in the past (feeGrowthRange*liquidityChunk.liquidity()) (s_accountFeesBase[positionKey])
1403                     int256 feesBase = FeesCalc.calculateAMMSwapFeesLiquidityChunk(
1404                         _univ3pool,
1405                         atTick,
1406                         netLiquidity,
1407                         tempChunk
1408                     );
1409                     amountToCollect = feesBase.sub(s_accountFeesBase[positionKey]);
1410                 }
1411 
1412                 (uint256 deltaPremiumOwed, uint256 deltaPremiumGross) = _getPremiaDeltas(
1413                     accountLiquidities,
1414                     amountToCollect
1415                 );
1416                 // Extract the account liquidity for a given uniswap pool, owner, token type, and ticks
1417                 acctPremia = isLong == 1
1418                     ? acctPremia.add(deltaPremiumOwed)
1419                     : acctPremia.add(deltaPremiumGross);
1420             }
1421:        }

GitHub : 417,424,687,985,1050,1390

File: contracts/libraries/FeesCalc.sol

106              if (currentTick < tickLower) {
107                  /**
108                    Diagrams shown for token0, and applies for token1 the same
109                    L = lowerTick, U = upperTick
110  
111                      liquidity         lowerOut0 (all fees collected in this price tick range for token0)
112                          ▲            ◄──────────────^v───► (to MAX_TICK)
113                          │
114                          │                      upperOut0
115                          │                     ◄─────^v───►
116                          │           ┌────────┐
117                          │           │ chunk  │
118                          │           │        │
119                          └─────▲─────┴────────┴────────► price tick
120                                │     L        U
121                                │
122                             current
123                              tick
124                  */
125                  feeGrowthInside0X128 = lowerOut0 - upperOut0; // fee growth inside the chunk
126                  feeGrowthInside1X128 = lowerOut1 - upperOut1;
127              } else if (currentTick >= tickUpper) {
128                  /**
129                      liquidity
130                          ▲           upperOut0
131                          │◄─^v─────────────────────►
132                          │     
133                          │     lowerOut0  ┌────────┐
134                          │◄─^v───────────►│ chunk  │
135                          │                │        │
136                          └────────────────┴────────┴─▲─────► price tick
137                                           L        U │
138                                                      │
139                                                   current
140                                                    tick
141                   */
142                  feeGrowthInside0X128 = upperOut0 - lowerOut0;
143                  feeGrowthInside1X128 = upperOut1 - lowerOut1;
144              } else {
145                  /**
146                    current AMM tick is within the option position range (within the chunk)
147  
148                       liquidity
149                          ▲        feeGrowthGlobal0X128 = global fee growth
150                          │                             = (all fees collected for the entire price range for token 0)
151                          │
152                          │                        
153                          │     lowerOut0  ┌──────────────┐ upperOut0
154                          │◄─^v───────────►│              │◄─────^v───►
155                          │                │     chunk    │
156                          │                │              │
157                          └────────────────┴───────▲──────┴─────► price tick
158                                           L       │      U
159                                                   │
160                                                current
161                                                 tick
162                  */
163                  feeGrowthInside0X128 = univ3pool.feeGrowthGlobal0X128() - lowerOut0 - upperOut0;
164                  feeGrowthInside1X128 = univ3pool.feeGrowthGlobal1X128() - lowerOut1 - upperOut1;
165:             }

GitHub : 106

File: contracts/libraries/Math.sol

41:              if (absTick > uint256(int256(Constants.MAX_V3POOL_TICK))) revert Errors.InvalidTick();

86:              if (tick > 0) sqrtR = type(uint256).max / sqrtR;

GitHub : 41,86

File: contracts/libraries/PanopticMath.sol

149              if (sqrtPriceX96 < 340275971719517849884101479065584693834) {
150                  int256 absResult = Math
151                      .mulDiv192(Math.absUint(amount), uint256(sqrtPriceX96) ** 2)
152                      .toInt256();
153                  return amount < 0 ? -absResult : absResult;
154              } else {
155                  int256 absResult = Math
156                      .mulDiv128(Math.absUint(amount), Math.mulDiv64(sqrtPriceX96, sqrtPriceX96))
157                      .toInt256();
158                  return amount < 0 ? -absResult : absResult;
159:             }

172              if (sqrtPriceX96 < 340275971719517849884101479065584693834) {
173                  int256 absResult = Math
174                      .mulDiv(Math.absUint(amount), 2 ** 192, uint256(sqrtPriceX96) ** 2)
175                      .toInt256();
176                  return amount < 0 ? -absResult : absResult;
177              } else {
178                  int256 absResult = Math
179                      .mulDiv(
180                          Math.absUint(amount),
181                          2 ** 128,
182                          Math.mulDiv64(sqrtPriceX96, sqrtPriceX96)
183                      )
184                      .toInt256();
185                  return amount < 0 ? -absResult : absResult;
186:             }

GitHub : 149,172

File: contracts/types/LeftRight.sol

55:          if (right < 0) revert Errors.LeftRightInputError();

213:         if (self > uint256(type(int256).max)) revert Errors.CastingError();

GitHub : 55,213

File: contracts/types/TokenId.sol

343              } else if (optionRatios < 2 ** 208) {
344                  optionRatios = 3;
345              } else {
346                  optionRatios = 4;
347:             }

341              } else if (optionRatios < 2 ** 160) {
342                  optionRatios = 2;
343              } else if (optionRatios < 2 ** 208) {
344                  optionRatios = 3;
345              } else {
346                  optionRatios = 4;
347:             }

339              } else if (optionRatios < 2 ** 112) {
340                  optionRatios = 1;
341              } else if (optionRatios < 2 ** 160) {
342                  optionRatios = 2;
343              } else if (optionRatios < 2 ** 208) {
344                  optionRatios = 3;
345              } else {
346                  optionRatios = 4;
347:             }

337              if (optionRatios < 2 ** 64) {
338                  optionRatios = 0;
339              } else if (optionRatios < 2 ** 112) {
340                  optionRatios = 1;
341              } else if (optionRatios < 2 ** 160) {
342                  optionRatios = 2;
343              } else if (optionRatios < 2 ** 208) {
344                  optionRatios = 3;
345              } else {
346                  optionRatios = 4;
347:             }

423          } else if (optionRatios < 2 ** 208) {
424              return 3;
425:         }

421          } else if (optionRatios < 2 ** 160) {
422              return 2;
423          } else if (optionRatios < 2 ** 208) {
424              return 3;
425:         }

419          } else if (optionRatios < 2 ** 112) {
420              return 1;
421          } else if (optionRatios < 2 ** 160) {
422              return 2;
423          } else if (optionRatios < 2 ** 208) {
424              return 3;
425:         }

417          if (optionRatios < 2 ** 64) {
418              return 0;
419          } else if (optionRatios < 2 ** 112) {
420              return 1;
421          } else if (optionRatios < 2 ** 160) {
422              return 2;
423          } else if (optionRatios < 2 ** 208) {
424              return 3;
425:         }

GitHub : 343,341,339,337,423,421,419,417

[G-27] A memory array's length should not be looked up in every iteration of a for/while-loop

Caching the length of memory arrays changes each length lookup (i.e. on every iteration) from an MLOAD to a DUP<N> (3 gas), and gets rid of the extra DUP<N> needed to store the stack offset, saving 3 gas.

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

550:         for (uint256 i = 0; i < ids.length; ) {

GitHub : 550

[G-28] Split revert checks to save gas

Splitting the conditions into two separate checks saves 2 gas

There are 9 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

614              if (
615                  (s_accountLiquidity[positionKey_to] != 0) ||
616                  (s_accountFeesBase[positionKey_to] != 0)
617:             ) revert Errors.TransferFailed();

713:         if ((newTick >= tickLimitHigh) || (newTick <= tickLimitLow)) revert Errors.PriceBoundFail();

917          if (amount0 > uint128(type(int128).max) || amount1 > uint128(type(int128).max))
918:             revert Errors.PositionTooLarge();

GitHub : 614,713,917

File: contracts/types/LeftRight.sol

151:             if (z < x || (uint128(z) < uint128(x))) revert Errors.UnderOverFlow();

167:             if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

185:             if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

GitHub : 151,167,185

File: contracts/types/TokenId.sol

396              if (
397                  legLowerTick % tickSpacing != 0 ||
398                  legUpperTick % tickSpacing != 0 ||
399                  legLowerTick < minTick ||
400                  legUpperTick > maxTick
401:             ) revert Errors.TicksNotInitializable();

482                  if (
483                      (self.strike(i) == Constants.MIN_V3POOL_TICK) ||
484                      (self.strike(i) == Constants.MAX_V3POOL_TICK)
485:                 ) revert Errors.InvalidTokenIdParameter(4);

497                      if (
498                          (self.asset(riskPartnerIndex) != self.asset(i)) ||
499                          (self.optionRatio(riskPartnerIndex) != self.optionRatio(i))
500:                     ) revert Errors.InvalidTokenIdParameter(3);

GitHub : 396,482,497

[G-29] Using private rather than public, saves gas

For constants, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table

There are 2 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

62:      mapping(address account => mapping(uint256 tokenId => uint256 balance)) public balanceOf;

67       mapping(address owner => mapping(address operator => bool approvedForAll))
68:          public isApprovedForAll;

GitHub : 62,67

NonCritical Risk Issues

[N-01] 2**<n> - 1 should be re-written as type(uint<n>).max

Earlier versions of solidity can use uint<n>(-1) instead. Expressions not including the - 1 can often be re-written to accomodate the change (e.g. by using a > rather than a >=, which will also save some gas)

There are 21 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

384:              s_AddrToPoolIdData[univ3pool] = uint256(poolId) + 2 ** 255;

1281:                     .mulDiv(collected0, totalLiquidity * 2 ** 64, netLiquidity ** 2)

1284:                     .mulDiv(collected1, totalLiquidity * 2 ** 64, netLiquidity ** 2)

GitHub : 384,1281,1284

File: contracts/libraries/Math.sol

311:              require(2 ** 64 > prod1);

338:              prod0 |= prod1 * 2 ** 192;

373:              require(2 ** 96 > prod1);

400:              prod0 |= prod1 * 2 ** 160;

435:              require(2 ** 128 > prod1);

462:              prod0 |= prod1 * 2 ** 128;

497:              require(2 ** 192 > prod1);

524:              prod0 |= prod1 * 2 ** 64;

GitHub : 311,338,373,400,435,462,497,524

File: contracts/libraries/PanopticMath.sol

174:                      .mulDiv(Math.absUint(amount), 2 ** 192, uint256(sqrtPriceX96) ** 2)

181:                          2 ** 128,

GitHub : 174,181

File: contracts/types/TokenId.sol

337:              if (optionRatios < 2 ** 64) {

339:              } else if (optionRatios < 2 ** 112) {

341:              } else if (optionRatios < 2 ** 160) {

343:              } else if (optionRatios < 2 ** 208) {

417:          if (optionRatios < 2 ** 64) {

419:          } else if (optionRatios < 2 ** 112) {

421:          } else if (optionRatios < 2 ** 160) {

423:          } else if (optionRatios < 2 ** 208) {

GitHub : 337,339,341,343,417,419,421,423

[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 164 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

384:             s_AddrToPoolIdData[univ3pool] = uint256(poolId) + 2 ** 255;

1281:                    .mulDiv(collected0, totalLiquidity * 2 ** 64, netLiquidity ** 2)

1284:                    .mulDiv(collected1, totalLiquidity * 2 ** 64, netLiquidity ** 2)

GitHub : 384,1281,1284

File: contracts/libraries/CallbackLib.sol

41:                                  bytes1(0xff),

GitHub : 41

File: contracts/libraries/Math.sol

43:              uint256 sqrtR = absTick & 0x1 != 0

45:                  : 0x100000000000000000000000000000000;

44:                  ? 0xfffcb933bd6fad37aa2d162d1a594001

47:              if (absTick & 0x2 != 0) sqrtR = (sqrtR * 0xfff97272373d413259a46990580e213a) >> 128;

47:              if (absTick & 0x2 != 0) sqrtR = (sqrtR * 0xfff97272373d413259a46990580e213a) >> 128;

47:              if (absTick & 0x2 != 0) sqrtR = (sqrtR * 0xfff97272373d413259a46990580e213a) >> 128;

49:              if (absTick & 0x4 != 0) sqrtR = (sqrtR * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;

49:              if (absTick & 0x4 != 0) sqrtR = (sqrtR * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;

49:              if (absTick & 0x4 != 0) sqrtR = (sqrtR * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;

51:              if (absTick & 0x8 != 0) sqrtR = (sqrtR * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;

51:              if (absTick & 0x8 != 0) sqrtR = (sqrtR * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;

51:              if (absTick & 0x8 != 0) sqrtR = (sqrtR * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;

53:              if (absTick & 0x10 != 0) sqrtR = (sqrtR * 0xffcb9843d60f6159c9db58835c926644) >> 128;

53:              if (absTick & 0x10 != 0) sqrtR = (sqrtR * 0xffcb9843d60f6159c9db58835c926644) >> 128;

53:              if (absTick & 0x10 != 0) sqrtR = (sqrtR * 0xffcb9843d60f6159c9db58835c926644) >> 128;

55:              if (absTick & 0x20 != 0) sqrtR = (sqrtR * 0xff973b41fa98c081472e6896dfb254c0) >> 128;

55:              if (absTick & 0x20 != 0) sqrtR = (sqrtR * 0xff973b41fa98c081472e6896dfb254c0) >> 128;

55:              if (absTick & 0x20 != 0) sqrtR = (sqrtR * 0xff973b41fa98c081472e6896dfb254c0) >> 128;

57:              if (absTick & 0x40 != 0) sqrtR = (sqrtR * 0xff2ea16466c96a3843ec78b326b52861) >> 128;

57:              if (absTick & 0x40 != 0) sqrtR = (sqrtR * 0xff2ea16466c96a3843ec78b326b52861) >> 128;

57:              if (absTick & 0x40 != 0) sqrtR = (sqrtR * 0xff2ea16466c96a3843ec78b326b52861) >> 128;

59:              if (absTick & 0x80 != 0) sqrtR = (sqrtR * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;

59:              if (absTick & 0x80 != 0) sqrtR = (sqrtR * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;

59:              if (absTick & 0x80 != 0) sqrtR = (sqrtR * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;

61:              if (absTick & 0x100 != 0) sqrtR = (sqrtR * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;

61:              if (absTick & 0x100 != 0) sqrtR = (sqrtR * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;

61:              if (absTick & 0x100 != 0) sqrtR = (sqrtR * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;

63:              if (absTick & 0x200 != 0) sqrtR = (sqrtR * 0xf987a7253ac413176f2b074cf7815e54) >> 128;

63:              if (absTick & 0x200 != 0) sqrtR = (sqrtR * 0xf987a7253ac413176f2b074cf7815e54) >> 128;

63:              if (absTick & 0x200 != 0) sqrtR = (sqrtR * 0xf987a7253ac413176f2b074cf7815e54) >> 128;

65:              if (absTick & 0x400 != 0) sqrtR = (sqrtR * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;

65:              if (absTick & 0x400 != 0) sqrtR = (sqrtR * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;

65:              if (absTick & 0x400 != 0) sqrtR = (sqrtR * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;

67:              if (absTick & 0x800 != 0) sqrtR = (sqrtR * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;

67:              if (absTick & 0x800 != 0) sqrtR = (sqrtR * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;

67:              if (absTick & 0x800 != 0) sqrtR = (sqrtR * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;

69:              if (absTick & 0x1000 != 0) sqrtR = (sqrtR * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;

69:              if (absTick & 0x1000 != 0) sqrtR = (sqrtR * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;

69:              if (absTick & 0x1000 != 0) sqrtR = (sqrtR * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;

71:              if (absTick & 0x2000 != 0) sqrtR = (sqrtR * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;

71:              if (absTick & 0x2000 != 0) sqrtR = (sqrtR * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;

71:              if (absTick & 0x2000 != 0) sqrtR = (sqrtR * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;

73:              if (absTick & 0x4000 != 0) sqrtR = (sqrtR * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;

73:              if (absTick & 0x4000 != 0) sqrtR = (sqrtR * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;

73:              if (absTick & 0x4000 != 0) sqrtR = (sqrtR * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;

75:              if (absTick & 0x8000 != 0) sqrtR = (sqrtR * 0x31be135f97d08fd981231505542fcfa6) >> 128;

75:              if (absTick & 0x8000 != 0) sqrtR = (sqrtR * 0x31be135f97d08fd981231505542fcfa6) >> 128;

75:              if (absTick & 0x8000 != 0) sqrtR = (sqrtR * 0x31be135f97d08fd981231505542fcfa6) >> 128;

77:              if (absTick & 0x10000 != 0) sqrtR = (sqrtR * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;

77:              if (absTick & 0x10000 != 0) sqrtR = (sqrtR * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;

77:              if (absTick & 0x10000 != 0) sqrtR = (sqrtR * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;

79:              if (absTick & 0x20000 != 0) sqrtR = (sqrtR * 0x5d6af8dedb81196699c329225ee604) >> 128;

79:              if (absTick & 0x20000 != 0) sqrtR = (sqrtR * 0x5d6af8dedb81196699c329225ee604) >> 128;

79:              if (absTick & 0x20000 != 0) sqrtR = (sqrtR * 0x5d6af8dedb81196699c329225ee604) >> 128;

81:              if (absTick & 0x40000 != 0) sqrtR = (sqrtR * 0x2216e584f5fa1ea926041bedfe98) >> 128;

81:              if (absTick & 0x40000 != 0) sqrtR = (sqrtR * 0x2216e584f5fa1ea926041bedfe98) >> 128;

81:              if (absTick & 0x40000 != 0) sqrtR = (sqrtR * 0x2216e584f5fa1ea926041bedfe98) >> 128;

83:              if (absTick & 0x80000 != 0) sqrtR = (sqrtR * 0x48a170391f7dc42444e8fa2) >> 128;

83:              if (absTick & 0x80000 != 0) sqrtR = (sqrtR * 0x48a170391f7dc42444e8fa2) >> 128;

83:              if (absTick & 0x80000 != 0) sqrtR = (sqrtR * 0x48a170391f7dc42444e8fa2) >> 128;

89:              sqrtPriceX96 = uint160((sqrtR >> 32) + (sqrtR % (1 << 32) == 0 ? 0 : 1));

89:              sqrtPriceX96 = uint160((sqrtR >> 32) + (sqrtR % (1 << 32) == 0 ? 0 : 1));

109:                     uint256(liquidityChunk.liquidity()) << 96,

260:             uint256 inv = (3 * denominator) ^ 2;

311:             require(2 ** 64 > prod1);

338:             prod0 |= prod1 * 2 ** 192;

373:             require(2 ** 96 > prod1);

400:             prod0 |= prod1 * 2 ** 160;

435:             require(2 ** 128 > prod1);

462:             prod0 |= prod1 * 2 ** 128;

497:             require(2 ** 192 > prod1);

524:             prod0 |= prod1 * 2 ** 64;

GitHub : 43,45,44,47,47,47,49,49,49,51,51,51,53,53,53,55,55,55,57,57,57,59,59,59,61,61,61,63,63,63,65,65,65,67,67,67,69,69,69,71,71,71,73,73,73,75,75,75,77,77,77,79,79,79,81,81,81,83,83,83,89,89,109,260,311,338,373,400,435,462,497,524

File: contracts/libraries/PanopticMath.sol

39:          return uint64(uint160(univ3pool) >> 96);

57:                  (uint64(uint256(keccak256(abi.encodePacked(token0, token1, fee)))) >> 32);

149:             if (sqrtPriceX96 < 340275971719517849884101479065584693834) {

172:             if (sqrtPriceX96 < 340275971719517849884101479065584693834) {

181:                         2 ** 128,

174:                     .mulDiv(Math.absUint(amount), 2 ** 192, uint256(sqrtPriceX96) ** 2)

GitHub : 39,57,149,172,181,174

File: contracts/tokens/ERC1155Minimal.sol

202:             interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165

203:             interfaceId == 0xd9b67a26; // ERC165 Interface ID for ERC1155

GitHub : 202,203

File: contracts/types/LeftRight.sol

90:          return uint128(self >> 128);

97:          return int128(self >> 128);

110:             return self + (uint256(left) << 128);

120:             return self + (int256(int128(left)) << 128);

130:             return self + (int256(left) << 128);

GitHub : 90,97,110,120,130

File: contracts/types/LiquidityChunk.sol

90:              return self + (uint256(uint24(_tickLower)) << 232);

101:             return self + ((uint256(uint24(_tickUpper))) << 208);

114:             return int24(int256(self >> 232));

123:             return int24(int256(self >> 208));

GitHub : 90,101,114,123

File: contracts/types/TokenId.sol

95:              return uint256((self >> (64 + legIndex * 48)) % 2);

95:              return uint256((self >> (64 + legIndex * 48)) % 2);

105:             return uint256((self >> (64 + legIndex * 48 + 1)) % 128);

105:             return uint256((self >> (64 + legIndex * 48 + 1)) % 128);

105:             return uint256((self >> (64 + legIndex * 48 + 1)) % 128);

115:             return uint256((self >> (64 + legIndex * 48 + 8)) % 2);

115:             return uint256((self >> (64 + legIndex * 48 + 8)) % 2);

115:             return uint256((self >> (64 + legIndex * 48 + 8)) % 2);

125:             return uint256((self >> (64 + legIndex * 48 + 9)) % 2);

125:             return uint256((self >> (64 + legIndex * 48 + 9)) % 2);

125:             return uint256((self >> (64 + legIndex * 48 + 9)) % 2);

141:             return uint256((self >> (64 + legIndex * 48 + 10)) % 4);

141:             return uint256((self >> (64 + legIndex * 48 + 10)) % 4);

141:             return uint256((self >> (64 + legIndex * 48 + 10)) % 4);

151:             return int24(int256(self >> (64 + legIndex * 48 + 12)));

151:             return int24(int256(self >> (64 + legIndex * 48 + 12)));

151:             return int24(int256(self >> (64 + legIndex * 48 + 12)));

162:             return int24(int256((self >> (64 + legIndex * 48 + 36)) % 4096));

162:             return int24(int256((self >> (64 + legIndex * 48 + 36)) % 4096));

162:             return int24(int256((self >> (64 + legIndex * 48 + 36)) % 4096));

162:             return int24(int256((self >> (64 + legIndex * 48 + 36)) % 4096));

195:             return self + (uint256(_asset % 2) << (64 + legIndex * 48));

195:             return self + (uint256(_asset % 2) << (64 + legIndex * 48));

210:             return self + (uint256(_optionRatio % 128) << (64 + legIndex * 48 + 1));

210:             return self + (uint256(_optionRatio % 128) << (64 + legIndex * 48 + 1));

210:             return self + (uint256(_optionRatio % 128) << (64 + legIndex * 48 + 1));

226:             return self + ((_isLong % 2) << (64 + legIndex * 48 + 8));

226:             return self + ((_isLong % 2) << (64 + legIndex * 48 + 8));

226:             return self + ((_isLong % 2) << (64 + legIndex * 48 + 8));

240:             return self + (uint256(_tokenType % 2) << (64 + legIndex * 48 + 9));

240:             return self + (uint256(_tokenType % 2) << (64 + legIndex * 48 + 9));

240:             return self + (uint256(_tokenType % 2) << (64 + legIndex * 48 + 9));

254:             return self + (uint256(_riskPartner % 4) << (64 + legIndex * 48 + 10));

254:             return self + (uint256(_riskPartner % 4) << (64 + legIndex * 48 + 10));

254:             return self + (uint256(_riskPartner % 4) << (64 + legIndex * 48 + 10));

268:             return self + uint256((int256(_strike) & BITMASK_INT24) << (64 + legIndex * 48 + 12));

268:             return self + uint256((int256(_strike) & BITMASK_INT24) << (64 + legIndex * 48 + 12));

268:             return self + uint256((int256(_strike) & BITMASK_INT24) << (64 + legIndex * 48 + 12));

283:             return self + (uint256(uint24(_width) % 4096) << (64 + legIndex * 48 + 36));

283:             return self + (uint256(uint24(_width) % 4096) << (64 + legIndex * 48 + 36));

283:             return self + (uint256(uint24(_width) % 4096) << (64 + legIndex * 48 + 36));

283:             return self + (uint256(uint24(_width) % 4096) << (64 + legIndex * 48 + 36));

337:             if (optionRatios < 2 ** 64) {

339:             } else if (optionRatios < 2 ** 112) {

341:             } else if (optionRatios < 2 ** 160) {

343:             } else if (optionRatios < 2 ** 208) {

346:                 optionRatios = 4;

344:                 optionRatios = 3;

353:             return self ^ ((LONG_MASK >> (48 * (4 - optionRatios))) & CLEAR_POOLID_MASK);

353:             return self ^ ((LONG_MASK >> (48 * (4 - optionRatios))) & CLEAR_POOLID_MASK);

363:             return self.isLong(0) + self.isLong(1) + self.isLong(2) + self.isLong(3);

417:         if (optionRatios < 2 ** 64) {

419:         } else if (optionRatios < 2 ** 112) {

421:         } else if (optionRatios < 2 ** 160) {

423:         } else if (optionRatios < 2 ** 208) {

424:             return 3;

426:         return 4;

444:             return self & 0xFFFFFFFFFFFF_FFFFFFFFFFFF_FFFFFFFFFFFF_000000000000_FFFFFFFFFFFFFFFF;

446:             return self & 0xFFFFFFFFFFFF_FFFFFFFFFFFF_000000000000_FFFFFFFFFFFF_FFFFFFFFFFFFFFFF;

448:             return self & 0xFFFFFFFFFFFF_000000000000_FFFFFFFFFFFF_FFFFFFFFFFFF_FFFFFFFFFFFFFFFF;

449:         if (i == 3)

450:             return self & 0x000000000000_FFFFFFFFFFFF_FFFFFFFFFFFF_FFFFFFFFFFFF_FFFFFFFFFFFFFFFF;

473:                     if ((self >> (64 + 48 * i)) != 0) revert Errors.InvalidTokenIdParameter(1);

473:                     if ((self >> (64 + 48 * i)) != 0) revert Errors.InvalidTokenIdParameter(1);

480:                 if ((self.width(i) == 0)) revert Errors.InvalidTokenIdParameter(5);

485:                 ) revert Errors.InvalidTokenIdParameter(4);

494:                         revert Errors.InvalidTokenIdParameter(3);

500:                     ) revert Errors.InvalidTokenIdParameter(3);

513:                         revert Errors.InvalidTokenIdParameter(4);

518:                         revert Errors.InvalidTokenIdParameter(5);

468:             for (uint256 i = 0; i < 4; ++i) {

GitHub : 95,95,105,105,105,115,115,115,125,125,125,141,141,141,151,151,151,162,162,162,162,195,195,210,210,210,226,226,226,240,240,240,254,254,254,268,268,268,283,283,283,283,337,339,341,343,346,344,353,353,363,417,419,421,423,424,426,444,446,448,449,450,473,473,480,485,494,500,513,518,468

[N-03] else-block not required

One level of nesting can be removed by not having an else block when the if-block returns, and if (foo) { return 1; } else { return 2; } becomes if (foo) { return 1; } return 2;. A following else if can become if

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

985                  if (startingLiquidity < chunkLiquidity) {
986                      // the amount we want to move (liquidityChunk.legLiquidity()) out of uniswap is greater than
987                      // what the account that owns the liquidity in uniswap has (startingLiquidity)
988                      // we must ensure that an account can only move its own liquidity out of uniswap
989                      // so we revert in this case
990                      revert Errors.NotEnoughLiquidity();
991                  } else {
992                      // we want to move less than what already sits in uniswap, no problem:
993                      updatedLiquidity = startingLiquidity - chunkLiquidity;
994:                 }

GitHub : 985

[N-04] if-statement can be converted to a ternary

The code can be made more compact while also increasing readability by converting the following if-statements to ternaries (e.g. foo += (x > y) ? a : b)

There are 1 instance(s) of this issue:

File: contracts/libraries/PanopticMath.sol

120          if (tokenId.asset(legIndex) == 0) {
121              legLiquidity = Math.getLiquidityForAmount0(
122                  uint256(0).addTickLower(tickLower).addTickUpper(tickUpper),
123                  amount
124              );
125          } else {
126              legLiquidity = Math.getLiquidityForAmount1(
127                  uint256(0).addTickLower(tickLower).addTickUpper(tickUpper),
128                  amount
129              );
130:         }

GitHub : 120

[N-05] 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 7 instance(s) of this issue:

File: contracts/libraries/FeesCalc.sol

54        function calculateAMMSwapFeesLiquidityChunk(
55            IUniswapV3Pool univ3pool,
56            int24 currentTick,
57            uint128 startingLiquidity,
58            uint256 liquidityChunk
59:       ) public view returns (int256 feesEachToken) {

GitHub : 54

File: contracts/multicall/Multicall.sol

12:       function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {

GitHub : 12

File: contracts/tokens/ERC1155Minimal.sol

77:       function setApprovalForAll(address operator, bool approved) public {

90        function safeTransferFrom(
91            address from,
92            address to,
93            uint256 id,
94            uint256 amount,
95:           bytes calldata data

128       function safeBatchTransferFrom(
129           address from,
130           address to,
131           uint256[] calldata ids,
132           uint256[] calldata amounts,
133:          bytes calldata data

178       function balanceOfBatch(
179           address[] calldata owners,
180           uint256[] calldata ids
181:      ) public view returns (uint256[] memory balances) {

200:      function supportsInterface(bytes4 interfaceId) public pure returns (bool) {

GitHub : 77,90,128,178,200

[N-06] require()/revert() statements should have descriptive reason strings

There are 6 instance(s) of this issue:

File: contracts/libraries/Math.sol

207:                 require(denominator > 0);

216:             require(denominator > prod1);

311:             require(2 ** 64 > prod1);

373:             require(2 ** 96 > prod1);

435:             require(2 ** 128 > prod1);

497:             require(2 ** 192 > prod1);

GitHub : 207,216,311,373,435,497

[N-07] Add inline comments for unnamed variables

function foo(address x, address) -> function foo(address x, address /* y */)

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

492           // Call a function that contains other functions to mint/burn position, collect amounts, swap if necessary
493:          (totalCollected, totalSwapped, newTick) = _validateAndForwardToAMM(

692           // initialize some variables returned by the _createPositionInAMM function
693           int256 itmAmounts;
694   
695           {
696               // calls a function that loops through each leg of tokenId and mints/burns liquidity in Uni v3 pool
697:              (totalMoved, totalCollectedFromAMM, itmAmounts) = _createPositionInAMM(

GitHub : 492,692

File: contracts/libraries/SafeTransferLib.sol

23                // Write the abi-encoded calldata into memory, beginning with the function selector.
24:               mstore(p, 0x23b872dd00000000000000000000000000000000000000000000000000000000)

GitHub : 23

[N-08] Adding a return statement when the function defines a named return variable, is redundant

Once the return variable has been assigned (or has its default value), there is no need to explicitly return it at the end of the function, since it's returned automatically.

There are 1 instance(s) of this issue:

File: contracts/libraries/Math.sol

211:                 return result;

GitHub : 211

[N-09] Assembly block creates dirty bits

Writing data to the free memory pointer without later updating the free memory pointer will cause there to be dirty bits at that memory location. Not updating the free memory pointer will make it harder for the optimizer to reason about whether the memory needs to be cleaned, which may lead to worse optimizations. Annotate the block with assembly ("memory-safe") { ... } if the memory's value can be discarded. If the memory needs to be saved, update the free memory pointer in addtion to using the annotation. See this link for other cases where the annotation can be used

There are 1 instance(s) of this issue:

File: contracts/libraries/SafeTransferLib.sol

18   
19           assembly ("memory-safe") {
20               // Get free memory pointer - we will store our calldata in scratch space starting at the offset specified here.
21               let p := mload(0x40)
22   
23               // Write the abi-encoded calldata into memory, beginning with the function selector.
24               mstore(p, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
25               mstore(add(4, p), from) // Append the "from" argument.
26               mstore(add(36, p), to) // Append the "to" argument.
27               mstore(add(68, p), amount) // Append the "amount" argument.
28   
29               success := and(
30                   // Set success to whether the call reverted, if not we check it either
31                   // returned exactly 1 (can't just be non-zero data), or had no return data.
32                   or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
33                   // We use 100 because that's the total length of our calldata (4 + 32 * 3)
34                   // Counterintuitively, this call() must be positioned after the or() in the
35                   // surrounding and() because and() evaluates its arguments from right to left.
36                   call(gas(), token, 0, p, 100, 0, 32)
37               )
38:          }

GitHub : 18

[N-10] Assembly blocks should have extensive comments

Assembly blocks take a lot more time to audit than normal Solidity code, and often have gotchas and side-effects that the Solidity versions of the same code do not. Consider adding more comments explaining what is being done in every step of the assembly code, and describe why assembly is being used instead of Solidity.

There are 21 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

393           assembly {
394               mstore(0, 0xFA20F71C)
395:          }

GitHub : 393

File: contracts/libraries/Math.sol

199               assembly ("memory-safe") {
200                   let mm := mulmod(a, b, not(0))
201                   prod0 := mul(a, b)
202                   prod1 := sub(sub(mm, prod0), lt(mm, prod0))
203:              }

208                   assembly ("memory-safe") {
209                       result := div(prod0, denominator)
210:                  }

225               assembly ("memory-safe") {
226                   remainder := mulmod(a, b, denominator)
227:              }

229               assembly ("memory-safe") {
230                   prod1 := sub(prod1, gt(remainder, prod0))
231                   prod0 := sub(prod0, remainder)
232:              }

239               assembly ("memory-safe") {
240                   denominator := div(denominator, twos)
241:              }

244               assembly ("memory-safe") {
245                   prod0 := div(prod0, twos)
246:              }

250               assembly ("memory-safe") {
251                   twos := add(div(sub(0, twos), twos), 1)
252:              }

295               assembly ("memory-safe") {
296                   let mm := mulmod(a, b, not(0))
297                   prod0 := mul(a, b)
298                   prod1 := sub(sub(mm, prod0), lt(mm, prod0))
299:              }

320               assembly ("memory-safe") {
321                   remainder := mulmod(a, b, 0x10000000000000000)
322:              }

324               assembly ("memory-safe") {
325                   prod1 := sub(prod1, gt(remainder, prod0))
326                   prod0 := sub(prod0, remainder)
327:              }

357               assembly ("memory-safe") {
358                   let mm := mulmod(a, b, not(0))
359                   prod0 := mul(a, b)
360                   prod1 := sub(sub(mm, prod0), lt(mm, prod0))
361:              }

382               assembly ("memory-safe") {
383                   remainder := mulmod(a, b, 0x1000000000000000000000000)
384:              }

386               assembly ("memory-safe") {
387                   prod1 := sub(prod1, gt(remainder, prod0))
388                   prod0 := sub(prod0, remainder)
389:              }

419               assembly ("memory-safe") {
420                   let mm := mulmod(a, b, not(0))
421                   prod0 := mul(a, b)
422                   prod1 := sub(sub(mm, prod0), lt(mm, prod0))
423:              }

444               assembly ("memory-safe") {
445                   remainder := mulmod(a, b, 0x100000000000000000000000000000000)
446:              }

448               assembly ("memory-safe") {
449                   prod1 := sub(prod1, gt(remainder, prod0))
450                   prod0 := sub(prod0, remainder)
451:              }

481               assembly ("memory-safe") {
482                   let mm := mulmod(a, b, not(0))
483                   prod0 := mul(a, b)
484                   prod1 := sub(sub(mm, prod0), lt(mm, prod0))
485:              }

506               assembly ("memory-safe") {
507                   remainder := mulmod(a, b, 0x1000000000000000000000000000000000000000000000000)
508:              }

510               assembly ("memory-safe") {
511                   prod1 := sub(prod1, gt(remainder, prod0))
512                   prod0 := sub(prod0, remainder)
513:              }

GitHub : 199,208,225,229,239,244,250,295,320,324,357,382,386,419,444,448,481,506,510

File: contracts/multicall/Multicall.sol

25                    assembly ("memory-safe") {
26                        revert(add(result, 32), mload(result))
27:                   }

GitHub : 25

[N-11] Complex casting

Consider whether the number of casts is really necessary, or whether using a different type would be more appropriate. Alternatively, add comments to explain in detail why the casts are necessary, and any implicit reasons why the cast does not introduce an overflow.

There are 25 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1119         feesBase = int256(0)
1120:            .toRightSlot(int128(int256(Math.mulDiv128(feeGrowthInside0LastX128, liquidity))))

1120             .toRightSlot(int128(int256(Math.mulDiv128(feeGrowthInside0LastX128, liquidity))))
1121:            .toLeftSlot(int128(int256(Math.mulDiv128(feeGrowthInside1LastX128, liquidity))));

1158         // from msg.sender to the uniswap pool, stored as negative value to represent amount debited
1159:        movedAmounts = int256(0).toRightSlot(int128(int256(amount0))).toLeftSlot(

1159         movedAmounts = int256(0).toRightSlot(int128(int256(amount0))).toLeftSlot(
1160:            int128(int256(amount1))

1185         unchecked {
1186:            movedAmounts = int256(0).toRightSlot(-int128(int256(amount0))).toLeftSlot(

1186             movedAmounts = int256(0).toRightSlot(-int128(int256(amount0))).toLeftSlot(
1187:                -int128(int256(amount1))

GitHub : 1119,1120,1158,1159,1185,1186

File: contracts/libraries/CallbackLib.sol

35           if (
36               address(
37                   uint160(
38                       uint256(
39                           keccak256(
40                               abi.encodePacked(
41                                   bytes1(0xff),
42                                   factory,
43                                   keccak256(abi.encode(features)),
44                                   Constants.V3POOL_INIT_CODE_HASH
45                               )
46                           )
47                       )
48                   )
49:              ) != sender

GitHub : 35

File: contracts/libraries/FeesCalc.sol

75           feesEachToken = feesEachToken
76:              .toRightSlot(int128(int256(Math.mulDiv128(ammFeesPerLiqToken0X128, startingLiquidity))))

76               .toRightSlot(int128(int256(Math.mulDiv128(ammFeesPerLiqToken0X128, startingLiquidity))))
77:              .toLeftSlot(int128(int256(Math.mulDiv128(ammFeesPerLiqToken1X128, startingLiquidity))));

GitHub : 75,76

File: contracts/libraries/Math.sol

39           unchecked {
40:              uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));

39           unchecked {
40:              uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));

40               uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
41:              if (absTick > uint256(int256(Constants.MAX_V3POOL_TICK))) revert Errors.InvalidTick();

GitHub : 39,39,40

File: contracts/libraries/PanopticMath.sol

38       function getPoolId(address univ3pool) internal pure returns (uint64) {
39:          return uint64(uint160(univ3pool) >> 96);

56                   basePoolId +
57:                  (uint64(uint256(keccak256(abi.encodePacked(token0, token1, fee)))) >> 32);

GitHub : 38,56

File: contracts/types/LeftRight.sol

56           unchecked {
57:              return self + uint256(int256(right));

66           unchecked {
67:              return self + int256(uint256(right));

119          unchecked {
120:             return self + (int256(int128(left)) << 128);

GitHub : 56,66,119

File: contracts/types/LiquidityChunk.sol

89           unchecked {
90:              return self + (uint256(uint24(_tickLower)) << 232);

100              // convert tick upper to uint24 as explicit conversion from int24 to uint256 is not allowed
101:             return self + ((uint256(uint24(_tickUpper))) << 208);

113          unchecked {
114:             return int24(int256(self >> 232));

122          unchecked {
123:             return int24(int256(self >> 208));

GitHub : 89,100,113,122

File: contracts/types/TokenId.sol

150          unchecked {
151:             return int24(int256(self >> (64 + legIndex * 48 + 12)));

161          unchecked {
162:             return int24(int256((self >> (64 + legIndex * 48 + 36)) % 4096));

267          unchecked {
268:             return self + uint256((int256(_strike) & BITMASK_INT24) << (64 + legIndex * 48 + 12));

282          unchecked {
283:             return self + (uint256(uint24(_width) % 4096) << (64 + legIndex * 48 + 36));

GitHub : 150,161,267,282

[N-12] Consider adding a block/deny-list

Doing so will significantly increase centralization, but will help to prevent hackers from using stolen tokens

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit ERC1155 handles tokens
72   contract SemiFungiblePositionManager is ERC1155, Multicall {
73       /*//////////////////////////////////////////////////////////////
74                                   EVENTS
75       //////////////////////////////////////////////////////////////*/
76   
77       /// @notice Emitted when a UniswapV3Pool is initialized.
78:      /// @param uniswapPool Address of the underlying Uniswap v3 pool

GitHub : 72

File: contracts/tokens/ERC1155Minimal.sol

/// @audit ERC1155 handles tokens
10   abstract contract ERC1155 {
11       /*//////////////////////////////////////////////////////////////
12                                    EVENTS
13       //////////////////////////////////////////////////////////////*/
14   
15       /// @notice Emitted when only a single token is transferred
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20:      /// @param amount the amount of tokens transferred

GitHub : 10

[N-13] Consider adding formal verification proofs

Consider using formal verification to mathematically prove that your code does what is intended, and does not have any edge cases with unexpected behavior. The solidity compiler itself has this functionality built in

There are 1 instance(s) of this issue:

File: Various Files

GitHub : various

[N-14] Consider bounding input array length

The functions below take in an unbounded array, and make function calls for entries in the array. While the function will revert if it eventually runs out of gas, it may be a nicer user experience to require() that the length of the array is below some reasonable maximum, so that the user doesn't have to use up a full transaction's gas only to see that the transaction reverts.

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

550          for (uint256 i = 0; i < ids.length; ) {
551              registerTokenTransfer(from, to, ids[i], amounts[i]);
552              unchecked {
553                  ++i;
554              }
555:         }

GitHub : 550

[N-15] Consider defining system-wide constants in a single file

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

127:     bool internal constant MINT = false;

128:     bool internal constant BURN = true;

135:     uint128 private constant VEGOID = 2;

GitHub : 127,128,135

[N-16] Consider making contracts Upgradeable

This allows for bugs to be fixed in production, at the expense of significantly increasing centralization.

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

72   contract SemiFungiblePositionManager is ERC1155, Multicall {
73       /*//////////////////////////////////////////////////////////////
74                                   EVENTS
75       //////////////////////////////////////////////////////////////*/
76   
77       /// @notice Emitted when a UniswapV3Pool is initialized.
78:      /// @param uniswapPool Address of the underlying Uniswap v3 pool

GitHub : 72

[N-17] Consider moving msg.sender checks to a common authorization modifier

There are 3 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

111              if (
112                  ERC1155Holder(to).onERC1155Received(msg.sender, from, id, amount, data) !=
113                  ERC1155Holder.onERC1155Received.selector
114              ) {
115                  revert UnsafeRecipient();
116:             }

164              if (
165                  ERC1155Holder(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) !=
166                  ERC1155Holder.onERC1155BatchReceived.selector
167              ) {
168                  revert UnsafeRecipient();
169:             }

223              if (
224                  ERC1155Holder(to).onERC1155Received(msg.sender, address(0), id, amount, "") !=
225                  ERC1155Holder.onERC1155Received.selector
226              ) {
227                  revert UnsafeRecipient();
228:             }

GitHub : 111,164,223

[N-18] Consider returning a struct rather than having multiple return values

There are 5 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

476      function burnTokenizedPosition(
477          uint256 tokenId,
478          uint128 positionSize,
479          int24 slippageTickLimitLow,
480          int24 slippageTickLimitHigh
481      )
482          external
483          ReentrancyLock(tokenId.univ3pool())
484          returns (int256 totalCollected, int256 totalSwapped, int24 newTick)
485:     {

510      function mintTokenizedPosition(
511          uint256 tokenId,
512          uint128 positionSize,
513          int24 slippageTickLimitLow,
514          int24 slippageTickLimitHigh
515      )
516          external
517          ReentrancyLock(tokenId.univ3pool())
518          returns (int256 totalCollected, int256 totalSwapped, int24 newTick)
519:     {

663      function _validateAndForwardToAMM(
664          uint256 tokenId,
665          uint128 positionSize,
666          int24 tickLimitLow,
667          int24 tickLimitHigh,
668          bool isBurn
669:     ) internal returns (int256 totalCollectedFromAMM, int256 totalMoved, int24 newTick) {

848      function _createPositionInAMM(
849          IUniswapV3Pool univ3pool,
850          uint256 tokenId,
851          uint128 positionSize,
852          bool isBurn
853:     ) internal returns (int256 totalMoved, int256 totalCollected, int256 itmAmounts) {

936      function _createLegInAMM(
937          IUniswapV3Pool _univ3pool,
938          uint256 _tokenId,
939          uint256 _leg,
940          uint256 _liquidityChunk,
941          bool _isBurn
942:     ) internal returns (int256 _moved, int256 _itmAmounts, int256 _totalCollected) {

GitHub : 476,510,663,848,936

[N-19] Consider splitting long calculations

The longer a string of operations is, the harder it is to understand it. Consider splitting the full calculation into more steps, with more descriptive temporary variable names, and add extensive comments.

There are 17 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1313                     uint256 numerator = totalLiquidity ** 2 -
1314                         totalLiquidity *
1315                         removedLiquidity +
1316:                        ((removedLiquidity ** 2) / 2 ** (VEGOID));

GitHub : 1313

File: contracts/libraries/Math.sol

89:              sqrtPriceX96 = uint160((sqrtR >> 32) + (sqrtR % (1 << 32) == 0 ? 0 : 1));

GitHub : 89

File: contracts/types/TokenId.sol

95:              return uint256((self >> (64 + legIndex * 48)) % 2);

105:             return uint256((self >> (64 + legIndex * 48 + 1)) % 128);

115:             return uint256((self >> (64 + legIndex * 48 + 8)) % 2);

125:             return uint256((self >> (64 + legIndex * 48 + 9)) % 2);

141:             return uint256((self >> (64 + legIndex * 48 + 10)) % 4);

151:             return int24(int256(self >> (64 + legIndex * 48 + 12)));

162:             return int24(int256((self >> (64 + legIndex * 48 + 36)) % 4096));

195:             return self + (uint256(_asset % 2) << (64 + legIndex * 48));

210:             return self + (uint256(_optionRatio % 128) << (64 + legIndex * 48 + 1));

226:             return self + ((_isLong % 2) << (64 + legIndex * 48 + 8));

240:             return self + (uint256(_tokenType % 2) << (64 + legIndex * 48 + 9));

254:             return self + (uint256(_riskPartner % 4) << (64 + legIndex * 48 + 10));

268:             return self + uint256((int256(_strike) & BITMASK_INT24) << (64 + legIndex * 48 + 12));

283:             return self + (uint256(uint24(_width) % 4096) << (64 + legIndex * 48 + 36));

353:             return self ^ ((LONG_MASK >> (48 * (4 - optionRatios))) & CLEAR_POOLID_MASK);

GitHub : 95,105,115,125,141,151,162,195,210,226,240,254,268,283,353

[N-20] Consider using delete rather than assigning zero/false 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 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

333:          s_poolContext[poolId].locked = false;

627:              s_accountLiquidity[positionKey_from] = 0;

630:              s_accountFeesBase[positionKey_from] = 0;

GitHub : 333,627,630

[N-21] Consider using a struct rather than having many function input parameters

There are 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1343     function getAccountLiquidity(
1344         address univ3pool,
1345         address owner,
1346         uint256 tokenType,
1347         int24 tickLower,
1348         int24 tickUpper
1349:    ) external view returns (uint256 accountLiquidities) {

1371     function getAccountPremium(
1372         address univ3pool,
1373         address owner,
1374         uint256 tokenType,
1375         int24 tickLower,
1376         int24 tickUpper,
1377         int24 atTick,
1378         uint256 isLong
1379:    ) external view returns (uint128 premiumToken0, uint128 premiumToken1) {

1437     function getAccountFeesBase(
1438         address univ3pool,
1439         address owner,
1440         uint256 tokenType,
1441         int24 tickLower,
1442         int24 tickUpper
1443:    ) external view returns (int128 feesBase0, int128 feesBase1) {

GitHub : 1343,1371,1437

File: contracts/tokens/ERC1155Minimal.sol

90       function safeTransferFrom(
91           address from,
92           address to,
93           uint256 id,
94           uint256 amount,
95           bytes calldata data
96:      ) public {

GitHub : 90

[N-22] Consider using descriptive constants when passing zero as a function argument

Passing zero as a function argument can sometimes result in a security issue (e.g. passing zero as the slippage parameter). Consider using a constant variable with a descriptive name, so it's clear that the argument is intentionally being used, and for the right reasons.

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1398:                    uint256 tempChunk = uint256(0).createChunk(tickLower, tickUpper, 0);

GitHub : 1398

File: contracts/types/TokenId.sol

363:             return self.isLong(0) + self.isLong(1) + self.isLong(2) + self.isLong(3);

464:         if (self.optionRatio(0) == 0) revert Errors.InvalidTokenIdParameter(1);

GitHub : 363,464

[N-23] Constants in comparisons should appear on the left side

Doing so will prevent typo bugs

There are 60 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

363:         if (s_AddrToPoolIdData[univ3pool] != 0) return;

615:                 (s_accountLiquidity[positionKey_to] != 0) ||

616:                 (s_accountFeesBase[positionKey_to] != 0)

671:         if (positionSize == 0) revert Errors.OptionsBalanceZero();

706:         if ((itmAmounts != 0) && (swapAtMint)) {

774:             if ((itm0 != 0) && (itm1 != 0)) {

774:             if ((itm0 != 0) && (itm1 != 0)) {

810:             } else if (itm0 != 0) {

820:             if (swapAmount == 0) return int256(0);

971:             if (isLong == 0) {

1031:            _moved = isLong == 0

1038:            if (_tokenType == 1) {

1043:            if (_tokenType == 0) {

1213:        if (isLong == 1) {

1217:        if (amountToCollect != 0) {

1385:        uint256 acctPremia = isLong == 1

1394:            if (netLiquidity != 0) {

1417:                acctPremia = isLong == 1

GitHub : 363,615,616,671,706,774,774,810,820,971,1031,1038,1043,1213,1217,1385,1394,1417

File: contracts/libraries/Math.sol

43:              uint256 sqrtR = absTick & 0x1 != 0

47:              if (absTick & 0x2 != 0) sqrtR = (sqrtR * 0xfff97272373d413259a46990580e213a) >> 128;

49:              if (absTick & 0x4 != 0) sqrtR = (sqrtR * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;

51:              if (absTick & 0x8 != 0) sqrtR = (sqrtR * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;

53:              if (absTick & 0x10 != 0) sqrtR = (sqrtR * 0xffcb9843d60f6159c9db58835c926644) >> 128;

55:              if (absTick & 0x20 != 0) sqrtR = (sqrtR * 0xff973b41fa98c081472e6896dfb254c0) >> 128;

57:              if (absTick & 0x40 != 0) sqrtR = (sqrtR * 0xff2ea16466c96a3843ec78b326b52861) >> 128;

59:              if (absTick & 0x80 != 0) sqrtR = (sqrtR * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;

61:              if (absTick & 0x100 != 0) sqrtR = (sqrtR * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;

63:              if (absTick & 0x200 != 0) sqrtR = (sqrtR * 0xf987a7253ac413176f2b074cf7815e54) >> 128;

65:              if (absTick & 0x400 != 0) sqrtR = (sqrtR * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;

67:              if (absTick & 0x800 != 0) sqrtR = (sqrtR * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;

69:              if (absTick & 0x1000 != 0) sqrtR = (sqrtR * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;

71:              if (absTick & 0x2000 != 0) sqrtR = (sqrtR * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;

73:              if (absTick & 0x4000 != 0) sqrtR = (sqrtR * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;

75:              if (absTick & 0x8000 != 0) sqrtR = (sqrtR * 0x31be135f97d08fd981231505542fcfa6) >> 128;

77:              if (absTick & 0x10000 != 0) sqrtR = (sqrtR * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;

79:              if (absTick & 0x20000 != 0) sqrtR = (sqrtR * 0x5d6af8dedb81196699c329225ee604) >> 128;

81:              if (absTick & 0x40000 != 0) sqrtR = (sqrtR * 0x2216e584f5fa1ea926041bedfe98) >> 128;

83:              if (absTick & 0x80000 != 0) sqrtR = (sqrtR * 0x48a170391f7dc42444e8fa2) >> 128;

89:              sqrtPriceX96 = uint160((sqrtR >> 32) + (sqrtR % (1 << 32) == 0 ? 0 : 1));

206:             if (prod1 == 0) {

302:             if (prod1 == 0) {

364:             if (prod1 == 0) {

426:             if (prod1 == 0) {

488:             if (prod1 == 0) {

GitHub : 43,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79,81,83,89,206,302,364,426,488

File: contracts/libraries/PanopticMath.sol

120:         if (tokenId.asset(legIndex) == 0) {

GitHub : 120

File: contracts/tokens/ERC1155Minimal.sol

110:         if (to.code.length != 0) {

163:         if (to.code.length != 0) {

202:             interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165

203:             interfaceId == 0xd9b67a26; // ERC165 Interface ID for ERC1155

222:         if (to.code.length != 0) {

GitHub : 110,163,202,203,222

File: contracts/types/TokenId.sol

397:                 legLowerTick % tickSpacing != 0 ||

398:                 legUpperTick % tickSpacing != 0 ||

443:         if (i == 0)

445:         if (i == 1)

447:         if (i == 2)

449:         if (i == 3)

464:         if (self.optionRatio(0) == 0) revert Errors.InvalidTokenIdParameter(1);

469:                 if (self.optionRatio(i) == 0) {

473:                     if ((self >> (64 + 48 * i)) != 0) revert Errors.InvalidTokenIdParameter(1);

480:                 if ((self.width(i) == 0)) revert Errors.InvalidTokenIdParameter(5);

GitHub : 397,398,443,445,447,449,464,469,473,480

[N-24] Contract should expose an interface

The contracts should expose an interface so that other projects can more easily integrate with it, without having to develop their own non-standard variants.

There are 16 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

351:     function initializeAMMPool(address token0, address token1, uint24 fee) external {

407      function uniswapV3MintCallback(
408          uint256 amount0Owed,
409          uint256 amount1Owed,
410          bytes calldata data
411:     ) external {

441      function uniswapV3SwapCallback(
442          int256 amount0Delta,
443          int256 amount1Delta,
444          bytes calldata data
445:     ) external {

476      function burnTokenizedPosition(
477          uint256 tokenId,
478          uint128 positionSize,
479          int24 slippageTickLimitLow,
480          int24 slippageTickLimitHigh
481      )
482          external
483          ReentrancyLock(tokenId.univ3pool())
484          returns (int256 totalCollected, int256 totalSwapped, int24 newTick)
485:     {

510      function mintTokenizedPosition(
511          uint256 tokenId,
512          uint128 positionSize,
513          int24 slippageTickLimitLow,
514          int24 slippageTickLimitHigh
515      )
516          external
517          ReentrancyLock(tokenId.univ3pool())
518          returns (int256 totalCollected, int256 totalSwapped, int24 newTick)
519:     {

1343     function getAccountLiquidity(
1344         address univ3pool,
1345         address owner,
1346         uint256 tokenType,
1347         int24 tickLower,
1348         int24 tickUpper
1349:    ) external view returns (uint256 accountLiquidities) {

1371     function getAccountPremium(
1372         address univ3pool,
1373         address owner,
1374         uint256 tokenType,
1375         int24 tickLower,
1376         int24 tickUpper,
1377         int24 atTick,
1378         uint256 isLong
1379:    ) external view returns (uint128 premiumToken0, uint128 premiumToken1) {

1437     function getAccountFeesBase(
1438         address univ3pool,
1439         address owner,
1440         uint256 tokenType,
1441         int24 tickLower,
1442         int24 tickUpper
1443:    ) external view returns (int128 feesBase0, int128 feesBase1) {

1457     function getUniswapV3PoolFromId(
1458         uint64 poolId
1459:    ) external view returns (IUniswapV3Pool UniswapV3Pool) {

1468:    function getPoolId(address univ3pool) external view returns (uint64 poolId) {

GitHub : 351,407,441,476,510,1343,1371,1437,1457,1468

File: contracts/multicall/Multicall.sol

12:      function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {

GitHub : 12

File: contracts/tokens/ERC1155Minimal.sol

77:      function setApprovalForAll(address operator, bool approved) public {

90       function safeTransferFrom(
91           address from,
92           address to,
93           uint256 id,
94           uint256 amount,
95           bytes calldata data
96:      ) public {

128      function safeBatchTransferFrom(
129          address from,
130          address to,
131          uint256[] calldata ids,
132          uint256[] calldata amounts,
133          bytes calldata data
134:     ) public virtual {

178      function balanceOfBatch(
179          address[] calldata owners,
180          uint256[] calldata ids
181:     ) public view returns (uint256[] memory balances) {

200:     function supportsInterface(bytes4 interfaceId) public pure returns (bool) {

GitHub : 77,90,128,178,200

[N-25] Contract uses both require()/revert() as well as custom errors

Consider using just one method in a single file

There are 1 instance(s) of this issue:

File: contracts/libraries/Math.sol

12:  library Math {

GitHub : 12

[N-26] 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 are 1 instance(s) of this issue:

File: Various Files

GitHub : various

[N-27] Critical system parameter changes should be behind a timelock

From the point of view of a user, the changing of the owner of a contract is a high risk operation that may have outcomes ranging from an attacker gaining control over the protocol, to the function no longer functioning due to a typo in the destination address. To give users plenty of warning so that they can validate any ownership or other critical parameter changes, these changes should be behind a timelock.

There are 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

77       function setApprovalForAll(address operator, bool approved) public {
78           isApprovedForAll[msg.sender][operator] = approved;
79   
80           emit ApprovalForAll(msg.sender, operator, approved);
81:      }

GitHub : 77

[N-28] Custom error has no error details

Consider adding parameters to the error to indicate which user or values caused the failure

There are 16 instance(s) of this issue:

File: contracts/libraries/Errors.sol

11:      error CastingError();

14:      error InvalidTick();

17:      error InvalidUniswapCallback();

24:      error LeftRightInputError();

27:      error NoLegsExercisable();

30:      error PositionTooLarge();

33:      error NotEnoughLiquidity();

36:      error OptionsBalanceZero();

39:      error PriceBoundFail();

42:      error ReentrantCall();

45:      error TransferFailed();

49:      error TicksNotInitializable();

52:      error UnderOverFlow();

55:      error UniswapPoolNotInitialized();

GitHub : 11,14,17,24,27,30,33,36,39,42,45,49,52,55

File: contracts/tokens/ERC1155Minimal.sol

51:      error NotAuthorized();

54:      error UnsafeRecipient();

GitHub : 51,54

[N-29] Custom errors should be used rather than revert()/require()

Custom errors are available from solidity version 0.8.4. Custom errors are more easily processed in try-catch blocks, and are easier to re-use and maintain.

There are 6 instance(s) of this issue:

File: contracts/libraries/Math.sol

207:                  require(denominator > 0);

216:              require(denominator > prod1);

311:              require(2 ** 64 > prod1);

373:              require(2 ** 96 > prod1);

435:              require(2 ** 128 > prod1);

497:              require(2 ** 192 > prod1);

GitHub : 207,216,311,373,435,497

[N-30] 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 2 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

135:          if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

GitHub : 135

File: contracts/types/LeftRight.sol

185:              if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

GitHub : 185

[N-31] Events are missing sender information

When an action is triggered based on a user's action, not being able to filter based on who triggered the action makes event processing a lot more cumbersome. Including the msg.sender the events of these types of action will make events much more useful to end users, especially when msg.sender is not tx.origin.

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

386:         emit PoolInitialized(univ3pool);

GitHub : 386

[N-32] 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 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

/// @audit setApprovalForAll()
80:           emit ApprovalForAll(msg.sender, operator, approved);

GitHub : 80

[N-33] Expressions for constant values should use immutable rather than constant

While it does not save gas for some simple binary expressions because the compiler knows that developers often make this mistake, it's still best to use the right tool for the task at hand. There is a difference between constant variables and immutable variables, and they should each be used in their appropriate contexts. constants should be used for literal values written into the code, and immutable variables should be used for expressions, or values calculated in, or passed into the constructor.

There are 2 instance(s) of this issue:

File: contracts/libraries/Constants.sol

11:      int24 internal constant MIN_V3POOL_TICK = -887272;

25       bytes32 internal constant V3POOL_INIT_CODE_HASH =
26           keccak256(
27               hex"6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000a"
28:          );

GitHub : 11,25

[N-34] High cyclomatic complexity

Consider breaking down these blocks into more manageable units, by splitting things into utility functions, by reducing nesting, and by using early returns

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

936      function _createLegInAMM(
937          IUniswapV3Pool _univ3pool,
938          uint256 _tokenId,
939          uint256 _leg,
940          uint256 _liquidityChunk,
941          bool _isBurn
942      ) internal returns (int256 _moved, int256 _itmAmounts, int256 _totalCollected) {
943          uint256 _tokenType = TokenId.tokenType(_tokenId, _leg);
944          // unique key to identify the liquidity chunk in this uniswap pool
945          bytes32 positionKey = keccak256(
946              abi.encodePacked(
947                  address(_univ3pool),
948                  msg.sender,
949                  _tokenType,
950                  _liquidityChunk.tickLower(),
951                  _liquidityChunk.tickUpper()
952              )
953          );
954  
955          // update our internal bookkeeping of how much liquidity we have deployed in the AMM
956          // for example: if this _leg is short, we add liquidity to the amm, make sure to add that to our tracking
957          uint128 updatedLiquidity;
958          uint256 isLong = TokenId.isLong(_tokenId, _leg);
959          uint256 currentLiquidity = s_accountLiquidity[positionKey]; //cache
960  
961          unchecked {
962              // did we have liquidity already deployed in Uniswap for this chunk range from some past mint?
963  
964              // s_accountLiquidity is a LeftRight. The right slot represents the liquidity currently sold (added) in the AMM owned by the user
965              // the left slot represents the amount of liquidity currently bought (removed) that has been removed from the AMM - the user owes it to a seller
966              // the reason why it is called "removedLiquidity" is because long options are created by removing -ie.short selling LP positions
967              uint128 startingLiquidity = currentLiquidity.rightSlot();
968              uint128 removedLiquidity = currentLiquidity.leftSlot();
969              uint128 chunkLiquidity = _liquidityChunk.liquidity();
970  
971              if (isLong == 0) {
972                  // selling/short: so move from msg.sender *to* uniswap
973                  // we're minting more liquidity in uniswap: so add the incoming liquidity chunk to the existing liquidity chunk
974                  updatedLiquidity = startingLiquidity + chunkLiquidity;
975  
976                  /// @dev If the isLong flag is 0=short but the position was burnt, then this is closing a long position
977                  /// @dev so the amount of short liquidity should decrease.
978                  if (_isBurn) {
979                      removedLiquidity -= chunkLiquidity;
980                  }
981              } else {
982                  // the _leg is long (buying: moving *from* uniswap to msg.sender)
983                  // so we seek to move the incoming liquidity chunk *out* of uniswap - but was there sufficient liquidity sitting in uniswap
984                  // in the first place?
985                  if (startingLiquidity < chunkLiquidity) {
986                      // the amount we want to move (liquidityChunk.legLiquidity()) out of uniswap is greater than
987                      // what the account that owns the liquidity in uniswap has (startingLiquidity)
988                      // we must ensure that an account can only move its own liquidity out of uniswap
989                      // so we revert in this case
990                      revert Errors.NotEnoughLiquidity();
991                  } else {
992                      // we want to move less than what already sits in uniswap, no problem:
993                      updatedLiquidity = startingLiquidity - chunkLiquidity;
994                  }
995  
996                  /// @dev If the isLong flag is 1=long and the position is minted, then this is opening a long position
997                  /// @dev so the amount of short liquidity should increase.
998                  if (!_isBurn) {
999                      removedLiquidity += chunkLiquidity;
1000                 }
1001             }
1002 
1003             // update the starting liquidity for this position for next time around
1004             s_accountLiquidity[positionKey] = uint256(0).toLeftSlot(removedLiquidity).toRightSlot(
1005                 updatedLiquidity
1006             );
1007         }
1008 
1009         // track how much liquidity we need to collect from uniswap
1010         // add the fees that accumulated in uniswap within the liquidityChunk:
1011         {
1012             /** if the position is NOT long (selling a put or a call), then _mintLiquidity to move liquidity
1013                 from the msg.sender to the uniswap v3 pool:
1014                 Selling(isLong=0): Mint chunk of liquidity in Uniswap (defined by upper tick, lower tick, and amount)
1015                        ┌─────────────────────────────────┐
1016                 ▲     ┌▼┐ liquidityChunk                 │
1017                 │  ┌──┴─┴──┐                         ┌───┴──┐
1018                 │  │       │                         │      │
1019                 └──┴───────┴──►                      └──────┘
1020                    Uniswap v3                      msg.sender
1021             
1022              else: the position is long (buying a put or a call), then _burnLiquidity to remove liquidity from univ3
1023                 Buying(isLong=1): Burn in Uniswap
1024                        ┌─────────────────┐
1025                 ▲     ┌┼┐                │
1026                 │  ┌──┴─┴──┐         ┌───▼──┐
1027                 │  │       │         │      │
1028                 └──┴───────┴──►      └──────┘
1029                     Uniswap v3      msg.sender 
1030             */
1031             _moved = isLong == 0
1032                 ? _mintLiquidity(_liquidityChunk, _univ3pool)
1033                 : _burnLiquidity(_liquidityChunk, _univ3pool); // from msg.sender to Uniswap
1034             // add the moved liquidity chunk to amount we need to collect from uniswap:
1035 
1036             // Is this _leg ITM?
1037             // if tokenType is 1, and we transacted some token0: then this leg is ITM!
1038             if (_tokenType == 1) {
1039                 // extract amount moved out of UniswapV3 pool
1040                 _itmAmounts = _itmAmounts.toRightSlot(_moved.rightSlot());
1041             }
1042             // if tokenType is 0, and we transacted some token1: then this leg is ITM
1043             if (_tokenType == 0) {
1044                 // Add this in-the-money amount transacted.
1045                 _itmAmounts = _itmAmounts.toLeftSlot(_moved.leftSlot());
1046             }
1047         }
1048 
1049         // if there was liquidity at that tick before the transaction, collect any accumulated fees
1050         if (currentLiquidity.rightSlot() > 0) {
1051             _totalCollected = _collectAndWritePositionData(
1052                 _liquidityChunk,
1053                 _univ3pool,
1054                 currentLiquidity,
1055                 positionKey,
1056                 _moved,
1057                 isLong
1058             );
1059         }
1060 
1061         // position has been touched, update s_accountFeesBase with the latest values from the pool.positions
1062         s_accountFeesBase[positionKey] = _getFeesBase(
1063             _univ3pool,
1064             updatedLiquidity,
1065             _liquidityChunk
1066         );
1067:    }

GitHub : 936

File: contracts/types/TokenId.sol

463      function validate(uint256 self) internal pure returns (uint64) {
464          if (self.optionRatio(0) == 0) revert Errors.InvalidTokenIdParameter(1);
465  
466          // loop through the 4 (possible) legs in the tokenId `self`
467          unchecked {
468              for (uint256 i = 0; i < 4; ++i) {
469                  if (self.optionRatio(i) == 0) {
470                      // final leg in this position identified;
471                      // make sure any leg above this are zero as well
472                      // (we don't allow gaps eg having legs 1 and 4 active without 2 and 3 is not allowed)
473                      if ((self >> (64 + 48 * i)) != 0) revert Errors.InvalidTokenIdParameter(1);
474  
475                      break; // we are done iterating over potential legs
476                  }
477                  // now validate this ith leg in the position:
478  
479                  // The width cannot be 0; the minimum is 1
480                  if ((self.width(i) == 0)) revert Errors.InvalidTokenIdParameter(5);
481                  // Strike cannot be MIN_TICK or MAX_TICK
482                  if (
483                      (self.strike(i) == Constants.MIN_V3POOL_TICK) ||
484                      (self.strike(i) == Constants.MAX_V3POOL_TICK)
485                  ) revert Errors.InvalidTokenIdParameter(4);
486  
487                  // In the following, we check whether the risk partner of this leg is itself
488                  // or another leg in this position.
489                  // Handles case where riskPartner(i) != i ==> leg i has a risk partner that is another leg
490                  uint256 riskPartnerIndex = self.riskPartner(i);
491                  if (riskPartnerIndex != i) {
492                      // Ensures that risk partners are mutual
493                      if (self.riskPartner(riskPartnerIndex) != i)
494                          revert Errors.InvalidTokenIdParameter(3);
495  
496                      // Ensures that risk partners have 1) the same asset, and 2) the same ratio
497                      if (
498                          (self.asset(riskPartnerIndex) != self.asset(i)) ||
499                          (self.optionRatio(riskPartnerIndex) != self.optionRatio(i))
500                      ) revert Errors.InvalidTokenIdParameter(3);
501  
502                      // long/short status of associated legs
503                      uint256 isLong = self.isLong(i);
504                      uint256 isLongP = self.isLong(riskPartnerIndex);
505  
506                      // token type status of associated legs (call/put)
507                      uint256 tokenType = self.tokenType(i);
508                      uint256 tokenTypeP = self.tokenType(riskPartnerIndex);
509  
510                      // if the position is the same i.e both long calls, short put's etc.
511                      // then this is a regular position, not a defined risk position
512                      if ((isLong == isLongP) && (tokenType == tokenTypeP))
513                          revert Errors.InvalidTokenIdParameter(4);
514  
515                      // if the two token long-types and the tokenTypes are both different (one is a short call, the other a long put, e.g.), this is a synthetic position
516                      // A synthetic long or short is more capital efficient than each leg separated because the long+short premia accumulate proportionally
517                      if ((isLong != isLongP) && (tokenType != tokenTypeP))
518                          revert Errors.InvalidTokenIdParameter(5);
519                  }
520              } // end for loop over legs
521          }
522  
523          return self.univ3pool();
524:     }

GitHub : 463

[N-35] Inconsistent method of specifying a floating pragma

Some files use >=, some use ^. The instances below are examples of the method that has the fewest instances for a specific version. Note that using >= without also specifying <= will lead to failures to compile, or external project incompatability, when the major version changes and there are breaking-changes, so ^ should be preferred regardless of the instance counts

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

2:    pragma solidity =0.8.18;

GitHub : 2

File: contracts/multicall/Multicall.sol

2:    pragma solidity =0.8.18;

GitHub : 2

[N-36] 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 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

593:              //construct the positionKey for the from and to addresses

625:              //update+store liquidity and fee values between accounts

808:                  //compute the swap amount, set as positive (exact input)

959:          uint256 currentLiquidity = s_accountLiquidity[positionKey]; //cache

GitHub : 593,625,808,959

[N-37] Invalid NatSpec comment style

NatSpec must begin with ///, or use the /** ... */ syntax. The compiler doesn't count // or /* ... */ as NatSpec

There are 7 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

359:          // @dev pools can be initialized from a Panoptic pool or by calling initializeAMMPool directly, reverting

361:          // @dev some pools may not be deployable if the poolId has a collision (since we take only 8 bytes)

366:          // @dev in the unlikely case that there is a collision between the first 8 bytes of two different Uni v3 pools

367:          // @dev increase the poolId by a pseudo-random number

585:              // @dev see `contracts/types/LiquidityChunk.sol`

823:              // @dev note this triggers our swap callback function

881:                  // @dev see `contracts/types/LiquidityChunk.sol`

GitHub : 359,361,366,367,585,823,881

[N-38] Large numeric literals should use underscores for readability

There are 8 instance(s) of this issue:

File: contracts/types/TokenId.sol

/// @audit 4096
162:             return int24(int256((self >> (64 + legIndex * 48 + 36)) % 4096));

GitHub : 162

File: contracts/libraries/Constants.sol

/// @audit 887272
11:      int24 internal constant MIN_V3POOL_TICK = -887272;

/// @audit 887272
14:      int24 internal constant MAX_V3POOL_TICK = 887272;

/// @audit 4295128739
17:      uint160 internal constant MIN_V3POOL_SQRT_RATIO = 4295128739;

/// @audit 1461446703485210103287273052203988822378723970342
20       uint160 internal constant MAX_V3POOL_SQRT_RATIO =
21:          1461446703485210103287273052203988822378723970342;

GitHub : 11,14,17,20

File: contracts/libraries/PanopticMath.sol

/// @audit 340275971719517849884101479065584693834
149:             if (sqrtPriceX96 < 340275971719517849884101479065584693834) {

/// @audit 340275971719517849884101479065584693834
172:             if (sqrtPriceX96 < 340275971719517849884101479065584693834) {

GitHub : 149,172

File: contracts/types/TokenId.sol

/// @audit 4096
283:             return self + (uint256(uint24(_width) % 4096) << (64 + legIndex * 48 + 36));

GitHub : 283

[N-39] Large or complicated code bases should implement invariant tests

Large code bases, or code with lots of inline-assembly, complicated math, or complicated interactions between multiple contracts, should implement invariant fuzzing tests. Invariant 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 invariant fuzzers, with properly and extensively-written invariants, can close this testing gap significantly.

There are 1 instance(s) of this issue:

File: Various Files

GitHub : various

[N-40] Libraries should be defined in separate files from their usage

The libraries below should be defined in separate files, so that it's easier for future projects to import them, and to avoid duplication later on if they need to be used elsewhere in the project

There are 3 instance(s) of this issue:

File: contracts/types/LeftRight.sol

13:  library LeftRight {

GitHub : 13

File: contracts/types/LiquidityChunk.sol

50:  library LiquidityChunk {

GitHub : 50

File: contracts/types/TokenId.sol

56:  library TokenId {

GitHub : 56

[N-41] Local variable shadows state variable

Note that this is not the same as shadowing, which is reported with a different compiler warning.

There are 2 instance(s) of this issue:

File: contracts/types/TokenId.sol

/// @audit TokenId.isLong()
503:                     uint256 isLong = self.isLong(i);

/// @audit TokenId.tokenType()
507:                     uint256 tokenType = self.tokenType(i);

GitHub : 503,507

[N-42] Long functions should be refactored into multiple, smaller, functions

There are 16 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit 58 lines (56 in the body)
578:      function registerTokenTransfer(address from, address to, uint256 id, uint256 amount) internal {

/// @audit 54 lines (46 in the body)
663       function _validateAndForwardToAMM(
664           uint256 tokenId,
665           uint128 positionSize,
666           int24 tickLimitLow,
667           int24 tickLimitHigh,
668           bool isBurn
669:      ) internal returns (int256 totalCollectedFromAMM, int256 totalMoved, int24 newTick) {

/// @audit 95 lines (90 in the body)
743       function swapInAMM(
744           IUniswapV3Pool univ3pool,
745           int256 itmAmounts
746:      ) internal returns (int256 totalSwapped) {

/// @audit 72 lines (65 in the body)
848       function _createPositionInAMM(
849           IUniswapV3Pool univ3pool,
850           uint256 tokenId,
851           uint128 positionSize,
852           bool isBurn
853:      ) internal returns (int256 totalMoved, int256 totalCollected, int256 itmAmounts) {

/// @audit 132 lines (124 in the body)
936       function _createLegInAMM(
937           IUniswapV3Pool _univ3pool,
938           uint256 _tokenId,
939           uint256 _leg,
940           uint256 _liquidityChunk,
941           bool _isBurn
942:      ) internal returns (int256 _moved, int256 _itmAmounts, int256 _totalCollected) {

/// @audit 75 lines (70 in the body)
1255      function _getPremiaDeltas(
1256          uint256 currentLiquidity,
1257          int256 collectedAmounts
1258:     ) private pure returns (uint256 deltaPremiumOwed, uint256 deltaPremiumGross) {

/// @audit 55 lines (45 in the body)
1371      function getAccountPremium(
1372          address univ3pool,
1373          address owner,
1374          uint256 tokenType,
1375          int24 tickLower,
1376          int24 tickUpper,
1377          int24 atTick,
1378          uint256 isLong
1379:     ) external view returns (uint128 premiumToken0, uint128 premiumToken1) {

GitHub : 578,663,743,848,936,1255,1371

File: contracts/libraries/FeesCalc.sol

/// @audit 79 lines (72 in the body)
89        function _getAMMSwapFeesPerLiquidityCollected(
90            IUniswapV3Pool univ3pool,
91            int24 currentTick,
92            int24 tickLower,
93            int24 tickUpper
94:       ) internal view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) {

GitHub : 89

File: contracts/libraries/Math.sol

/// @audit 54 lines (52 in the body)
38:       function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {

/// @audit 95 lines (89 in the body)
186       function mulDiv(
187           uint256 a,
188           uint256 b,
189           uint256 denominator
190:      ) internal pure returns (uint256 result) {

/// @audit 57 lines (55 in the body)
286:      function mulDiv64(uint256 a, uint256 b) internal pure returns (uint256 result) {

/// @audit 57 lines (55 in the body)
348:      function mulDiv96(uint256 a, uint256 b) internal pure returns (uint256 result) {

/// @audit 57 lines (55 in the body)
410:      function mulDiv128(uint256 a, uint256 b) internal pure returns (uint256 result) {

/// @audit 57 lines (55 in the body)
472:      function mulDiv192(uint256 a, uint256 b) internal pure returns (uint256 result) {

GitHub : 38,186,286,348,410,472

File: contracts/libraries/PanopticMath.sol

/// @audit 53 lines (46 in the body)
82        function getLiquidityChunk(
83            uint256 tokenId,
84            uint256 legIndex,
85            uint128 positionSize,
86            int24 tickSpacing
87:       ) internal pure returns (uint256 liquidityChunk) {

GitHub : 82

File: contracts/types/TokenId.sol

/// @audit 62 lines (60 in the body)
463:      function validate(uint256 self) internal pure returns (uint64) {

GitHub : 463

[N-43] Multiple address/ID mappings can be combined into a single mapping of an address/ID to a struct, for readability

Well-organized data structures make code reviews easier, which may lead to fewer bugs. Consider combining related mappings into mappings to structs, so it's clear what data is related. The instances below refer to both mappings using the same key in the same function, so the mappings are related.

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit combine: s_accountFeesBase,s_accountLiquidity
/// @audit combine: s_accountFeesBase,s_accountLiquidity,s_accountPremiumGross,s_accountPremiumOwed
/// @audit combine: s_accountPremiumGross,s_accountPremiumOwed
72   contract SemiFungiblePositionManager is ERC1155, Multicall {
73       /*//////////////////////////////////////////////////////////////
74                                   EVENTS
75       //////////////////////////////////////////////////////////////*/
76   
77       /// @notice Emitted when a UniswapV3Pool is initialized.
78:      /// @param uniswapPool Address of the underlying Uniswap v3 pool

GitHub : 72,72,72

[N-44] NatSpec: Contract declarations should have @dev tags

@dev is used to explain extra details to developers

There are 7 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

10   library CallbackLib {
11:      // Defining characteristics of a Uni V3 pool

GitHub : 10

File: contracts/libraries/Constants.sol

6    library Constants {
7:       // Fixed point multiplier: 2**96

GitHub : 6

File: contracts/libraries/Errors.sol

6    library Errors {
7        /// Errors are alphabetically ordered
8    
9        /// @notice Casting error
10:      /// @dev e.g. uint128(uint256(a)) fails

GitHub : 6

File: contracts/libraries/Math.sol

12:  library Math {

GitHub : 12

File: contracts/libraries/PanopticMath.sol

13   library PanopticMath {
14:      // enables packing of types within int128|int128 or uint128|uint128 containers.

GitHub : 13

File: contracts/tokens/ERC1155Minimal.sol

10   abstract contract ERC1155 {
11       /*//////////////////////////////////////////////////////////////
12                                    EVENTS
13       //////////////////////////////////////////////////////////////*/
14   
15       /// @notice Emitted when only a single token is transferred
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20:      /// @param amount the amount of tokens transferred

GitHub : 10

File: contracts/types/LeftRight.sol

13:  library LeftRight {

GitHub : 13

[N-45] NatSpec: Contract declarations should have @title tags

There are 1 instance(s) of this issue:

File: contracts/libraries/SafeTransferLib.sol

11   library SafeTransferLib {
12       /*//////////////////////////////////////////////////////////////
13                               ERC20 OPERATIONS
14       //////////////////////////////////////////////////////////////*/
15:  

GitHub : 11

[N-46] NatSpec: Error declarations should have descriptions

There are 2 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

51:      error NotAuthorized();

54:      error UnsafeRecipient();

GitHub : 51,54

[N-47] NatSpec: Event @param tag is missing

There are 20 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit Missing '@param uniswapPool'
69   /// @title Semi-Fungible Position Manager (ERC1155) - a gas-efficient Uniswap V3 position manager.
70   /// @notice Wraps Uniswap V3 positions with up to 4 legs behind an ERC1155 token.
71   /// @dev Replaces the NonfungiblePositionManager.sol (ERC721) from Uniswap Labs
72   contract SemiFungiblePositionManager is ERC1155, Multicall {
73       /*//////////////////////////////////////////////////////////////
74                                   EVENTS
75       //////////////////////////////////////////////////////////////*/
76   
77       /// @notice Emitted when a UniswapV3Pool is initialized.
78       /// @param uniswapPool Address of the underlying Uniswap v3 pool
79:      event PoolInitialized(address indexed uniswapPool);

/// @audit Missing '@param recipient'
77       /// @notice Emitted when a UniswapV3Pool is initialized.
78       /// @param uniswapPool Address of the underlying Uniswap v3 pool
79       event PoolInitialized(address indexed uniswapPool);
80   
81       /// @notice Emitted when a position is destroyed/burned
82       /// @dev Recipient is used to track whether it was burned directly by the user or through an option contract
83       /// @param recipient The address of the user who burned the position
84       /// @param tokenId The tokenId of the burned position
85       /// @param positionSize The number of contracts burnt, expressed in terms of the asset
86       event TokenizedPositionBurnt(
87:          address indexed recipient,

/// @audit Missing '@param tokenId'
78       /// @param uniswapPool Address of the underlying Uniswap v3 pool
79       event PoolInitialized(address indexed uniswapPool);
80   
81       /// @notice Emitted when a position is destroyed/burned
82       /// @dev Recipient is used to track whether it was burned directly by the user or through an option contract
83       /// @param recipient The address of the user who burned the position
84       /// @param tokenId The tokenId of the burned position
85       /// @param positionSize The number of contracts burnt, expressed in terms of the asset
86       event TokenizedPositionBurnt(
87           address indexed recipient,
88:          uint256 indexed tokenId,

/// @audit Missing '@param positionSize'
79       event PoolInitialized(address indexed uniswapPool);
80   
81       /// @notice Emitted when a position is destroyed/burned
82       /// @dev Recipient is used to track whether it was burned directly by the user or through an option contract
83       /// @param recipient The address of the user who burned the position
84       /// @param tokenId The tokenId of the burned position
85       /// @param positionSize The number of contracts burnt, expressed in terms of the asset
86       event TokenizedPositionBurnt(
87           address indexed recipient,
88           uint256 indexed tokenId,
89:          uint128 positionSize

/// @audit Missing '@param caller'
88           uint256 indexed tokenId,
89           uint128 positionSize
90       );
91   
92       /// @notice Emitted when a position is created/minted
93       /// @dev Recipient is used to track whether it was minted directly by the user or through an option contract
94       /// @param caller the caller who created the position. In 99% of cases `caller` == `recipient`.
95       /// @param tokenId The tokenId of the minted position
96       /// @param positionSize The number of contracts minted, expressed in terms of the asset
97       event TokenizedPositionMinted(
98:          address indexed caller,

/// @audit Missing '@param tokenId'
89           uint128 positionSize
90       );
91   
92       /// @notice Emitted when a position is created/minted
93       /// @dev Recipient is used to track whether it was minted directly by the user or through an option contract
94       /// @param caller the caller who created the position. In 99% of cases `caller` == `recipient`.
95       /// @param tokenId The tokenId of the minted position
96       /// @param positionSize The number of contracts minted, expressed in terms of the asset
97       event TokenizedPositionMinted(
98           address indexed caller,
99:          uint256 indexed tokenId,

/// @audit Missing '@param positionSize'
90       );
91   
92       /// @notice Emitted when a position is created/minted
93       /// @dev Recipient is used to track whether it was minted directly by the user or through an option contract
94       /// @param caller the caller who created the position. In 99% of cases `caller` == `recipient`.
95       /// @param tokenId The tokenId of the minted position
96       /// @param positionSize The number of contracts minted, expressed in terms of the asset
97       event TokenizedPositionMinted(
98           address indexed caller,
99           uint256 indexed tokenId,
100:         uint128 positionSize

GitHub : 69,77,78,79,88,89,90

File: contracts/tokens/ERC1155Minimal.sol

/// @audit Missing '@param operator'
12                                    EVENTS
13       //////////////////////////////////////////////////////////////*/
14   
15       /// @notice Emitted when only a single token is transferred
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20       /// @param amount the amount of tokens transferred
21       event TransferSingle(
22:          address indexed operator,

/// @audit Missing '@param from'
13       //////////////////////////////////////////////////////////////*/
14   
15       /// @notice Emitted when only a single token is transferred
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20       /// @param amount the amount of tokens transferred
21       event TransferSingle(
22           address indexed operator,
23:          address indexed from,

/// @audit Missing '@param to'
14   
15       /// @notice Emitted when only a single token is transferred
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20       /// @param amount the amount of tokens transferred
21       event TransferSingle(
22           address indexed operator,
23           address indexed from,
24:          address indexed to,

/// @audit Missing '@param id'
15       /// @notice Emitted when only a single token is transferred
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20       /// @param amount the amount of tokens transferred
21       event TransferSingle(
22           address indexed operator,
23           address indexed from,
24           address indexed to,
25:          uint256 id,

/// @audit Missing '@param amount'
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20       /// @param amount the amount of tokens transferred
21       event TransferSingle(
22           address indexed operator,
23           address indexed from,
24           address indexed to,
25           uint256 id,
26:          uint256 amount

/// @audit Missing '@param operator'
26           uint256 amount
27       );
28   
29       /// @notice Emitted when multiple tokens are transferred from one user to another
30       /// @param operator the user who initiated the transfer
31       /// @param from the user who sent the tokens
32       /// @param to the user who received the tokens
33       /// @param ids the ERC1155 token ids
34       /// @param amounts the amounts of tokens transferred
35       event TransferBatch(
36:          address indexed operator,

/// @audit Missing '@param from'
27       );
28   
29       /// @notice Emitted when multiple tokens are transferred from one user to another
30       /// @param operator the user who initiated the transfer
31       /// @param from the user who sent the tokens
32       /// @param to the user who received the tokens
33       /// @param ids the ERC1155 token ids
34       /// @param amounts the amounts of tokens transferred
35       event TransferBatch(
36           address indexed operator,
37:          address indexed from,

/// @audit Missing '@param to'
28   
29       /// @notice Emitted when multiple tokens are transferred from one user to another
30       /// @param operator the user who initiated the transfer
31       /// @param from the user who sent the tokens
32       /// @param to the user who received the tokens
33       /// @param ids the ERC1155 token ids
34       /// @param amounts the amounts of tokens transferred
35       event TransferBatch(
36           address indexed operator,
37           address indexed from,
38:          address indexed to,

/// @audit Missing '@param ids'
29       /// @notice Emitted when multiple tokens are transferred from one user to another
30       /// @param operator the user who initiated the transfer
31       /// @param from the user who sent the tokens
32       /// @param to the user who received the tokens
33       /// @param ids the ERC1155 token ids
34       /// @param amounts the amounts of tokens transferred
35       event TransferBatch(
36           address indexed operator,
37           address indexed from,
38           address indexed to,
39:          uint256[] ids,

/// @audit Missing '@param amounts'
30       /// @param operator the user who initiated the transfer
31       /// @param from the user who sent the tokens
32       /// @param to the user who received the tokens
33       /// @param ids the ERC1155 token ids
34       /// @param amounts the amounts of tokens transferred
35       event TransferBatch(
36           address indexed operator,
37           address indexed from,
38           address indexed to,
39           uint256[] ids,
40:          uint256[] amounts

/// @audit Missing '@param owner'
/// @audit Missing '@param operator'
/// @audit Missing '@param approved'
34       /// @param amounts the amounts of tokens transferred
35       event TransferBatch(
36           address indexed operator,
37           address indexed from,
38           address indexed to,
39           uint256[] ids,
40           uint256[] amounts
41       );
42   
43       /// @notice Emitted when an operator is approved to transfer all tokens on behalf of a user
44:      event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

GitHub : 12,13,14,15,16,26,27,28,29,30,34,34,34

[N-48] NatSpec: File is missing NatSpec

There are 1 instance(s) of this issue:

File: contracts/libraries/Constants.sol

GitHub : various

[N-49] NatSpec: Function @param tag is missing

There are 11 instance(s) of this issue:

File: contracts/libraries/SafeTransferLib.sol

/// @audit Missing '@param token'
/// @audit Missing '@param from'
/// @audit Missing '@param to'
/// @audit Missing '@param amount'
16:      function safeTransferFrom(address token, address from, address to, uint256 amount) internal {

GitHub : 16,16,16,16

File: contracts/types/TokenId.sol

/// @audit Missing '@param _poolId'
170      /// @notice Add the Uniswap v3 Pool pointed to by this option position.
171      /// @param self the option position Id.
172      /// @return the tokenId with the Uniswap V3 pool added to it.
173:     function addUniv3pool(uint256 self, uint64 _poolId) internal pure returns (uint256) {

/// @audit Missing '@param _asset'
183      /// @notice Add the asset basis for this position.
184      /// @param self the option position Id.
185      /// @param legIndex the leg index of this position (in {0,1,2,3})
186      /// @dev occupies the leftmost bit of the optionRatio 4 bits slot
187      /// @dev The final mod: "% 2" = takes the rightmost bit of the pattern
188      /// @return the tokenId with numerarire added to the incoming leg index
189      function addAsset(
190          uint256 self,
191:         uint256 _asset,

/// @audit Missing '@param _optionRatio'
199      /// @notice Add the number of contracts to leg index `legIndex`.
200      /// @param self the option position Id
201      /// @param legIndex the leg index of the position (in {0,1,2,3})
202      /// @dev The final mod: "% 128" = takes the rightmost (2 ** 7 = 128) 7 bits of the pattern.
203      /// @return the tokenId with optionRatio added to the incoming leg index
204      function addOptionRatio(
205          uint256 self,
206:         uint256 _optionRatio,

/// @audit Missing '@param _tokenType'
230      /// @notice Add the type of token moved for a given leg (implies a call or put). Either Token0 or Token1.
231      /// @param self the tokenId in the SFPM representing an option position
232      /// @param legIndex the leg index of this position (in {0,1,2,3})
233      /// @return the tokenId with tokenType added to its relevant leg.
234      function addTokenType(
235          uint256 self,
236:         uint256 _tokenType,

/// @audit Missing '@param _riskPartner'
244      /// @notice Add the associated risk partner of the leg index (generally another leg in the overall position).
245      /// @param self the tokenId in the SFPM representing an option position
246      /// @param legIndex the leg index of this position (in {0,1,2,3})
247      /// @return the tokenId with riskPartner added to its relevant leg.
248      function addRiskPartner(
249          uint256 self,
250:         uint256 _riskPartner,

/// @audit Missing '@param _strike'
258      /// @notice Add the strike price tick of the nth leg (index `legIndex`).
259      /// @param self the tokenId in the SFPM representing an option position.
260      /// @param legIndex the leg index of this position (in {0,1,2,3})
261      /// @return the tokenId with strike price tick added to its relevant leg
262      function addStrike(
263          uint256 self,
264:         int24 _strike,

/// @audit Missing '@param _width'
272      /// @notice Add the width of the nth leg (index `legIndex`). This is half the tick-range covered by the leg (tickUpper - tickLower)/2.
273      /// @param self the tokenId in the SFPM representing an option position.
274      /// @param legIndex the leg index of this position (in {0,1,2,3})
275      /// @return the tokenId with width added to its relevant leg
276      function addWidth(
277          uint256 self,
278:         int24 _width,

GitHub : 170,183,199,230,244,258,272

[N-50] NatSpec: Function @return tag is missing

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit Missing '@return feesBase'
1089     /// @notice Compute the feesGrowth * liquidity / 2**128 by reading feeGrowthInside0LastX128 and feeGrowthInside1LastX128 from univ3pool.positions.
1090     /// @param univ3pool the Uniswap pool.
1091     /// @param liquidity the total amount of liquidity in the AMM for the specific position
1092     /// @param liquidityChunk has lower tick, upper tick, and liquidity amount to mint
1093     function _getFeesBase(
1094         IUniswapV3Pool univ3pool,
1095         uint128 liquidity,
1096         uint256 liquidityChunk
1097:    ) private view returns (int256 feesBase) {

GitHub : 1089

File: contracts/types/TokenId.sol

/// @audit Missing '@return  '
99       /// @notice Get the number of contracts per leg.
100      /// @param self the option position Id.
101      /// @param legIndex the leg index of this position (in {0,1,2,3})
102      /// @dev The final mod: "% 2**7" = takes the rightmost (2 ** 7 = 128) 7 bits of the pattern.
103:     function optionRatio(uint256 self, uint256 legIndex) internal pure returns (uint256) {

/// @audit Missing '@return  '
322      /// @notice Flip all the `isLong` positions in the legs in the `tokenId` option position.
323      /// @dev uses XOR on existing isLong bits.
324      /// @dev useful during burning an option position. So we need to take an existing tokenId but now burn it.
325      /// The way to do this is to simply flip it to a short instead.
326      /// @param self the tokenId in the SFPM representing an option position.
327:     function flipToBurnToken(uint256 self) internal pure returns (uint256) {

GitHub : 99,322

[N-51] NatSpec: Non-public state variable declarations should use @dev tags

i.e. @dev tags. Note that since they're non-public, @notice is not the right tag to use.

There are 16 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

128:     bool internal constant BURN = true;

135:     uint128 private constant VEGOID = 2;

288:     mapping(bytes32 positionKey => uint256 accountPremium) private s_accountPremiumOwed;

290:     mapping(bytes32 positionKey => uint256 accountPremium) private s_accountPremiumGross;

GitHub : 128,135,288,290

File: contracts/libraries/Constants.sol

8:       uint256 internal constant FP96 = 0x1000000000000000000000000;

11:      int24 internal constant MIN_V3POOL_TICK = -887272;

14:      int24 internal constant MAX_V3POOL_TICK = 887272;

17:      uint160 internal constant MIN_V3POOL_SQRT_RATIO = 4295128739;

20       uint160 internal constant MAX_V3POOL_SQRT_RATIO =
21:          1461446703485210103287273052203988822378723970342;

25       bytes32 internal constant V3POOL_INIT_CODE_HASH =
26           keccak256(
27               hex"6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000a"
28:          );

GitHub : 8,11,14,17,20,25

File: contracts/types/LeftRight.sol

16:      int256 internal constant RIGHT_HALF_BIT_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

GitHub : 16

File: contracts/types/TokenId.sol

60       uint256 internal constant LONG_MASK =
61:          0x100_000000000100_000000000100_000000000100_0000000000000000;

63       uint256 internal constant CLEAR_POOLID_MASK =
64:          0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_0000000000000000;

66       uint256 internal constant OPTION_RATIO_MASK =
67:          0x0000000000FE_0000000000FE_0000000000FE_0000000000FE_0000000000000000;

68:      int256 internal constant BITMASK_INT24 = 0xFFFFFF;

71:      uint256 internal constant RISK_PARTNER_MASK = 0xFFFFFFFFF3FF;

GitHub : 60,63,66,68,71

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

Note that some file names may indicate an interface, but actually contain abstract contracts

There are 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

[N-53] Not using the named return variables anywhere in the function is confusing

Consider changing the variable to be an unnamed one, since the variable is never assigned, nor is it returned by name. If the optimizer is not turned on, leaving the code as it is will also waste gas for the stack variable.

There are 5 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit UniswapV3Pool
1457     function getUniswapV3PoolFromId(
1458         uint64 poolId
1459:    ) external view returns (IUniswapV3Pool UniswapV3Pool) {

GitHub : 1457

File: contracts/libraries/Math.sol

/// @audit amount0
101      function getAmount0ForLiquidity(
102          uint256 liquidityChunk
103:     ) internal pure returns (uint256 amount0) {

/// @audit amount1
119      function getAmount1ForLiquidity(
120          uint256 liquidityChunk
121:     ) internal pure returns (uint256 amount1) {

/// @audit liquidity
135      function getLiquidityForAmount0(
136          uint256 liquidityChunk,
137          uint256 amount0
138:     ) internal pure returns (uint128 liquidity) {

/// @audit liquidity
154      function getLiquidityForAmount1(
155          uint256 liquidityChunk,
156          uint256 amount1
157:     ) internal pure returns (uint128 liquidity) {

GitHub : 101,119,135,154

[N-54] Polymorphic functions make security audits more time-consuming and error-prone

The instances below point to one of two functions with the same name. Consider naming each function differently, in order to make code navigation and analysis easier.

There are 10 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

563      function afterTokenTransfer(
564          address from,
565          address to,
566          uint256 id,
567          uint256 amount
568:     ) internal override {

GitHub : 563

File: contracts/tokens/ERC1155Minimal.sol

265      function afterTokenTransfer(
266          address from,
267          address to,
268          uint256 id,
269          uint256 amount
270:     ) internal virtual;

GitHub : 265

File: contracts/types/LeftRight.sol

32:      function rightSlot(int256 self) internal pure returns (int128) {

54:      function toRightSlot(uint256 self, int128 right) internal pure returns (uint256) {

65:      function toRightSlot(int256 self, uint128 right) internal pure returns (int256) {

75:      function toRightSlot(int256 self, int128 right) internal pure returns (int256) {

96:      function leftSlot(int256 self) internal pure returns (int128) {

118:     function toLeftSlot(int256 self, uint128 left) internal pure returns (int256) {

128:     function toLeftSlot(int256 self, int128 left) internal pure returns (int256) {

159:     function add(int256 x, int256 y) internal pure returns (int256 z) {

GitHub : 32,54,65,75,96,118,128,159

[N-55] Setters should prevent re-setting of the same value

This especially problematic when the setter also emits the same value, which may be confusing to offline parsers

There are 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

/// @audit isApprovedForAll:  setApprovalForAll()
77       function setApprovalForAll(address operator, bool approved) public {
78           isApprovedForAll[msg.sender][operator] = approved;
79   
80           emit ApprovalForAll(msg.sender, operator, approved);
81:      }

GitHub : 77

[N-56] Style guide: Contract does not follow the Solidity style guide's suggested layout ordering

The style guide says that, within a contract, the ordering should be 1) Type declarations, 2) State variables, 3) Events, 4) Modifiers, and 5) Functions, but the contract(s) below do not follow this ordering

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit event TokenizedPositionMinted came earlier
127:      bool internal constant MINT = false;

GitHub : 127

File: contracts/tokens/ERC1155Minimal.sol

/// @audit event ApprovalForAll came earlier
62:       mapping(address account => mapping(uint256 tokenId => uint256 balance)) public balanceOf;

GitHub : 62

[N-57] Style guide: Control structures do not follow the Solidity Style Guide

See the control structures section of the Solidity Style Guide

There are 12 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

417           if (amount0Owed > 0)
418:              SafeTransferLib.safeTransferFrom(

424           if (amount1Owed > 0)
425:              SafeTransferLib.safeTransferFrom(

323:          if (s_poolContext[poolId].locked) revert Errors.ReentrantCall();

671:          if (positionSize == 0) revert Errors.OptionsBalanceZero();

GitHub : 417,424,323,671

File: contracts/libraries/SafeTransferLib.sol

40:           if (!success) revert Errors.TransferFailed();

GitHub : 40

File: contracts/types/LeftRight.sol

55:           if (right < 0) revert Errors.LeftRightInputError();

167:              if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

185:              if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

GitHub : 55,167,185

File: contracts/types/TokenId.sol

443           if (i == 0)
444:              return self & 0xFFFFFFFFFFFF_FFFFFFFFFFFF_FFFFFFFFFFFF_000000000000_FFFFFFFFFFFFFFFF;

445           if (i == 1)
446:              return self & 0xFFFFFFFFFFFF_FFFFFFFFFFFF_000000000000_FFFFFFFFFFFF_FFFFFFFFFFFFFFFF;

447           if (i == 2)
448:              return self & 0xFFFFFFFFFFFF_000000000000_FFFFFFFFFFFF_FFFFFFFFFFFF_FFFFFFFFFFFFFFFF;

449           if (i == 3)
450:              return self & 0x000000000000_FFFFFFFFFFFF_FFFFFFFFFFFF_FFFFFFFFFFFF_FFFFFFFFFFFFFFFF;

GitHub : 443,445,447,449

[N-58] Style guide: Function ordering does not follow the Solidity style guide

According to the Solidity style guide, functions should be laid out in the following order :constructor(), receive(), fallback(), external, public, internal, private, but the cases below do not follow this pattern

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit endReentrancyLock() came earlier
342:      constructor(IUniswapV3Factory _factory) {

/// @audit _getFeesBase() came earlier
1129      function _mintLiquidity(
1130          uint256 liquidityChunk,
1131          IUniswapV3Pool univ3pool
1132:     ) internal returns (int256 movedAmounts) {

/// @audit _getPremiaDeltas() came earlier
1343      function getAccountLiquidity(
1344          address univ3pool,
1345          address owner,
1346          uint256 tokenType,
1347          int24 tickLower,
1348          int24 tickUpper
1349:     ) external view returns (uint256 accountLiquidities) {

GitHub : 342,1129,1343

[N-59] Style guide: 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. The solidity style guide recommends a maximumum line length of 120 characters, so the lines below should be split when they reach that length.

There are 162 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

24:   //                       ,.                                   .,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.                                    ,,

25:   //                    ,,,,,,,                           ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,                            ,,,,,,

26:   //                  .,,,,,,,,,,.                   ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,                     ,,,,,,,,,,,

27:   //                .,,,,,,,,,,,,,,,             ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.              ,,,,,,,,,,,,,,,

28:   //               ,,,,,,,,,,,,,,.            ,,,,,,,,,,,,,,,,,,,,,,,,,,,                ,,,,,,,,,,,,,,,,,,,,,,,,,,.             ,,,,,,,,,,,,,,,

29:   //             ,,,,,,,,,,,,,,,           ,,,,,,,,,,,,,,,,,,,,,,                                ,,,,,,,,,,,,,,,,,,,,,,            ,,,,,,,,,,,,,,,

30:   //            ,,,,,,,,,,,,,.           ,,,,,,,,,,,,,,,,,,                                           .,,,,,,,,,,,,,,,,,,            ,,,,,,,,,,,,,,

31:   //          ,,,,,,,,,,,,,,          ,,,,,,,,,,,,,,,,,.                                                  ,,,,,,,,,,,,,,,,,           .,,,,,,,,,,,,,

32:   //         ,,,,,,,,,,,,,.         .,,,,,,,,,,,,,,,.                                                        ,,,,,,,,,,,,,,,,           ,,,,,,,,,,,,,.

33:   //        ,,,,,,,,,,,,,          ,,,,,,,,,,,,,,,                                                              ,,,,,,,,,,,,,,,           ,,,,,,,,,,,,,

34:   //       ,,,,,,,,,,,,,         ,,,,,,,,,,,,,,.                                                                  ,,,,,,,,,,,,,,           ,,,,,,,,,,,,,

35:   //      ,,,,,,,,,,,,,         ,,,,,,,,,,,,,,                                                                      ,,,,,,,,,,,,,,          ,,,,,,,,,,,,,

36:   //     ,,,,,,,,,,,,,         ,,,,,,,,,,,,,                                                                         ,,,,,,,,,,,,,,          ,,,,,,,,,,,,.

37:   //    .,,,,,,,,,,,,        .,,,,,,,,,,,,,                                                                            ,,,,,,,,,,,,,          ,,,,,,,,,,,,

38:   //    ,,,,,,,,,,,,         ,,,,,,,,,,,,                                                                               ,,,,,,,,,,,,,         .,,,,,,,,,,,,

39:   //   ,,,,,,,,,,,,         ,,,,,,,,,,,,                                                                                 ,,,,,,,,,,,,.         ,,,,,,,,,,,,

40:   //   ,,,,,,,,,,,,        ,,,,,,,,,,,,.                █████████  ███████████ ███████████  ██████   ██████               ,,,,,,,,,,,,          ,,,,,,,,,,,,

41:   //  .,,,,,,,,,,,,        ,,,,,,,,,,,,                ███░░░░░███░░███░░░░░░█░░███░░░░░███░░██████ ██████                .,,,,,,,,,,,,         ,,,,,,,,,,,,

42:   //  ,,,,,,,,,,,,        ,,,,,,,,,,,,                ░███    ░░░  ░███   █ ░  ░███    ░███ ░███░█████░███                 ,,,,,,,,,,,,         ,,,,,,,,,,,,.

43:   //  ,,,,,,,,,,,,        ,,,,,,,,,,,,                ░░█████████  ░███████    ░██████████  ░███░░███ ░███                 .,,,,,,,,,,,          ,,,,,,,,,,,.

44:   //  ,,,,,,,,,,,,        ,,,,,,,,,,,,                 ░░░░░░░░███ ░███░░░█    ░███░░░░░░   ░███ ░░░  ░███                  ,,,,,,,,,,,.         ,,,,,,,,,,,,

45:   //  ,,,,,,,,,,,,        ,,,,,,,,,,,,                 ███    ░███ ░███  ░     ░███         ░███      ░███                  ,,,,,,,,,,,,         ,,,,,,,,,,,,

46:   //  ,,,,,,,,,,,,        ,,,,,,,,,,,,                ░░█████████  █████       █████        █████     █████                 ,,,,,,,,,,,          ,,,,,,,,,,,,

47:   //  ,,,,,,,,,,,,        ,,,,,,,,,,,,                 ░░░░░░░░░  ░░░░░       ░░░░░        ░░░░░     ░░░░░                 ,,,,,,,,,,,,          ,,,,,,,,,,,.

48:   //  ,,,,,,,,,,,,        .,,,,,,,,,,,.                                                                                    ,,,,,,,,,,,,         ,,,,,,,,,,,,

49:   //  .,,,,,,,,,,,,        ,,,,,,,,,,,,                                                                                   .,,,,,,,,,,,,         ,,,,,,,,,,,,

50:   //   ,,,,,,,,,,,,        ,,,,,,,,,,,,,                                                                                  ,,,,,,,,,,,,          ,,,,,,,,,,,,

51:   //   ,,,,,,,,,,,,.        ,,,,,,,,,,,,.                                                                                ,,,,,,,,,,,,.         ,,,,,,,,,,,,

52:   //    ,,,,,,,,,,,,         ,,,,,,,,,,,,,                                                                              ,,,,,,,,,,,,,         .,,,,,,,,,,,,

53:   //     ,,,,,,,,,,,,         ,,,,,,,,,,,,,                                                                            ,,,,,,,,,,,,,         .,,,,,,,,,,,,

54:   //     .,,,,,,,,,,,,         ,,,,,,,,,,,,,                                                                         ,,,,,,,,,,,,,.          ,,,,,,,,,,,,

55:   //      ,,,,,,,,,,,,,         ,,,,,,,,,,,,,,                                                                     .,,,,,,,,,,,,,.          ,,,,,,,,,,,,

56:   //       ,,,,,,,,,,,,,         .,,,,,,,,,,,,,,                                                                 .,,,,,,,,,,,,,,          .,,,,,,,,,,,,

57:   //        ,,,,,,,,,,,,,          ,,,,,,,,,,,,,,,                                                             ,,,,,,,,,,,,,,,.          ,,,,,,,,,,,,,.

58:   //         ,,,,,,,,,,,,,,          ,,,,,,,,,,,,,,,,                                                       .,,,,,,,,,,,,,,,,           ,,,,,,,,,,,,,

59:   //          .,,,,,,,,,,,,,           ,,,,,,,,,,,,,,,,,                                                 .,,,,,,,,,,,,,,,,,           ,,,,,,,,,,,,,,

60:   //            ,,,,,,,,,,,,,,           ,,,,,,,,,,,,,,,,,,,.                                        ,,,,,,,,,,,,,,,,,,,.            ,,,,,,,,,,,,,,

61:   //             ,,,,,,,,,,,,,,,            ,,,,,,,,,,,,,,,,,,,,,,                             .,,,,,,,,,,,,,,,,,,,,,,             ,,,,,,,,,,,,,,

62:   //               ,,,,,,,,,,,,,,,            .,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.        ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,             .,,,,,,,,,,,,,,.

63:   //                 ,,,,,,,,,,,,,,.              ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,               ,,,,,,,,,,,,,,,

64:   //                   ,,,,,,,,,,                     ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,                     .,,,,,,,,,,

65:   //                     ,,,,,.                            ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,                             ,,,,,,

131:      // Similar to vega in options because the liquidity utilization is somewhat reflective of the implied volatility (IV),

134:      // The effect of vegoid on the long premium multiplier can be explored here: https://www.desmos.com/calculator/mdeqob2m04

175:      /// @dev mapping that stores the liquidity data of keccak256(abi.encodePacked(address poolAddress, address owner, int24 tickLower, int24 tickUpper))

176:      // liquidityData is a LeftRight. The right slot represents the liquidity currently sold (added) in the AMM owned by the user

177:      // the left slot represents the amount of liquidity currently bought (removed) that has been removed from the AMM - the user owes it to a seller

178:      // the reason why it is called "removedLiquidity" is because long options are created by removed liquidity -ie. short selling LP positions

292:      /// @dev mapping that stores a LeftRight packing of feesBase of  keccak256(abi.encodePacked(address poolAddress, address owner, int24 tickLower, int24 tickUpper))

293:      /// @dev Base fees is stored as int128((feeGrowthInside0LastX128 * liquidity) / 2**128), which allows us to store the accumulated fees as int128 instead of uint256

295:      /// feesBase represents the baseline fees collected by the position last time it was updated - this is recalculated every time the position is collected from with the new value

392:          // we need this because enabling `memoryguard` and therefore StackLimitEvader increases the size of the contract significantly beyond the size limit

471:      /// @param slippageTickLimitLow The lower price slippage limit when minting an ITM position (set to larger than slippageTickLimitHigh for swapping when minting)

472:      /// @param slippageTickLimitHigh The higher slippage limit when minting an ITM position (set to lower than slippageTickLimitLow for swapping when minting)

473:      /// @return totalCollected A LeftRight encoded word containing the total amount of token0 and token1 collected as fees

474:      /// @return totalSwapped A LeftRight encoded word containing the total amount of token0 and token1 swapped if minting ITM

505:      /// @param slippageTickLimitLow The lower price slippage limit when minting an ITM position (set to larger than slippageTickLimitHigh for swapping when minting)

506:      /// @param slippageTickLimitHigh The higher slippage limit when minting an ITM position (set to lower than slippageTickLimitLow for swapping when minting)

507:      /// @return totalCollected A LeftRight encoded word containing the total amount of token0 and token1 collected as fees

508:      /// @return totalSwapped A LeftRight encoded word containing the total amount of token0 and token1 swapped if minting ITM

573:      /// @dev token transfers are only allowed if you transfer your entire balance of a given tokenId and the recipient has none

584:              // for this leg index: extract the liquidity chunk: a 256bit word containing the liquidity amount and upper/lower tick

641:      /// @notice Helper that checks the proposed option position and size and forwards the minting and potential swapping tasks.

646:      /// @notice and then forwards the minting/burning/swapping to another internal helper functions which perform the AMM pool actions.

705:          // if the in-the-money amount is not zero (i.e. positions were minted ITM) and the user did provide tick limits LOW > HIGH, then swap necessary amounts

718:      /// @notice When a position is minted or burnt in-the-money (ITM) we are *not* 100% token0 or 100% token1: we have a mix of both tokens.

719:      /// @notice The swapping for ITM options is needed because only one of the tokens are "borrowed" by a user to create the position.

737:      ///   If we take token0 as an example, we deploy it to the AMM pool and *then* swap to get the right mix of token0 and token1

739:      ///   It that position is burnt, then we remove a mix of the two tokens and swap one of them so that the user receives only one.

771:              // note: upstream users of this function such as the Panoptic Pool should ensure users always compensate for the ITM amount delta

772:              // the netting swap is not perfectly accurate, and it is possible for swaps to run out of liquidity, so we do not want to rely on it

778:                  // note: negative ITM amounts denote a surplus of tokens (burning liquidity), while positive amounts denote a shortage of tokens (minting liquidity)

780:                  // we do this by flipping the signs on the token1 ITM amount converting+deducting it against the token0 ITM amount

875:                      // We loop in reverse order if burning a position so that any dependent long liquidity is returned to the pool first,

880:                  // for this _leg index: extract the liquidity chunk: a 256bit word containing the liquidity amount and upper/lower tick

898:                      // increment accumulators of the upper bound on tokens contained across all legs of the position at any given tick

914:          // Ensure upper bound on amount of tokens contained across all legs of the position on any given tick does not exceed a maximum of (2**127-1).

915:          // This is the maximum value of the `int128` type we frequently use to hold token amounts, so a given position's size should be guaranteed to

964:              // s_accountLiquidity is a LeftRight. The right slot represents the liquidity currently sold (added) in the AMM owned by the user

965:              // the left slot represents the amount of liquidity currently bought (removed) that has been removed from the AMM - the user owes it to a seller

966:              // the reason why it is called "removedLiquidity" is because long options are created by removing -ie.short selling LP positions

973:                  // we're minting more liquidity in uniswap: so add the incoming liquidity chunk to the existing liquidity chunk

983:                  // so we seek to move the incoming liquidity chunk *out* of uniswap - but was there sufficient liquidity sitting in uniswap

1089:     /// @notice Compute the feesGrowth * liquidity / 2**128 by reading feeGrowthInside0LastX128 and feeGrowthInside1LastX128 from univ3pool.positions.

1114:         /// @dev here we're converting the value to an int128 even though all values (feeGrowth, liquidity, Q128) are strictly positive.

1115:         /// That's because of the way feeGrowthInside works in Uniswap v3, where it can underflow when stored for the first time.

1116:         /// This is not a problem in Uniswap v3 because the fees are always calculated by taking the difference of the feeGrowths,

1118:         /// So by using int128 instead of uint128, we remove the need to handle extremely large underflows and simply allow it to be negative

1164:     /// @notice Burn a chunk of liquidity (`liquidityChunk`) in the Uniswap v3 pool and send to msg.sender; return the amount moved.

1192:     /// @notice Helper to collect amounts between msg.sender and Uniswap and also to update the Uniswap fees collected to date from the AMM.

1195:     /// @param currentLiquidity the existing liquidity msg.sender owns in the AMM for this chunk before the SFPM was called

1199:     /// @return collectedOut the incoming totalCollected with potentially whatever is collected in this function added to it

1219:             // Collect only if there was existing startingLiquidity=liquidities.rightSlot() at that position: collect all fees

1253:     /// @return deltaPremiumOwed The extra premium (per liquidity X64) to be added to the owed accumulator for token0 (right) and token1 (right)

1254:     /// @return deltaPremiumGross The extra premium (per liquidity X64) to be added to the gross accumulator for token0 (right) and token1 (right)

1264:         // explains how we get from the premium per liquidity (calculated here) to the total premia collected and the multiplier

1342:     /// @return accountLiquidities The amount of liquidity that has been shorted/added to the Uniswap contract (removedLiquidity:netLiquidity -> rightSlot:leftSlot)

1351:         /// @dev tokenType input here is the asset of the positions minted, this avoids put liquidity to be used for call, and vice-versa

1357:     /// @notice Return the premium associated with a given position, where Premium is an accumulator of feeGrowth for the touched position.

1358:     /// @dev Computes s_accountPremium{isLong ? Owed : Gross}[keccak256(abi.encodePacked(univ3pool, owner, tokenType, tickLower, tickUpper))]

1359:     /// @dev if an atTick parameter is provided that is different from type(int24).max, then it will update the premium up to the current

1360:     /// @dev block at the provided atTick value. We do this because this may be called immediately after the Uni v3 pool has been touched

1367:     /// @param atTick The current tick. Set atTick < type(int24).max = 8388608 to get latest premium up to the current block

1369:     /// @return premiumToken0 The amount of premium (per liquidity X64) for token0 = sum (feeGrowthLast0X128) over every block where the position has been touched

1370:     /// @return premiumToken1 The amount of premium (per liquidity X64) for token1 = sum (feeGrowthLast0X128) over every block where the position has been touched

1389:         // Compute the premium up to the current block (ie. after last touch until now). Do not proceed if atTick == type(int24).max = 8388608

1399:                     // how much fees have been accumulated within the liquidity chunk since last time we updated this chunk?

1401:                     // currentFeesGrowth (calculated from FeesCalc.calculateAMMSwapFeesLiquidityChunk) is (ammFeesCollectedPerLiquidity * liquidityChunk.liquidity())

1402:                     // oldFeesGrowth is the last stored update of fee growth within the position range in the past (feeGrowthRange*liquidityChunk.liquidity()) (s_accountFeesBase[positionKey])

GitHub : 24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,131,134,175,176,177,178,292,293,295,392,471,472,473,474,505,506,507,508,573,584,641,646,705,718,719,737,739,771,772,778,780,875,880,898,914,915,964,965,966,973,983,1089,1114,1115,1116,1118,1164,1192,1195,1199,1219,1253,1254,1264,1342,1351,1357,1358,1359,1360,1367,1369,1370,1389,1399,1401,1402

File: contracts/libraries/Constants.sol

27:               hex"6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000a"

GitHub : 27

File: contracts/libraries/Errors.sol

16:       /// @notice A mint or swap callback was attempted from an address that did not match the canonical Uniswap V3 pool with the claimed features

GitHub : 16

File: contracts/libraries/FeesCalc.sol

14:   /// @notice Some options positions involve moving liquidity chunks to the AMM/Uniswap. Those chunks can then earn AMM swap fees.

53:       /// @return feesEachToken the fees collected from the AMM for each token (LeftRight-packed) with token0 in the right slot and token1 in the left slot

96:           // lowerOut0: For token0: fee growth per unit of liquidity on the _other_ side of tickLower (relative to currentTick)

GitHub : 14,53,96

File: contracts/libraries/Math.sol

34:       /// @dev Implemented using Uniswap's "incorrect" constants. Supplying commented-out real values for an accurate calculation

180:      /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0.

282:      /// @notice Calculates floor(a×b÷2^64) with full precision. Throws if result overflows a uint256 or denominator == 0.

329:              // Divide [prod1 prod0] by the factors of two (note that this is just 2**96 since the denominator is a power of 2 itself)

344:      /// @notice Calculates floor(a×b÷2^96) with full precision. Throws if result overflows a uint256 or denominator == 0.

391:              // Divide [prod1 prod0] by the factors of two (note that this is just 2**96 since the denominator is a power of 2 itself)

406:      /// @notice Calculates floor(a×b÷2^128) with full precision. Throws if result overflows a uint256 or denominator == 0.

453:              // Divide [prod1 prod0] by the factors of two (note that this is just 2**128 since the denominator is a power of 2 itself)

468:      /// @notice Calculates floor(a×b÷2^192) with full precision. Throws if result overflows a uint256 or denominator == 0.

515:              // Divide [prod1 prod0] by the factors of two (note that this is just 2**96 since the denominator is a power of 2 itself)

GitHub : 34,180,282,329,344,391,406,453,468,515

File: contracts/libraries/PanopticMath.sol

28:       ///      the 64 bits are the 64 *last* (most significant) bits - and thus corresponds to the *first* 16 hex characters (reading left to right)

47:       /// @return finalPoolId the final 64-bit pool id as encoded in the `TokenId` type - composed of the last 64 bits of the address and a hash of the parameters

65:       /// @notice For a given option position (`tokenId`), leg index within that position (`legIndex`), and `positionSize` get the tick range spanned and its

81:       /// @return liquidityChunk a uint256 bit-packed (see `LiquidityChunk.sol`) with `tickLower`, `tickUpper`, and `liquidity`

104:          //  Because Uni v3 chooses token0 and token1 from the alphanumeric order, there is no consistency as to whether token0 is

105:          //  stablecoin, ETH, or an ERC20. Some pools may want ETH to be the asset (e.g. ETH-DAI) and some may wish the stablecoin to

109:          //  To solve this, we encode the asset value in tokenId. This parameter specifies which of token0 or token1 is the

140:      /// @notice Convert an amount of token0 into an amount of token1 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

163:      /// @notice Convert an amount of token0 into an amount of token1 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

GitHub : 28,47,65,81,104,105,109,140,163

File: contracts/libraries/SafeTransferLib.sol

20:               // Get free memory pointer - we will store our calldata in scratch space starting at the offset specified here.

GitHub : 20

File: contracts/multicall/Multicall.sol

22:                   // Other solutions will do work to differentiate the revert reasons and provide paranthetical information

24:                   // NOTE: memory-safe because it reads from memory already allocated by solidity (the bytes memory result)

GitHub : 22,24

File: contracts/types/LeftRight.sol

12:   /// @notice higher-order bits are cut off. For example: uint32 a = 0x12345678; uint16 b = uint16(a); // b will be 0x5678 now

37:       /// @dev Typically, the slot is already clear when writing to it, but if it is not, the bits will be added to the existing bits

101:      /// @dev Typically, the slot is already clear when writing to it, but if it is not, the bits will be added to the existing bits

GitHub : 12,37,101

File: contracts/types/LiquidityChunk.sol

7:    /// @title A Panoptic Liquidity Chunk. Tracks Tick Range and Liquidity Information for a "chunk." Used to track movement of chunks.

11:   ///   A liquidity chunk is an amount of `liquidity` (an amount of WETH, e.g.) deployed between two ticks: `tickLower` and `tickUpper`

GitHub : 7,11

File: contracts/types/TokenId.sol

13:   /// @notice our terminology: "leg n" or "nth leg" (in {1,2,3,4}) corresponds to "leg index n-1" or `legIndex` (in {0,1,2,3})

21:   /// (1) univ3pool        64bits     0bits      : first 8 bytes of the Uniswap v3 pool address (first 64 bits; little-endian), plus a pseudorandom number in the event of a collision

47:   ///   - if a leg is active (e.g. leg 1) there can be no gaps in other legs meaning: if leg 1 is active then leg 3 cannot be active if leg 2 is inactive.

51:   ///  We also refer to the legs via their index, so leg number 2 has leg index 1 (legIndex) (counting from zero), and in general leg number N has leg index N-1.

52:   ///  - the underlying strike price of the 2nd leg (leg index = 1) in this option position starts at bit index  (64 + 12 + 48 * (leg index=1))=123

62:       // This mask contains zero bits where the poolId is. It is used via & to strip the poolId section from a number, leaving the rest.

130:      /// @notice that returning the riskPartner for any leg is 0 by default, this does not necessarily imply that token 1 (index 0)

131:      /// @notice is the risk partner of that leg. We are assuming here that the position has been validated before this and that

132:      /// @notice the risk partner of any leg always makes sense in this way. A leg btw. does not need to have a risk partner.

133:      /// @notice the point here is that this function is very low level and must be used with utmost care because it comes down

155:      /// @notice Get the width of the nth leg (index `legIndex`). This is half the tick-range covered by the leg (tickUpper - tickLower)/2.

272:      /// @notice Add the width of the nth leg (index `legIndex`). This is half the tick-range covered by the leg (tickUpper - tickLower)/2.

330:              // We copy the logic from the countLegs function, using it here adds 5K to the contract size with IR for some reason

336:              // Since only the option ratios remain, we can be sure that no bits above the start of the inactive legs will be 1

351:              // i.e the whole mask is used to flip all legs with 4 legs, but only the first leg is flipped with 1 leg so we shift by 3 legs

352:              // We also clear the poolId area of the mask to ensure the bits that are shifted right into the area don't flip and cause issues

383:              // The max/min ticks that can be initialized are the closest multiple of tickSpacing to the actual max/min tick abs()=887272

408:      /// @dev ASSUMPTION: For any leg, the option ratio is always > 0 (the leg always has a number of contracts associated with it).

416:          // Since only the option ratios remain, we can be sure that no bits above the start of the inactive legs will be 1

515:                      // if the two token long-types and the tokenTypes are both different (one is a short call, the other a long put, e.g.), this is a synthetic position

516:                      // A synthetic long or short is more capital efficient than each leg separated because the long+short premia accumulate proportionally

GitHub : 13,21,47,51,52,62,130,131,132,133,155,272,330,336,351,352,383,408,416,515,516

[N-60] Style guide: Modifier names should use lowerCamelCase

According to the Solidity style guide modifier names should be in mixedCase (lowerCamelCase)

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

306      modifier ReentrancyLock(uint64 poolId) {
307          // check if the pool is already locked
308          // init lock if not
309          beginReentrancyLock(poolId);
310  
311          // execute function
312          _;
313  
314          // remove lock
315          endReentrancyLock(poolId);
316:     }

GitHub : 306

[N-61] Style guide: Non-external/public function names should begin with an underscore

According to the Solidity Style Guide, non-external/public function names should begin with an underscore

There are 8 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

321:     function beginReentrancyLock(uint64 poolId) internal {

331:     function endReentrancyLock(uint64 poolId) internal {

544      function afterTokenTransfer(
545          address from,
546          address to,
547          uint256[] memory ids,
548          uint256[] memory amounts
549:     ) internal override {

563      function afterTokenTransfer(
564          address from,
565          address to,
566          uint256 id,
567          uint256 amount
568:     ) internal override {

578:     function registerTokenTransfer(address from, address to, uint256 id, uint256 amount) internal {

743      function swapInAMM(
744          IUniswapV3Pool univ3pool,
745          int256 itmAmounts
746:     ) internal returns (int256 totalSwapped) {

GitHub : 321,331,544,563,578,743

File: contracts/tokens/ERC1155Minimal.sol

252      function afterTokenTransfer(
253          address from,
254          address to,
255          uint256[] memory ids,
256          uint256[] memory amounts
257:     ) internal virtual;

265      function afterTokenTransfer(
266          address from,
267          address to,
268          uint256 id,
269          uint256 amount
270:     ) internal virtual;

GitHub : 252,265

[N-62] Style guide: Non-external/public variable names should begin with an underscore

According to the Solidity Style Guide, non-external/public variable names should begin with an underscore

There are 22 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

127:     bool internal constant MINT = false;

128:     bool internal constant BURN = true;

135:     uint128 private constant VEGOID = 2;

139:     IUniswapV3Factory internal immutable FACTORY;

147:     mapping(address univ3pool => uint256 poolIdData) internal s_AddrToPoolIdData;

152:     mapping(uint64 poolId => PoolAddressAndLock contextData) internal s_poolContext;

179:     mapping(bytes32 positionKey => uint256 removedAndNetLiquidity) internal s_accountLiquidity;

288:     mapping(bytes32 positionKey => uint256 accountPremium) private s_accountPremiumOwed;

290:     mapping(bytes32 positionKey => uint256 accountPremium) private s_accountPremiumGross;

296:     mapping(bytes32 positionKey => int256 baseFees0And1) internal s_accountFeesBase;

GitHub : 127,128,135,139,147,152,179,288,290,296

File: contracts/libraries/Constants.sol

8:       uint256 internal constant FP96 = 0x1000000000000000000000000;

11:      int24 internal constant MIN_V3POOL_TICK = -887272;

14:      int24 internal constant MAX_V3POOL_TICK = 887272;

17:      uint160 internal constant MIN_V3POOL_SQRT_RATIO = 4295128739;

20       uint160 internal constant MAX_V3POOL_SQRT_RATIO =
21:          1461446703485210103287273052203988822378723970342;

25       bytes32 internal constant V3POOL_INIT_CODE_HASH =
26           keccak256(
27               hex"6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000a"
28:          );

GitHub : 8,11,14,17,20,25

File: contracts/types/LeftRight.sol

16:      int256 internal constant RIGHT_HALF_BIT_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

GitHub : 16

File: contracts/types/TokenId.sol

60       uint256 internal constant LONG_MASK =
61:          0x100_000000000100_000000000100_000000000100_0000000000000000;

63       uint256 internal constant CLEAR_POOLID_MASK =
64:          0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_0000000000000000;

66       uint256 internal constant OPTION_RATIO_MASK =
67:          0x0000000000FE_0000000000FE_0000000000FE_0000000000FE_0000000000000000;

68:      int256 internal constant BITMASK_INT24 = 0xFFFFFF;

71:      uint256 internal constant RISK_PARTNER_MASK = 0xFFFFFFFFF3FF;

GitHub : 60,63,66,68,71

[N-63] Typos

There are 8 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit postion
1069:     /// @notice caches/stores the accumulated premia values for the specified postion.

/// @audit seperated
1267:         // premia, and is only seperated to simplify the calculation

GitHub : 1069,1267

File: contracts/libraries/FeesCalc.sol

/// @audit sinlge
44:       // represents an option position of up to four legs as a sinlge ERC1155 tokenId

GitHub : 44

File: contracts/libraries/Math.sol

/// @audit precoditions
273:              // correct result modulo 2**256. Since the precoditions guarantee

GitHub : 273

File: contracts/libraries/PanopticMath.sol

/// @audit sinlge
19:       // represents an option position of up to four legs as a sinlge ERC1155 tokenId

GitHub : 19

File: contracts/multicall/Multicall.sol

/// @audit paranthetical
22:                   // Other solutions will do work to differentiate the revert reasons and provide paranthetical information

GitHub : 22

File: contracts/types/LeftRight.sol

/// @audit explictily
144:              // adding leftRight packed uint128's is same as just adding the values explictily

/// @audit occured
150:              // then an overflow has occured

GitHub : 144,150

[N-64] Unnecessary cast

The variable is being cast to its own type

There are 13 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit address
356:         if (address(univ3pool) == address(0)) revert Errors.UniswapPoolNotInitialized();

/// @audit address
453:             ? address(decoded.poolFeatures.token0)

/// @audit address
454:             : address(decoded.poolFeatures.token1);

/// @audit address
1381:            abi.encodePacked(address(univ3pool), owner, tokenType, tickLower, tickUpper)

GitHub : 356,453,454,1381

File: contracts/types/TokenId.sol

/// @audit uint256
95:              return uint256((self >> (64 + legIndex * 48)) % 2);

/// @audit uint256
105:             return uint256((self >> (64 + legIndex * 48 + 1)) % 128);

/// @audit uint256
115:             return uint256((self >> (64 + legIndex * 48 + 8)) % 2);

/// @audit uint256
125:             return uint256((self >> (64 + legIndex * 48 + 9)) % 2);

/// @audit uint256
141:             return uint256((self >> (64 + legIndex * 48 + 10)) % 4);

/// @audit uint256
195:             return self + (uint256(_asset % 2) << (64 + legIndex * 48));

/// @audit uint256
210:             return self + (uint256(_optionRatio % 128) << (64 + legIndex * 48 + 1));

/// @audit uint256
240:             return self + (uint256(_tokenType % 2) << (64 + legIndex * 48 + 9));

/// @audit uint256
254:             return self + (uint256(_riskPartner % 4) << (64 + legIndex * 48 + 10));

GitHub : 95,105,115,125,141,195,210,240,254

[N-65] Unsafe conversion from unsigned to signed values

Solidity follows two's complement rules for its integers, meaning that the most significant bit for signed integers is used to denote the sign, and converting between the two requires inverting all of the bits and adding one. Because of this, casting an unsigned integer to a signed one may result in a change of the sign and or magnitude of the value. For example, int8(type(uint8).max) is not equal to type(int8).max, but is equal to -1. type(uint8).max in binary is 11111111, which if cast to a signed value, means the first binary 1 indicates a negative value, and the binary 1s, invert to all zeroes, and when one is added, it becomes one, but negative, and therefore the decimal value of binary 11111111 is -1.

There are 6 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit uint256 amount1 -> int256
1160:             int128(int256(amount1))

/// @audit uint256 amount0 -> int256
1186:             movedAmounts = int256(0).toRightSlot(-int128(int256(amount0))).toLeftSlot(

/// @audit uint256 amount1 -> int256
1187:                 -int128(int256(amount1))

GitHub : 1160,1186,1187

File: contracts/types/LeftRight.sol

/// @audit int256 -> uint256
67:               return self + int256(uint256(right));

/// @audit uint128 left -> int128
120:              return self + (int256(int128(left)) << 128);

/// @audit uint256 self -> int256
214:          return int256(self);

GitHub : 67,120,214

[N-66] Unused error definition

Note that there may be cases where an error superficially appears to be used, but this is only because there are multiple definitions of the error in different files. In such cases, the error definition should be moved into a separate file. The instances below are the unused definitions.

There are 1 instance(s) of this issue:

File: contracts/libraries/Errors.sol

27:      error NoLegsExercisable();

GitHub : 27

[N-67] Unused contract variables

Note that there may be cases where a variable appears to be used, but this is only because there are multiple definitions of the varible in different files. In such cases, the variable definition should be moved into a separate file. The instances below are the unused variables.

There are 1 instance(s) of this issue:

File: contracts/types/TokenId.sol

71:      uint256 internal constant RISK_PARTNER_MASK = 0xFFFFFFFFF3FF;

GitHub : 71

[N-68] Unused import

The identifier is imported but never used within the file

There are 1 instance(s) of this issue:

File: contracts/types/LiquidityChunk.sol

/// @audit TokenId
5:   import {TokenId} from "@types/TokenId.sol";

GitHub : 5

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

There are 2 instance(s) of this issue:

File: contracts/libraries/Constants.sol

8:        uint256 internal constant FP96 = 0x1000000000000000000000000;

GitHub : 8

File: contracts/libraries/Math.sol

45:                   : 0x100000000000000000000000000000000;

GitHub : 45

[N-70] Use of override is unnecessary

Starting with Solidity version 0.8.8, using the override keyword when the function solely overrides an interface function, and the function doesn't exist in multiple base contracts, is unnecessary.

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

544      function afterTokenTransfer(
545          address from,
546          address to,
547          uint256[] memory ids,
548          uint256[] memory amounts
549:     ) internal override {

563      function afterTokenTransfer(
564          address from,
565          address to,
566          uint256 id,
567          uint256 amount
568:     ) internal override {

GitHub : 544,563

[N-71] Variables need not be initialized to false

The default value for boolean variables is false, so initializing them to false is superfluous.

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

127:     bool internal constant MINT = false;

GitHub : 127

[N-72] Variables need not be initialized to zero

The default value for variables is zero, so initializing them to zero is superfluous.

There are 7 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

550:         for (uint256 i = 0; i < ids.length; ) {

583:         for (uint256 leg = 0; leg < numLegs; ) {

860:         for (uint256 leg = 0; leg < numLegs; ) {

GitHub : 550,583,860

File: contracts/multicall/Multicall.sol

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

GitHub : 14

File: contracts/tokens/ERC1155Minimal.sol

141:         for (uint256 i = 0; i < ids.length; ) {

187:             for (uint256 i = 0; i < owners.length; ++i) {

GitHub : 141,187

File: contracts/types/TokenId.sol

468:             for (uint256 i = 0; i < 4; ++i) {

GitHub : 468

Disputed Risk Issues

[D-01] abi.encodePacked() should not be used with dynamic types when passing the result to a hash function such as keccak256()

These do not have consecutive dynamic typed arguments

There are 9 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

594              bytes32 positionKey_from = keccak256(
595                  abi.encodePacked(
596                      address(univ3pool),
597                      from,
598                      id.tokenType(leg),
599                      liquidityChunk.tickLower(),
600                      liquidityChunk.tickUpper()
601                  )
602:             );

603              bytes32 positionKey_to = keccak256(
604                  abi.encodePacked(
605                      address(univ3pool),
606                      to,
607                      id.tokenType(leg),
608                      liquidityChunk.tickLower(),
609                      liquidityChunk.tickUpper()
610                  )
611:             );

945          bytes32 positionKey = keccak256(
946              abi.encodePacked(
947                  address(_univ3pool),
948                  msg.sender,
949                  _tokenType,
950                  _liquidityChunk.tickLower(),
951                  _liquidityChunk.tickUpper()
952              )
953:         );

1104                 keccak256(
1105                     abi.encodePacked(
1106                         address(this),
1107                         liquidityChunk.tickLower(),
1108                         liquidityChunk.tickUpper()
1109                     )
1110:                )

1353:            keccak256(abi.encodePacked(univ3pool, owner, tokenType, tickLower, tickUpper))

1380         bytes32 positionKey = keccak256(
1381             abi.encodePacked(address(univ3pool), owner, tokenType, tickLower, tickUpper)
1382:        );

1446:            keccak256(abi.encodePacked(univ3pool, owner, tokenType, tickLower, tickUpper))

GitHub : 594,603,945,1104,1353,1380,1446

File: contracts/libraries/CallbackLib.sol

39                           keccak256(
40                               abi.encodePacked(
41                                   bytes1(0xff),
42                                   factory,
43                                   keccak256(abi.encode(features)),
44                                   Constants.V3POOL_INIT_CODE_HASH
45                               )
46:                          )

GitHub : 39

File: contracts/libraries/PanopticMath.sol

57:                  (uint64(uint256(keccak256(abi.encodePacked(token0, token1, fee)))) >> 32);

GitHub : 57

[D-02] else-block not required

Not a simple if-else

There are 3 instance(s) of this issue:

File: contracts/types/TokenId.sol

417          if (optionRatios < 2 ** 64) {
418              return 0;
419          } else if (optionRatios < 2 ** 112) {
420              return 1;
421          } else if (optionRatios < 2 ** 160) {
422              return 2;
423          } else if (optionRatios < 2 ** 208) {
424              return 3;
425:         }

419          } else if (optionRatios < 2 ** 112) {
420              return 1;
421          } else if (optionRatios < 2 ** 160) {
422              return 2;
423          } else if (optionRatios < 2 ** 208) {
424              return 3;
425:         }

421          } else if (optionRatios < 2 ** 160) {
422              return 2;
423          } else if (optionRatios < 2 ** 208) {
424              return 3;
425:         }

GitHub : 417,419,421

[D-03] if-statement can be converted to a ternary

Not a simple if-else

There are 1 instance(s) of this issue:

File: contracts/types/TokenId.sol

343              } else if (optionRatios < 2 ** 208) {
344                  optionRatios = 3;
345              } else {
346                  optionRatios = 4;
347:             }

GitHub : 343

[D-04] internal functions not called by the contract should be removed

These functions are referenced by other contracts other than the defining one

There are 48 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

28       function validateCallback(
29           address sender,
30           address factory,
31           PoolFeatures memory features
32:      ) internal pure {

GitHub : 28

File: contracts/libraries/Math.sol

23:      function absUint(int256 x) internal pure returns (uint256) {

101      function getAmount0ForLiquidity(
102          uint256 liquidityChunk
103:     ) internal pure returns (uint256 amount0) {

119      function getAmount1ForLiquidity(
120          uint256 liquidityChunk
121:     ) internal pure returns (uint256 amount1) {

135      function getLiquidityForAmount0(
136          uint256 liquidityChunk,
137          uint256 amount0
138:     ) internal pure returns (uint128 liquidity) {

154      function getLiquidityForAmount1(
155          uint256 liquidityChunk,
156          uint256 amount1
157:     ) internal pure returns (uint128 liquidity) {

186      function mulDiv(
187          uint256 a,
188          uint256 b,
189          uint256 denominator
190:     ) internal pure returns (uint256 result) {

286:     function mulDiv64(uint256 a, uint256 b) internal pure returns (uint256 result) {

410:     function mulDiv128(uint256 a, uint256 b) internal pure returns (uint256 result) {

472:     function mulDiv192(uint256 a, uint256 b) internal pure returns (uint256 result) {

GitHub : 23,101,119,135,154,186,286,410,472

File: contracts/libraries/PanopticMath.sol

38:      function getPoolId(address univ3pool) internal pure returns (uint64) {

48       function getFinalPoolId(
49           uint64 basePoolId,
50           address token0,
51           address token1,
52           uint24 fee
53:      ) internal pure returns (uint64) {

82       function getLiquidityChunk(
83           uint256 tokenId,
84           uint256 legIndex,
85           uint128 positionSize,
86           int24 tickSpacing
87:      ) internal pure returns (uint256 liquidityChunk) {

168:     function convert1to0(int256 amount, uint160 sqrtPriceX96) internal pure returns (int256) {

GitHub : 38,48,82,168

File: contracts/libraries/SafeTransferLib.sol

16:      function safeTransferFrom(address token, address from, address to, uint256 amount) internal {

GitHub : 16

File: contracts/tokens/ERC1155Minimal.sol

214:     function _mint(address to, uint256 id, uint256 amount) internal {

236:     function _burn(address from, uint256 id, uint256 amount) internal {

GitHub : 214,236

File: contracts/types/LeftRight.sol

25:      function rightSlot(uint256 self) internal pure returns (uint128) {

32:      function rightSlot(int256 self) internal pure returns (int128) {

44:      function toRightSlot(uint256 self, uint128 right) internal pure returns (uint256) {

65:      function toRightSlot(int256 self, uint128 right) internal pure returns (int256) {

75:      function toRightSlot(int256 self, int128 right) internal pure returns (int256) {

89:      function leftSlot(uint256 self) internal pure returns (uint128) {

96:      function leftSlot(int256 self) internal pure returns (int128) {

108:     function toLeftSlot(uint256 self, uint128 left) internal pure returns (uint256) {

118:     function toLeftSlot(int256 self, uint128 left) internal pure returns (int256) {

128:     function toLeftSlot(int256 self, int128 left) internal pure returns (int256) {

142:     function add(uint256 x, uint256 y) internal pure returns (uint256 z) {

159:     function add(int256 x, int256 y) internal pure returns (int256 z) {

177:     function sub(int256 x, int256 y) internal pure returns (int256 z) {

198:     function toInt128(int256 self) internal pure returns (int128 selfAsInt128) {

205:     function toUint128(uint256 self) internal pure returns (uint128 selfAsUint128) {

212:     function toInt256(uint256 self) internal pure returns (int256) {

GitHub : 25,32,44,65,75,89,96,108,118,128,142,159,177,198,205,212

File: contracts/types/LiquidityChunk.sol

63       function createChunk(
64           uint256 self,
65           int24 _tickLower,
66           int24 _tickUpper,
67           uint128 amount
68:      ) internal pure returns (uint256) {

88:      function addTickLower(uint256 self, int24 _tickLower) internal pure returns (uint256) {

98:      function addTickUpper(uint256 self, int24 _tickUpper) internal pure returns (uint256) {

112:     function tickLower(uint256 self) internal pure returns (int24) {

121:     function tickUpper(uint256 self) internal pure returns (int24) {

130:     function liquidity(uint256 self) internal pure returns (uint128) {

GitHub : 63,88,98,112,121,130

File: contracts/types/TokenId.sol

80:      function univ3pool(uint256 self) internal pure returns (uint64) {

93:      function asset(uint256 self, uint256 legIndex) internal pure returns (uint256) {

103:     function optionRatio(uint256 self, uint256 legIndex) internal pure returns (uint256) {

113:     function isLong(uint256 self, uint256 legIndex) internal pure returns (uint256) {

123:     function tokenType(uint256 self, uint256 legIndex) internal pure returns (uint256) {

327:     function flipToBurnToken(uint256 self) internal pure returns (uint256) {

374      function asTicks(
375          uint256 self,
376          uint256 legIndex,
377          int24 tickSpacing
378:     ) internal pure returns (int24 legLowerTick, int24 legUpperTick) {

410:     function countLegs(uint256 self) internal pure returns (uint256) {

463:     function validate(uint256 self) internal pure returns (uint64) {

GitHub : 80,93,103,113,123,327,374,410,463

[D-05] internal functions not called by the contract should be removed

These are required to exist, and override parent contracts' functions

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

544      function afterTokenTransfer(
545          address from,
546          address to,
547          uint256[] memory ids,
548          uint256[] memory amounts
549:     ) internal override {

563      function afterTokenTransfer(
564          address from,
565          address to,
566          uint256 id,
567          uint256 amount
568:     ) internal override {

GitHub : 544,563

[D-06] internal functions not called by the contract should be removed

The function is in fact used

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

544      function afterTokenTransfer(
545          address from,
546          address to,
547          uint256[] memory ids,
548          uint256[] memory amounts
549:     ) internal override {

563      function afterTokenTransfer(
564          address from,
565          address to,
566          uint256 id,
567          uint256 amount
568:     ) internal override {

GitHub : 544,563

[D-07] internal functions not called by the contract should be removed

The function is in fact used

There are 50 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

28       function validateCallback(
29           address sender,
30           address factory,
31           PoolFeatures memory features
32:      ) internal pure {

GitHub : 28

File: contracts/libraries/Math.sol

23:      function absUint(int256 x) internal pure returns (uint256) {

101      function getAmount0ForLiquidity(
102          uint256 liquidityChunk
103:     ) internal pure returns (uint256 amount0) {

119      function getAmount1ForLiquidity(
120          uint256 liquidityChunk
121:     ) internal pure returns (uint256 amount1) {

135      function getLiquidityForAmount0(
136          uint256 liquidityChunk,
137          uint256 amount0
138:     ) internal pure returns (uint128 liquidity) {

154      function getLiquidityForAmount1(
155          uint256 liquidityChunk,
156          uint256 amount1
157:     ) internal pure returns (uint128 liquidity) {

186      function mulDiv(
187          uint256 a,
188          uint256 b,
189          uint256 denominator
190:     ) internal pure returns (uint256 result) {

286:     function mulDiv64(uint256 a, uint256 b) internal pure returns (uint256 result) {

410:     function mulDiv128(uint256 a, uint256 b) internal pure returns (uint256 result) {

472:     function mulDiv192(uint256 a, uint256 b) internal pure returns (uint256 result) {

GitHub : 23,101,119,135,154,186,286,410,472

File: contracts/libraries/PanopticMath.sol

38:      function getPoolId(address univ3pool) internal pure returns (uint64) {

48       function getFinalPoolId(
49           uint64 basePoolId,
50           address token0,
51           address token1,
52           uint24 fee
53:      ) internal pure returns (uint64) {

82       function getLiquidityChunk(
83           uint256 tokenId,
84           uint256 legIndex,
85           uint128 positionSize,
86           int24 tickSpacing
87:      ) internal pure returns (uint256 liquidityChunk) {

168:     function convert1to0(int256 amount, uint160 sqrtPriceX96) internal pure returns (int256) {

GitHub : 38,48,82,168

File: contracts/libraries/SafeTransferLib.sol

16:      function safeTransferFrom(address token, address from, address to, uint256 amount) internal {

GitHub : 16

File: contracts/types/LeftRight.sol

25:      function rightSlot(uint256 self) internal pure returns (uint128) {

32:      function rightSlot(int256 self) internal pure returns (int128) {

44:      function toRightSlot(uint256 self, uint128 right) internal pure returns (uint256) {

65:      function toRightSlot(int256 self, uint128 right) internal pure returns (int256) {

75:      function toRightSlot(int256 self, int128 right) internal pure returns (int256) {

89:      function leftSlot(uint256 self) internal pure returns (uint128) {

96:      function leftSlot(int256 self) internal pure returns (int128) {

108:     function toLeftSlot(uint256 self, uint128 left) internal pure returns (uint256) {

118:     function toLeftSlot(int256 self, uint128 left) internal pure returns (int256) {

128:     function toLeftSlot(int256 self, int128 left) internal pure returns (int256) {

142:     function add(uint256 x, uint256 y) internal pure returns (uint256 z) {

159:     function add(int256 x, int256 y) internal pure returns (int256 z) {

177:     function sub(int256 x, int256 y) internal pure returns (int256 z) {

198:     function toInt128(int256 self) internal pure returns (int128 selfAsInt128) {

205:     function toUint128(uint256 self) internal pure returns (uint128 selfAsUint128) {

212:     function toInt256(uint256 self) internal pure returns (int256) {

GitHub : 25,32,44,65,75,89,96,108,118,128,142,159,177,198,205,212

File: contracts/types/LiquidityChunk.sol

63       function createChunk(
64           uint256 self,
65           int24 _tickLower,
66           int24 _tickUpper,
67           uint128 amount
68:      ) internal pure returns (uint256) {

78:      function addLiquidity(uint256 self, uint128 amount) internal pure returns (uint256) {

88:      function addTickLower(uint256 self, int24 _tickLower) internal pure returns (uint256) {

98:      function addTickUpper(uint256 self, int24 _tickUpper) internal pure returns (uint256) {

112:     function tickLower(uint256 self) internal pure returns (int24) {

121:     function tickUpper(uint256 self) internal pure returns (int24) {

130:     function liquidity(uint256 self) internal pure returns (uint128) {

GitHub : 63,78,88,98,112,121,130

File: contracts/types/TokenId.sol

80:      function univ3pool(uint256 self) internal pure returns (uint64) {

93:      function asset(uint256 self, uint256 legIndex) internal pure returns (uint256) {

103:     function optionRatio(uint256 self, uint256 legIndex) internal pure returns (uint256) {

113:     function isLong(uint256 self, uint256 legIndex) internal pure returns (uint256) {

123:     function tokenType(uint256 self, uint256 legIndex) internal pure returns (uint256) {

139:     function riskPartner(uint256 self, uint256 legIndex) internal pure returns (uint256) {

149:     function strike(uint256 self, uint256 legIndex) internal pure returns (int24) {

160:     function width(uint256 self, uint256 legIndex) internal pure returns (int24) {

327:     function flipToBurnToken(uint256 self) internal pure returns (uint256) {

374      function asTicks(
375          uint256 self,
376          uint256 legIndex,
377          int24 tickSpacing
378:     ) internal pure returns (int24 legLowerTick, int24 legUpperTick) {

410:     function countLegs(uint256 self) internal pure returns (uint256) {

463:     function validate(uint256 self) internal pure returns (uint64) {

GitHub : 80,93,103,113,123,139,149,160,327,374,410,463

[D-08] keccak256() should only need to be called on a specific string literal once

This was fixed as of 0.6.12: Code Generator: Evaluate keccak256 of string literals at compile-time. so no gas is saved

There are 1 instance(s) of this issue:

File: contracts/libraries/Constants.sol

26           keccak256(
27               hex"6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000a"
28:          );

GitHub : 26

[D-09] payable function does not transfer Eth

The general rule is valid, but the instances below are invalid

There are 1 instance(s) of this issue:

File: contracts/multicall/Multicall.sol

12       function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
13           results = new bytes[](data.length);
14           for (uint256 i = 0; i < data.length; ) {
15               (bool success, bytes memory result) = address(this).delegatecall(data[i]);
16   
17               if (!success) {
18                   // Bubble up the revert reason
19                   // The bytes type is ABI encoded as a length-prefixed byte array
20                   // So we simply need to add 32 to the pointer to get the start of the data
21                   // And then revert with the size loaded from the first 32 bytes
22                   // Other solutions will do work to differentiate the revert reasons and provide paranthetical information
23                   // However, we have chosen to simply replicate the the normal behavior of the call
24                   // NOTE: memory-safe because it reads from memory already allocated by solidity (the bytes memory result)
25                   assembly ("memory-safe") {
26                       revert(add(result, 32), mload(result))
27                   }
28               }
29   
30               results[i] = result;
31   
32               unchecked {
33                   ++i;
34               }
35           }
36:      }

GitHub : 12

[D-10] require() / revert() statements should have descriptive reason strings

These are not revert() calls, so these findings are invalid

There are 34 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

323:         if (s_poolContext[poolId].locked) revert Errors.ReentrantCall();

356:         if (address(univ3pool) == address(0)) revert Errors.UniswapPoolNotInitialized();

617:             ) revert Errors.TransferFailed();

621:             if (fromLiq.rightSlot() != liquidityChunk.liquidity()) revert Errors.TransferFailed();

671:         if (positionSize == 0) revert Errors.OptionsBalanceZero();

683:         if (univ3pool == IUniswapV3Pool(address(0))) revert Errors.UniswapPoolNotInitialized();

713:         if ((newTick >= tickLimitHigh) || (newTick <= tickLimitLow)) revert Errors.PriceBoundFail();

918:             revert Errors.PositionTooLarge();

990:                     revert Errors.NotEnoughLiquidity();

GitHub : 323,356,617,621,671,683,713,918,990

File: contracts/libraries/CallbackLib.sol

50:          ) revert Errors.InvalidUniswapCallback();

GitHub : 50

File: contracts/libraries/Math.sol

41:              if (absTick > uint256(int256(Constants.MAX_V3POOL_TICK))) revert Errors.InvalidTick();

173:         if ((downcastedInt = uint128(toDowncast)) != toDowncast) revert Errors.CastingError();

GitHub : 41,173

File: contracts/libraries/SafeTransferLib.sol

40:          if (!success) revert Errors.TransferFailed();

GitHub : 40

File: contracts/tokens/ERC1155Minimal.sol

97:          if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

115:                 revert UnsafeRecipient();

135:         if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

168:                 revert UnsafeRecipient();

227:                 revert UnsafeRecipient();

GitHub : 97,115,135,168,227

File: contracts/types/LeftRight.sol

55:          if (right < 0) revert Errors.LeftRightInputError();

151:             if (z < x || (uint128(z) < uint128(x))) revert Errors.UnderOverFlow();

167:             if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

185:             if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

199:         if (!((selfAsInt128 = int128(self)) == self)) revert Errors.CastingError();

206:         if (!((selfAsUint128 = uint128(self)) == self)) revert Errors.CastingError();

213:         if (self > uint256(type(int256).max)) revert Errors.CastingError();

GitHub : 55,151,167,185,199,206,213

File: contracts/types/TokenId.sol

401:             ) revert Errors.TicksNotInitializable();

464:         if (self.optionRatio(0) == 0) revert Errors.InvalidTokenIdParameter(1);

473:                     if ((self >> (64 + 48 * i)) != 0) revert Errors.InvalidTokenIdParameter(1);

480:                 if ((self.width(i) == 0)) revert Errors.InvalidTokenIdParameter(5);

485:                 ) revert Errors.InvalidTokenIdParameter(4);

494:                         revert Errors.InvalidTokenIdParameter(3);

500:                     ) revert Errors.InvalidTokenIdParameter(3);

513:                         revert Errors.InvalidTokenIdParameter(4);

518:                         revert Errors.InvalidTokenIdParameter(5);

GitHub : 401,464,473,480,485,494,500,513,518

[D-11] safeTransfer function does not check for contract existence

The examples below are either not token transfers, or are making high-level transfer()/transferFrom() calls (which check for contract existence), or are from a library that checks for contract existence.

There are 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

90       function safeTransferFrom(
91           address from,
92           address to,
93           uint256 id,
94           uint256 amount,
95           bytes calldata data
96       ) public {
97           if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();
98   
99           balanceOf[from][id] -= amount;
100  
101          // balance will never overflow
102          unchecked {
103              balanceOf[to][id] += amount;
104          }
105  
106          afterTokenTransfer(from, to, id, amount);
107  
108          emit TransferSingle(msg.sender, from, to, id, amount);
109  
110          if (to.code.length != 0) {
111              if (
112                  ERC1155Holder(to).onERC1155Received(msg.sender, from, id, amount, data) !=
113                  ERC1155Holder.onERC1155Received.selector
114              ) {
115                  revert UnsafeRecipient();
116              }
117          }
118:     }

GitHub : 90

[D-12] unchecked {} can be used on the division of two uints in order to save gas

These are already unchecked

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1293:                    uint256 numerator = netLiquidity + (removedLiquidity / 2 ** VEGOID);

1316:                        ((removedLiquidity ** 2) / 2 ** (VEGOID));

GitHub : 1293,1316

File: contracts/libraries/Math.sol

86:              if (tick > 0) sqrtR = type(uint256).max / sqrtR;

GitHub : 86

[D-13] A calldata array's length should not be looked up in every iteration of a for/while-loop

Caching the length of calldata arrays does not save any gas

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

550:         for (uint256 i = 0; i < ids.length; ) {

GitHub : 550

[D-14] Adding a return statement when the function defines a named return variable, is redundant

The general rule is valid, but the instances below are invalid

There are 5 instance(s) of this issue:

File: contracts/libraries/Math.sol

278:             return result;

307:                 return result;

369:                 return result;

431:                 return result;

493:                 return result;

GitHub : 278,307,369,431,493

[D-15] All interfaces used within a project should be imported

These contracts don't rely on other contracts for their definitions, so there's nothing to import

There are 12 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

10   library CallbackLib {
11:      // Defining characteristics of a Uni V3 pool

GitHub : 10

File: contracts/libraries/Constants.sol

6    library Constants {
7:       // Fixed point multiplier: 2**96

GitHub : 6

File: contracts/libraries/Errors.sol

6    library Errors {
7        /// Errors are alphabetically ordered
8    
9        /// @notice Casting error
10:      /// @dev e.g. uint128(uint256(a)) fails

GitHub : 6

File: contracts/libraries/FeesCalc.sol

38   library FeesCalc {
39:      // enables packing of types within int128|int128 or uint128|uint128 containers.

GitHub : 38

File: contracts/libraries/Math.sol

12:  library Math {

GitHub : 12

File: contracts/libraries/PanopticMath.sol

13   library PanopticMath {
14:      // enables packing of types within int128|int128 or uint128|uint128 containers.

GitHub : 13

File: contracts/libraries/SafeTransferLib.sol

11   library SafeTransferLib {
12       /*//////////////////////////////////////////////////////////////
13                               ERC20 OPERATIONS
14       //////////////////////////////////////////////////////////////*/
15:  

GitHub : 11

File: contracts/multicall/Multicall.sol

8    abstract contract Multicall {
9        /// @notice Performs multiple calls on the inheritor in a single transaction, and returns the data from each call.
10       /// @param data The calldata for each call
11:      /// @return results The data returned by each call

GitHub : 8

File: contracts/tokens/ERC1155Minimal.sol

10   abstract contract ERC1155 {
11       /*//////////////////////////////////////////////////////////////
12                                    EVENTS
13       //////////////////////////////////////////////////////////////*/
14   
15       /// @notice Emitted when only a single token is transferred
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20:      /// @param amount the amount of tokens transferred

GitHub : 10

File: contracts/types/LeftRight.sol

13:  library LeftRight {

GitHub : 13

File: contracts/types/LiquidityChunk.sol

50:  library LiquidityChunk {

GitHub : 50

File: contracts/types/TokenId.sol

56:  library TokenId {

GitHub : 56

[D-16] Array lengths not checked

These instances only have one array

There are 1 instance(s) of this issue:

File: contracts/multicall/Multicall.sol

12:      function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {

GitHub : 12

[D-17] Assembly blocks should have comments

These blocks already have comments

There are 9 instance(s) of this issue:

File: contracts/libraries/Math.sol

303                   assembly ("memory-safe") {
304                       // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
305                       result := shr(64, prod0)
306:                  }

330               assembly ("memory-safe") {
331                   // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
332                   prod0 := shr(64, prod0)
333:              }

365                   assembly ("memory-safe") {
366                       // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
367                       result := shr(96, prod0)
368:                  }

392               assembly ("memory-safe") {
393                   // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
394                   prod0 := shr(96, prod0)
395:              }

427                   assembly ("memory-safe") {
428                       // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
429                       result := shr(128, prod0)
430:                  }

454               assembly ("memory-safe") {
455                   // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
456                   prod0 := shr(128, prod0)
457:              }

489                   assembly ("memory-safe") {
490                       // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
491                       result := shr(192, prod0)
492:                  }

516               assembly ("memory-safe") {
517                   // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
518                   prod0 := shr(192, prod0)
519:              }

GitHub : 303,330,365,392,427,454,489,516

File: contracts/libraries/SafeTransferLib.sol

19            assembly ("memory-safe") {
20                // Get free memory pointer - we will store our calldata in scratch space starting at the offset specified here.
21                let p := mload(0x40)
22    
23                // Write the abi-encoded calldata into memory, beginning with the function selector.
24                mstore(p, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
25                mstore(add(4, p), from) // Append the "from" argument.
26                mstore(add(36, p), to) // Append the "to" argument.
27                mstore(add(68, p), amount) // Append the "amount" argument.
28    
29                success := and(
30                    // Set success to whether the call reverted, if not we check it either
31                    // returned exactly 1 (can't just be non-zero data), or had no return data.
32                    or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
33                    // We use 100 because that's the total length of our calldata (4 + 32 * 3)
34                    // Counterintuitively, this call() must be positioned after the or() in the
35                    // surrounding and() because and() evaluates its arguments from right to left.
36                    call(gas(), token, 0, p, 100, 0, 32)
37                )
38:           }

GitHub : 19

[D-18] Assembly: Check msg.sender using xor and the scratch space

These are not msg.sender checks where assembly can be used. If calling a function, the check should be flagged in the function, since assembly cannot involve solidity function calls, especially external ones

There are 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

417:         if (amount0Owed > 0)

424:         if (amount1Owed > 0)

GitHub : 417,424

File: contracts/tokens/ERC1155Minimal.sol

97:          if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

135:         if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

GitHub : 97,135

[D-19] Assembly: Checks for address(0x0) are more efficient in assembly

The gas savings only applies when the variable being checked is smaller than a full word, and for anything besides an address, including the higher-order bits will introduce bugs.

There are 2 instance(s) of this issue:

File: contracts/libraries/Math.sol

207:                 require(denominator > 0);

GitHub : 207

File: contracts/tokens/ERC1155Minimal.sol

224                  ERC1155Holder(to).onERC1155Received(msg.sender, address(0), id, amount, "") !=
225:                 ERC1155Holder.onERC1155Received.selector

GitHub : 224

[D-20] Avoid fetching a low-level call's return data by using assembly

The return data is in fact used, so assembly provides no gas savings

There are 1 instance(s) of this issue:

File: contracts/multicall/Multicall.sol

15:              (bool success, bytes memory result) = address(this).delegatecall(data[i]);

GitHub : 15

[D-21] Bad bot rules

The titles below correspond to issues submitted by various bots, where the submitting bot solely submitted invalid findings (i.e. the submitter didn't filter the results of the rule), so they should be given extra scrutiny:

  • Max allowance is not compatible with all tokens - internal approval for the contract's own balance, so the rule is pointing to the support for max allowance
  • increase/decrease allowance should be used instead of approve - this is an internal approval function
  • Must approve or increase allowance first - the rule is flagging all transferFrom() calls, without approval logic
  • Contract existence is not checked before low level call - reading calldata, not making an external call
  • Empty function blocks - the bot's removed the extensive comment documentation in the 'code blocks' it shows for these virtual functions used to allow child contracts to implement functionality, or are constructors
  • Utility contracts can be made into libraries - all provided examples are invalid
  • Address values should be used through variables rather than used as literals - none of the examples are of addresses
  • Employ Explicit Casting to Bytes or Bytes32 for Enhanced Code Clarity and Meaning - the large majority of the examples are of multiple arguments, not just one
  • Some if-statement can be converted to a ternary - you can't use a ternary when only one of the branches is a return
  • Addresses shouldn't be hard-coded - none of these are addresses
  • State variables used within a function more than once should be cached to save gas - none of these are state variables
  • Use storage instead of memory for structs/arrays - these all are array call arguments, not arrays copied from storage
  • Use bitmap to save gas - none of these are examples where bitmaps can be used
  • Consider merging sequential for loops - the examples cannot be merged
  • Emitting storage values instead of the memory one. - this is a gas finding, not a Low one
  • selfbalance() is cheaper than address(this).balance - some bots submit the issue twice (under the heading Use assembly when getting a contract's balance of ETH)
  • Imports could be organized more systematically - a lot of bots are blindly checking for interfaces not coming first. That is not the only way of organizing imports, and most projects are doing it in a systematic, valid, way
  • Unused * definition - some bots are reporting false positives for these rules. Check that it isn't used, or that if it's used, that there are two definitions, with one being unused
  • internal functions not called by the contract should be removed - some bots are reporting false positives when the function is called by a child contract, rather than the defining contract
  • Change public to external for functions that are not called internally - some bots are reporting false positives when the function is called by a child contract, rather than the defining contract
  • Avoid contract existence checks by using low level calls - at least one bot isn't checking that the version is prior to 0.8.10
  • For Operations that will not overflow, you could use unchecked - at least one bot is flagging every single line, which has nothing to do with using unchecked

Some of these have been raised as invalid in multiple contests, and the bot owners have not fixed them. Without penalties, they're unlikely to make any changes

There are 1 instance(s) of this issue:

File: contracts/types/TokenId.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

[D-22] Cast to bytes or bytes32 for clearer semantic meaning

These calls to abi.encodePacked() have more than one argument

There are 9 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

595                  abi.encodePacked(
596                      address(univ3pool),
597                      from,
598                      id.tokenType(leg),
599                      liquidityChunk.tickLower(),
600                      liquidityChunk.tickUpper()
601:                 )

604                  abi.encodePacked(
605                      address(univ3pool),
606                      to,
607                      id.tokenType(leg),
608                      liquidityChunk.tickLower(),
609                      liquidityChunk.tickUpper()
610:                 )

946              abi.encodePacked(
947                  address(_univ3pool),
948                  msg.sender,
949                  _tokenType,
950                  _liquidityChunk.tickLower(),
951                  _liquidityChunk.tickUpper()
952:             )

1105                     abi.encodePacked(
1106                         address(this),
1107                         liquidityChunk.tickLower(),
1108                         liquidityChunk.tickUpper()
1109:                    )

1353:            keccak256(abi.encodePacked(univ3pool, owner, tokenType, tickLower, tickUpper))

1381:            abi.encodePacked(address(univ3pool), owner, tokenType, tickLower, tickUpper)

1446:            keccak256(abi.encodePacked(univ3pool, owner, tokenType, tickLower, tickUpper))

GitHub : 595,604,946,1105,1353,1381,1446

File: contracts/libraries/CallbackLib.sol

40                               abi.encodePacked(
41                                   bytes1(0xff),
42                                   factory,
43                                   keccak256(abi.encode(features)),
44                                   Constants.V3POOL_INIT_CODE_HASH
45:                              )

GitHub : 40

File: contracts/libraries/PanopticMath.sol

57:                  (uint64(uint256(keccak256(abi.encodePacked(token0, token1, fee)))) >> 32);

GitHub : 57

[D-23] Change public function visibility to external to save gas

Both public and external functions use the same amount of gas (both deployment and runtime gas), so this finding is invalid

There are 5 instance(s) of this issue:

File: contracts/multicall/Multicall.sol

12:      function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {

GitHub : 12

File: contracts/tokens/ERC1155Minimal.sol

77:      function setApprovalForAll(address operator, bool approved) public {

90       function safeTransferFrom(
91           address from,
92           address to,
93           uint256 id,
94           uint256 amount,
95           bytes calldata data
96:      ) public {

178      function balanceOfBatch(
179          address[] calldata owners,
180          uint256[] calldata ids
181:     ) public view returns (uint256[] memory balances) {

200:     function supportsInterface(bytes4 interfaceId) public pure returns (bool) {

GitHub : 77,90,178,200

[D-24] Consider adding a block/deny-list

Contract doesn't handle tokens

There are 1 instance(s) of this issue:

File: contracts/multicall/Multicall.sol

8    abstract contract Multicall {
9        /// @notice Performs multiple calls on the inheritor in a single transaction, and returns the data from each call.
10       /// @param data The calldata for each call
11:      /// @return results The data returned by each call

GitHub : 8

[D-25] Contract implements a payable multicall and has payable functions

The general rule is valid, but the instances below are invalid

There are 1 instance(s) of this issue:

File: contracts/multicall/Multicall.sol

/// @audit multicall
8    abstract contract Multicall {
9        /// @notice Performs multiple calls on the inheritor in a single transaction, and returns the data from each call.
10       /// @param data The calldata for each call
11:      /// @return results The data returned by each call

GitHub : 8

[D-26] Contract should expose an interface

These are library functions, so they cannot use an interface

There are 1 instance(s) of this issue:

File: contracts/libraries/FeesCalc.sol

54       function calculateAMMSwapFeesLiquidityChunk(
55           IUniswapV3Pool univ3pool,
56           int24 currentTick,
57           uint128 startingLiquidity,
58           uint256 liquidityChunk
59       ) public view returns (int256 feesEachToken) {
60           // extract the amount of AMM fees collected within the liquidity chunk`
61:          // note: the fee variables are *per unit of liquidity*; so more "rate" variables

GitHub : 54

[D-27] Contracts are vulnerable to rebasing accounting-related issues

No evidence of a rebasing issue in these instances. Just a transfer in or out is not proof of a rebasing issue.

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit uniswapV3MintCallback()
414          // Validate caller to ensure we got called from the AMM pool
415          CallbackLib.validateCallback(msg.sender, address(FACTORY), decoded.poolFeatures);
416          // Sends the amount0Owed and amount1Owed quantities provided
417          if (amount0Owed > 0)
418              SafeTransferLib.safeTransferFrom(
419                  decoded.poolFeatures.token0,
420                  decoded.payer,
421                  msg.sender,
422                  amount0Owed
423:             );

/// @audit uniswapV3MintCallback()
421                  msg.sender,
422                  amount0Owed
423              );
424          if (amount1Owed > 0)
425              SafeTransferLib.safeTransferFrom(
426                  decoded.poolFeatures.token1,
427                  decoded.payer,
428                  msg.sender,
429                  amount1Owed
430:             );

GitHub : 414,421

[D-28] Control structures do not follow the Solidity Style Guide

The instances below properly drop down to the next line when the arguments are too long

There are 53 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

406       /// @param data Contains the payer address and the pool features required to validate the callback
407       function uniswapV3MintCallback(
408:          uint256 amount0Owed,

440       /// @param data Contains the payer address and the pool features required to validate the callback
441       function uniswapV3SwapCallback(
442:          int256 amount0Delta,

475       /// @return newTick the current tick in the pool after all the mints and swaps
476       function burnTokenizedPosition(
477:          uint256 tokenId,

509       /// @return newTick the current tick in the pool after all the mints and swaps
510       function mintTokenizedPosition(
511:          uint256 tokenId,

543       /// @param amounts The amounts of each token being transferred
544       function afterTokenTransfer(
545:          address from,

562       /// @param amount The amount of the token being transferred
563       function afterTokenTransfer(
564:          address from,

613               // Revert if recipient already has that position
614               if (
615:                  (s_accountLiquidity[positionKey_to] != 0) ||

662       /// @return newTick the tick *after* the mint+swap
663       function _validateAndForwardToAMM(
664:          uint256 tokenId,

742       /// @return totalSwapped the amount swapped in the AMM
743       function swapInAMM(
744:          IUniswapV3Pool univ3pool,

847       /// @return itmAmounts the amount of tokens swapped due to legs being in-the-money
848       function _createPositionInAMM(
849:          IUniswapV3Pool univ3pool,

935       /// @return _totalCollected the total amount of liquidity collected from Uniswap to msg.sender
936       function _createLegInAMM(
937:          IUniswapV3Pool _univ3pool,

1072      /// @param collectedAmounts amount of tokens (token0 and token1) collected from Uniswap
1073      function _updateStoredPremia(
1074:         bytes32 positionKey,

1092      /// @param liquidityChunk has lower tick, upper tick, and liquidity amount to mint
1093      function _getFeesBase(
1094:         IUniswapV3Pool univ3pool,

1128      /// @return movedAmounts how many tokens were moved from msg.sender to Uniswap
1129      function _mintLiquidity(
1130:         uint256 liquidityChunk,

1168      /// @return movedAmounts how many tokens were moved from Uniswap to msg.sender
1169      function _burnLiquidity(
1170:         uint256 liquidityChunk,

1199      /// @return collectedOut the incoming totalCollected with potentially whatever is collected in this function added to it
1200      function _collectAndWritePositionData(
1201:         uint256 liquidityChunk,

1254      /// @return deltaPremiumGross The extra premium (per liquidity X64) to be added to the gross accumulator for token0 (right) and token1 (right)
1255      function _getPremiaDeltas(
1256:         uint256 currentLiquidity,

1342      /// @return accountLiquidities The amount of liquidity that has been shorted/added to the Uniswap contract (removedLiquidity:netLiquidity -> rightSlot:leftSlot)
1343      function getAccountLiquidity(
1344:         address univ3pool,

1370      /// @return premiumToken1 The amount of premium (per liquidity X64) for token1 = sum (feeGrowthLast0X128) over every block where the position has been touched
1371      function getAccountPremium(
1372:         address univ3pool,

1436      /// @return feesBase1 The feesBase of the position for token1
1437      function getAccountFeesBase(
1438:         address univ3pool,

1456      /// @return UniswapV3Pool The unique poolId for that Uni v3 pool
1457      function getUniswapV3PoolFromId(
1458:         uint64 poolId

GitHub : 406,440,475,509,543,562,613,662,742,847,935,1072,1092,1128,1168,1199,1254,1342,1370,1436,1456

File: contracts/libraries/CallbackLib.sol

27        /// @param features The features `sender` claims to contain
28        function validateCallback(
29:           address sender,

34            // then, check against the actual address and verify that the callback came from the real, correct pool
35            if (
36:               address(

GitHub : 27,34

File: contracts/libraries/FeesCalc.sol

53        /// @return feesEachToken the fees collected from the AMM for each token (LeftRight-packed) with token0 in the right slot and token1 in the left slot
54        function calculateAMMSwapFeesLiquidityChunk(
55:           IUniswapV3Pool univ3pool,

88        /// @return feeGrowthInside1X128 the fee growth in the AMM of token1
89        function _getAMMSwapFeesPerLiquidityCollected(
90:           IUniswapV3Pool univ3pool,

GitHub : 53,88

File: contracts/libraries/Math.sol

100       /// @return amount0 The amount of token0
101       function getAmount0ForLiquidity(
102:          uint256 liquidityChunk

118       /// @return amount1 The amount of token1
119       function getAmount1ForLiquidity(
120:          uint256 liquidityChunk

134       /// @return liquidity The calculated amount of liquidity
135       function getLiquidityForAmount0(
136:          uint256 liquidityChunk,

153       /// @return liquidity The calculated amount of liquidity
154       function getLiquidityForAmount1(
155:          uint256 liquidityChunk,

185       /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
186       function mulDiv(
187:          uint256 a,

GitHub : 100,118,134,153,185

File: contracts/libraries/PanopticMath.sol

47        /// @return finalPoolId the final 64-bit pool id as encoded in the `TokenId` type - composed of the last 64 bits of the address and a hash of the parameters
48        function getFinalPoolId(
49:           uint64 basePoolId,

81        /// @return liquidityChunk a uint256 bit-packed (see `LiquidityChunk.sol`) with `tickLower`, `tickUpper`, and `liquidity`
82        function getLiquidityChunk(
83:           uint256 tokenId,

GitHub : 47,81

File: contracts/tokens/ERC1155Minimal.sol

89        /// @param data optional data to include in the receive hook
90        function safeTransferFrom(
91:           address from,

110           if (to.code.length != 0) {
111               if (
112:                  ERC1155Holder(to).onERC1155Received(msg.sender, from, id, amount, data) !=

127       /// @param data optional data to include in the receive hook
128       function safeBatchTransferFrom(
129:          address from,

163           if (to.code.length != 0) {
164               if (
165:                  ERC1155Holder(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) !=

177       /// @return balances the balances for each user-token pair in the same order as the input
178       function balanceOfBatch(
179:          address[] calldata owners,

222           if (to.code.length != 0) {
223               if (
224:                  ERC1155Holder(to).onERC1155Received(msg.sender, address(0), id, amount, "") !=

251       /// @param amounts the amounts of tokens to transfer
252       function afterTokenTransfer(
253:          address from,

264       /// @param amount the amount of tokens to transfer
265       function afterTokenTransfer(
266:          address from,

GitHub : 89,110,127,163,177,222,251,264

File: contracts/types/LiquidityChunk.sol

62        /// @return the new liquidity chunk
63        function createChunk(
64:           uint256 self,

GitHub : 62

File: contracts/types/TokenId.sol

188       /// @return the tokenId with numerarire added to the incoming leg index
189       function addAsset(
190:          uint256 self,

203       /// @return the tokenId with optionRatio added to the incoming leg index
204       function addOptionRatio(
205:          uint256 self,

219       /// @return the tokenId with isLong added to its relevant leg
220       function addIsLong(
221:          uint256 self,

233       /// @return the tokenId with tokenType added to its relevant leg.
234       function addTokenType(
235:          uint256 self,

247       /// @return the tokenId with riskPartner added to its relevant leg.
248       function addRiskPartner(
249:          uint256 self,

261       /// @return the tokenId with strike price tick added to its relevant leg
262       function addStrike(
263:          uint256 self,

275       /// @return the tokenId with width added to its relevant leg
276       function addWidth(
277:          uint256 self,

297       /// @return tokenId the tokenId with the leg added
298       function addLeg(
299:          uint256 self,

373       /// @return legUpperTick the upper tick of the leg/liquidity chunk.
374       function asTicks(
375:          uint256 self,

395               // These are invalid states, and would revert silently later in `univ3Pool.mint`
396               if (
397:                  legLowerTick % tickSpacing != 0 ||

481                   // Strike cannot be MIN_TICK or MAX_TICK
482                   if (
483:                      (self.strike(i) == Constants.MIN_V3POOL_TICK) ||

496                       // Ensures that risk partners have 1) the same asset, and 2) the same ratio
497                       if (
498:                          (self.asset(riskPartnerIndex) != self.asset(i)) ||

GitHub : 188,203,219,233,247,261,275,297,373,395,481,496

[D-29] Default bool values are manually reset

Using delete instead of assigning zero/false to state variables does not save any extra gas with the optimizer on (saves 5-8 gas with optimizer completely off), so this finding is invalid, especially since if they were interested in gas savings, they'd have the optimizer enabled. Some bots are also flagging true rather than just false

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

326:         s_poolContext[poolId].locked = true;

333:         s_poolContext[poolId].locked = false;

GitHub : 326,333

[D-30] Dependence on external protocols

There is no way to ascertain whether external monitoring is in place, and no specific vulnerabilities are identified, so this rule is not useful.

There are 34 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

5:   import {IUniswapV3Factory} from "univ3-core/interfaces/IUniswapV3Factory.sol";

5:   import {IUniswapV3Factory} from "univ3-core/interfaces/IUniswapV3Factory.sol";

6:   import {IUniswapV3Pool} from "univ3-core/interfaces/IUniswapV3Pool.sol";

6:   import {IUniswapV3Pool} from "univ3-core/interfaces/IUniswapV3Pool.sol";

79:      event PoolInitialized(address indexed uniswapPool);

118:         IUniswapV3Pool pool;

139:     IUniswapV3Factory internal immutable FACTORY;

342:     constructor(IUniswapV3Factory _factory) {

376:             pool: IUniswapV3Pool(univ3pool),

407      function uniswapV3MintCallback(
408          uint256 amount0Owed,
409          uint256 amount1Owed,
410          bytes calldata data
411:     ) external {

441      function uniswapV3SwapCallback(
442          int256 amount0Delta,
443          int256 amount1Delta,
444          bytes calldata data
445:     ) external {

580:         IUniswapV3Pool univ3pool = s_poolContext[id.validate()].pool;

680:         IUniswapV3Pool univ3pool = s_poolContext[tokenId.validate()].pool;

683:         if (univ3pool == IUniswapV3Pool(address(0))) revert Errors.UniswapPoolNotInitialized();

744:         IUniswapV3Pool univ3pool,

752:         IUniswapV3Pool _univ3pool = univ3pool;

849:         IUniswapV3Pool univ3pool,

867:                 IUniswapV3Pool _univ3pool = univ3pool;

937:         IUniswapV3Pool _univ3pool,

1094:        IUniswapV3Pool univ3pool,

1131:        IUniswapV3Pool univ3pool

1171:        IUniswapV3Pool univ3pool

1202:        IUniswapV3Pool univ3pool,

1397:                    IUniswapV3Pool _univ3pool = IUniswapV3Pool(univ3pool);

1397:                    IUniswapV3Pool _univ3pool = IUniswapV3Pool(univ3pool);

1459:    ) external view returns (IUniswapV3Pool UniswapV3Pool) {

1459:    ) external view returns (IUniswapV3Pool UniswapV3Pool) {

1457     function getUniswapV3PoolFromId(
1458         uint64 poolId
1459:    ) external view returns (IUniswapV3Pool UniswapV3Pool) {

GitHub : 5,5,6,6,79,118,139,342,376,407,441,580,680,683,744,752,849,867,937,1094,1131,1171,1202,1397,1397,1459,1459,1457

File: contracts/libraries/Errors.sol

17:      error InvalidUniswapCallback();

55:      error UniswapPoolNotInitialized();

GitHub : 17,55

File: contracts/libraries/FeesCalc.sol

5:   import {IUniswapV3Pool} from "univ3-core/interfaces/IUniswapV3Pool.sol";

5:   import {IUniswapV3Pool} from "univ3-core/interfaces/IUniswapV3Pool.sol";

55:          IUniswapV3Pool univ3pool,

90:          IUniswapV3Pool univ3pool,

GitHub : 5,5,55,90

[D-31] Division by zero not prevented

The general rule is valid, but the instances below are invalid

There are 2 instance(s) of this issue:

File: contracts/types/TokenId.sol

382  
383              // The max/min ticks that can be initialized are the closest multiple of tickSpacing to the actual max/min tick abs()=887272
384              // Dividing and multiplying by tickSpacing rounds down and forces the tick to be a multiple of tickSpacing
385:             int24 minTick = (Constants.MIN_V3POOL_TICK / tickSpacing) * tickSpacing;

383              // The max/min ticks that can be initialized are the closest multiple of tickSpacing to the actual max/min tick abs()=887272
384              // Dividing and multiplying by tickSpacing rounds down and forces the tick to be a multiple of tickSpacing
385              int24 minTick = (Constants.MIN_V3POOL_TICK / tickSpacing) * tickSpacing;
386:             int24 maxTick = (Constants.MAX_V3POOL_TICK / tickSpacing) * tickSpacing;

GitHub : 382,383

[D-32] Do not use UNDERSCORE in struct elements names

These are not struct members

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit positionKey_from
594:             bytes32 positionKey_from = keccak256(

/// @audit positionKey_to
603:             bytes32 positionKey_to = keccak256(

GitHub : 594,603

[D-33] Duplicated require()/revert() checks should be refactored to a modifier or function

This instance appears only once

There are 6 instance(s) of this issue:

File: contracts/libraries/Math.sol

207:                  require(denominator > 0);

216:              require(denominator > prod1);

311:              require(2 ** 64 > prod1);

373:              require(2 ** 96 > prod1);

435:              require(2 ** 128 > prod1);

497:              require(2 ** 192 > prod1);

GitHub : 207,216,311,373,435,497

[D-34] Duplicated require()/revert() checks should be refactored to a modifier Or function to save gas

If the compiler inlines the function, there will be no gas savings. If it doesn't, there's extra runtime overhead due to the JUMP instructions. Either way, this suggestion is not helpful.

There are 2 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

135:          if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

GitHub : 135

File: contracts/types/LeftRight.sol

185:              if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

GitHub : 185

[D-35] Event names should use CamelCase

The instances below are already CamelCase (events are supposed to use CamelCase, not lowerCamelCase)

There are 6 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

79:      event PoolInitialized(address indexed uniswapPool);

86       event TokenizedPositionBurnt(
87           address indexed recipient,
88           uint256 indexed tokenId,
89           uint128 positionSize
90:      );

97       event TokenizedPositionMinted(
98           address indexed caller,
99           uint256 indexed tokenId,
100          uint128 positionSize
101:     );

GitHub : 79,86,97

File: contracts/tokens/ERC1155Minimal.sol

21       event TransferSingle(
22           address indexed operator,
23           address indexed from,
24           address indexed to,
25           uint256 id,
26           uint256 amount
27:      );

35       event TransferBatch(
36           address indexed operator,
37           address indexed from,
38           address indexed to,
39           uint256[] ids,
40           uint256[] amounts
41:      );

44:      event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

GitHub : 21,35,44

[D-36] Events that mark critical parameter changes should contain both the old and the new value

These are not critical parameter changes

There are 7 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit initializeAMMPool()
386:         emit PoolInitialized(univ3pool);

/// @audit burnTokenizedPosition()
490:         emit TokenizedPositionBurnt(msg.sender, tokenId, positionSize);

/// @audit mintTokenizedPosition()
523:         emit TokenizedPositionMinted(msg.sender, tokenId, positionSize);

GitHub : 386,490,523

File: contracts/tokens/ERC1155Minimal.sol

/// @audit safeTransferFrom()
108:         emit TransferSingle(msg.sender, from, to, id, amount);

/// @audit safeBatchTransferFrom()
161:         emit TransferBatch(msg.sender, from, to, ids, amounts);

/// @audit _mint()
220:         emit TransferSingle(msg.sender, address(0), to, id, amount);

/// @audit _burn()
239:         emit TransferSingle(msg.sender, from, address(0), id, amount);

GitHub : 108,161,220,239

[D-37] Function doesn't perform any updates

The general rule is valid, but the instances below are invalid

There are 11 instance(s) of this issue:

File: contracts/types/LiquidityChunk.sol

78       function addLiquidity(uint256 self, uint128 amount) internal pure returns (uint256) {
79           unchecked {
80               return self + uint256(amount);
81           }
82:      }

88       function addTickLower(uint256 self, int24 _tickLower) internal pure returns (uint256) {
89           unchecked {
90               return self + (uint256(uint24(_tickLower)) << 232);
91           }
92:      }

98       function addTickUpper(uint256 self, int24 _tickUpper) internal pure returns (uint256) {
99           unchecked {
100              // convert tick upper to uint24 as explicit conversion from int24 to uint256 is not allowed
101              return self + ((uint256(uint24(_tickUpper))) << 208);
102          }
103:     }

GitHub : 78,88,98

File: contracts/types/TokenId.sol

173      function addUniv3pool(uint256 self, uint64 _poolId) internal pure returns (uint256) {
174          unchecked {
175              return self + uint256(_poolId);
176          }
177:     }

189      function addAsset(
190          uint256 self,
191          uint256 _asset,
192          uint256 legIndex
193      ) internal pure returns (uint256) {
194          unchecked {
195              return self + (uint256(_asset % 2) << (64 + legIndex * 48));
196          }
197:     }

204      function addOptionRatio(
205          uint256 self,
206          uint256 _optionRatio,
207          uint256 legIndex
208      ) internal pure returns (uint256) {
209          unchecked {
210              return self + (uint256(_optionRatio % 128) << (64 + legIndex * 48 + 1));
211          }
212:     }

220      function addIsLong(
221          uint256 self,
222          uint256 _isLong,
223          uint256 legIndex
224      ) internal pure returns (uint256) {
225          unchecked {
226              return self + ((_isLong % 2) << (64 + legIndex * 48 + 8));
227          }
228:     }

234      function addTokenType(
235          uint256 self,
236          uint256 _tokenType,
237          uint256 legIndex
238      ) internal pure returns (uint256) {
239          unchecked {
240              return self + (uint256(_tokenType % 2) << (64 + legIndex * 48 + 9));
241          }
242:     }

248      function addRiskPartner(
249          uint256 self,
250          uint256 _riskPartner,
251          uint256 legIndex
252      ) internal pure returns (uint256) {
253          unchecked {
254              return self + (uint256(_riskPartner % 4) << (64 + legIndex * 48 + 10));
255          }
256:     }

262      function addStrike(
263          uint256 self,
264          int24 _strike,
265          uint256 legIndex
266      ) internal pure returns (uint256) {
267          unchecked {
268              return self + uint256((int256(_strike) & BITMASK_INT24) << (64 + legIndex * 48 + 12));
269          }
270:     }

276      function addWidth(
277          uint256 self,
278          int24 _width,
279          uint256 legIndex
280      ) internal pure returns (uint256) {
281          // % 4096 -> take 12 bits from the incoming 24 bits (there's no uint12)
282          unchecked {
283              return self + (uint256(uint24(_width) % 4096) << (64 + legIndex * 48 + 36));
284          }
285:     }

GitHub : 173,189,204,220,234,248,262,276

[D-38] Functions which are either private or internal should have a preceding _ in their name

This rule does not apply to internal library functions, so these instances are invalid.

There are 66 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

28       function validateCallback(
29           address sender,
30           address factory,
31           PoolFeatures memory features
32:      ) internal pure {

GitHub : 28

File: contracts/libraries/Math.sol

23:      function absUint(int256 x) internal pure returns (uint256) {

38:      function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {

101      function getAmount0ForLiquidity(
102          uint256 liquidityChunk
103:     ) internal pure returns (uint256 amount0) {

119      function getAmount1ForLiquidity(
120          uint256 liquidityChunk
121:     ) internal pure returns (uint256 amount1) {

135      function getLiquidityForAmount0(
136          uint256 liquidityChunk,
137          uint256 amount0
138:     ) internal pure returns (uint128 liquidity) {

154      function getLiquidityForAmount1(
155          uint256 liquidityChunk,
156          uint256 amount1
157:     ) internal pure returns (uint128 liquidity) {

172:     function toUint128(uint256 toDowncast) internal pure returns (uint128 downcastedInt) {

186      function mulDiv(
187          uint256 a,
188          uint256 b,
189          uint256 denominator
190:     ) internal pure returns (uint256 result) {

286:     function mulDiv64(uint256 a, uint256 b) internal pure returns (uint256 result) {

348:     function mulDiv96(uint256 a, uint256 b) internal pure returns (uint256 result) {

410:     function mulDiv128(uint256 a, uint256 b) internal pure returns (uint256 result) {

472:     function mulDiv192(uint256 a, uint256 b) internal pure returns (uint256 result) {

GitHub : 23,38,101,119,135,154,172,186,286,348,410,472

File: contracts/libraries/PanopticMath.sol

38:      function getPoolId(address univ3pool) internal pure returns (uint64) {

48       function getFinalPoolId(
49           uint64 basePoolId,
50           address token0,
51           address token1,
52           uint24 fee
53:      ) internal pure returns (uint64) {

82       function getLiquidityChunk(
83           uint256 tokenId,
84           uint256 legIndex,
85           uint128 positionSize,
86           int24 tickSpacing
87:      ) internal pure returns (uint256 liquidityChunk) {

145:     function convert0to1(int256 amount, uint160 sqrtPriceX96) internal pure returns (int256) {

168:     function convert1to0(int256 amount, uint160 sqrtPriceX96) internal pure returns (int256) {

GitHub : 38,48,82,145,168

File: contracts/libraries/SafeTransferLib.sol

16:      function safeTransferFrom(address token, address from, address to, uint256 amount) internal {

GitHub : 16

File: contracts/types/LeftRight.sol

25:      function rightSlot(uint256 self) internal pure returns (uint128) {

32:      function rightSlot(int256 self) internal pure returns (int128) {

44:      function toRightSlot(uint256 self, uint128 right) internal pure returns (uint256) {

54:      function toRightSlot(uint256 self, int128 right) internal pure returns (uint256) {

65:      function toRightSlot(int256 self, uint128 right) internal pure returns (int256) {

75:      function toRightSlot(int256 self, int128 right) internal pure returns (int256) {

89:      function leftSlot(uint256 self) internal pure returns (uint128) {

96:      function leftSlot(int256 self) internal pure returns (int128) {

108:     function toLeftSlot(uint256 self, uint128 left) internal pure returns (uint256) {

118:     function toLeftSlot(int256 self, uint128 left) internal pure returns (int256) {

128:     function toLeftSlot(int256 self, int128 left) internal pure returns (int256) {

142:     function add(uint256 x, uint256 y) internal pure returns (uint256 z) {

159:     function add(int256 x, int256 y) internal pure returns (int256 z) {

177:     function sub(int256 x, int256 y) internal pure returns (int256 z) {

198:     function toInt128(int256 self) internal pure returns (int128 selfAsInt128) {

205:     function toUint128(uint256 self) internal pure returns (uint128 selfAsUint128) {

212:     function toInt256(uint256 self) internal pure returns (int256) {

GitHub : 25,32,44,54,65,75,89,96,108,118,128,142,159,177,198,205,212

File: contracts/types/LiquidityChunk.sol

63       function createChunk(
64           uint256 self,
65           int24 _tickLower,
66           int24 _tickUpper,
67           uint128 amount
68:      ) internal pure returns (uint256) {

78:      function addLiquidity(uint256 self, uint128 amount) internal pure returns (uint256) {

88:      function addTickLower(uint256 self, int24 _tickLower) internal pure returns (uint256) {

98:      function addTickUpper(uint256 self, int24 _tickUpper) internal pure returns (uint256) {

112:     function tickLower(uint256 self) internal pure returns (int24) {

121:     function tickUpper(uint256 self) internal pure returns (int24) {

130:     function liquidity(uint256 self) internal pure returns (uint128) {

GitHub : 63,78,88,98,112,121,130

File: contracts/types/TokenId.sol

80:      function univ3pool(uint256 self) internal pure returns (uint64) {

93:      function asset(uint256 self, uint256 legIndex) internal pure returns (uint256) {

103:     function optionRatio(uint256 self, uint256 legIndex) internal pure returns (uint256) {

113:     function isLong(uint256 self, uint256 legIndex) internal pure returns (uint256) {

123:     function tokenType(uint256 self, uint256 legIndex) internal pure returns (uint256) {

139:     function riskPartner(uint256 self, uint256 legIndex) internal pure returns (uint256) {

149:     function strike(uint256 self, uint256 legIndex) internal pure returns (int24) {

160:     function width(uint256 self, uint256 legIndex) internal pure returns (int24) {

173:     function addUniv3pool(uint256 self, uint64 _poolId) internal pure returns (uint256) {

189      function addAsset(
190          uint256 self,
191          uint256 _asset,
192          uint256 legIndex
193:     ) internal pure returns (uint256) {

204      function addOptionRatio(
205          uint256 self,
206          uint256 _optionRatio,
207          uint256 legIndex
208:     ) internal pure returns (uint256) {

220      function addIsLong(
221          uint256 self,
222          uint256 _isLong,
223          uint256 legIndex
224:     ) internal pure returns (uint256) {

234      function addTokenType(
235          uint256 self,
236          uint256 _tokenType,
237          uint256 legIndex
238:     ) internal pure returns (uint256) {

248      function addRiskPartner(
249          uint256 self,
250          uint256 _riskPartner,
251          uint256 legIndex
252:     ) internal pure returns (uint256) {

262      function addStrike(
263          uint256 self,
264          int24 _strike,
265          uint256 legIndex
266:     ) internal pure returns (uint256) {

276      function addWidth(
277          uint256 self,
278          int24 _width,
279          uint256 legIndex
280:     ) internal pure returns (uint256) {

298      function addLeg(
299          uint256 self,
300          uint256 legIndex,
301          uint256 _optionRatio,
302          uint256 _asset,
303          uint256 _isLong,
304          uint256 _tokenType,
305          uint256 _riskPartner,
306          int24 _strike,
307          int24 _width
308:     ) internal pure returns (uint256 tokenId) {

327:     function flipToBurnToken(uint256 self) internal pure returns (uint256) {

361:     function countLongs(uint256 self) internal pure returns (uint256) {

374      function asTicks(
375          uint256 self,
376          uint256 legIndex,
377          int24 tickSpacing
378:     ) internal pure returns (int24 legLowerTick, int24 legUpperTick) {

410:     function countLegs(uint256 self) internal pure returns (uint256) {

442:     function clearLeg(uint256 self, uint256 i) internal pure returns (uint256) {

463:     function validate(uint256 self) internal pure returns (uint64) {

GitHub : 80,93,103,113,123,139,149,160,173,189,204,220,234,248,262,276,298,327,361,374,410,442,463

[D-39] Getter for public state variables are redundant

The variable is not public, so this function is not redundant

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1457     function getUniswapV3PoolFromId(
1458         uint64 poolId
1459     ) external view returns (IUniswapV3Pool UniswapV3Pool) {
1460         return s_poolContext[poolId].pool;
1461:    }

GitHub : 1457

[D-40] Inconsistent comment spacing

URLs are not comments

There are 5 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

134:      // The effect of vegoid on the long premium multiplier can be explored here: https://www.desmos.com/calculator/mdeqob2m04

1263:         // premia spread equations are graphed and documented here: https://www.desmos.com/calculator/mdeqob2m04

GitHub : 134,1263

File: contracts/libraries/Math.sol

185:      /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv

GitHub : 185

File: contracts/libraries/SafeTransferLib.sol

9:    /// @author Modified from Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)

GitHub : 9

File: contracts/tokens/ERC1155Minimal.sol

9:    /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/v7/src/tokens/ERC1155.sol)

GitHub : 9

[D-41] Inline modifiers that are only used once, to save gas

These modifiers are used more than once

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

306      modifier ReentrancyLock(uint64 poolId) {
307          // check if the pool is already locked
308          // init lock if not
309          beginReentrancyLock(poolId);
310  
311          // execute function
312          _;
313  
314          // remove lock
315          endReentrancyLock(poolId);
316:     }

GitHub : 306

[D-42] Input array lengths may differ

If the caller makes a copy-paste error, the lengths may be mismatched and an operation believed to have been completed may not in fact have been completed (e.g. if the array being iterated over is shorter than the one being indexed into).

There are 2 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

/// @audit amounts[]
143:             amount = amounts[i];

/// @audit ids[]
188:                 balances[i] = balanceOf[owners[i]][ids[i]];

GitHub : 143,188

[D-43] It is standard for all external and public functions to be override from an interface

According to the Solidity docs, "Starting from Solidity 0.8.8, the override keyword is not required when overriding an interface function, except for the case where the function is defined in multiple bases", so while it may have been a requirement in the past, they're trying to change that. Paired with the advice of making all public and external functions a part of an interface, this finding would end up having all sponsors mark all public/external functions with override, making the keyword meaningless. It's better to use override only when something is actually being overridden.

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

544      function afterTokenTransfer(
545          address from,
546          address to,
547          uint256[] memory ids,
548          uint256[] memory amounts
549:     ) internal override {

563      function afterTokenTransfer(
564          address from,
565          address to,
566          uint256 id,
567          uint256 amount
568:     ) internal override {

GitHub : 544,563

[D-44] It's not standard to end and begin a code object on the same line

These are perfectly standard

There are 34 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

5:   import {IUniswapV3Factory} from "univ3-core/interfaces/IUniswapV3Factory.sol";

6:   import {IUniswapV3Pool} from "univ3-core/interfaces/IUniswapV3Pool.sol";

8:   import {ERC1155} from "@tokens/ERC1155Minimal.sol";

9:   import {Multicall} from "@multicall/Multicall.sol";

11:  import {CallbackLib} from "@libraries/CallbackLib.sol";

12:  import {Constants} from "@libraries/Constants.sol";

13:  import {Errors} from "@libraries/Errors.sol";

14:  import {FeesCalc} from "@libraries/FeesCalc.sol";

15:  import {Math} from "@libraries/Math.sol";

16:  import {PanopticMath} from "@libraries/PanopticMath.sol";

17:  import {SafeTransferLib} from "@libraries/SafeTransferLib.sol";

19:  import {LeftRight} from "@types/LeftRight.sol";

20:  import {LiquidityChunk} from "@types/LiquidityChunk.sol";

21:  import {TokenId} from "@types/TokenId.sol";

GitHub : 5,6,8,9,11,12,13,14,15,16,17,19,20,21

File: contracts/libraries/CallbackLib.sol

5:   import {Constants} from "@libraries/Constants.sol";

6:   import {Errors} from "@libraries/Errors.sol";

GitHub : 5,6

File: contracts/libraries/FeesCalc.sol

5:   import {IUniswapV3Pool} from "univ3-core/interfaces/IUniswapV3Pool.sol";

7:   import {Math} from "@libraries/Math.sol";

9:   import {LeftRight} from "@types/LeftRight.sol";

10:  import {LiquidityChunk} from "@types/LiquidityChunk.sol";

11:  import {TokenId} from "@types/TokenId.sol";

GitHub : 5,7,9,10,11

File: contracts/libraries/Math.sol

5:   import {Errors} from "@libraries/Errors.sol";

6:   import {Constants} from "@libraries/Constants.sol";

8:   import {LiquidityChunk} from "@types/LiquidityChunk.sol";

GitHub : 5,6,8

File: contracts/libraries/PanopticMath.sol

5:   import {Math} from "@libraries/Math.sol";

7:   import {LeftRight} from "@types/LeftRight.sol";

8:   import {LiquidityChunk} from "@types/LiquidityChunk.sol";

9:   import {TokenId} from "@types/TokenId.sol";

GitHub : 5,7,8,9

File: contracts/libraries/SafeTransferLib.sol

5:   import {Errors} from "@libraries/Errors.sol";

GitHub : 5

File: contracts/tokens/ERC1155Minimal.sol

5:   import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";

GitHub : 5

File: contracts/types/LeftRight.sol

5:   import {Errors} from "@libraries/Errors.sol";

GitHub : 5

File: contracts/types/LiquidityChunk.sol

5:   import {TokenId} from "@types/TokenId.sol";

GitHub : 5

File: contracts/types/TokenId.sol

5:   import {Constants} from "@libraries/Constants.sol";

6:   import {Errors} from "@libraries/Errors.sol";

GitHub : 5,6

[D-45] Lack of unchecked in loops

The increment/decrement is already in an unchecked block

There are 2 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

187:              for (uint256 i = 0; i < owners.length; ++i) {

GitHub : 187

File: contracts/types/TokenId.sol

468:              for (uint256 i = 0; i < 4; ++i) {

GitHub : 468

[D-46] Loss of precision

The general rule is valid, but the instances below are invalid

There are 1 instance(s) of this issue:

File: contracts/libraries/Math.sol

/// @audit division by sqrtR
86:              if (tick > 0) sqrtR = type(uint256).max / sqrtR;

GitHub : 86

[D-47] Loss of precision

The division is in order to bin values, so there's no loss of precision

There are 2 instance(s) of this issue:

File: contracts/types/TokenId.sol

/// @audit division by tickSpacing, multiplied by tickSpacing
385:             int24 minTick = (Constants.MIN_V3POOL_TICK / tickSpacing) * tickSpacing;

/// @audit division by tickSpacing, multiplied by tickSpacing
386:             int24 maxTick = (Constants.MAX_V3POOL_TICK / tickSpacing) * tickSpacing;

GitHub : 385,386

[D-48] Low level calls with Solidity before 0.8.14 result in an optimiser bug

This assembly block does not call mstore(), so it's not possible to hit the bug here even if there are small future changes, so this doesn't seem low severity.

There are 28 instance(s) of this issue:

File: contracts/libraries/Math.sol

199              assembly ("memory-safe") {
200                  let mm := mulmod(a, b, not(0))
201                  prod0 := mul(a, b)
202                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
203:             }

208                  assembly ("memory-safe") {
209                      result := div(prod0, denominator)
210:                 }

225              assembly ("memory-safe") {
226                  remainder := mulmod(a, b, denominator)
227:             }

229              assembly ("memory-safe") {
230                  prod1 := sub(prod1, gt(remainder, prod0))
231                  prod0 := sub(prod0, remainder)
232:             }

239              assembly ("memory-safe") {
240                  denominator := div(denominator, twos)
241:             }

244              assembly ("memory-safe") {
245                  prod0 := div(prod0, twos)
246:             }

250              assembly ("memory-safe") {
251                  twos := add(div(sub(0, twos), twos), 1)
252:             }

295              assembly ("memory-safe") {
296                  let mm := mulmod(a, b, not(0))
297                  prod0 := mul(a, b)
298                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
299:             }

303                  assembly ("memory-safe") {
304                      // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
305                      result := shr(64, prod0)
306:                 }

320              assembly ("memory-safe") {
321                  remainder := mulmod(a, b, 0x10000000000000000)
322:             }

324              assembly ("memory-safe") {
325                  prod1 := sub(prod1, gt(remainder, prod0))
326                  prod0 := sub(prod0, remainder)
327:             }

330              assembly ("memory-safe") {
331                  // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
332                  prod0 := shr(64, prod0)
333:             }

357              assembly ("memory-safe") {
358                  let mm := mulmod(a, b, not(0))
359                  prod0 := mul(a, b)
360                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
361:             }

365                  assembly ("memory-safe") {
366                      // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
367                      result := shr(96, prod0)
368:                 }

382              assembly ("memory-safe") {
383                  remainder := mulmod(a, b, 0x1000000000000000000000000)
384:             }

386              assembly ("memory-safe") {
387                  prod1 := sub(prod1, gt(remainder, prod0))
388                  prod0 := sub(prod0, remainder)
389:             }

392              assembly ("memory-safe") {
393                  // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
394                  prod0 := shr(96, prod0)
395:             }

419              assembly ("memory-safe") {
420                  let mm := mulmod(a, b, not(0))
421                  prod0 := mul(a, b)
422                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
423:             }

427                  assembly ("memory-safe") {
428                      // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
429                      result := shr(128, prod0)
430:                 }

444              assembly ("memory-safe") {
445                  remainder := mulmod(a, b, 0x100000000000000000000000000000000)
446:             }

448              assembly ("memory-safe") {
449                  prod1 := sub(prod1, gt(remainder, prod0))
450                  prod0 := sub(prod0, remainder)
451:             }

454              assembly ("memory-safe") {
455                  // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
456                  prod0 := shr(128, prod0)
457:             }

481              assembly ("memory-safe") {
482                  let mm := mulmod(a, b, not(0))
483                  prod0 := mul(a, b)
484                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
485:             }

489                  assembly ("memory-safe") {
490                      // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
491                      result := shr(192, prod0)
492:                 }

506              assembly ("memory-safe") {
507                  remainder := mulmod(a, b, 0x1000000000000000000000000000000000000000000000000)
508:             }

510              assembly ("memory-safe") {
511                  prod1 := sub(prod1, gt(remainder, prod0))
512                  prod0 := sub(prod0, remainder)
513:             }

516              assembly ("memory-safe") {
517                  // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
518                  prod0 := shr(192, prod0)
519:             }

GitHub : 199,208,225,229,239,244,250,295,303,320,324,330,357,365,382,386,392,419,427,444,448,454,481,489,506,510,516

File: contracts/multicall/Multicall.sol

25                   assembly ("memory-safe") {
26                       revert(add(result, 32), mload(result))
27:                  }

GitHub : 25

[D-49] Missing checks for state variable assignments

There are checks for these variables

There are 13 instance(s) of this issue:

File: contracts/libraries/Math.sol

/// @audit denominator
207:                 require(denominator > 0);

/// @audit denominator
216:             require(denominator > prod1);

GitHub : 207,216

File: contracts/tokens/ERC1155Minimal.sol

/// @audit to
/// @audit id
/// @audit amount
/// @audit data
/// @audit from
111              if (
112                  ERC1155Holder(to).onERC1155Received(msg.sender, from, id, amount, data) !=
113                  ERC1155Holder.onERC1155Received.selector
114              ) {
115                  revert UnsafeRecipient();
116:             }

/// @audit data
/// @audit from
/// @audit to
164              if (
165                  ERC1155Holder(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) !=
166                  ERC1155Holder.onERC1155BatchReceived.selector
167              ) {
168                  revert UnsafeRecipient();
169:             }

/// @audit to
/// @audit id
/// @audit amount
223              if (
224                  ERC1155Holder(to).onERC1155Received(msg.sender, address(0), id, amount, "") !=
225                  ERC1155Holder.onERC1155Received.selector
226              ) {
227                  revert UnsafeRecipient();
228:             }

GitHub : 111,111,111,111,111,164,164,164,223,223,223

[D-50] Missing contract-existence checks before low-level calls

The contract or caller exists, or it's a transfer of funds

There are 1 instance(s) of this issue:

File: contracts/multicall/Multicall.sol

9        /// @notice Performs multiple calls on the inheritor in a single transaction, and returns the data from each call.
10       /// @param data The calldata for each call
11       /// @return results The data returned by each call
12       function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
13           results = new bytes[](data.length);
14           for (uint256 i = 0; i < data.length; ) {
15               (bool success, bytes memory result) = address(this).delegatecall(data[i]);
16   
17               if (!success) {
18:                  // Bubble up the revert reason

GitHub : 9

[D-51] Modulus operations that could be unchecked

The modulo operator is unaffected by being in an unchecked block, so there is no gas savings

There are 15 instance(s) of this issue:

File: contracts/libraries/Math.sol

89:              sqrtPriceX96 = uint160((sqrtR >> 32) + (sqrtR % (1 << 32) == 0 ? 0 : 1));

GitHub : 89

File: contracts/types/TokenId.sol

95:              return uint256((self >> (64 + legIndex * 48)) % 2);

105:             return uint256((self >> (64 + legIndex * 48 + 1)) % 128);

115:             return uint256((self >> (64 + legIndex * 48 + 8)) % 2);

125:             return uint256((self >> (64 + legIndex * 48 + 9)) % 2);

141:             return uint256((self >> (64 + legIndex * 48 + 10)) % 4);

162:             return int24(int256((self >> (64 + legIndex * 48 + 36)) % 4096));

195:             return self + (uint256(_asset % 2) << (64 + legIndex * 48));

210:             return self + (uint256(_optionRatio % 128) << (64 + legIndex * 48 + 1));

226:             return self + ((_isLong % 2) << (64 + legIndex * 48 + 8));

240:             return self + (uint256(_tokenType % 2) << (64 + legIndex * 48 + 9));

254:             return self + (uint256(_riskPartner % 4) << (64 + legIndex * 48 + 10));

283:             return self + (uint256(uint24(_width) % 4096) << (64 + legIndex * 48 + 36));

397:                 legLowerTick % tickSpacing != 0 ||

398:                 legUpperTick % tickSpacing != 0 ||

GitHub : 95,105,115,125,141,162,195,210,226,240,254,283,397,398

[D-52] Must approve or increase allowance first

The bot is just flagging transferFrom() calls without a prior approval. Many projects require you to approve their contract before using it, so this suggestion is not helpful, and certainly is not 'Low' severity, since that's the design and no funds are lost. There is no way for the project to address this issue other than by requiring that the caller send the tokens themselves, which has its own risks.

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

418              SafeTransferLib.safeTransferFrom(
419                  decoded.poolFeatures.token0,
420                  decoded.payer,
421                  msg.sender,
422                  amount0Owed
423:             );

425              SafeTransferLib.safeTransferFrom(
426                  decoded.poolFeatures.token1,
427                  decoded.payer,
428                  msg.sender,
429                  amount1Owed
430:             );

460:         SafeTransferLib.safeTransferFrom(token, decoded.payer, msg.sender, amountToPay);

GitHub : 418,425,460

[D-53] NatSpec: Contract declarations should have @notice tags

The compiler interprets /// or /** comments as this tag if one wasn't explicitly provided

There are 13 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

72   contract SemiFungiblePositionManager is ERC1155, Multicall {
73       /*//////////////////////////////////////////////////////////////
74                                   EVENTS
75       //////////////////////////////////////////////////////////////*/
76   
77       /// @notice Emitted when a UniswapV3Pool is initialized.
78:      /// @param uniswapPool Address of the underlying Uniswap v3 pool

GitHub : 72

File: contracts/libraries/CallbackLib.sol

10   library CallbackLib {
11:      // Defining characteristics of a Uni V3 pool

GitHub : 10

File: contracts/libraries/Constants.sol

6    library Constants {
7:       // Fixed point multiplier: 2**96

GitHub : 6

File: contracts/libraries/Errors.sol

6    library Errors {
7        /// Errors are alphabetically ordered
8    
9        /// @notice Casting error
10:      /// @dev e.g. uint128(uint256(a)) fails

GitHub : 6

File: contracts/libraries/FeesCalc.sol

38   library FeesCalc {
39:      // enables packing of types within int128|int128 or uint128|uint128 containers.

GitHub : 38

File: contracts/libraries/Math.sol

12:  library Math {

GitHub : 12

File: contracts/libraries/PanopticMath.sol

13   library PanopticMath {
14:      // enables packing of types within int128|int128 or uint128|uint128 containers.

GitHub : 13

File: contracts/libraries/SafeTransferLib.sol

11   library SafeTransferLib {
12       /*//////////////////////////////////////////////////////////////
13                               ERC20 OPERATIONS
14       //////////////////////////////////////////////////////////////*/
15:  

GitHub : 11

File: contracts/multicall/Multicall.sol

8    abstract contract Multicall {
9        /// @notice Performs multiple calls on the inheritor in a single transaction, and returns the data from each call.
10       /// @param data The calldata for each call
11:      /// @return results The data returned by each call

GitHub : 8

File: contracts/tokens/ERC1155Minimal.sol

10   abstract contract ERC1155 {
11       /*//////////////////////////////////////////////////////////////
12                                    EVENTS
13       //////////////////////////////////////////////////////////////*/
14   
15       /// @notice Emitted when only a single token is transferred
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20:      /// @param amount the amount of tokens transferred

GitHub : 10

File: contracts/types/LeftRight.sol

13:  library LeftRight {

GitHub : 13

File: contracts/types/LiquidityChunk.sol

50:  library LiquidityChunk {

GitHub : 50

File: contracts/types/TokenId.sol

56:  library TokenId {

GitHub : 56

[D-54] NatSpec: Function declarations should have @notice tags

The compiler interprets /// or /** comments as this tag if one wasn't explicitly provided

There are 18 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

342:     constructor(IUniswapV3Factory _factory) {

351:     function initializeAMMPool(address token0, address token1, uint24 fee) external {

407      function uniswapV3MintCallback(
408          uint256 amount0Owed,
409          uint256 amount1Owed,
410          bytes calldata data
411:     ) external {

441      function uniswapV3SwapCallback(
442          int256 amount0Delta,
443          int256 amount1Delta,
444          bytes calldata data
445:     ) external {

476      function burnTokenizedPosition(
477          uint256 tokenId,
478          uint128 positionSize,
479          int24 slippageTickLimitLow,
480          int24 slippageTickLimitHigh
481      )
482          external
483          ReentrancyLock(tokenId.univ3pool())
484          returns (int256 totalCollected, int256 totalSwapped, int24 newTick)
485:     {

510      function mintTokenizedPosition(
511          uint256 tokenId,
512          uint128 positionSize,
513          int24 slippageTickLimitLow,
514          int24 slippageTickLimitHigh
515      )
516          external
517          ReentrancyLock(tokenId.univ3pool())
518          returns (int256 totalCollected, int256 totalSwapped, int24 newTick)
519:     {

1343     function getAccountLiquidity(
1344         address univ3pool,
1345         address owner,
1346         uint256 tokenType,
1347         int24 tickLower,
1348         int24 tickUpper
1349:    ) external view returns (uint256 accountLiquidities) {

1371     function getAccountPremium(
1372         address univ3pool,
1373         address owner,
1374         uint256 tokenType,
1375         int24 tickLower,
1376         int24 tickUpper,
1377         int24 atTick,
1378         uint256 isLong
1379:    ) external view returns (uint128 premiumToken0, uint128 premiumToken1) {

1437     function getAccountFeesBase(
1438         address univ3pool,
1439         address owner,
1440         uint256 tokenType,
1441         int24 tickLower,
1442         int24 tickUpper
1443:    ) external view returns (int128 feesBase0, int128 feesBase1) {

1457     function getUniswapV3PoolFromId(
1458         uint64 poolId
1459:    ) external view returns (IUniswapV3Pool UniswapV3Pool) {

1468:    function getPoolId(address univ3pool) external view returns (uint64 poolId) {

GitHub : 342,351,407,441,476,510,1343,1371,1437,1457,1468

File: contracts/libraries/FeesCalc.sol

54       function calculateAMMSwapFeesLiquidityChunk(
55           IUniswapV3Pool univ3pool,
56           int24 currentTick,
57           uint128 startingLiquidity,
58           uint256 liquidityChunk
59       ) public view returns (int256 feesEachToken) {
60           // extract the amount of AMM fees collected within the liquidity chunk`
61:          // note: the fee variables are *per unit of liquidity*; so more "rate" variables

GitHub : 54

File: contracts/multicall/Multicall.sol

12:      function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {

GitHub : 12

File: contracts/tokens/ERC1155Minimal.sol

77:      function setApprovalForAll(address operator, bool approved) public {

90       function safeTransferFrom(
91           address from,
92           address to,
93           uint256 id,
94           uint256 amount,
95           bytes calldata data
96:      ) public {

128      function safeBatchTransferFrom(
129          address from,
130          address to,
131          uint256[] calldata ids,
132          uint256[] calldata amounts,
133          bytes calldata data
134:     ) public virtual {

178      function balanceOfBatch(
179          address[] calldata owners,
180          uint256[] calldata ids
181:     ) public view returns (uint256[] memory balances) {

200:     function supportsInterface(bytes4 interfaceId) public pure returns (bool) {

GitHub : 77,90,128,178,200

[D-55] NatSpec: Modifier declarations should have @notice tags

The compiler interprets /// or /** comments as this tag if one wasn't explicitly provided

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

306      modifier ReentrancyLock(uint64 poolId) {
307          // check if the pool is already locked
308          // init lock if not
309          beginReentrancyLock(poolId);
310  
311          // execute function
312          _;
313  
314          // remove lock
315          endReentrancyLock(poolId);
316:     }

GitHub : 306

[D-56] Nesting if-statements is cheaper than using &&

Nesting when there's an else-block uses more gas, not less

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

774              if ((itm0 != 0) && (itm1 != 0)) {
775                  (uint160 sqrtPriceX96, , , , , , ) = _univ3pool.slot0();
776  
777                  // implement a single "netting" swap. Thank you @danrobinson for this puzzle/idea
778                  // note: negative ITM amounts denote a surplus of tokens (burning liquidity), while positive amounts denote a shortage of tokens (minting liquidity)
779                  // compute the approximate delta of token0 that should be resolved in the swap at the current tick
780                  // we do this by flipping the signs on the token1 ITM amount converting+deducting it against the token0 ITM amount
781                  // couple examples (price = 2 1/0):
782                  //  - 100 surplus 0, 100 surplus 1 (itm0 = -100, itm1 = -100)
783                  //    normal swap 0: 100 0 => 200 1
784                  //    normal swap 1: 100 1 => 50 0
785                  //    final swap amounts: 50 0 => 100 1
786                  //    netting swap: net0 = -100 - (-100/2) = -50, ZF1 = true, 50 0 => 100 1
787                  // - 100 surplus 0, 100 shortage 1 (itm0 = -100, itm1 = 100)
788                  //    normal swap 0: 100 0 => 200 1
789                  //    normal swap 1: 50 0 => 100 1
790                  //    final swap amounts: 150 0 => 300 1
791                  //    netting swap: net0 = -100 - (100/2) = -150, ZF1 = true, 150 0 => 300 1
792                  // - 100 shortage 0, 100 surplus 1 (itm0 = 100, itm1 = -100)
793                  //    normal swap 0: 200 1 => 100 0
794                  //    normal swap 1: 100 1 => 50 0
795                  //    final swap amounts: 300 1 => 150 0
796                  //    netting swap: net0 = 100 - (-100/2) = 150, ZF1 = false, 300 1 => 150 0
797                  // - 100 shortage 0, 100 shortage 1 (itm0 = 100, itm1 = 100)
798                  //    normal swap 0: 200 1 => 100 0
799                  //    normal swap 1: 50 0 => 100 1
800                  //    final swap amounts: 100 1 => 50 0
801                  //    netting swap: net0 = 100 - (100/2) = 50, ZF1 = false, 100 1 => 50 0
802                  // - = Net surplus of token0
803                  // + = Net shortage of token0
804                  int256 net0 = itm0 - PanopticMath.convert1to0(itm1, sqrtPriceX96);
805  
806                  zeroForOne = net0 < 0;
807  
808                  //compute the swap amount, set as positive (exact input)
809                  swapAmount = -net0;
810              } else if (itm0 != 0) {
811                  zeroForOne = itm0 < 0;
812                  swapAmount = -itm0;
813              } else {
814                  zeroForOne = itm1 > 0;
815                  swapAmount = -itm1;
816:             }

GitHub : 774

[D-57] NFT contract redefines _mint()/_safeMint(), but not both

The general rule is valid, but the instances below are invalid

There are 1 instance(s) of this issue:

File: contracts/tokens/ERC1155Minimal.sol

214      function _mint(address to, uint256 id, uint256 amount) internal {
215          // balance will never overflow
216          unchecked {
217              balanceOf[to][id] += amount;
218          }
219  
220          emit TransferSingle(msg.sender, address(0), to, id, amount);
221  
222          if (to.code.length != 0) {
223              if (
224                  ERC1155Holder(to).onERC1155Received(msg.sender, address(0), id, amount, "") !=
225                  ERC1155Holder.onERC1155Received.selector
226              ) {
227                  revert UnsafeRecipient();
228              }
229          }
230:     }

GitHub : 214

[D-58] Non-assembly method available

Low-level assembly calls are usually used to avoid externalities. If these are using assembly to do so, the suggestion to use non-assembly low-level calls is invalid.

There are 1 instance(s) of this issue:

File: contracts/libraries/SafeTransferLib.sol

/// @audit call(): safeTransferFrom()
19           assembly ("memory-safe") {
20               // Get free memory pointer - we will store our calldata in scratch space starting at the offset specified here.
21               let p := mload(0x40)
22   
23               // Write the abi-encoded calldata into memory, beginning with the function selector.
24               mstore(p, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
25               mstore(add(4, p), from) // Append the "from" argument.
26               mstore(add(36, p), to) // Append the "to" argument.
27               mstore(add(68, p), amount) // Append the "amount" argument.
28   
29               success := and(
30                   // Set success to whether the call reverted, if not we check it either
31                   // returned exactly 1 (can't just be non-zero data), or had no return data.
32                   or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
33                   // We use 100 because that's the total length of our calldata (4 + 32 * 3)
34                   // Counterintuitively, this call() must be positioned after the or() in the
35                   // surrounding and() because and() evaluates its arguments from right to left.
36                   call(gas(), token, 0, p, 100, 0, 32)
37               )
38:          }

GitHub : 19

[D-59] Non-library/interface files should use fixed compiler versions, not floating ones

Interfaces should not use fixed compiler versions, since they may be used by projects using a different version

There are 10 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/Constants.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/Errors.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/FeesCalc.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/Math.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/PanopticMath.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/libraries/SafeTransferLib.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/types/LeftRight.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/types/LiquidityChunk.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

File: contracts/types/TokenId.sol

2:   pragma solidity ^0.8.0;

GitHub : 2

[D-60] Not initializing local variables to zero saves gas

This is only true for state variables, and does not save gas for local variables. The examples below are for local variables and therefore do not save gas, and are invalid.

There are 7 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

550:         for (uint256 i = 0; i < ids.length; ) {

583:         for (uint256 leg = 0; leg < numLegs; ) {

860:         for (uint256 leg = 0; leg < numLegs; ) {

GitHub : 550,583,860

File: contracts/multicall/Multicall.sol

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

GitHub : 14

File: contracts/tokens/ERC1155Minimal.sol

141:         for (uint256 i = 0; i < ids.length; ) {

187:             for (uint256 i = 0; i < owners.length; ++i) {

GitHub : 141,187

File: contracts/types/TokenId.sol

468:             for (uint256 i = 0; i < 4; ++i) {

GitHub : 468

[D-61] Numbers downcast to addresses may result in collisions

The general rule is valid, but the instances below are invalid

There are 1 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

36               address(
37                   uint160(
38                       uint256(
39                           keccak256(
40                               abi.encodePacked(
41                                   bytes1(0xff),
42                                   factory,
43                                   keccak256(abi.encode(features)),
44                                   Constants.V3POOL_INIT_CODE_HASH
45                               )
46                           )
47                       )
48                   )
49:              ) != sender

GitHub : 36

[D-62] Open TODOs

Code architecture, incentives, and error handling/reporting questions/issues should be resolved before deployment

There are 2 instance(s) of this issue:

File: contracts/libraries/Math.sol

170:      /// @param toDowncast the uint256 to be downcasted

172:      function toUint128(uint256 toDowncast) internal pure returns (uint128 downcastedInt) {

GitHub : 170,172

[D-63] Optimal State Variable Order

These are constant/immutable variables, so any packing involving them is invalid

There are 5 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

135:     uint128 private constant VEGOID = 2;

GitHub : 135

File: contracts/libraries/Constants.sol

11:      int24 internal constant MIN_V3POOL_TICK = -887272;

14:      int24 internal constant MAX_V3POOL_TICK = 887272;

17:      uint160 internal constant MIN_V3POOL_SQRT_RATIO = 4295128739;

20       uint160 internal constant MAX_V3POOL_SQRT_RATIO =
21:          1461446703485210103287273052203988822378723970342;

GitHub : 11,14,17,20

[D-64] Optimize Gas Usage by Combining Mappings into a Struct

Saves a storage slot for each of the removed mappings, but this is only a deployment gas savings, so if a bot is counting this as anything but zero, it's invalid. In order to save gas, the mappings have to actually be used in the same function/transaction, and that needs to be shown specifically, rather than just flagging all mappings.

There are 8 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit mapping s_poolContext
/// @audit mapping s_accountLiquidity
/// @audit mapping s_accountPremiumOwed
/// @audit mapping s_accountPremiumGross
/// @audit mapping s_accountFeesBase
/// @audit mapping s_AddrToPoolIdData
72   contract SemiFungiblePositionManager is ERC1155, Multicall {
73       /*//////////////////////////////////////////////////////////////
74                                   EVENTS
75       //////////////////////////////////////////////////////////////*/
76   
77       /// @notice Emitted when a UniswapV3Pool is initialized.
78:      /// @param uniswapPool Address of the underlying Uniswap v3 pool

GitHub : 72,72,72,72,72,72

File: contracts/tokens/ERC1155Minimal.sol

/// @audit mapping balanceOf
/// @audit mapping isApprovedForAll
10   abstract contract ERC1155 {
11       /*//////////////////////////////////////////////////////////////
12                                    EVENTS
13       //////////////////////////////////////////////////////////////*/
14   
15       /// @notice Emitted when only a single token is transferred
16       /// @param operator the user who initiated the transfer
17       /// @param from the user who sent the tokens
18       /// @param to the user who received the tokens
19       /// @param id the ERC1155 token id
20:      /// @param amount the amount of tokens transferred

GitHub : 10,10

[D-65] Overflows in unchecked blocks

This cannot overflow due to the for-/while-condition

There are 7 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

553:                 ++i;

632:                 ++leg;

910:                 ++leg;

GitHub : 553,632,910

File: contracts/multicall/Multicall.sol

33:                  ++i;

GitHub : 33

File: contracts/tokens/ERC1155Minimal.sol

155:                 ++i;

187:             for (uint256 i = 0; i < owners.length; ++i) {

GitHub : 155,187

File: contracts/types/TokenId.sol

468:             for (uint256 i = 0; i < 4; ++i) {

GitHub : 468

[D-66] Overly complicated arithmetic

At least one bot is incorrectly flagging code comments as 'complicated arithmetic'

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

171:       * |<------- 128 bits ------->|<------- 128 bits ------->|

172:       * |<---------------------- 256 bits ------------------->|

GitHub : 171,172

[D-67] Public functions not used internally can be marked as external to save gas

After Solidity version 0.6.9 both public and external functions save the same amount of gas, and since these files are >0.6.9, these findings are invalid

There are 7 instance(s) of this issue:

File: contracts/libraries/FeesCalc.sol

54        function calculateAMMSwapFeesLiquidityChunk(
55            IUniswapV3Pool univ3pool,
56            int24 currentTick,
57            uint128 startingLiquidity,
58            uint256 liquidityChunk
59:       ) public view returns (int256 feesEachToken) {

GitHub : 54

File: contracts/multicall/Multicall.sol

12:       function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {

GitHub : 12

File: contracts/tokens/ERC1155Minimal.sol

77:       function setApprovalForAll(address operator, bool approved) public {

90        function safeTransferFrom(
91            address from,
92            address to,
93            uint256 id,
94            uint256 amount,
95:           bytes calldata data

128       function safeBatchTransferFrom(
129           address from,
130           address to,
131           uint256[] calldata ids,
132           uint256[] calldata amounts,
133:          bytes calldata data

178       function balanceOfBatch(
179           address[] calldata owners,
180           uint256[] calldata ids
181:      ) public view returns (uint256[] memory balances) {

200:      function supportsInterface(bytes4 interfaceId) public pure returns (bool) {

GitHub : 77,90,128,178,200

[D-68] Redundant Contract Existence Check in Consecutive External Calls

These are not external calls, so instances involving these are invalid

There are 22 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

368:         uint64 poolId = PanopticMath.getPoolId(univ3pool);

415:         CallbackLib.validateCallback(msg.sender, address(FACTORY), decoded.poolFeatures);

449:         CallbackLib.validateCallback(msg.sender, address(FACTORY), decoded.poolFeatures);

460:         SafeTransferLib.safeTransferFrom(token, decoded.payer, msg.sender, amountToPay);

582:         uint256 numLegs = id.countLegs();

586              uint256 liquidityChunk = PanopticMath.getLiquidityChunk(
587                  id,
588                  leg,
589                  uint128(amount),
590                  univ3pool.tickSpacing()
591:             );

858:         uint256 numLegs = tokenId.countLegs();

882                  uint256 liquidityChunk = PanopticMath.getLiquidityChunk(
883                      _tokenId,
884                      _leg,
885                      _positionSize,
886                      _univ3pool.tickSpacing()
887:                 );

943:         uint256 _tokenType = TokenId.tokenType(_tokenId, _leg);

958:         uint256 isLong = TokenId.isLong(_tokenId, _leg);

1208:        uint128 startingLiquidity = currentLiquidity.rightSlot();

1260:        uint256 removedLiquidity = currentLiquidity.leftSlot();

1261:        uint256 netLiquidity = currentLiquidity.rightSlot();

1393:            uint128 netLiquidity = accountLiquidities.rightSlot();

1403                     int256 feesBase = FeesCalc.calculateAMMSwapFeesLiquidityChunk(
1404                         _univ3pool,
1405                         atTick,
1406                         netLiquidity,
1407                         tempChunk
1408:                    );

GitHub : 368,415,449,460,582,586,858,882,943,958,1208,1260,1261,1393,1403

File: contracts/libraries/PanopticMath.sol

89:          (int24 tickLower, int24 tickUpper) = tokenId.asTicks(legIndex, tickSpacing);

GitHub : 89

File: contracts/types/TokenId.sol

490:                 uint256 riskPartnerIndex = self.riskPartner(i);

503:                     uint256 isLong = self.isLong(i);

504:                     uint256 isLongP = self.isLong(riskPartnerIndex);

507:                     uint256 tokenType = self.tokenType(i);

508:                     uint256 tokenTypeP = self.tokenType(riskPartnerIndex);

523:         return self.univ3pool();

GitHub : 490,503,504,507,508,523

[D-69] Return values of transfer()/transferFrom() not checked

The examples below are for known contracts that revert if they fail, are for non-ERC20 contracts, or aren't the right function

There are 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

551:             registerTokenTransfer(from, to, ids[i], amounts[i]);

569:         registerTokenTransfer(from, to, id, amount);

GitHub : 551,569

File: contracts/tokens/ERC1155Minimal.sol

106:         afterTokenTransfer(from, to, id, amount);

159:         afterTokenTransfer(from, to, ids, amounts);

GitHub : 106,159

[D-70] Revert on transfer to the zero address

Forcing called tokens to not allow transfers to address(0) breaks composability if that token requires this functionality.

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

418              SafeTransferLib.safeTransferFrom(
419                  decoded.poolFeatures.token0,
420                  decoded.payer,
421                  msg.sender,
422                  amount0Owed
423:             );

425              SafeTransferLib.safeTransferFrom(
426                  decoded.poolFeatures.token1,
427                  decoded.payer,
428                  msg.sender,
429                  amount1Owed
430:             );

460:         SafeTransferLib.safeTransferFrom(token, decoded.payer, msg.sender, amountToPay);

GitHub : 418,425,460

[D-71] safeMint should be used in place of mint

These are not ERC721.mint() calls

There are 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1147         (uint256 amount0, uint256 amount1) = univ3pool.mint(
1148             address(this),
1149             liquidityChunk.tickLower(),
1150             liquidityChunk.tickUpper(),
1151             liquidityChunk.liquidity(),
1152             mintdata
1153:        );

GitHub : 1147

[D-72] Same cast is done multiple times

The general rule is valid, but the instances below are invalid

There are 1 instance(s) of this issue:

File: contracts/libraries/Math.sol

40:              uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));

GitHub : 40

[D-73] SPDX identifier should be the in the first line of a solidity file

It's already on the first line

There are 13 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1:    // SPDX-License-Identifier: BUSL-1.1

GitHub : 1

File: contracts/libraries/CallbackLib.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

File: contracts/libraries/Constants.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

File: contracts/libraries/Errors.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

File: contracts/libraries/FeesCalc.sol

1:    // SPDX-License-Identifier: BUSL-1.1

GitHub : 1

File: contracts/libraries/Math.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

File: contracts/libraries/PanopticMath.sol

1:    // SPDX-License-Identifier: BUSL-1.1

GitHub : 1

File: contracts/libraries/SafeTransferLib.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

File: contracts/multicall/Multicall.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

File: contracts/tokens/ERC1155Minimal.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

File: contracts/types/LeftRight.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

File: contracts/types/LiquidityChunk.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

File: contracts/types/TokenId.sol

1:    // SPDX-License-Identifier: GPL-2.0-or-later

GitHub : 1

[D-74] State variable read in a loop

These references to the variable cannot be cached, or the variable is constant/immutable

There are 14 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit s_poolContext
370:         while (address(s_poolContext[poolId].pool) != address(0)) {

/// @audit s_accountLiquidity
615:                 (s_accountLiquidity[positionKey_to] != 0) ||

/// @audit s_accountFeesBase
616:                 (s_accountFeesBase[positionKey_to] != 0)

/// @audit s_accountLiquidity
620:             uint256 fromLiq = s_accountLiquidity[positionKey_from];

/// @audit s_accountFeesBase
623:             int256 fromBase = s_accountFeesBase[positionKey_from];

/// @audit s_accountLiquidity
626:             s_accountLiquidity[positionKey_to] = fromLiq;

/// @audit s_accountLiquidity
627:             s_accountLiquidity[positionKey_from] = 0;

/// @audit s_accountFeesBase
629:             s_accountFeesBase[positionKey_to] = fromBase;

/// @audit s_accountFeesBase
630:             s_accountFeesBase[positionKey_from] = 0;

GitHub : 370,615,616,620,623,626,627,629,630

File: contracts/tokens/ERC1155Minimal.sol

/// @audit balanceOf
145:             balanceOf[from][id] -= amount;

/// @audit balanceOf
149:                 balanceOf[to][id] += amount;

/// @audit balanceOf
188:                 balances[i] = balanceOf[owners[i]][ids[i]];

GitHub : 145,149,188

File: contracts/types/TokenId.sol

/// @audit MIN_V3POOL_TICK
483:                     (self.strike(i) == Constants.MIN_V3POOL_TICK) ||

/// @audit MAX_V3POOL_TICK
484:                     (self.strike(i) == Constants.MAX_V3POOL_TICK)

GitHub : 483,484

[D-75] Storage Write Removal Bug On Conditional Early Termination

In solidity versions 0.8.13 through 0.8.16, there is a bug involving the use of the Yul functions return() and stop(). If those functions aren't called, or if the Solidity version doesn't match, the finding is not low severity.

There are 30 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

393          assembly {
394              mstore(0, 0xFA20F71C)
395:         }

GitHub : 393

File: contracts/libraries/Math.sol

199              assembly ("memory-safe") {
200                  let mm := mulmod(a, b, not(0))
201                  prod0 := mul(a, b)
202                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
203:             }

208                  assembly ("memory-safe") {
209                      result := div(prod0, denominator)
210:                 }

225              assembly ("memory-safe") {
226                  remainder := mulmod(a, b, denominator)
227:             }

229              assembly ("memory-safe") {
230                  prod1 := sub(prod1, gt(remainder, prod0))
231                  prod0 := sub(prod0, remainder)
232:             }

239              assembly ("memory-safe") {
240                  denominator := div(denominator, twos)
241:             }

244              assembly ("memory-safe") {
245                  prod0 := div(prod0, twos)
246:             }

250              assembly ("memory-safe") {
251                  twos := add(div(sub(0, twos), twos), 1)
252:             }

295              assembly ("memory-safe") {
296                  let mm := mulmod(a, b, not(0))
297                  prod0 := mul(a, b)
298                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
299:             }

303                  assembly ("memory-safe") {
304                      // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
305                      result := shr(64, prod0)
306:                 }

320              assembly ("memory-safe") {
321                  remainder := mulmod(a, b, 0x10000000000000000)
322:             }

324              assembly ("memory-safe") {
325                  prod1 := sub(prod1, gt(remainder, prod0))
326                  prod0 := sub(prod0, remainder)
327:             }

330              assembly ("memory-safe") {
331                  // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
332                  prod0 := shr(64, prod0)
333:             }

357              assembly ("memory-safe") {
358                  let mm := mulmod(a, b, not(0))
359                  prod0 := mul(a, b)
360                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
361:             }

365                  assembly ("memory-safe") {
366                      // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
367                      result := shr(96, prod0)
368:                 }

382              assembly ("memory-safe") {
383                  remainder := mulmod(a, b, 0x1000000000000000000000000)
384:             }

386              assembly ("memory-safe") {
387                  prod1 := sub(prod1, gt(remainder, prod0))
388                  prod0 := sub(prod0, remainder)
389:             }

392              assembly ("memory-safe") {
393                  // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
394                  prod0 := shr(96, prod0)
395:             }

419              assembly ("memory-safe") {
420                  let mm := mulmod(a, b, not(0))
421                  prod0 := mul(a, b)
422                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
423:             }

427                  assembly ("memory-safe") {
428                      // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
429                      result := shr(128, prod0)
430:                 }

444              assembly ("memory-safe") {
445                  remainder := mulmod(a, b, 0x100000000000000000000000000000000)
446:             }

448              assembly ("memory-safe") {
449                  prod1 := sub(prod1, gt(remainder, prod0))
450                  prod0 := sub(prod0, remainder)
451:             }

454              assembly ("memory-safe") {
455                  // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
456                  prod0 := shr(128, prod0)
457:             }

481              assembly ("memory-safe") {
482                  let mm := mulmod(a, b, not(0))
483                  prod0 := mul(a, b)
484                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
485:             }

489                  assembly ("memory-safe") {
490                      // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
491                      result := shr(192, prod0)
492:                 }

506              assembly ("memory-safe") {
507                  remainder := mulmod(a, b, 0x1000000000000000000000000000000000000000000000000)
508:             }

510              assembly ("memory-safe") {
511                  prod1 := sub(prod1, gt(remainder, prod0))
512                  prod0 := sub(prod0, remainder)
513:             }

516              assembly ("memory-safe") {
517                  // Right shift by n is equivalent and 2 gas cheaper than division by 2^n
518                  prod0 := shr(192, prod0)
519:             }

GitHub : 199,208,225,229,239,244,250,295,303,320,324,330,357,365,382,386,392,419,427,444,448,454,481,489,506,510,516

File: contracts/libraries/SafeTransferLib.sol

19           assembly ("memory-safe") {
20               // Get free memory pointer - we will store our calldata in scratch space starting at the offset specified here.
21               let p := mload(0x40)
22   
23               // Write the abi-encoded calldata into memory, beginning with the function selector.
24               mstore(p, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
25               mstore(add(4, p), from) // Append the "from" argument.
26               mstore(add(36, p), to) // Append the "to" argument.
27               mstore(add(68, p), amount) // Append the "amount" argument.
28   
29               success := and(
30                   // Set success to whether the call reverted, if not we check it either
31                   // returned exactly 1 (can't just be non-zero data), or had no return data.
32                   or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
33                   // We use 100 because that's the total length of our calldata (4 + 32 * 3)
34                   // Counterintuitively, this call() must be positioned after the or() in the
35                   // surrounding and() because and() evaluates its arguments from right to left.
36                   call(gas(), token, 0, p, 100, 0, 32)
37               )
38:          }

GitHub : 19

File: contracts/multicall/Multicall.sol

25                   assembly ("memory-safe") {
26                       revert(add(result, 32), mload(result))
27:                  }

GitHub : 25

[D-76] Style guide: constant/immutable variable names should use capital letters and underscores

These are already CONSTANT_CASE

There are 7 instance(s) of this issue:

File: contracts/libraries/Constants.sol

8:       uint256 internal constant FP96 = 0x1000000000000000000000000;

11:      int24 internal constant MIN_V3POOL_TICK = -887272;

14:      int24 internal constant MAX_V3POOL_TICK = 887272;

17:      uint160 internal constant MIN_V3POOL_SQRT_RATIO = 4295128739;

20       uint160 internal constant MAX_V3POOL_SQRT_RATIO =
21:          1461446703485210103287273052203988822378723970342;

25       bytes32 internal constant V3POOL_INIT_CODE_HASH =
26           keccak256(
27               hex"6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000a"
28:          );

GitHub : 8,11,14,17,20,25

File: contracts/types/TokenId.sol

68:      int256 internal constant BITMASK_INT24 = 0xFFFFFF;

GitHub : 68

[D-77] Style guide: Contract does not follow the Solidity style guide's suggested layout ordering

There are no issues with contract layout in these contracts

There are 11 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

10:   library CallbackLib {

GitHub : 10

File: contracts/libraries/Constants.sol

6:    library Constants {

GitHub : 6

File: contracts/libraries/Errors.sol

6:    library Errors {

GitHub : 6

File: contracts/libraries/FeesCalc.sol

38:   library FeesCalc {

GitHub : 38

File: contracts/libraries/Math.sol

12:   library Math {

GitHub : 12

File: contracts/libraries/PanopticMath.sol

13:   library PanopticMath {

GitHub : 13

File: contracts/libraries/SafeTransferLib.sol

11:   library SafeTransferLib {

GitHub : 11

File: contracts/multicall/Multicall.sol

8:    abstract contract Multicall {

GitHub : 8

File: contracts/types/LeftRight.sol

13:   library LeftRight {

GitHub : 13

File: contracts/types/LiquidityChunk.sol

50:   library LiquidityChunk {

GitHub : 50

File: contracts/types/TokenId.sol

56:   library TokenId {

GitHub : 56

[D-78] Style guide: Function Names Not in mixedCase

According to the Solidity Style Guide, non-external/public function names should begin with an underscore, and all of these fall into that category

There are 8 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

1073     function _updateStoredPremia(
1074         bytes32 positionKey,
1075         uint256 currentLiquidity,
1076         int256 collectedAmounts
1077:    ) private {

1093     function _getFeesBase(
1094         IUniswapV3Pool univ3pool,
1095         uint128 liquidity,
1096         uint256 liquidityChunk
1097:    ) private view returns (int256 feesBase) {

1129     function _mintLiquidity(
1130         uint256 liquidityChunk,
1131         IUniswapV3Pool univ3pool
1132:    ) internal returns (int256 movedAmounts) {

1169     function _burnLiquidity(
1170         uint256 liquidityChunk,
1171         IUniswapV3Pool univ3pool
1172:    ) internal returns (int256 movedAmounts) {

1200     function _collectAndWritePositionData(
1201         uint256 liquidityChunk,
1202         IUniswapV3Pool univ3pool,
1203         uint256 currentLiquidity,
1204         bytes32 positionKey,
1205         int256 movedInLeg,
1206         uint256 isLong
1207:    ) internal returns (int256 collectedOut) {

1255     function _getPremiaDeltas(
1256         uint256 currentLiquidity,
1257         int256 collectedAmounts
1258:    ) private pure returns (uint256 deltaPremiumOwed, uint256 deltaPremiumGross) {

GitHub : 1073,1093,1129,1169,1200,1255

File: contracts/tokens/ERC1155Minimal.sol

214:     function _mint(address to, uint256 id, uint256 amount) internal {

236:     function _burn(address from, uint256 id, uint256 amount) internal {

GitHub : 214,236

[D-79] Style guide: Function names should use lowerCamelCase

The general rule is valid, but the instances below are invalid

There are 3 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

351:     function initializeAMMPool(address token0, address token1, uint24 fee) external {

GitHub : 351

File: contracts/libraries/FeesCalc.sol

54       function calculateAMMSwapFeesLiquidityChunk(
55           IUniswapV3Pool univ3pool,
56           int24 currentTick,
57           uint128 startingLiquidity,
58           uint256 liquidityChunk
59       ) public view returns (int256 feesEachToken) {
60           // extract the amount of AMM fees collected within the liquidity chunk`
61:          // note: the fee variables are *per unit of liquidity*; so more "rate" variables

89       function _getAMMSwapFeesPerLiquidityCollected(
90           IUniswapV3Pool univ3pool,
91           int24 currentTick,
92           int24 tickLower,
93           int24 tickUpper
94:      ) internal view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) {

GitHub : 54,89

[D-80] Subtraction in unchecked block is unsafe

The general rule is valid, but the instances below are invalid

There are 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

804:                 int256 net0 = itm0 - PanopticMath.convert1to0(itm1, sqrtPriceX96);

GitHub : 804

File: contracts/libraries/Math.sol

126:             return mulDiv96(liquidityChunk.liquidity(), highPriceX96 - lowPriceX96);

145:                     mulDiv(amount0, mulDiv96(highPriceX96, lowPriceX96), highPriceX96 - lowPriceX96)

161:             return toUint128(mulDiv(amount1, Constants.FP96, highPriceX96 - lowPriceX96));

GitHub : 126,145,161

[D-81] Subtraction may underflow if multiplication is too large

The general rule is valid, but the instances below are invalid

There are 6 instance(s) of this issue:

File: contracts/libraries/Math.sol

264:             inv *= 2 - denominator * inv; // inverse mod 2**8

265:             inv *= 2 - denominator * inv; // inverse mod 2**16

266:             inv *= 2 - denominator * inv; // inverse mod 2**32

267:             inv *= 2 - denominator * inv; // inverse mod 2**64

268:             inv *= 2 - denominator * inv; // inverse mod 2**128

269:             inv *= 2 - denominator * inv; // inverse mod 2**256

GitHub : 264,265,266,267,268,269

[D-82] 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 1 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit Errors.TransferFailed() on line 617
621:              if (fromLiq.rightSlot() != liquidityChunk.liquidity()) revert Errors.TransferFailed();

GitHub : 621

[D-83] Top level pragma declarations should be separated by two blank lines

Pragmas aren't top-level declarations, and the style guide doesn't use two spaces there.

There are 13 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

2    pragma solidity =0.8.18;
3    
4:   // Interfaces

GitHub : 2

File: contracts/libraries/CallbackLib.sol

2    pragma solidity ^0.8.0;
3    
4:   // Libraries

GitHub : 2

File: contracts/libraries/Constants.sol

2    pragma solidity ^0.8.0;
3    
4:   /// @title Library of Constants used in Panoptic.

GitHub : 2

File: contracts/libraries/Errors.sol

2    pragma solidity ^0.8.0;
3    
4:   /// @title Custom Errors library.

GitHub : 2

File: contracts/libraries/FeesCalc.sol

2    pragma solidity ^0.8.0;
3    
4:   // Interfaces

GitHub : 2

File: contracts/libraries/Math.sol

2    pragma solidity ^0.8.0;
3    
4:   // Libraries

GitHub : 2

File: contracts/libraries/PanopticMath.sol

2    pragma solidity ^0.8.0;
3    
4:   // Libraries

GitHub : 2

File: contracts/libraries/SafeTransferLib.sol

2    pragma solidity ^0.8.0;
3    
4:   // Libraries

GitHub : 2

File: contracts/multicall/Multicall.sol

2    pragma solidity =0.8.18;
3    
4:   /// @title Multicall

GitHub : 2

File: contracts/tokens/ERC1155Minimal.sol

2    pragma solidity ^0.8.0;
3    
4:   // OpenZeppelin libraries

GitHub : 2

File: contracts/types/LeftRight.sol

2    pragma solidity ^0.8.0;
3    
4:   // Libraries

GitHub : 2

File: contracts/types/LiquidityChunk.sol

2    pragma solidity ^0.8.0;
3    
4:   // Custom types

GitHub : 2

File: contracts/types/TokenId.sol

2    pragma solidity ^0.8.0;
3    
4:   // Libraries

GitHub : 2

[D-84] Trade-offs Between Modifiers and Internal Functions

There is nothing that the sponsor can do that would make this finding disappear, besides never using modifiers, so it's not a useful finding.

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

483:         ReentrancyLock(tokenId.univ3pool())

517:         ReentrancyLock(tokenId.univ3pool())

GitHub : 483,517

[D-85] Unchecked return value of low-level call()/delegatecall()

The general rule is valid, but the instances below are invalid

There are 1 instance(s) of this issue:

File: contracts/multicall/Multicall.sol

15               (bool success, bytes memory result) = address(this).delegatecall(data[i]);
16   
17               if (!success) {
18:                  // Bubble up the revert reason

GitHub : 15

[D-86] Unnecessary cast wastes gas

Removing the cast does not save any gas

There are 13 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit address
356:         if (address(univ3pool) == address(0)) revert Errors.UniswapPoolNotInitialized();

/// @audit address
453:             ? address(decoded.poolFeatures.token0)

/// @audit address
454:             : address(decoded.poolFeatures.token1);

/// @audit address
1381:            abi.encodePacked(address(univ3pool), owner, tokenType, tickLower, tickUpper)

GitHub : 356,453,454,1381

File: contracts/types/TokenId.sol

/// @audit uint256
95:              return uint256((self >> (64 + legIndex * 48)) % 2);

/// @audit uint256
105:             return uint256((self >> (64 + legIndex * 48 + 1)) % 128);

/// @audit uint256
115:             return uint256((self >> (64 + legIndex * 48 + 8)) % 2);

/// @audit uint256
125:             return uint256((self >> (64 + legIndex * 48 + 9)) % 2);

/// @audit uint256
141:             return uint256((self >> (64 + legIndex * 48 + 10)) % 4);

/// @audit uint256
195:             return self + (uint256(_asset % 2) << (64 + legIndex * 48));

/// @audit uint256
210:             return self + (uint256(_optionRatio % 128) << (64 + legIndex * 48 + 1));

/// @audit uint256
240:             return self + (uint256(_tokenType % 2) << (64 + legIndex * 48 + 9));

/// @audit uint256
254:             return self + (uint256(_riskPartner % 4) << (64 + legIndex * 48 + 10));

GitHub : 95,105,115,125,141,195,210,240,254

[D-87] Unnecessary look up in if condition

There are 14 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

615                  (s_accountLiquidity[positionKey_to] != 0) ||
616:                 (s_accountFeesBase[positionKey_to] != 0)

713:         if ((newTick >= tickLimitHigh) || (newTick <= tickLimitLow)) revert Errors.PriceBoundFail();

917:         if (amount0 > uint128(type(int128).max) || amount1 > uint128(type(int128).max))

GitHub : 615,713,917

File: contracts/tokens/ERC1155Minimal.sol

97:          if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

135:         if (!(msg.sender == from || isApprovedForAll[from][msg.sender])) revert NotAuthorized();

202              interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
203:             interfaceId == 0xd9b67a26; // ERC165 Interface ID for ERC1155

GitHub : 97,135,202

File: contracts/types/LeftRight.sol

151:             if (z < x || (uint128(z) < uint128(x))) revert Errors.UnderOverFlow();

167:             if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

185:             if (left128 != left256 || right128 != right256) revert Errors.UnderOverFlow();

GitHub : 151,167,185

File: contracts/types/TokenId.sol

397                  legLowerTick % tickSpacing != 0 ||
398                  legUpperTick % tickSpacing != 0 ||
399                  legLowerTick < minTick ||
400:                 legUpperTick > maxTick

397                  legLowerTick % tickSpacing != 0 ||
398                  legUpperTick % tickSpacing != 0 ||
399:                 legLowerTick < minTick ||

397                  legLowerTick % tickSpacing != 0 ||
398:                 legUpperTick % tickSpacing != 0 ||

483                      (self.strike(i) == Constants.MIN_V3POOL_TICK) ||
484:                     (self.strike(i) == Constants.MAX_V3POOL_TICK)

498                          (self.asset(riskPartnerIndex) != self.asset(i)) ||
499:                         (self.optionRatio(riskPartnerIndex) != self.optionRatio(i))

GitHub : 397,397,397,483,498

[D-88] Unsafe downcast

When a type is downcast to a smaller type, the higher order bits are truncated, effectively applying a modulo to the original value. Without any other checks, this wrapping will lead to unexpected behavior and bugs

There are 51 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit uint256 amount -> uint128
589:                  uint128(amount),

/// @audit int256
820:              if (swapAmount == 0) return int256(0);

/// @audit int256
835:              totalSwapped = int256(0).toRightSlot(swap0.toInt128()).toLeftSlot(swap1.toInt128());

/// @audit uint128
917:          if (amount0 > uint128(type(int128).max) || amount1 > uint128(type(int128).max))

/// @audit int256
1119:         feesBase = int256(0)

/// @audit int128 -> int256
/// @audit int256
1120:             .toRightSlot(int128(int256(Math.mulDiv128(feeGrowthInside0LastX128, liquidity))))

/// @audit int128 -> int256
/// @audit int256
1121:             .toLeftSlot(int128(int256(Math.mulDiv128(feeGrowthInside1LastX128, liquidity))));

/// @audit int256
/// @audit int128 -> int256
1159:         movedAmounts = int256(0).toRightSlot(int128(int256(amount0))).toLeftSlot(

/// @audit int128 -> int256
1160:             int128(int256(amount1))

/// @audit int256
/// @audit int128 -> int256
1186:             movedAmounts = int256(0).toRightSlot(-int128(int256(amount0))).toLeftSlot(

/// @audit int128 -> int256
1187:                 -int128(int256(amount1))

/// @audit uint128
1226:                 uint128(amountToCollect.rightSlot()),

/// @audit uint128
1227:                 uint128(amountToCollect.leftSlot())

/// @audit uint128
1235:                     ? receivedAmount0 - uint128(-movedInLeg.rightSlot())

/// @audit uint128
1238:                     ? receivedAmount1 - uint128(-movedInLeg.leftSlot())

/// @audit int256
1244:             collectedOut = int256(0).toRightSlot(collected0).toLeftSlot(collected1);

/// @audit uint128
1276:                 uint128 collected0 = uint128(collectedAmounts.rightSlot());

/// @audit uint128
1277:                 uint128 collected1 = uint128(collectedAmounts.leftSlot());

GitHub : 589,820,835,917,1119,1120,1120,1121,1121,1159,1159,1160,1186,1186,1187,1226,1227,1235,1238,1244,1276,1277

File: contracts/libraries/CallbackLib.sol

/// @audit uint160 -> uint256
37                    uint160(
38                        uint256(
39                            keccak256(
40                                abi.encodePacked(
41                                    bytes1(0xff),
42                                    factory,
43                                    keccak256(abi.encode(features)),
44                                    Constants.V3POOL_INIT_CODE_HASH
45                                )
46                            )
47                        )
48:                   )

GitHub : 37

File: contracts/libraries/FeesCalc.sol

/// @audit int128 -> int256
/// @audit int256
76:               .toRightSlot(int128(int256(Math.mulDiv128(ammFeesPerLiqToken0X128, startingLiquidity))))

/// @audit int128 -> int256
/// @audit int256
77:               .toLeftSlot(int128(int256(Math.mulDiv128(ammFeesPerLiqToken1X128, startingLiquidity))));

GitHub : 76,76,77,[77](https://github.com/code-423n4/2023-11-panoptic/blob/2647928c33be4a58883110befd7fd065448478ef/contr

View raw

(Sorry about that, but we can’t show files that are this big right now.)

@thebrittfactor
Copy link

Report was inadvertently truncated. Remainder of report added below:

GitHub : 76,76,77,77

File: contracts/libraries/Math.sol

/// @audit int256
41:               if (absTick > uint256(int256(Constants.MAX_V3POOL_TICK))) revert Errors.InvalidTick();

/// @audit uint160
89:               sqrtPriceX96 = uint160((sqrtR >> 32) + (sqrtR % (1 << 32) == 0 ? 0 : 1));

/// @audit uint256 toDowncast -> uint128
173:          if ((downcastedInt = uint128(toDowncast)) != toDowncast) revert Errors.CastingError();

GitHub : 41,89,173

File: contracts/types/LeftRight.sol

/// @audit uint256 self -> uint128
26:           return uint128(self);

/// @audit int256 self -> int128
33:           return int128(self);

/// @audit uint128
90:           return uint128(self >> 128);

/// @audit int128
97:           return int128(self >> 128);

/// @audit uint256 z -> uint128
/// @audit uint256 x -> uint128
151:              if (z < x || (uint128(z) < uint128(x))) revert Errors.UnderOverFlow();

/// @audit int256
161:              int256 left256 = int256(x.leftSlot()) + y.leftSlot();

/// @audit int256 left256 -> int128
162:              int128 left128 = int128(left256);

/// @audit int256
164:              int256 right256 = int256(x.rightSlot()) + y.rightSlot();

/// @audit int256 right256 -> int128
165:              int128 right128 = int128(right256);

/// @audit int256
179:              int256 left256 = int256(x.leftSlot()) - y.leftSlot();

/// @audit int256 left256 -> int128
180:              int128 left128 = int128(left256);

/// @audit int256
182:              int256 right256 = int256(x.rightSlot()) - y.rightSlot();

/// @audit int256 right256 -> int128
183:              int128 right128 = int128(right256);

/// @audit int256 self -> int128
199:          if (!((selfAsInt128 = int128(self)) == self)) revert Errors.CastingError();

/// @audit uint256 self -> uint128
206:          if (!((selfAsUint128 = uint128(self)) == self)) revert Errors.CastingError();

GitHub : 26,33,90,97,151,151,161,162,164,165,179,180,182,183,199,206

File: contracts/types/LiquidityChunk.sol

/// @audit int24 -> int256
/// @audit int256
114:              return int24(int256(self >> 232));

/// @audit int24 -> int256
/// @audit int256
123:              return int24(int256(self >> 208));

/// @audit uint256 self -> uint128
132:              return uint128(self);

GitHub : 114,114,123,123,132

[D-89] Unused error definition

The error is used in a file that is different from the one in which it is defined

There are 14 instance(s) of this issue:

File: contracts/libraries/Errors.sol

11:      error CastingError();

14:      error InvalidTick();

17:      error InvalidUniswapCallback();

21:      error InvalidTokenIdParameter(uint256 parameterType);

24:      error LeftRightInputError();

30:      error PositionTooLarge();

33:      error NotEnoughLiquidity();

36:      error OptionsBalanceZero();

39:      error PriceBoundFail();

42:      error ReentrantCall();

45:      error TransferFailed();

49:      error TicksNotInitializable();

52:      error UnderOverFlow();

55:      error UniswapPoolNotInitialized();

GitHub : 11,14,17,21,24,30,33,36,39,42,45,49,52,55

[D-90] Unused struct definition

These structs are used outside of the defining contract

There are 2 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

12       struct PoolFeatures {
13           address token0;
14           address token1;
15           uint24 fee;
16:      }

19       struct CallbackData {
20           PoolFeatures poolFeatures;
21           address payer;
22:      }

GitHub : 12,19

[D-91] Unused contract variables

The variable is used outside of the contract in which it is defined

There are 21 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

127:     bool internal constant MINT = false;

128:     bool internal constant BURN = true;

135:     uint128 private constant VEGOID = 2;

139:     IUniswapV3Factory internal immutable FACTORY;

147:     mapping(address univ3pool => uint256 poolIdData) internal s_AddrToPoolIdData;

152:     mapping(uint64 poolId => PoolAddressAndLock contextData) internal s_poolContext;

179:     mapping(bytes32 positionKey => uint256 removedAndNetLiquidity) internal s_accountLiquidity;

288:     mapping(bytes32 positionKey => uint256 accountPremium) private s_accountPremiumOwed;

290:     mapping(bytes32 positionKey => uint256 accountPremium) private s_accountPremiumGross;

296:     mapping(bytes32 positionKey => int256 baseFees0And1) internal s_accountFeesBase;

GitHub : 127,128,135,139,147,152,179,288,290,296

File: contracts/libraries/Constants.sol

8:       uint256 internal constant FP96 = 0x1000000000000000000000000;

11:      int24 internal constant MIN_V3POOL_TICK = -887272;

14:      int24 internal constant MAX_V3POOL_TICK = 887272;

17:      uint160 internal constant MIN_V3POOL_SQRT_RATIO = 4295128739;

20       uint160 internal constant MAX_V3POOL_SQRT_RATIO =
21:          1461446703485210103287273052203988822378723970342;

25       bytes32 internal constant V3POOL_INIT_CODE_HASH =
26           keccak256(
27               hex"6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000a"
28:          );

GitHub : 8,11,14,17,20,25

File: contracts/types/LeftRight.sol

16:      int256 internal constant RIGHT_HALF_BIT_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

GitHub : 16

File: contracts/types/TokenId.sol

60       uint256 internal constant LONG_MASK =
61:          0x100_000000000100_000000000100_000000000100_0000000000000000;

63       uint256 internal constant CLEAR_POOLID_MASK =
64:          0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_0000000000000000;

66       uint256 internal constant OPTION_RATIO_MASK =
67:          0x0000000000FE_0000000000FE_0000000000FE_0000000000FE_0000000000000000;

68:      int256 internal constant BITMASK_INT24 = 0xFFFFFF;

GitHub : 60,63,66,68

[D-92] Unused function parameter

The variable is in fact used, so the instances below are invalid

There are 14 instance(s) of this issue:

File: contracts/libraries/Math.sol

/// @audit a
187:         uint256 a,

/// @audit b
188:         uint256 b,

/// @audit a
/// @audit b
286:     function mulDiv64(uint256 a, uint256 b) internal pure returns (uint256 result) {

/// @audit a
/// @audit b
348:     function mulDiv96(uint256 a, uint256 b) internal pure returns (uint256 result) {

/// @audit a
/// @audit b
410:     function mulDiv128(uint256 a, uint256 b) internal pure returns (uint256 result) {

/// @audit a
/// @audit b
472:     function mulDiv192(uint256 a, uint256 b) internal pure returns (uint256 result) {

GitHub : 187,188,286,286,348,348,410,410,472,472

File: contracts/libraries/SafeTransferLib.sol

/// @audit token
/// @audit from
/// @audit to
/// @audit amount
16:      function safeTransferFrom(address token, address from, address to, uint256 amount) internal {

GitHub : 16,16,16,16

[D-93] Unused import

These instances are used

There are 33 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit IUniswapV3Factory
5:   import {IUniswapV3Factory} from "univ3-core/interfaces/IUniswapV3Factory.sol";

/// @audit IUniswapV3Pool
6:   import {IUniswapV3Pool} from "univ3-core/interfaces/IUniswapV3Pool.sol";

/// @audit ERC1155
8:   import {ERC1155} from "@tokens/ERC1155Minimal.sol";

/// @audit Multicall
9:   import {Multicall} from "@multicall/Multicall.sol";

/// @audit CallbackLib
11:  import {CallbackLib} from "@libraries/CallbackLib.sol";

/// @audit Constants
12:  import {Constants} from "@libraries/Constants.sol";

/// @audit Errors
13:  import {Errors} from "@libraries/Errors.sol";

/// @audit FeesCalc
14:  import {FeesCalc} from "@libraries/FeesCalc.sol";

/// @audit Math
15:  import {Math} from "@libraries/Math.sol";

/// @audit PanopticMath
16:  import {PanopticMath} from "@libraries/PanopticMath.sol";

/// @audit SafeTransferLib
17:  import {SafeTransferLib} from "@libraries/SafeTransferLib.sol";

/// @audit LeftRight
19:  import {LeftRight} from "@types/LeftRight.sol";

/// @audit LiquidityChunk
20:  import {LiquidityChunk} from "@types/LiquidityChunk.sol";

/// @audit TokenId
21:  import {TokenId} from "@types/TokenId.sol";

GitHub : 5,6,8,9,11,12,13,14,15,16,17,19,20,21

File: contracts/libraries/CallbackLib.sol

/// @audit Constants
5:   import {Constants} from "@libraries/Constants.sol";

/// @audit Errors
6:   import {Errors} from "@libraries/Errors.sol";

GitHub : 5,6

File: contracts/libraries/FeesCalc.sol

/// @audit IUniswapV3Pool
5:   import {IUniswapV3Pool} from "univ3-core/interfaces/IUniswapV3Pool.sol";

/// @audit Math
7:   import {Math} from "@libraries/Math.sol";

/// @audit LeftRight
9:   import {LeftRight} from "@types/LeftRight.sol";

/// @audit LiquidityChunk
10:  import {LiquidityChunk} from "@types/LiquidityChunk.sol";

/// @audit TokenId
11:  import {TokenId} from "@types/TokenId.sol";

GitHub : 5,7,9,10,11

File: contracts/libraries/Math.sol

/// @audit Errors
5:   import {Errors} from "@libraries/Errors.sol";

/// @audit Constants
6:   import {Constants} from "@libraries/Constants.sol";

/// @audit LiquidityChunk
8:   import {LiquidityChunk} from "@types/LiquidityChunk.sol";

GitHub : 5,6,8

File: contracts/libraries/PanopticMath.sol

/// @audit Math
5:   import {Math} from "@libraries/Math.sol";

/// @audit LeftRight
7:   import {LeftRight} from "@types/LeftRight.sol";

/// @audit LiquidityChunk
8:   import {LiquidityChunk} from "@types/LiquidityChunk.sol";

/// @audit TokenId
9:   import {TokenId} from "@types/TokenId.sol";

GitHub : 5,7,8,9

File: contracts/libraries/SafeTransferLib.sol

/// @audit Errors
5:   import {Errors} from "@libraries/Errors.sol";

GitHub : 5

File: contracts/tokens/ERC1155Minimal.sol

/// @audit ERC1155Holder
5:   import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";

GitHub : 5

File: contracts/types/LeftRight.sol

/// @audit Errors
5:   import {Errors} from "@libraries/Errors.sol";

GitHub : 5

File: contracts/types/TokenId.sol

/// @audit Constants
5:   import {Constants} from "@libraries/Constants.sol";

/// @audit Errors
6:   import {Errors} from "@libraries/Errors.sol";

GitHub : 5,6

[D-94] Unused local variable

There are 5 instance(s) of this issue:

File: contracts/libraries/Math.sol

/// @audit remainder
224:             uint256 remainder;

/// @audit remainder
319:             uint256 remainder;

/// @audit remainder
381:             uint256 remainder;

/// @audit remainder
443:             uint256 remainder;

/// @audit remainder
505:             uint256 remainder;

GitHub : 224,319,381,443,505

[D-95] Unused named return variables without optimizer waste gas

Suggestions that only apply when the optimizer is off are not useful to sponsors. Why would they pay for gas optimizations if they don't have the optimizer on, and don't plan to turn it on? Only a small minority have the optimizer off; the majority have it set to more than 200 runs

There are 5 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

/// @audit UniswapV3Pool
1457     function getUniswapV3PoolFromId(
1458         uint64 poolId
1459:    ) external view returns (IUniswapV3Pool UniswapV3Pool) {

GitHub : 1457

File: contracts/libraries/Math.sol

/// @audit amount0
101      function getAmount0ForLiquidity(
102          uint256 liquidityChunk
103:     ) internal pure returns (uint256 amount0) {

/// @audit amount1
119      function getAmount1ForLiquidity(
120          uint256 liquidityChunk
121:     ) internal pure returns (uint256 amount1) {

/// @audit liquidity
135      function getLiquidityForAmount0(
136          uint256 liquidityChunk,
137          uint256 amount0
138:     ) internal pure returns (uint128 liquidity) {

/// @audit liquidity
154      function getLiquidityForAmount1(
155          uint256 liquidityChunk,
156          uint256 amount1
157:     ) internal pure returns (uint128 liquidity) {

GitHub : 101,119,135,154

[D-96] Unusual loop variable

The general rule is valid, but the instances below are invalid

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

583:         for (uint256 leg = 0; leg < numLegs; ) {

860:         for (uint256 leg = 0; leg < numLegs; ) {

GitHub : 583,860

[D-97] Unusual loop variable

These instances all properly use 'i' as the outer for-loop loop variable

There are 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

550:         for (uint256 i = 0; i < ids.length; ) {

GitHub : 550

File: contracts/multicall/Multicall.sol

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

GitHub : 14

File: contracts/tokens/ERC1155Minimal.sol

141:         for (uint256 i = 0; i < ids.length; ) {

187:             for (uint256 i = 0; i < owners.length; ++i) {

GitHub : 141,187

[D-98] Use != 0 instead of > 0 for unsigned integer comparison

Only valid prior to Solidity version 0.8.13, and only for require() statements, and at least one of those is not true for the examples below

There are 18 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

417:         if (amount0Owed > 0)

424:         if (amount1Owed > 0)

452:         address token = amount0Delta > 0

457:         uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);

814:                 zeroForOne = itm1 > 0;

811:                 zeroForOne = itm0 < 0;

806:                 zeroForOne = net0 < 0;

1050:        if (currentLiquidity.rightSlot() > 0) {

1234:                collected0 = movedInLeg.rightSlot() < 0

1237:                collected1 = movedInLeg.leftSlot() < 0

GitHub : 417,424,452,457,814,811,806,1050,1234,1237

File: contracts/libraries/Math.sol

25:              return x > 0 ? uint256(x) : uint256(-x);

40:              uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));

86:              if (tick > 0) sqrtR = type(uint256).max / sqrtR;

GitHub : 25,40,86

File: contracts/libraries/PanopticMath.sol

158:                 return amount < 0 ? -absResult : absResult;

153:                 return amount < 0 ? -absResult : absResult;

185:                 return amount < 0 ? -absResult : absResult;

176:                 return amount < 0 ? -absResult : absResult;

GitHub : 158,153,185,176

File: contracts/types/LeftRight.sol

55:          if (right < 0) revert Errors.LeftRightInputError();

GitHub : 55

[D-99] Use _safeMint instead of _mint for ERC721

The contract here isn't an ERC721 - it's some other token. Note that ERC1155 defines _mint(), not _safeMint()

There are 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

407      function uniswapV3MintCallback(
408          uint256 amount0Owed,
409          uint256 amount1Owed,
410          bytes calldata data
411:     ) external {

510      function mintTokenizedPosition(
511          uint256 tokenId,
512          uint128 positionSize,
513          int24 slippageTickLimitLow,
514          int24 slippageTickLimitHigh
515      )
516          external
517          ReentrancyLock(tokenId.univ3pool())
518          returns (int256 totalCollected, int256 totalSwapped, int24 newTick)
519:     {

1129     function _mintLiquidity(
1130         uint256 liquidityChunk,
1131         IUniswapV3Pool univ3pool
1132:    ) internal returns (int256 movedAmounts) {

GitHub : 407,510,1129

File: contracts/tokens/ERC1155Minimal.sol

214:     function _mint(address to, uint256 id, uint256 amount) internal {

GitHub : 214

[D-100] Use @inheritdoc rather than using a non-standard annotation

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

539      /// @notice called after batch transfers (NOT mints or burns)
540      /// @param from The address of the sender
541      /// @param to The address of the recipient
542      /// @param ids The tokenIds being transferred
543      /// @param amounts The amounts of each token being transferred
544      function afterTokenTransfer(
545          address from,
546          address to,
547          uint256[] memory ids,
548          uint256[] memory amounts
549:     ) internal override {

558      /// @notice called after single transfers (NOT mints or burns)
559      /// @param from The address of the sender
560      /// @param to The address of the recipient
561      /// @param id The tokenId being transferred
562      /// @param amount The amount of the token being transferred
563      function afterTokenTransfer(
564          address from,
565          address to,
566          uint256 id,
567          uint256 amount
568:     ) internal override {

GitHub : 539,558

[D-101] Use bytes.concat() on bytes instead of abi.encodePacked() for clearer semantic meaning

These instances don't use only bytes/strings, so they're invalid

There are 9 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

595                  abi.encodePacked(
596                      address(univ3pool),
597                      from,
598                      id.tokenType(leg),
599                      liquidityChunk.tickLower(),
600                      liquidityChunk.tickUpper()
601:                 )

604                  abi.encodePacked(
605                      address(univ3pool),
606                      to,
607                      id.tokenType(leg),
608                      liquidityChunk.tickLower(),
609                      liquidityChunk.tickUpper()
610:                 )

946              abi.encodePacked(
947                  address(_univ3pool),
948                  msg.sender,
949                  _tokenType,
950                  _liquidityChunk.tickLower(),
951                  _liquidityChunk.tickUpper()
952:             )

1105                     abi.encodePacked(
1106                         address(this),
1107                         liquidityChunk.tickLower(),
1108                         liquidityChunk.tickUpper()
1109:                    )

1353:            keccak256(abi.encodePacked(univ3pool, owner, tokenType, tickLower, tickUpper))

1381:            abi.encodePacked(address(univ3pool), owner, tokenType, tickLower, tickUpper)

1446:            keccak256(abi.encodePacked(univ3pool, owner, tokenType, tickLower, tickUpper))

GitHub : 595,604,946,1105,1353,1381,1446

File: contracts/libraries/CallbackLib.sol

40                               abi.encodePacked(
41                                   bytes1(0xff),
42                                   factory,
43                                   keccak256(abi.encode(features)),
44                                   Constants.V3POOL_INIT_CODE_HASH
45:                              )

@thebrittfactor
Copy link

GitHub : 40

File: contracts/libraries/PanopticMath.sol

57:                  (uint64(uint256(keccak256(abi.encodePacked(token0, token1, fee)))) >> 32);

GitHub : 57

[D-102] Use a single file for all system-wide constants

It's perfectly reasonable to split constants across multiple files, as long as they're appropriately scoped and not duplicated. This is especially true if the constants are members of libraries, which is the case for these constants.

There are 12 instance(s) of this issue:

File: contracts/libraries/Constants.sol

8:       uint256 internal constant FP96 = 0x1000000000000000000000000;

11:      int24 internal constant MIN_V3POOL_TICK = -887272;

14:      int24 internal constant MAX_V3POOL_TICK = 887272;

17:      uint160 internal constant MIN_V3POOL_SQRT_RATIO = 4295128739;

20       uint160 internal constant MAX_V3POOL_SQRT_RATIO =
21:          1461446703485210103287273052203988822378723970342;

25       bytes32 internal constant V3POOL_INIT_CODE_HASH =
26           keccak256(
27               hex"6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000a"
28:          );

GitHub : 8,11,14,17,20,25

File: contracts/types/LeftRight.sol

16:      int256 internal constant RIGHT_HALF_BIT_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

GitHub : 16

File: contracts/types/TokenId.sol

60       uint256 internal constant LONG_MASK =
61:          0x100_000000000100_000000000100_000000000100_0000000000000000;

63       uint256 internal constant CLEAR_POOLID_MASK =
64:          0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_0000000000000000;

66       uint256 internal constant OPTION_RATIO_MASK =
67:          0x0000000000FE_0000000000FE_0000000000FE_0000000000FE_0000000000000000;

68:      int256 internal constant BITMASK_INT24 = 0xFFFFFF;

71:      uint256 internal constant RISK_PARTNER_MASK = 0xFFFFFFFFF3FF;

GitHub : 60,63,66,68,71

[D-103] Use assembly for small keccak256 hashes, in order to save gas

The arguments are too large to fit into the scratch space

There are 1 instance(s) of this issue:

File: contracts/libraries/CallbackLib.sol

43:                                  keccak256(abi.encode(features)),

GitHub : 43

[D-104] Use assembly to emit events, in order to save gas

For these events, there doesn't appear to be more than one word's worth of unindexed args, or the arguments are too large to fit in the scratch space, so findings related to these events are likey invalid and definitely invalid, respectively.

There are 5 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

79:      event PoolInitialized(address indexed uniswapPool);

86       event TokenizedPositionBurnt(
87           address indexed recipient,
88           uint256 indexed tokenId,
89           uint128 positionSize
90:      );

97       event TokenizedPositionMinted(
98           address indexed caller,
99           uint256 indexed tokenId,
100          uint128 positionSize
101:     );

GitHub : 79,86,97

File: contracts/tokens/ERC1155Minimal.sol

35       event TransferBatch(
36           address indexed operator,
37           address indexed from,
38           address indexed to,
39           uint256[] ids,
40           uint256[] amounts
41:      );

44:      event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

GitHub : 35,44

[D-105] Use constants instead of type(uintx).max

Does not save any gas

There are 5 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

917:         if (amount0 > uint128(type(int128).max) || amount1 > uint128(type(int128).max))

917:         if (amount0 > uint128(type(int128).max) || amount1 > uint128(type(int128).max))

1390:        if (atTick < type(int24).max) {

GitHub : 917,917,1390

File: contracts/libraries/Math.sol

86:              if (tick > 0) sqrtR = type(uint256).max / sqrtR;

GitHub : 86

File: contracts/types/LeftRight.sol

213:         if (self > uint256(type(int256).max)) revert Errors.CastingError();

GitHub : 213

[D-106] Use delete instead of setting mapping/state variable to zero, to save gas

Using delete instead of assigning zero to state variables does not save any extra gas with the optimizer on (saves 5-8 gas with optimizer completely off), so this finding is invalid, especially since if they were interested in gas savings, they'd have the optimizer enabled.

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

627:             s_accountLiquidity[positionKey_from] = 0;

630:             s_accountFeesBase[positionKey_from] = 0;

GitHub : 627,630

[D-107] Use multiple require() and if statements instead of &&

The suggestion in this rule is not logically equivalent for if-statements unless they're nested, and cannot be done if there's an else-block without spending more gas. It doesn't seem more readable for require()s either

There are 4 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

706          if ((itmAmounts != 0) && (swapAtMint)) {
707              totalMoved = swapInAMM(univ3pool, itmAmounts).add(totalMoved);
708:         }

774              if ((itm0 != 0) && (itm1 != 0)) {
775                  (uint160 sqrtPriceX96, , , , , , ) = _univ3pool.slot0();
776: 

GitHub : 706,774

File: contracts/types/TokenId.sol

512                      if ((isLong == isLongP) && (tokenType == tokenTypeP))
513                          revert Errors.InvalidTokenIdParameter(4);
514: 

517                      if ((isLong != isLongP) && (tokenType != tokenTypeP))
518                          revert Errors.InvalidTokenIdParameter(5);
519:                 }

GitHub : 512,517

[D-108] Using bools for storage incurs overhead

These are constant/immutable so they can't change, and therefore there aren't any gas savings

There are 2 instance(s) of this issue:

File: contracts/SemiFungiblePositionManager.sol

127:     bool internal constant MINT = false;

128:     bool internal constant BURN = true;

GitHub : 127,128 ## Rubric
See this link for how to use this rubric:

{"salt":"db7f90","hashes":["50ec57f3c2","92c01335c8","069ec8a1c1","bf54dc3326","bfc1eb8cb3","90cd0e3ee5","b9d1b06713","9dbc6a2fe9","b91fa024de","1a6fc81613","03a5a21fe0","e6c39bfef0","a0b8fe9f73","84e60731f2","9dbc6a2fe9","b91fa024de","1a6fc81613","03a5a21fe0","e6c39bfef0","a0b8fe9f73","84e60731f2","7d595c21e0","1a075bac5d","6451ebd690","f6d388b7e2","c6229986ad","6851d4743c","fcc90e3260","dd93f7b870","8ee9105d8e","d7b6f720fb","04281b000c","f16a897085","d97e11d6f9","0c8bf487af","7e2ad711e3","c4316ed521","f332f594c1","b5e9c8f793","25cf5821fb","e3c10f55dd","ed3dd1bf4d","7e2ad711e3","c4316ed521","f332f594c1","b5e9c8f793","25cf5821fb","e3c10f55dd","ed3dd1bf4d","48f0ea55c1","c7879dc9f1","2d2a7f6aca","79cea39042","3a9da44d5c","0a529e0caa","f6b5eab21c","2b013c7d15","6116771b54","1f29566797","eadfcd66f6","53e607ae02","0b7b2b7f04","a9536f7a88","da579958be","35b8098f98","6cfeb0d0b3","7214ff6d22","ac272c467f","4e7f0f734d","1ce4c9991a","a07b96db88","1a11943f19","f008f02d09","a30c43d8bb","30c2bd9878","7fb1389d44","06b47164ca","7719f74cd0","9e63c24844","29508c2f9e","6aff3983f2","050b1aeb62","4b2b1ffdde","fccca1df3a","502df23c80","ffcc3ca7d6","f8166fada9","f6e041ceef","7b45c80e34","7df8c642f0","2e19a6e9eb","3cf2fd4c09","35b700bd36","14108d9773","8401e2df58","5a830128ea","6ac46fafff","85fdeca94d","48f0ea55c1","c7879dc9f1","2d2a7f6aca","79cea39042","3a9da44d5c","0a529e0caa","f6b5eab21c","abef8974a3","5157a5f756","fba00e00a2","3d0da39ec7","d53ddcf480","332cc780be","6b8670f4dc","facf6948e3","ff21f20d8f","d705ce6642","e2e8f49cef","c747a4467e","62583f074a","73582d7f56","632b45d11c","a22c629891","48b5480714","bd3212c503","80116a43c9","dd947d920c","b2236a94bd","41370fc328","58c685f6b8","33c8f963c2","4d7386f544","2f248c51e0","a4a257022b","ac31fa10cb","6490f1f293","979d931019","f3bf7e0884","ebd34a431c","7e349d36f8","23f9703ab7","d698681471","ec13b7fa9d","06c3187f81","60797c998e","98ecd72ba3","ca3024d8fe","303838ef7c","b282656991","628c8cc261","71585371c3","4110a27582","349f6d7e1e","541333f59c","5deea382d0","f5f862fae1","3d9c0fef2d","52db51ec71","712db08472","fa294707ee","cd55ebce7a","c7a0044cb3","7ecdf95759","c8499ab9f4","270986f9d0","1413295015","d2b7a854e7","0c0d9ead14","be563d498b","0660024ff4","d143906fd1","ab6761c28d","63b4b037c5","a0d0cf65b7","8ef26d7848","e17a180e5a","a0f81a9f8b","bed0b406fe","bc1ebce009","831d735e46","0f8e7e28b0","a2ee386396","7d47e90b1e","0b88385314","19b559ae37","b6e4c6c4bc","857cb703e9","b0cb73a8b8","3e81a7b13a","bea6160763","9b5dfc57c5","632b45d11c","a22c629891","48b5480714","bd3212c503","80116a43c9","dd947d920c","b2236a94bd","632b45d11c","a22c629891","48b5480714","bd3212c503","80116a43c9","dd947d920c","b2236a94bd","9977c0d645","629071f5ff","f290b8113e","ddc4267f75","e064b9c3a4","f7de4078f8","33b8effd96","834647b3c2","dbb2175c3e","684129e303","22bd285a2c","e2f97925e3","074023cb00","b267bce815","a16719c389","06f83f1377","a8c2757784","d4e7c4f476","58ed066459","80e015d356","a0d3f900d8","9cb50116da","192536999e","f095331f81","2a98a6978c","ea13fe3b04","6f15638f26","aa469ddb71","212fcd6ee0","bed5274dc9","d92ec58702","59502e7732","2a3cea32e5","1ae8a0f928","c9e2254d22","9d2d80fa79","9e35417a00","f6a31faa27","aca29ac4fa","4b068aa0d1","f53d572d8a","2c3f73df2d","3a706520b3","c6846e12af","63ddd1378d","73a6d46f4a","cbdc4235ed","0692dd44a2","1180849ffb","b7b493a6de","8834c23c66","a461ffc51f","4c95449486","ae2bd0ab8c","3ec460a177","3792bbf107","a16719c389","06f83f1377","a8c2757784","d4e7c4f476","58ed066459","80e015d356","a0d3f900d8","067ef2dc4d","0c534554a5","c2bf2d6cd6","68e19527d3","685f53e3b2","d87e373c6c","a26082747d","ed19252a63","b2e774d682","52111fcca7","fb05601082","482c911041","0cf2593229","f27402a764","a69f800320","f2d5f79d09","a398588c39","9731153a14","2632320620","e3f3fe9aac","a1cd50a85d","b4098a3985","ccad561da1","cd66280d1f","d1e71df612","dac8f5ba11","fcf200f2a2","d03d55f103","d1f9851cd6","954a5ab681","5995855c09","ef96a34f8f","8ebe43168a","3b775b4104","c1dd02b4d5","0b06b3d2d5","650053cba1","29b0a29d20","a9676008de","e5f9de9f10","4800b1b8e7","67b35edbee","2b0206b966","43c773cddd","ec03c684c7","6710c1e332","f081b85a0a","ab2c4c9ad3","0eedf3ef68","2da9732335","31205c75e4","86d341aaec","de4e513a80","a9e2ddf634","34d0ff9d26","9ad8cab7d7","2da9732335","31205c75e4","86d341aaec","de4e513a80","a9e2ddf634","34d0ff9d26","9ad8cab7d7","8b93aa5685","625604b48e","4c7b9c8402","7c245e480f","dab1681a93","5660f050ad","186d023833","054f539d1e","554960c7f4","34806c318f","fdc7fecfb6","112996b3a5","96e1339f4c","3144eed5be","e38a552672","18d946006b","7ca00d0c47","4b0a31d4ff","3fcf699fcb","c9d7f33754","b6b9193e5e","c83b83d4a8","0148b0bc47","761269f133","1a8ee434ce","13b0540bef","d35264ab99","ab232d6205","cada842797","0caeb2a855","348005e6ec","3a16ccde73","46ef864d28","7f4094e9a2","fac34d3063","6351ee60ba","14dd5d3e7d","e2ef57c181","f31fabf2ed","4797934191","315d7b2a4a","fa783412fe","365fe066c5","7ac778de78","337a6ffc98","0ea0ede2de","ed92687d9d","c8fddfec75","0bfe5531db","8b93aa5685","625604b48e","4c7b9c8402","7c245e480f","dab1681a93","5660f050ad","186d023833","f348d81651","b259b5d511","9cda03d25a","c0ec3ae465","efaf2e295a","f8ee3b111c","b25de9abd7","e99f1d1d79","237ac6e274","37d42abc20","f82cc3fcc3","b0915eb762","77c9ff7cd4","af0a5cba69","a80615e71e","01d295587f","355854014c","d8a37b9e64","d39014ac5f","9173859112","62f354edc0","9af90380da","aad0c3c50f","f15916df74","48180e1075","755ab188b3","8057e24ae6","105a433784","35c3d014c9","848049ee4f","fda4e6241b","e0258be4b7","9dc95b6af6","f061f094bd","bb09bb4efe","35c3d014c9","848049ee4f","fda4e6241b","e0258be4b7","9dc95b6af6","f061f094bd","bb09bb4efe","19975a5a08","aca9261289","ecc6164007","c32c17af51","7640a80f4d","11131cebf1","14d4494cf2","dc6e82a5dd","9b06c6ce45","bcf74c71e3","2249fa0e6b","b1c6709847","b5ce9e20b6","85af6902a2","86bebcd5b2","b9af3b2fd9","2f8f551034","bf333f015b","3ef70e8746","a260d90edc","07c7e0356b","2e888415a6","a335cba7ec","c009aa78f4","40cf31f2d9","15ab617088","77468e7f45","39082f6c79","e2f5820bef","b63fb1022a","96f74225bb","ba0be3193e","dfeda40600","69e93d3a82","e68d71acf7","b7028755c2","059baaf68d","41005fb874","23510254d2","f3ce662655","3932053375","7a3baaa675","19975a5a08","aca9261289","ecc6164007","c32c17af51","7640a80f4d","11131cebf1","14d4494cf2","19975a5a08","aca9261289","ecc6164007","c32c17af51","7640a80f4d","11131cebf1","14d4494cf2","7115498fc2","679ca4882c","b928258a9d","9c3d31a413","2e4d61c253","152dfdc6af","84c38e7486","a762ccb6ef","ddc65d0d22","8552cdd429","1c9941e554","2f4bd25f8c","dfee6724ce","611dd22d1f","a762ccb6ef","ddc65d0d22","8552cdd429","1c9941e554","2f4bd25f8c","dfee6724ce","611dd22d1f","f2625418ea","3aeb59b7a5","e067a96ed9","8314d94057","818ca28599","fd68e4d44a","1029482afe","3bc9649b4f","e71e4ff807","c2636e78ac","573f2f35e2","08e2908bd7","2732953ee4","29a24408dc","3bc9649b4f","e71e4ff807","c2636e78ac","573f2f35e2","08e2908bd7","2732953ee4","29a24408dc","68106d77d9","ddb6b6cd0a","611baf000a","d50e6ce340","ae4f1afe66","75c814a1fa","01f5e93136","6830739053","656df1ebe1","47cf5201f2","4a99397a6b","5d0744748f","7a358a15ec","7f2d5e94cb","fe8926cd8c","f9cc29bb4a","ac3cf870dc","220ef0453e","ad02ad2ee9","8ed8c1b8d5","5711513ff6","a37f31ba8d","11694171d4","573f925a23","1815ae2771","2e671ceb3a","20c14217e4","7e18948381","cb5eb09700","1f9cff8af7","e816113315","c17be625ef","6cbb0f96bf","90b2bd9ae6","71e42c8fab","c316015697","cda9b53756","32c6993a6c","5fe23add2f","429a185c22","7a9f1ad98d","7a7984889c","6bb90db860","7e6903755f","0a7a497ce8","693d29bb61","b854386f4a","b2d8a9f466","3c313b30d7","f8433aca66","339402f6f3","e2c174dcd7","08f521f3cf","6673b9128d","e0abdab3ea","c00cfb9f78","83f39a242d","2536601fb5","867f61fad2","f5bcee80e1","11ef038779","3e295ffb44","cee75b5bc1","c12033b43a","2c711cd68a","1f6bcd06ba","d0dc93dbe6","062338fa45","6b2d9207e2","92fca1266e","c12033b43a","2c711cd68a","1f6bcd06ba","d0dc93dbe6","062338fa45","6b2d9207e2","92fca1266e","aabba657a5","eb81669ee6","a1d55460b8","96fc7cc6c2","84b923d257","e2e3844b58","c80c525f20","744942af9c","0a0490f90b","040a9d18d5","930914d981","800c1c0bd9","80628dc20b","ee20ea53c3","afe8910577","e4bd399845","5fa4578413","b5eeb6279c","8ef0e65c5c","b3c8579f94","8da0122793","625196e5f5","93d2fe1623","42da488685","4ffb8cdaa5","3787339f2c","d7059d2068","3c7a881eb2","5cef21d96e","6d88230efb","6b2aad270f","38d88b374e","01f96ae89d","fd1899ac03","77a34378d0","625196e5f5","93d2fe1623","42da488685","4ffb8cdaa5","3787339f2c","d7059d2068","3c7a881eb2","afe8910577","e4bd399845","5fa4578413","b5eeb6279c","8ef0e65c5c","b3c8579f94","8da0122793","9841576f3a","bcec191056","74a3f7b0bb","387abcbcbc","e0d83a5177","326d236933","5e72fefb77","e05df3e942","6ad2ff8c32","0d10ebd4df","2a000b7b4d","25c060b308","62ae45bb1b","1e4a938e9d","afe8910577","e4bd399845","5fa4578413","b5eeb6279c","8ef0e65c5c","b3c8579f94","8da0122793","afe8910577","e4bd399845","5fa4578413","b5eeb6279c","8ef0e65c5c","b3c8579f94","8da0122793","216219411f","e69cc40c52","2793e6b97b","92ad6dab08","7cbccee816","6f7518f72e","c670267673","359feb7a33","89c6d85919","23b37a13b2","f2c92647b0","9ab0f9a652","6fc0bb89c7","4f4de873a3","11b740386e","f7c338f8f1","b9c9ceb4e5","f0de09abff","e7a5657922","7a417aab73","e317d726a4","e0cff00c14","8cb85b5892","6e796c7ff2","fb6a035d82","a2b842fe73","2db9768191","97fd42c824","1feaff0d52","bb69c68a46","cb442f4558","44e4df64b7","a5c45d30f8","441f6a3bca","d3088d9cf3","e0cff00c14","8cb85b5892","6e796c7ff2","fb6a035d82","a2b842fe73","2db9768191","97fd42c824","e0cff00c14","8cb85b5892","6e796c7ff2","fb6a035d82","a2b842fe73","2db9768191","97fd42c824","bb327c811e","d9bfb1ae94","d9f8b48000","6cf8a07401","1e228e2798","c7c9c9a232","0517d485c3","ed71ebfd64","0d6b45eff3","d903bab5e9","c79ec56907","f65dd347c2","2ac688889a","d13d20d58e","b26551632b","a083690607","12512569ce","453cae85f1","5605267aa7","e26ff9462b","51a74114c4","4ceaa1441c","6ef867e0d5","4a5fed2f57","314b749620","ce8641961e","a35beed8e4","6fe1edc564","b26551632b","a083690607","12512569ce","453cae85f1","5605267aa7","e26ff9462b","51a74114c4","ddf4ac2c8c","6d020ddeee","e7b8d3d862","8bb0fa2c17","72b4505ef2","b6b5dd9878","c237d2563d","1d10e010ad","be9ee46517","c987cbca41","640ba48419","c6d7300d3d","b3844990cd","1fd63fced2","1d10e010ad","be9ee46517","c987cbca41","640ba48419","c6d7300d3d","b3844990cd","1fd63fced2","b7697d0c9d","7f5c808ba0","7f50a04958","5b0e6179f2","ab0e489fad","fcf73c5b29","d799c676f5","dae5eedb17","10d55a8a25","0dd3ead912","2966487ea2","d34016bc42","94826c6ce0","c898410116","321f6fdd68","57bc7baa23","2c6134db50","427d0bbbbf","df676f919f","8b4ce1ca56","907884da71","30c7553ca2","f4a34090f8","857c70c939","45a493f4d5","76b5b836f4","08cde48db1","0d64c6ef06","33207bcaeb","235f07b23e","066300d86b","17a504ea5a","b4c0ee5dae","dec67bec9a","2b1e8e07ef","33207bcaeb","235f07b23e","066300d86b","17a504ea5a","b4c0ee5dae","dec67bec9a","2b1e8e07ef","349b7d9bd1","928b2b1d78","de9b9e01c5","5cadf55396","3adbbae21d","460c69b01d","010184f920","6015de9752","7ca75b5ddb","b92f2f1f19","d9c7eca8a9","b710583c54","9abffde0a3","e0ac781970","2041882e87","27d5033220","4027f1abf5","51992b941b","7c95e9f124","484cd6d247","453109fa8e","ad41e69639","0b8434bb1e","e87f73fc36","385b3febe3","b6919b9884","e801c8f792","ed975a91e6","ad41e69639","0b8434bb1e","e87f73fc36","385b3febe3","b6919b9884","e801c8f792","ed975a91e6","826f233fd2","dc0dc478fd","5c5bb4344d","518d21e41a","c8724a7436","82df76a680","8f27974daa","572908d774","c0be60314c","dd2ce45aaf","b361690093","b8aacbcad5","b47bbc51be","bdbb4f5cbc","3a9b12945c","2d45bf05f7","94e728fa7e","f92c6310c8","0a558d7132","a03dbe1a4e","3ff684ea40","3a9b12945c","2d45bf05f7","94e728fa7e","f92c6310c8","0a558d7132","a03dbe1a4e","3ff684ea40","45012b1695","0f7282e968","9d0254603b","13fa251593","22ee437acb","3c97bc7fb7","dab097d6bb","25d1c64a40","f925302217","c6576bf462","309b0bb680","c9661e47d4","c343c14ea5","fe0d211cd6","bf2d6b96b0","85c0278806","60b445cdf6","95bd4d5149","6fb8dec631","0243ed0fce","b14887228e","adcb23ed36","9ca5b98cd4","e4d16b4a7b","1d94f9e034","f2fef78547","79141b0906","fbb4d21e68","5d6fcc2264","7541b6387c","7a4df8345d","9b62bfb684","98f6ac8548","fd6ea9854a","07f8b7b229","2443640704","efafea3e41","84303b8fac","d1fd2781c6","309c701bb2","9185a44fa5","d682fbad24","96321079e0","4a91b42ccb","01846356e9","f09be5e327","7f15004e93","4ca5b20e80","ec6fd5ae3e","45012b1695","0f7282e968","9d0254603b","13fa251593","22ee437acb","3c97bc7fb7","dab097d6bb","45012b1695","0f7282e968","9d0254603b","13fa251593","22ee437acb","3c97bc7fb7","dab097d6bb","78efc8edde","5cc69e0f2e","ae76c0b70f","7f25dc9c63","2ac2261b18","3feb0d8f0c","e5c3438647","10457f5289","08016a8f2c","9160c61ec3","2d3f122010","153ecd3a01","f44e2eda64","daa24f5c0c","10457f5289","08016a8f2c","9160c61ec3","2d3f122010","153ecd3a01","f44e2eda64","daa24f5c0c","7cd94f2377","ef1cbea372","ae9b03ab99","d8546669b6","c06e402c99","9becbf10b5","baf0bf77a9","fa1c6cb083","282ab66b12","d4f8004f06","112384354c","d2003bd2ea","9fda9b71c1","a0a558d7c0","da04175f14","d66d26b362","9f87b233f2","80b077adba","16ab030141","83b7cb8c99","729335837c","0d7e6d1471","2f1082a15b","32a692e1eb","329e267e1c","562050afdd","2d12c016ec","f202a85012","36a3878be1","10ee5cef77","ed0a3eb94d","0869e910d8","29d1d73f33","75da981c83","b87fe2f232","79b7401d0c","c8758665e2","e778156d88","a3fa67f0cf","4ba3bc0f4f","afcbff23f9","c9bd3216cf","24d4eae32e","0f63c43cfe","c874bf9dc1","adf3e1d5de","c271092709","c62b7293e8","3ec98a5c32","24d4eae32e","0f63c43cfe","c874bf9dc1","adf3e1d5de","c271092709","c62b7293e8","3ec98a5c32","9c2c373f96","1fe77bd566","bb74121de0","b125a0111b","bd5c057a8c","58fa38df40","f2f511f347","d3bbe64c3f","d4eb734feb","ad6507f6fa","d9d2398c28","0625d184bd","5672e5b5d1","9a0322b32f","f074a3a9fe","8ce199cbe6","df96315698","de3dc11ca6","7fe708ebb4","002c3cc24c","e3bd44e823","4c9adda616","c65a933e86","96141eba2c","1c45235706","41febdd3a1","318dc0aa14","9f95d3ef84","0fc892064c","3e88a489ff","5ef36a4642","d4abed765d","094bfb781d","5c1894e562","3e34001ab7","31d748e01a","9fe43c9900","8d53c9520a","05f05d5ea7","0e3f3019bd","d2a2d572e8","796ff8e558","9c2c373f96","1fe77bd566","bb74121de0","b125a0111b","bd5c057a8c","58fa38df40","f2f511f347","3137190847","78fc23fdfd","9a52d4e745","bf03a70840","7c57973afa","3d9c693009","f45f03bcf2","d376223af6","b9719f953b","0ea64b7b2e","e43f7667c5","1aba27330f","5b78f0dfff","b2b7d38273","7ba6d9445f","8c505f5648","7604de925f","a2ac10cf20","ec0204b3a4","922d8f6684","a3aa7104d9","e1bfef6cfc","9d85897ced","ed76e6bc4a","7f04c1041f","9168fa1e80","e1e7ba4584","efd20e3e5d","a6610e7a58","36fb491310","53dc81d99e","4c8dfd9103","bcd4facdd7","9d0c6cb971","178be58729","5a639f1ecb","ee0c7a0af9","74cfc6fe5e","e6a2227399","a8c02e5b22","7a34082e79","9751f647a4","17845456a9","89c76019ab","107cd24000","1baaa68c45","b26e8d3411","3b45c5509e","1de64e38c5","70bc5226c8","57abe6e62f","dd49f7e517","3a7ebaf13f","a3685b8c75","55070428c2","c0653e6e5e","dae717784a","e940f4a580","8978f30cdc","09dc689beb","55d9513c38","a23690b7ba","703ae9caab","934c5297ff","9d8c62a84b","63fdbd2279","1802bf017d","7da8d42cd4","1d16c0da32","0d715beb97","fdc0f7e989","8c91ab0197","47305af9a4","fa686527ba","cd0638b150","6fccd9db55","9cddc86e5d","7ba6d9445f","8c505f5648","7604de925f","a2ac10cf20","ec0204b3a4","922d8f6684","a3aa7104d9","b734e1262d","15f5e9d9e5","37bb130448","18ac65fb3c","bad1b91221","ab791c9ea5","60b784df89","7c3c0b4005","924489135b","dd16df316b","23aceda063","07cc64e7ea","f2e5a163f9","99ee4ad12f","f5c97f9a1a","5c66b7f3a8","6e653fb874","514f918d0a","a9d9313e07","0b89909f1b","6441d7d350","5d9500d906","bcd951387b","0c01a42b07","bc8ce215ba","4c723af6b0","80d800e833","73d7ad32ad","5d9500d906","bcd951387b","0c01a42b07","bc8ce215ba","4c723af6b0","80d800e833","73d7ad32ad","c952ce0a11","d08565737e","93c0690e8c","4bdafb67c6","bd68006a46","4cb2871b41","14e0e0221d","0147c79578","de6bf2899c","c2936df4c5","e386e3a400","c796cc1e03","18de7e4f66","910cbc0055","4d68eb740a","9eafa4d5ac","f471280b5a","c9f1fefba9","520e8cabbb","217a385e50","233e24bf59","79119f312b","a57c860b74","6e4a0dda7b","e1d5c1a835","5dc858d5ac","7b57ac6fae","48b6d933fc","8907376583","8c891d4b06","76537affb2","25fbf5afb7","3b139a9e0f","f47f19fbb1","a52e66cc12","8907376583","8c891d4b06","76537affb2","25fbf5afb7","3b139a9e0f","f47f19fbb1","a52e66cc12","23ee96acbf","ce347b1c4c","6963651a74","7261a9103c","becabdeaf4","06ecf04229","1cc98b76ec","c4095eb2f9","60125900b1","83fd4c7461","0b5322a912","0f1d9fe536","586801b5d9","e16c8fd07b","65e65fbd1c","55d3109124","addb797adc","abcb243382","62d5319714","2bbf959b46","415ed1ddad","2b6f37f642","92c8fc435c","fc9eaa52e4","385dca78a1","e4328b3e5e","c7d206bb42","c1c146cf42","0b7b1ffc10","f0336014ac","07aff65b18","3c17624ece","4eeaef4180","919ce6c841","99383dfe2b","0b7b1ffc10","f0336014ac","07aff65b18","3c17624ece","4eeaef4180","919ce6c841","99383dfe2b","f4acfc3c90","7788d38ea0","99a6c2b0ac","265604899d","64af99673c","0b045558d7","fb65fb9a05","0ea28f2e99","144a7131b6","98dd14396e","c492b69b76","e21089f3e2","34d0ab29c8","c29225015d","0ea28f2e99","144a7131b6","98dd14396e","c492b69b76","e21089f3e2","34d0ab29c8","c29225015d","c5eb6287c8","0056181596","f1eaf8add9","a486b73e6f","b14ce97418","799feb7e5b","7fce40188a","9292ad720e","7ea12b5943","96f05b7038","4cd9f26530","5fe5cf2cf4","716c79d348","89127e4d9f","8804cebd9f","7383f8acd6","e784120830","acc611ff46","fafe7f34ea","e2b76df788","e83e101d59","b386b71abc","97812bb80a","549c4db993","28ebf3b865","4a58a40395","7fb4d0adac","057e6fff67","db6cf261e2","aaf7ef4203","7c2678306a","e0b395ba2f","2dddb93d12","f5c51df492","276088c171","db6cf261e2","aaf7ef4203","7c2678306a","e0b395ba2f","2dddb93d12","f5c51df492","276088c171","e1334281ac","33097b35d1","c0fbda6fcc","e50b499688","ad66d5e13b","9aff2d9191","2d68e76432","e1334281ac","33097b35d1","c0fbda6fcc","e50b499688","ad66d5e13b","9aff2d9191","2d68e76432","bc38b51d52","33669c929c","70305848fb","a67593d67f","44a79a33e3","959eef62a8","0e49b7f281","bc38b51d52","33669c929c","70305848fb","a67593d67f","44a79a33e3","959eef62a8","0e49b7f281","d0f67cbccf","6b6511dc72","f5496fc331","61010a4ac3","e24c68dc46","e8db2f4d0d","51fe5e5223","cf6c95e703","5ace406584","6cbca06f76","866bb40d43","3425abf396","c251eda5ed","3f8fdd1413","7403789de4","0e611fd0ba","be7daf398e","a6b041f3ca","3a386223a6","b85d5ebaea","791bb8d56c","c8c902b36d","ed84e27738","700a5f4731","285c39acd8","0149ee0e71","97c0b9c0f8","1dc4bae732","c8c902b36d","ed84e27738","700a5f4731","285c39acd8","0149ee0e71","97c0b9c0f8","1dc4bae732","b2096b4248","995e3c29b4","046760d802","1a2187f7ad","df9ddf9ecd","a77b67bb22","f9de746ba2","192340af06","1143bb2e17","3ebc9b4130","19f6728cad","b5d9b49417","9014321820","3d2d1dacec","d8ed2ff59d","57c34aceb5","5abf0964f2","768f2c1db0","93ce6d3256","1c5bf16ba5","a30243e8d7","f914a126b9","fae2b51baa","5bf29254d9","4374545fb3","7961308813","5b3565efc7","4626c28c5a","d68ec6d569","72df7c0934","dea0a09bd6","355d8412f0","89c026f780","9d172b2083","b1f4d06b61","d68ec6d569","72df7c0934","dea0a09bd6","355d8412f0","89c026f780","9d172b2083","b1f4d06b61","72fc316998","297aefc28a","a912f5dcea","46aa9941f7","3ea4462eed","53cbe0289d","e4dbd2a55a","d26fbcb980","fcaf27c93b","fb3fd8f8c0","4899258a5c","53dc0e70fe","1f398a7475","d7cd8d82b7","6840694f3d","2879246c12","aa151e483c","49973a1db6","46f50c7448","6faad2cd76","227f7e2764","b6f60d34e2","1b39904902","90881d0296","df981f9bac","49dada3ecc","806fdb29b3","572f055324","1728bcbbd9","8875c92993","bed044d36a","3a77238e84","8cd9711845","4de7af2f0f","c36f97b024","aa399c1b4e","131ce9f2cb","cd7e7ae40a","2e02bb1ccd","9378afcb52","02a1810b50","03c17d501b","aa399c1b4e","131ce9f2cb","cd7e7ae40a","2e02bb1ccd","9378afcb52","02a1810b50","03c17d501b","1728bcbbd9","8875c92993","bed044d36a","3a77238e84","8cd9711845","4de7af2f0f","c36f97b024","683295c373","ac37cd9a9e","c9ff1c8e4f","5eedb575da","30b9cd5905","9612fe91be","dae92252e1","cfe7919c8e","f01ae61a12","201e673d56","738986446d","adfcbc4c02","0e740edbfd","7fe3b19158","fe73230b4a","f470e553e9","9197f4a3c6","55e25c47de","640a30ebcb","6b3dfa807b","3df52ae895","fe73230b4a","f470e553e9","9197f4a3c6","55e25c47de","640a30ebcb","6b3dfa807b","3df52ae895","1660e97b16","19e6245e07","ac204c60d7","feee093dad","81090641f8","7f73b45184","12e773ba97","3fa1fa5157","004b5d66c5","c439d943a6","499d0c51d6","f8721d1906","a8c17ab7dc","b40f715d00","3fa1fa5157","004b5d66c5","c439d943a6","499d0c51d6","f8721d1906","a8c17ab7dc","b40f715d00","080ef35e90","a5432b2c72","cbdf8f8159","00e69ff5f8","2c278db6f6","ab65834156","8c4b91df99","ec8e9cc0f6","15ce118edb","c4d3101226","b2ba2b388f","6a465d702f","6ea304690f","9bd9822ada","c7adaa68d7","2045df52ba","07064d89a9","d4ff2511f7","650e1df953","8634fbb91c","da19abaefe","99ff5e6ae0","2578e91ea1","47681a5e3c","88bcd65997","325d529110","23f564f830","0097ad6bf6","d6fd5aafe8","0a47f26b72","aabb609e73","4e7d755d51","7ed668b1c3","fd2d32c378","cb03d958c1","11dc04f830","58a3755796","4cec22bb33","9f50783049","2b0ccd0ce1","344a7a8bb2","cb6744b35a","429fc2f4aa","d868fafd13","ec19b8c83b","4367fadb62","6bcbb8be7f","5844ef5c07","5fe9ddb5b4","ec8e9cc0f6","15ce118edb","c4d3101226","b2ba2b388f","6a465d702f","6ea304690f","9bd9822ada","ec8e9cc0f6","15ce118edb","c4d3101226","b2ba2b388f","6a465d702f","6ea304690f","9bd9822ada","f3839d1596","08de150d44","c1709eae52","39177fd21e","7496111939","1785885d10","29af000255","02e7f07bd2","0c207d71c7","3231dd097c","30361d7d3c","884e3728e2","86df2c0eea","35708de34c","814e690ca6","0f44cd800e","f71cf423de","1566f23666","b939f3ca0a","c863722321","8881920aa7","a655f8187f","5cd75a1d44","5bea78ffb1","0eed6967f7","30a32579f0","6e975cb803","59ded93d60","e63c241d9a","23e7c42ca4","98df9dcf2f","0ea6b4c25a","7d3ac829e2","fdacecc1ec","b03b12ac38","d909a6f9c1","c0d654773b","c6eba2332c","e05d71cbc6","14e16601cc","2d40ecbb3e","c64f2805a7","e63c241d9a","23e7c42ca4","98df9dcf2f","0ea6b4c25a","7d3ac829e2","fdacecc1ec","b03b12ac38","e63c241d9a","23e7c42ca4","98df9dcf2f","0ea6b4c25a","7d3ac829e2","fdacecc1ec","b03b12ac38","3c16a7b718","edd2fc30e2","205cc7c82f","3250b58613","692ec5b49b","044f5d71c0","7054d92525","b92e28dc84","1d9417f594","2867f174bd","a3dd11e5c9","10e95339cf","1944b4aec9","5db2e8b178","b92e28dc84","1d9417f594","2867f174bd","a3dd11e5c9","10e95339cf","1944b4aec9","5db2e8b178","5c74a6749a","2cd450fad8","71040ffb22","d774835b14","6d2b6f2baf","78ff8eaade","4719f2b7b0","92cfa93109","0347c8084d","78c663f971","18b29b4d76","43a15f0811","a26211aef1","661e272d08","77c60e337c","4396d8380a","1c2d1760a8","b86c532dc6","0def9bbda0","9703c9c440","2ce1adde1f","77c60e337c","4396d8380a","1c2d1760a8","b86c532dc6","0def9bbda0","9703c9c440","2ce1adde1f","73ac0e1d5b","8724650b3c","2a216feacf","3b4c5d5651","878bbc46f1","325bc9266c","65c3724d8c","3a53323584","8a24d8f4dc","d67f151407","86cafc2d65","a5a5a8d16f","08bbb91671","e574bf7deb","3a53323584","8a24d8f4dc","d67f151407","86cafc2d65","a5a5a8d16f","08bbb91671","e574bf7deb","6469b240f9","5a85f26cff","ce18b052e9","7385e2d2bb","8682011c9a","71359d1be3","4761c6868d","3649fcc432","6e084c2a02","6c4a541f47","b1bb984a15","a1ad18b343","96c26a8120","c5be9775b6","49729ead94","eb74929786","fc39608bd3","d8a6f37ed5","073eb5fc2e","9ea9bad99a","cc663f0d9c","c3952b1890","6628e545c8","3106d76ae4","2b5dd8dc20","1d0e7964f4","f6f177b9ee","de35eb6c12","2fc254cae4","55f59452c7","509e99b8bc","8ef29a3c3b","b8aba33c60","5ddfcf7b12","0526a61119","29bd93af98","6938fdb093","315fd8ecbf","c19c3a4d41","54f6c36ff7","554e4bf3b7","35c1dcd430","29bd93af98","6938fdb093","315fd8ecbf","c19c3a4d41","54f6c36ff7","554e4bf3b7","35c1dcd430","2dacb2e0af","92ed9c301f","82073e38b4","3b6f00ae10","20c4655df3","8e6bc87328","5e6146ff69","dfcc622f06","f3ab1e773b","ef97bf8bad","932eb26f81","de0f14d4b4","61c676a88c","1058e32960","ac530201b7","f67d058377","6f6db32cc5","eabfeed4af","a14f4e03b5","0d84eced70","f4d3efdfe6","24e3986e53","9d630fc772","98160ef68d","7ea3504e29","c40315a9e6","de95bbcc6b","d2ab9820a6","d1ac18c9d1","4d31248db8","461ec6895f","1c1921d8e4","42136fe922","c2aad09286","662523dcc9","e110919731","a1a40ccad9","33b680b0e6","50adeee64a","dadb96e149","58851d7df2","bcb8ddd1cc","e110919731","a1a40ccad9","33b680b0e6","50adeee64a","dadb96e149","58851d7df2","bcb8ddd1cc","fc997ae2c4","a85a43f12f","1412963360","e63f20f96a","7de433d423","741c935827","c50ad12603","2dacb2e0af","92ed9c301f","82073e38b4","3b6f00ae10","20c4655df3","8e6bc87328","5e6146ff69","074f9f8d24","f95afd7d1c","3993c41456","460e72cff2","9e266e61bd","9e65214deb","c8b4696143","a0fd80585a","b25493fd01","bc009345f9","f9d6c78d69","1421ecaa50","e83b1d6edd","019dd4f97c","dce79c577b","614a631a91","634e7499b4","c27fd0ede5","5a32047534","1b8b22308e","12a6fa5d1c","695ca7bbcc","c726458c9f","093669da9a","2a5bc2e847","10188a586b","7a9e623092","93ce3fd21d","1b76a79dbc","8a9093427b","8cd53f629d","8f1e3eec54","f6b69af61f","c763deb38a","b5a770c01b","7eb3ab3ff7","0f6ad32cf0","92e9470598","da139454da","86603869b9","bbc634a9b1","265519b1ca","fc4f92d242","cc23c24219","2d3c6fb0a0","c6fee9e791","40da65a9d0","50f7861a9a","c109efb95d","b3a658dc97","236efd17bf","15e9fee457","6d898a8581","8ceca7ff58","125b8ad8f4","65aef2925d","b3a658dc97","236efd17bf","15e9fee457","6d898a8581","8ceca7ff58","125b8ad8f4","65aef2925d","26808cd59d","71a53afeb8","f0e7a48354","ecd0da42cc","6c919c4517","6b9828b7e8","8eeca897fb","9ad0744bef","0b58fe86dd","a223e29f60","30ab3722df","f27eee01e6","6c9b91f101","a194d77dc1","9ad0744bef","0b58fe86dd","a223e29f60","30ab3722df","f27eee01e6","6c9b91f101","a194d77dc1","3c522db1c5","803a0b22d5","5c570048b2","cb81b4741f","001502a065","b0d6ac6448","330431cb6e","50adc1ebfd","47d3ac7922","1ecca86c40","ff7d9b689d","6b9e89d534","e6793a7b2b","0f0df404cf","2c1063058e","2c98b9c1ed","08e988a459","c775ea0afd","d12ed3f552","ddc85b4f08","41f22b85e4","0ebaa35e5c","a03a16eed3","b2ce672d2e","43282df18e","616b8e9aab","e64b5029ed","a3e3990c75","2c1063058e","2c98b9c1ed","08e988a459","c775ea0afd","d12ed3f552","ddc85b4f08","41f22b85e4","ea5f834d2a","2b4d3dc849","11291f828a","e9dc59adf5","184a2031c6","b35faef5e2","f7a820922e","835abb87d1","b9b2b63148","cb9bc47428","0b7ad0388b","c2b1ef0252","cb19b1bc9e","166841e198","c91f26d7cb","345fca04b3","c7afaefe6b","8d1baba594","5261476019","8e8eb0a075","7b19d74ce6","c91f26d7cb","345fca04b3","c7afaefe6b","8d1baba594","5261476019","8e8eb0a075","7b19d74ce6","518e704b9d","f8730929ed","e4537c97d7","64fbf2ba80","a17d043260","5be1473143","4fd1925821","19c4833d14","849c845228","4a06562a37","a216c99223","f6a09d76b2","9c7778e377","4d0a0552f6","ae88e4641d","779bc6da5c","d37c653a5c","f18d2792f6","5bb23da3b4","682b4155bf","95601c6584","bdb0020d7c","fb8a423745","b60c369289","299ceb3c80","26ecfbc432","923a0bb1b8","8f41ba46dc","3e96829bf1","caaaba638d","071097c3aa","395efb7346","acd84507c3","1e6ff28e56","e1b3010b2b","ba370afea1","4155bef9af","af6e80b9a1","f40fca9648","b7d8c86e7c","b4697aa086","6bb3f9f2e4","ae88e4641d","779bc6da5c","d37c653a5c","f18d2792f6","5bb23da3b4","682b4155bf","95601c6584","518e704b9d","f8730929ed","e4537c97d7","64fbf2ba80","a17d043260","5be1473143","4fd1925821","bb6fbe581a","593c96f698","20232bc7b6","242af6e8a0","a9a5419648","3957be2124","a6d54d8e65","349f08f7c1","c3c0084cd8","f24d9d3a45","765a84fe0b","7d7412f968","d56e1f4786","cf58d446af","3e96829bf1","caaaba638d","071097c3aa","395efb7346","acd84507c3","1e6ff28e56","e1b3010b2b","4e6d00d217","b8286fcc63","5e513559bc","dde62cab3b","28682fd53b","b3184947c7","f3e99fa425","a817bb243f","8dd7f91a37","cf11396ffc","a561dbddb2","54bb3ed671","02983bc6f1","677ed4ddc5","87b35ae9ee","ffd176218d","c2b933ed1a","f08f6d96eb","46ee9e384e","f54cb4032c","ad6af7e89e","16307a57e7","6facca8b0b","1ea855c17f","c082cfbd8e","0ddc30265e","66f1fa0f5b","afe966870f","9f65587068","f846f7bb3b","fbc2655c89","be8bed4272","c1d0f8d6b4","8cb2a47704","6069736792","7ffe9f01f9","e1117659e7","7631a27dd7","b25ea5a288","51c87155cd","fbdda34c8f","d65c9d0ae6","b1234a1f41","66c303aab1","7312865b44","0d1968ad55","535fbbae3a","38e004ac2c","d6d0afff4d","9f65587068","f846f7bb3b","fbc2655c89","be8bed4272","c1d0f8d6b4","8cb2a47704","6069736792","f87b2b9cf6","9600cabdec","c177b6e5a0","e9908ba45f","95b575b1cb","abe168f848","a3919604e4","781a97152e","9df1cd4015","67b96e6126","8408e0ff8d","5d57dc468e","ff3762d3f6","99882fbd42","d1987563fc","cc4f1fbf3d","f63d7a5a2b","a73bf025c1","5e9b17fe78","c79c8e01a3","25233b836b","68194fc298","30f0042cf7","c2fb8c2210","d9f4375b4a","38abf39a32","45af730062","5c13b719c1","aaff8a2362","abd530b843","2ddeebf519","7b016df516","612d36a738","13fdaead32","298b732987","af45145949","53956dda36","55d1e1ef1a","9a1b1d94f7","5b100fabee","b741ed9881","02986058f9","8cfc2b853b","414936ba1a","71fb45433c","cf634165a2","240d9c04cd","3c009840dc","3be20d16b1","8cfc2b853b","414936ba1a","71fb45433c","cf634165a2","240d9c04cd","3c009840dc","3be20d16b1","50f777639d","484be29e9b","99da5a3e01","724c50a3b2","1bfdb2af6c","05a7f0f321","ff6eeedd72","50f777639d","484be29e9b","99da5a3e01","724c50a3b2","1bfdb2af6c","05a7f0f321","ff6eeedd72","f778d6cfe5","fc69787eaf","86bd9162dc","7cf6e18668","cdf6632c76","a1b910287f","6eb9ae9866","2a1848a729","714620edd9","86e78913e6","9d7551952f","65ea630170","e615894309","4ff2f3cc26","04f1ac80f0","4ffe5146d4","058293f1d6","7568331909","4c514e44b4","aff4941f42","66b59003ef","04f1ac80f0","4ffe5146d4","058293f1d6","7568331909","4c514e44b4","aff4941f42","66b59003ef","dcaab3f59b","53ea14d0c6","34e281ee6d","cab33407df","751c2fdedb","bc2d1ca0c0","ff78cc5d23","5f1d3ca22e","43b588a68f","febf2ddf76","cdc3e58ec4","d62e0fb62f","d12155bcc6","192598440b","b2afe310fa","f79ca72959","9ed0004f04","78f9ee52b5","6880e8371c","bab1409c18","a77d288e5e","3acf2d7f5c","d36df586dc","3dfbb02a84","4cdaed1cd5","09c614f042","3aa46a5c9f","e90a0f070d","4d9c1dec04","d45ccf785b","70ab2e455b","be562f457f","aeb387560d","2ad1fd08da","e39bc2b909","5881c6457c","96413f3ac1","8799ae65b7","98ff285acd","522a936769","02a969f896","90def0d632","4932c2936b","2680e65ac4","c34a70952b","2797d3d07b","d5cdbf7fec","3f90d8fa70","36586ffdfd","6ad452c920","f8efebd894","c590cbb183","1774f2f0f8","cc445ffce8","f740011db1","294826e0c7","4d9c1dec04","d45ccf785b","70ab2e455b","be562f457f","aeb387560d","2ad1fd08da","e39bc2b909","e096bb2a78","1fb9a1d3fb","6add3df2f7","2146ab7c47","cfd5a1287a","bf1d4fda5b","c17f23cc0e","a58f7c7416","db21c18787","5fbff7f560","af83c6fa74","230573a477","2348605565","ff0f97baa0","414bdbe3cb","ce4d8a019c","92d808dbcc","2333776d54","c9431813b9","fe16e7cf93","5c9d23741c","a58f7c7416","db21c18787","5fbff7f560","af83c6fa74","230573a477","2348605565","ff0f97baa0","3d8fd823fb","2d1edeffe3","8b48fe4531","08eee0959a","a291acac32","13b034314b","5ca4403504","ff8d819431","e7975f2a50","ec21181451","6629889a28","7b07fff918","8fc311fa13","8f951ad5eb","43bf2702b4","8f6dec039c","bf80cae76a","30dd1ed345","d0ddcf10d4","4b268c5548","3d365cedb5","ff8d819431","e7975f2a50","ec21181451","6629889a28","7b07fff918","8fc311fa13","8f951ad5eb","6a52910d4e","d7eca52d15","37d61f25a6","04bedf26e9","27a750c5d3","cfe1d99f4a","69b8c2cd4c","6ccfadd12f","8a4e193464","a35a9fb940","61392aae5e","2a8a17149c","b67fa4e935","a3effab880","6ccfadd12f","8a4e193464","a35a9fb940","61392aae5e","2a8a17149c","b67fa4e935","a3effab880","afd6ebbe54","b46623c1cc","98e5fc5a3b","d6cc2384ad","ce6d500c69","8f605b204b","70ed74b7ef","ba5cac41c5","9ba9afca18","3c1401d2ce","a8086db243","f0de8dd161","1ffab42bef","883877ecf3","c1dd604c5a","f53320185a","1cda5cc90b","8e9db2842d","0f0c2240b8","b6f62bcb17","86c3b5d3a0","a3133733e8","eec77e7d0e","9f0c311036","cb2359b7d9","f7e18740ec","bbdda79073","39bce3ec5e","744c772248","85623030b7","b9ebef6f8f","c8ac641e26","67e6754240","0a671df835","74003c2ecb","d4385a1a6d","ff8baece9a","3294bee293","bb36e3302d","21f81a4765","7cb562c731","4d6c5681f3","33fe69cde0","7ad2e0ec4e","688d6e7030","1e86a956ab","ceae30eb1b","e9cde285d5","d030889c51","5f860fbd42","417eda1165","5778ca678b","90d4c5a9cd","2428fb238a","e9e9bcd888","4492eb9ef6","9ba37d7e40","1c4f621ee6","afee7be0a3","06ded82063","65c8fe2a64","f636960960","606d08fc88","c1dd604c5a","f53320185a","1cda5cc90b","8e9db2842d","0f0c2240b8","b6f62bcb17","86c3b5d3a0","654320dda1","1deb098c96","a4001122c7","8432e9135a","a811d6b236","147e48222e","47b33da7ae","0cadf9d6d5","61868607db","481059e5ff","ee1d060ec1","32361b4d7f","6feb162a84","2a9f49f51f","34ffc1d284","81f7898110","6077918a4b","b8a3c4d69c","6243099b8a","fb1c9d73a8","74a4b8eb3e","24c1951a0e","bf97284ed4","32201d7523","f52098779c","d5bcaba90a","0747b19f2a","14510cd084","27890d7cba","22526328be","94a7f68dd9","55afd5fed0","0e00951bc8","7f1c26ef97","c0cc144015","34ffc1d284","81f7898110","6077918a4b","b8a3c4d69c","6243099b8a","fb1c9d73a8","74a4b8eb3e","34ffc1d284","81f7898110","6077918a4b","b8a3c4d69c","6243099b8a","fb1c9d73a8","74a4b8eb3e","abff5dd1a4","1e384a24fe","7f894abaf5","ac364627f2","9d3207b55a","54198bd43a","685229be06","abff5dd1a4","1e384a24fe","7f894abaf5","ac364627f2","9d3207b55a","54198bd43a","685229be06","ab1faafcac","bdf4964b7f","2613d88471","360be00e62","30023ee593","9cb43d1a20","eb878c5ecf","79b0a14d4d","575e0c0393","96185cce88","43ff2b64af","70a6e64013","09bf0fd9c0","061d107dcd","745f769beb","e35e4b1547","1c2c9d4ee1","cb12a04b31","2112735ef3","85c8a6bb2f","05db96c8b7","745f769beb","e35e4b1547","1c2c9d4ee1","cb12a04b31","2112735ef3","85c8a6bb2f","05db96c8b7","961329cd2a","2792621063","4e8363b066","1463904896","21daa31f69","b84369881c","ebd5ad079a","5c635ad7b9","621ffa03de","f288a3cc02","46551fa049","340c0acb5e","dcacd63235","4047baec99","cd0942e42d","63c725cb6f","9a56098c7e","8e3d493aa8","1da9ab98e5","79b13d2fe1","1772ecad4e","4c3b0c30de","32c2353dc4","ae7e6eac76","147ff21f8a","515355f560","2520641887","b57d38e773","a1c7c4f955","3e6a2a1018","7d5463ec79","002efe0c67","e1a9e14e55","22764fb744","c8e499af10","7dab4df9e7","f8e5368172","2ba0a41288","3f8fc2b768","6f51338674","37482aa44e","f0ea694ab8","347ae59e55","a8c04ba091","029fb2b129","b3e0d34b38","692369482e","429e4ffe98","6971832478","a1c7c4f955","3e6a2a1018","7d5463ec79","002efe0c67","e1a9e14e55","22764fb744","c8e499af10","9001f75e56","97fbeb5cdb","3105b61244","1565f08bdc","2130728400","a10aba6604","1fd5f48952","d85ec10107","f041ee7e24","054793cb68","4ccaa734a7","fe5b99df25","1e7f92b799","cc6720a40e","b60b8a44ba","198031353b","5d2baea9fd","887bd7773b","6d327b2f19","423588e9bd","305f5cf092","ec2cc9d662","cb5f3a338f","d5bce3ee5c","dfdf888ce6","f6b7b0a0c9","f831ce1496","3754b76666","ec2cc9d662","cb5f3a338f","d5bce3ee5c","dfdf888ce6","f6b7b0a0c9","f831ce1496","3754b76666","7c9b04543d","19a5a4400b","58065cb717","512504f70a","cf3a93717d","9028ddb950","a8d8562dae","9f1733e1ec","346afda364","5413a1cf0e","f814522dd7","e250349c00","f84feb1d17","6ce53894f2","5f3c00246f","1774c527fa","54fa3605dc","8db28bd245","c99bc202e9","d7f7ece454","46aa1f0615","0c7f7f14cc","bef62622dd","ef63db185b","2491f3908b","2a83f47119","55bd3558fb","756c27b543","ce7e95b7fe","160e607eb6","c0d7d2c3bc","8040634c87","d3350e0010","6e2efd45c2","d5b1e52844","c2a7da987f","ee990ba6ec","b2ae3cf5ea","7fc2083036","f234a424f6","88c30c62b5","4d2c6d1b06","84eeba036b","9ab250f857","9f260f6e55","e1f0285c47","c2ce24364f","8004b633cd","45ce5f323c","2d7f4ca79a","ca6e1a5b25","68bc4728fe","15120e6c86","df7257c2ed","2ae868c246","84a652800e","d18291f88a","220e6aa139","cf489b1103","8c73ba8161","cf70cf8a6f","464b7f0dac","3eceddd07c","c2a7da987f","ee990ba6ec","b2ae3cf5ea","7fc2083036","f234a424f6","88c30c62b5","4d2c6d1b06","05473d042e","f36e4d5ec7","3dd186fba6","15a91ffe49","03c2979d18","7fcf03d78a","da02de551b","0b4b346aac","6a48bf6df5","d687d96c11","2df000c4ff","0cc2553827","3558ed04b1","d76bf895b4","eb3ff45682","c9d61b1c77","f9589baa60","8cb520c1db","c6c46b5669","ee47b5fee1","517f72081f","f262d4b408","34b14b147c","b48798fbf1","e312177c69","6da24e0fd5","9f5c009bc8","f23ca78577","08e91eb6b6","da6e0b5359","0e7f55935b","774e174785","b0a93b3e0e","bcca2eaa25","5027de31ef","0a27776ade","54679f2011","558648a9aa","80805c0cb2","eb723f43a8","40f997639b","17c1472485","96617697a8","bc85153675","00b58af21a","d97cff9435","81280499cf","ba17a70ed0","3d78939129","4c15c78fda","82c4b55781","eec13c04f4","1655724587","4566d6f2b4","9c8105ff7f","636ae06f1b","aff4bd5953","464cf6bcdc","30e72bf517","a3d7a75131","911b0fa678","da88b270a8","4e81da0f3b","aff4bd5953","464cf6bcdc","30e72bf517","a3d7a75131","911b0fa678","da88b270a8","4e81da0f3b","04d2b98b7b","c5a92b1d73","ff311bc3da","a1f24be008","0b905cc9cc","3f72560457","f8d2d8861d","8c2759f2d8","a02611a24f","14805ad869","5baaa6dc12","137410ade4","6df4b49dbf","fdb7b4bf86","d8630549da","17ce14e068","da88bee90c","1d91535a59","e881f76ecf","e03d84b79f","1bf0cd04ce","d8630549da","17ce14e068","da88bee90c","1d91535a59","e881f76ecf","e03d84b79f","1bf0cd04ce","d8e3dce236","b4c22b9297","ad7b188ea7","971d207673","a505b54dc7","0894250f43","7b27f6a812","6b16f8811f","0246ba1c64","21a5206037","957c613593","6804b88027","1a2dfcad51","d224f4595f","3fb15d6d66","e3fb953bf1","e3ebe24ace","c5b035d7a0","5300815ed9","73b888ee5f","9ad4466601","ab643f320d","b0615588fa","0b81d5d78c","e42f361daa","277922c42d","7d03530e5a","9b9e552f6c","2ab6115eda","8ff144bacf","2c7978fe89","e622448eea","94a0bdd6d0","d69a34d603","992c3ee43c","fad9285f9d","78c43041d3","cd7a1fe4c4","a8a6c72498","909b64cda6","d457b89ff5","867c647f60","966903101e","e32b9ba64e","62d46754cc","013441e446","6c15ebe220","68c45f732e","81aab211b2","f468c59a05","657998b79d","c5f14c890b","4c536f1b5d","3cb642cb18","a66d7e02c4","72587746de","f468c59a05","657998b79d","c5f14c890b","4c536f1b5d","3cb642cb18","a66d7e02c4","72587746de","33bd3450af","0cee71131f","a28374c922","83b7f88708","728ba9a9dd","9b85db7f16","6434f0079f","5d30a39abd","c8f184e7eb","cadf6a5ce7","29765a3331","f3fe75b84a","27389fda85","1ec388fea4","5d30a39abd","c8f184e7eb","cadf6a5ce7","29765a3331","f3fe75b84a","27389fda85","1ec388fea4","cb5ec39362","826ab30c97","a82ce4fe05","a4956e7162","4dbabc0a25","8696f5b91f","bdbda82512","c878eefb15","79d262946c","58a0fd386a","ecde80aca7","3996171c3c","0994f99209","0707067bfb","88fd8c7c56","53be3e0571","cd75dbd7e0","371845903b","bfd053eaf3","d674062179","5f46f12be9","9d298c7d2f","3d92162537","d7f63ba617","7f7f61e60f","39fe049972","48f77c979e","fe0abe8855","baee562f5b","34e2db3b05","0c6e7ae4e8","81c35019e0","0f474f56d6","c3d76d0444","4a38ec1a83","baee562f5b","34e2db3b05","0c6e7ae4e8","81c35019e0","0f474f56d6","c3d76d0444","4a38ec1a83","175b90809c","21061d7693","37cf4d3c03","d783ab4e77","d6f58ef33b","7440f2645e","bbfb41d326","14a24b5de0","b5710485d7","31fd72368a","92eee4a8da","e06fdd3328","cc1717e415","7f55a56681","0bd007fd06","155b75c504","6ab7d8a1b5","79205f1436","f47c9f12be","eca0140b7f","0407812779","448a30651b","14f03fe60e","34673cd8f7","5a8efc8eb0","dbd2ebd7d1","542dc15ac4","7f8bdf750b","c4582ca5c7","b869b8d9a2","27e4770428","8aee2cda33","4497b69848","22ef47bd00","e53ce8ccd0","36cb6021f8","640419fdd8","6f991dc177","b74defd827","0a17d5bec3","9df4ac5990","fce783d6c9","5b1c19d452","8736653cbd","6cfd6d13ff","73ee6a2b7c","c0551f5e4c","95c1be7e2d","b969c3fa91","aced327bf3","e37ceafd27","e23c27faa2","20ee9f2dbe","5b74af9d5f","cd79a77dae","8f92e5332f","6d7025bbd9","8439070eee","1555bc6901","068538b7ca","9f804dbe59","18c393ed25","f7f91797b6","18c58398e4","d688546ea1","28cfb94aba","fdea2a0d58","bcceb115db","ec1b827cd3","b625b9f92a","410d7d91bb","ea87881b55","09574aa3c1","a54a9d70a5","bb4593c0c8","3726998f04","aa7f72333f","2ce5a030d0","e89e24c3f1","960917dd01","f4923c4b64","c96f63c001","4397b0089e","467e44c43d","e04396d1da","ffd1471ed6","45f0a0325b","909cfb9fcd","cd2cbb3899","c9b61edd22","055abcb298","ffbe079fd1","fe4242c9c6","970d4fcbe9","b9af600581","5b997c9f37","f4e14f6ab2","a5fb45c3bb","c4a08d45ad","cb9c11c62b","3eea4b579c","47a07cb95b","f0c2737761","504bd4543f","e65e9ec8e2","c4a08d45ad","cb9c11c62b","3eea4b579c","47a07cb95b","f0c2737761","504bd4543f","e65e9ec8e2","3f17882bdb","684b4eded8","605b085bc6","5eaa66e950","ace7072fab","679d449754","34b838a7af","1b70e75441","22da6bbf62","9b68827490","b76438a8d2","8782416a76","310fca493d","4abe1a24c6","611f4f73c4","fbee56819d","066c71de7e","d71521c403","683cca7df0","2a53341e67","58bc8fde00","46435e49ee","4c3b7e9c8b","05d56d9310","f785c15086","a2be33b8e9","d2ad2770b5","c9e4530dac","0213e423cd","72579618c4","f533463f43","2004e605c6","5f0b2fa088","df4ce9cb71","835150fa0f","0213e423cd","72579618c4","f533463f43","2004e605c6","5f0b2fa088","df4ce9cb71","835150fa0f","8f63f3258b","ec628d75f5","a3bc60faf8","3e609458ff","738b3a08cc","0f1f1c2543","1d9e7a24ca","d2bb9bb204","3bcf253e78","9706a88d55","84c0f91a99","c29f870101","f63671833e","ac7dfcb9a7","0213e423cd","72579618c4","f533463f43","2004e605c6","5f0b2fa088","df4ce9cb71","835150fa0f","1dd64500b2","3f327325d9","e8b9d4c28e","8ee35baeec","170838255e","0577e851e9","dec26d8188","6a219d9b51","2f41b66a4d","f27f373461","ef6575c11d","b515595db4","bb698cf46a","9ca8fb8620","bda4cf8f54","94eeeb2e9c","918d4cfc02","1d0f40e1ac","d048aa71e5","4f48c2bf91","267eaecf81","2521a74603","77c122f38a","828a5af4bd","3390235771","c5d0d4ea17","1f5e6e62c1","440d554f12","3918900d02","bbe5276488","ab3eeabf66","2ac09e70cc","bf02b0a399","5acf45788b","382d160920","3918900d02","bbe5276488","ab3eeabf66","2ac09e70cc","bf02b0a399","5acf45788b","382d160920","b6ff5b906a","d1ed13e45c","963e87e47d","580487d735","ad88a7cf92","bce7b334b3","c92b307522","7a32b94229","c4398cfad3","bbb925613c","83ed6b4e5b","6dc064a0ff","8b436f6521","7a13381079","982c76f30a","5deece102b","45ea512ebd","2bccf0774b","298f4d6a36","50ec1d0713","d4efd89055","982c76f30a","5deece102b","45ea512ebd","2bccf0774b","298f4d6a36","50ec1d0713","d4efd89055","34f74d4c5a","7c593bcef9","ea3556ecc8","18de275f9b","5cca76a803","197ab0b130","fe85b220aa","d1821e664d","2a7277641a","2dbfa5f91c","497bc5dd0b","48546df962","17ce3efbba","4321e78862","701670a5ce","b82953c250","cb1a5566ee","7c5b2a2661","87166a91c5","dc61c7f38b","b7a56bc4cb","359f4e07ab","e5a6d9e12b","4a94ea8fab","9960a20ea5","9e701b5b6d","96e24123e2","6845ff1117","602c993d05","94e141567d","8306231fb6","e614eb8fab","eb97dbd1a2","8eb9ec8b37","304088ed2b","98f0425e44","6dc44abbb4","be255e9e2f","10cfce26c2","56f4efcdd9","6caad5b35c","34bb1df7ce","7fafcdf697","feacd9c086","0781860908","048267839a","9d158aaa55","d624a248a3","2f8b99ecdf","7a52e2b82f","d76d58fe02","108198b5c0","6340b8fb0f","0c964d9f0a","fef303247e","5654dc7f92","d12286f76a","af5d823cf9","0cf9fb3f2d","ebc56289d0","74714c3fc3","b4444dbd40","f3e445abca","8206bdfcea","1ce9828608","98c70725a7","34c8f41771","e5115fc2b6","8f43196fd2","55577db35e","8eb6b18e10","1a5f2b138d","1961a8f188","1cbfc1db32","03d64b751e","847373eb58","d280607fea","7756cc031c","d0e75b96ce","5389a32d17","76ddd9bbfd","2a294ad2b7","fe040be92b","7222ffd4d7","84a5f6fe5b","7ea5f5250c","ad6ae5caf8","8dde7cbf8b","fe3d5ea8ac","7b57c3b04d","94a227e36c","84a5f6fe5b","7ea5f5250c","ad6ae5caf8","8dde7cbf8b","fe3d5ea8ac","7b57c3b04d","94a227e36c","f91151df23","73fce91bf1","e9bfae21b5","cfaabbdfc5","0b17be2bf6","7bd35f83a0","3d9e1911db","fdfa2d65e3","df0f52d7c3","2ce0a1a8c1","57c34c9310","4300551c42","4cbc89adce","7fa4890ca3","58f904e6bb","cc7e105030","285972786c","e9c0ec94e7","794ff88364","426f410ce2","de39e97f72","fdfa2d65e3","df0f52d7c3","2ce0a1a8c1","57c34c9310","4300551c42","4cbc89adce","7fa4890ca3","a444adb6a4","a5775a7f11","364cd576a0","6f735a0273","af0d8d0894","8066287dcd","b55cf5e039","45eb95c41d","755151f2c1","8315fee00f","fe3191a3f9","1961da3eb1","4d9771147f","c4ba795082","45eb95c41d","755151f2c1","8315fee00f","fe3191a3f9","1961da3eb1","4d9771147f","c4ba795082","baf2b49eb3","75affd135e","392ff9cbe6","b761e6d871","5ae7bf0e55","f0a26e8caf","aacf6c173e","1b03c5e497","37f05e8218","c274d3a841","b42c17418e","ce81fb084f","d1598b6a4b","1a6e5eb741","1570b637e9","3b02781e62","bf7a8f60d4","b0e8cd06d4","c9d1534306","ccdd1fa234","5a7c146347","1a22ed9ffc","ec9d1b95d5","d7923ded95","d789704a81","6c9aee1028","40dad56902","f80f8fd66d","bd8269258d","28cdd7afeb","f98f6d6649","a7cd510729","564c472a2a","6521268ba9","f8ca9f7538","bd8269258d","28cdd7afeb","f98f6d6649","a7cd510729","564c472a2a","6521268ba9","f8ca9f7538","5091e5a038","02c66e0846","172f6fba00","be92ae306b","679fca61a5","9f2c8b3ae4","063b0694eb","0b6ee67b0f","e55454018c","6128b22d86","1712dde7f8","835844c196","c05391e91f","fcaf6e0061","a9ccad0f8c","4c60f69345","e0680e44d8","efa5104edd","bfed0fe08f","61b452a690","b91c467888","7fa95ad935","7a6338cbf2","563669cb70","a36bf44af4","da74c94a51","5b0b7aa620","aa47441cdf","c32860e4bb","f277419fc7","f0968f806f","aa5e623376","2f634fc0fd","2eb2c0a9f9","51366944e9","0c2730661a","327df5802c","732c46fcca","166d4a1b9b","218401b148","306ed42156","ef4cfaa2a6","7f3995be56","7135bf0552","412fe32642","c4e64c0cd9","24b962b2f0","21df0e4aef","d290b85e27","32d62497e1","74b4c5656c","3a4d4539e7","8be33f4455","d979b7fe01","127dedadd3","3784d8a403","960f26bd0e","857bbf277b","e18a53104e","23893b29fb","da4a374936","e5e40996fd","f75ef481ef","db04bea067","a7de286776","7f9c9f9eb0","21d3826373","35aac72f75","139de06149","70265c89f3","db04bea067","a7de286776","7f9c9f9eb0","21d3826373","35aac72f75","139de06149","70265c89f3","95f08ae21b","25c4d091f2","b8f6b2d717","d13b57daaa","b2fe26342d","f34b82f3fb","7df8af127c","5cdaa9beb7","a8268355c9","5e7869c027","3cf0255302","10797408ec","19e8e60f15","4606e29916","948a377b1b","ff72e5cdf2","7ec25d8a5d","9a626a213d","7187fcf3f6","26c696fa50","4a3fd8b99f","f398f4d133","e6591a04c0","1c41a0c1dd","ca0db91a4a","7c6102d0c3","521dd088eb","b0ec7aef33","a9ccad0f8c","4c60f69345","e0680e44d8","efa5104edd","bfed0fe08f","61b452a690","b91c467888","cc5babfbe3","748bfa7114","b33d54d67c","6a4f3e4f59","f9e67df77d","2914384fa2","3a50cd6ecd","c9f19d87f7","a7de6cc332","f1ee3f5de0","bc6e27f1de","73a514bd8d","95d73dbd8e","cf791bc852","a9a9dad590","5797bd04fa","8f0bff278c","86dee547f1","0901ab23e8","d7635dbd65","96feac2359","0d2440f41a","1a97dea299","7e18e90a30","60965582aa","7d8271fe13","5477af6e84","59147be4f3","c48116a491","56d098da6b","b38d454c69","0126607392","aac5ebe2c4","6d00fe0228","2d8b259cda","d27b0cb417","03c2668f70","7222d187b2","e7c7b137bf","7944d614b1","396ea9d00a","4c33bfe06e","5907806d5b","a2a4acaebd","fbe50d8438","ef16325cac","48934a34f5","a7d6a1bfc0","c9d6cdddcd","5907806d5b","a2a4acaebd","fbe50d8438","ef16325cac","48934a34f5","a7d6a1bfc0","c9d6cdddcd","355b4931e5","86e6b814ea","7b7dd61d02","2e55d41e7b","0dae1794d3","8bc891c32d","e0d016c980","e989b98bfc","a5486df2d2","871d2a1bfa","eafc394c5f","d3acc8dfc7","9f236bf64b","cbc8ca2a0b","5b62d8bf2c","38bbe1f0ad","ace43671c1","7518346df2","e5e7844f10","230583ff12","641f3f4274","a438fb3eaf","4e52d8341d","4c122f9b4d","ec88b3dec5","18d77414d5","9c65e54873","552d2317ff","bfd085762f","be79ac6f6d","0de39ccdab","3a3c446a7e","8282efa2ea","f05d3195f4","8b29d6f301","a7aabeecf2","e77ae7374e","79e1c36c9e","910aedba63","a4c0cd4dc3","ecbab2a191","d949fc63e4","a7aabeecf2","e77ae7374e","79e1c36c9e","910aedba63","a4c0cd4dc3","ecbab2a191","d949fc63e4","23e8e3d46a","89d842cdc4","5b2eac2612","8937128c2b","c7d949204b","96a817f1f2","67d052950a","9a46baef58","8a0f247ccf","1e2d7e851c","a8001fa401","97a9f3e695","804272f02a","e1a3f2c48e","3867f2e78d","941ef1450f","b53f391de3","de79fd7f93","d8bb45bbf1","320e4acadf","0af68883a1","73f0afc48e","ad08d3a7e9","6cf7d6eff1","2a5b4b0741","7f7ae12ea5","f1caba0f2e","9dbf70df04","1515f52655","48edc07305","0d22827880","fa21c02134","0932d9b665","a20fe4e925","94c6106e17","e8e310e7ef","dc3645c9b9","a1b9c15d4d","cd4a341755","ca909fd150","cd1c3b50bf","675f4e02c1","64e6af65cb","645213dcdc","12338eef8d","67e79ce1c0","e8eb8d6c68","1eb893d98d","1dd09882a7","81a085915b","55c5d346a1","50eac29fbd","197b071d5b","fc4f663b70","ec21cfdfea","1a4cf6be2c","098d178494","a12a94d91f","ab9a58637b","d9b6a27413","44d436e3db","31af98b84f","02c8c843d9","a5e5d7c487","7b90a5bd25","0f8fbc6245","db575d1967","f2444c017f","14bc780da6","76185ac6f6","db20178ef0","354ec636cf","246913ec84","b0a25ebe99","355e37a99d","92dd31738c","dc61237cf3","12169f00e3","41d9f259cf","82bd89d4e6","d1dcba7616","982768cf9d","a10f542611","a5c9f8f254","d2d8fff271","fba1ef49c8","1382f19496","e15e25355e","bb7f7055ed","decedf024c","136b254cec","d2d8fff271","fba1ef49c8","1382f19496","e15e25355e","bb7f7055ed","decedf024c","136b254cec","5890c65f19","b82576e660","10a0e9b721","c69f2c9461","5edafe992b","d0df82bbc8","991b0f72e5","81eaf5642f","62e1cedf8f","75460e7f9c","0f9a308944","d705316d75","38819be8e6","323e57fc5f","1a6734b838","2fb4bf0cd8","e131a4e22d","b4babe7c4b","a4822f7b30","bf47dac3e9","ea666ba35a","65d0009411","3c8e21a1f7","bd280e9ec6","522ce2e300","ec5bc4e63c","ddba7e0c1a","bce75bb188","b5c21b6550","78f33258bf","70af0f57af","b8678475b0","d2803269ff","cfc535b646","20b4ee8dfd","f51eb173d0","261d1028a2","926a5fc7c3","4f0666ea81","75ecdd4180","d412d1e34a","9a412c899f","080a3392ad","5e589c55d0","385e31e328","de56c360e3","237ddc4e3e","121755bde8","51be1611b4","659ed87f51","d6709be6bc","28ec229d80","3981f48290","90f0d09df7","eacdb35d07","f7b47108b2","17242bf35a","f426891296","16165368dc","42587d5a66","7c628d2669","d04315eabb","45e226a224","17242bf35a","f426891296","16165368dc","42587d5a66","7c628d2669","d04315eabb","45e226a224","7114ea0a09","f646dfee71","67387be153","76311a4106","6c2ddf9881","aa4830249f","dabf7a1779","b1b78d8e14","f755fbe398","d7b13f41a6","320052a00e","3fa34b6ef7","efd5a08f37","e66499757f","bda51ba576","a976198061","5a4d361a8e","662987a691","fde5579df9","91b88138f5","1d53df27f1","d5776beee6","4843a76e70","9e3848fee7","17d9da3c0f","42f9a74ebd","0b52e647eb","0bfee56d62","d762e99ea9","38a37d2ef0","f8f44729f8","9fbc31dd1d","e0edf67531","3962eb920e","88b2c8f08c","175d828bed","bcb5ca2282","86ce49d9e9","23cd811ec5","24257c740c","609054438c","ff7aea9116","40fd36c30c","72d58c11e8","5b9762c992","470bb11b3b","c8b88cb1a6","cb39d2f38e","1a9d0c7613","a4d72ad776","c5bc647c9a","3088157937","71dcba1ae8","dc281ca972","599f679da8","74130daa39","d0a5c5fb3c","6c517ad2f2","a914354705","33435af38f","13bf506734","693d95c1ea","8cfcb20bf8","5f1d9195c7","f5d580e4c7","6d19872f62","d895918a30","ea41d99f3a","8a8a28ac63","2fdb883959","5f1d9195c7","f5d580e4c7","6d19872f62","d895918a30","ea41d99f3a","8a8a28ac63","2fdb883959","a863ecf349","c47774ef07","641ae84227","77655952a4","5941926c9b","b4bb95b47e","9024659253","41b445dd3b","d01295e5e3","79473ccd82","c28a9c9ae6","e12c72122a","79b2b925d0","702bcd9e31","69273aa401","30a2fcb12d","153c07714b","d003c51e15","7eca135be0","8cf20de638","f73938dabc","a863ecf349","c47774ef07","641ae84227","77655952a4","5941926c9b","b4bb95b47e","9024659253","4bd3ead448","a1dc4a31d4","8304e22721","a06879c2d3","10c552dcc6","36b06c92da","624294e823","7f8d4f2a17","7caa2abc6e","0febe9a067","cac5f9a813","1a2c16b195","d9776b7803","6834211d32","c78fd9faeb","0993663b7a","cf19cc114a","8a33c89528","27f259a22f","8caca7aa6b","36cdf69269","93c0d2f62f","4103b54308","e1a5f5bc01","980ca928ae","6a2c1d5c52","3258cce662","a6f9147681","a946a88503","f3a5786c74","8e80a7e1c8","b1f8931291","e78fdbb373","e04de4b7e0","556de54dd8","c75add0f84","4d0b34eb4d","871c7612cb","bd5366e3e0","c009a33f3d","35efe36249","b2410678ac","e8994427f9","d20c412a89","779d35dc3a","e325d03097","32c7118480","e362d2e0ed","080d7d1133","e5514626e9","f2030670ad","192823a716","c0a0b1122a","7c8846a382","b1d726b0ff","350aca6185","5b837bc528","08a32cbf9d","c3301d3dbb","26919c7337","afb6fa60dc","166421761e","09498a2dc1","c185c7c824","c4ae3ff999","688501135d","eb7bafc21a","2cc73b0395","f3c04b41d5","62968e2fbe","90bf265bad","ae2199785d","07b829b2ac","fcb8c7245c","72ad3f9c2f","522c7a6d60","132cfd52d5","90bf265bad","ae2199785d","07b829b2ac","fcb8c7245c","72ad3f9c2f","522c7a6d60","132cfd52d5","6a635161cc","bb133764b6","20afd3ad36","32cc24688b","77b9638750","5b14361ce3","057c4add8b","fd5d438cdf","705eca4420","fb6a206f3b","f68f12b86a","a172032286","e4727ebdac","84b8ea1f35","134fa6f212","b4f226b80b","d32714e661","42708e861e","6f1c95e9f7","8c08550ced","f5da55e621","49c877f1f1","e66667010c","40dc99c755","55d89a09d1","81f2342da5","3b730706cc","b8f92171dd","dc17972638","dde534ed2e","688b1a70fe","fad1551aa4","b17fb7e603","0578860773","6991594626","fdab1938ae","45d7260be8","329a7331fd","8151edf64d","9cb45c7b5f","862909b203","1d591ef9b2","c91220c239","c8c56d101b","cc6b4d2fb5","df761f63fa","692e6a8f7c","202c155ed1","e8090aaef0","da6afcc0d4","cd941d6836","66df38f970","c5a918acc6","74006a31b8","0afc25ad36","222ee778c4","599fbdb4df","4804dcd87f","df43b63c00","ff2ddf5ded","7a22d9ecc8","5606860c20","66d46c2b8f","0bb3a965d7","248e6660d8","28fc225038","eff7992dab","b66321d47c","656c54fa93","d513e9fdc2","19202e17b3","db495d6093","704f11d812","e3919f3657","f5a0be15e7","2b9087514b","95602c3dd7","b701633ab0","6018cae500","79a08de4e9","64c8fdebdf","6110c14d12","413b19e36d","cda034197c","2edde01a0f","601e66955d","5bef719b4e","9fea7ab7f7","ab4e16d4bd","3d5557ca83","b6125e23bd","1d24d02c88","6988e82ea9","0d2597169d","a23410cc7c","3abd93bf02","162199b53a","d4958b07a6","0015b8bb1a","291cafff6d","544cf208f0","b5351c2841","185fc5a0fd","6ac90015bb","7ca5951bf9","49c877f1f1","e66667010c","40dc99c755","55d89a09d1","81f2342da5","3b730706cc","b8f92171dd","e789a4a041","5e23b5a572","5db2eb5466","dec868c91f","231803468f","a8212f532e","080c97d087","2edde01a0f","601e66955d","5bef719b4e","9fea7ab7f7","ab4e16d4bd","3d5557ca83","b6125e23bd","5ea99a510f","d2f28b0d2e","3a241b9318","28cb5b233f","cf2b7b6fce","76f32e461f","1b88c609c2","5ea99a510f","d2f28b0d2e","3a241b9318","28cb5b233f","cf2b7b6fce","76f32e461f","1b88c609c2","245556c6bb","9f0229fbf7","6dd4e8aa9b","d584f45cde","b9aeace160","cfbef55c93","b1e2bbfb05","b4b14f8015","fe0c6b8be6","d7cf61539d","97def53642","6ab903a7a5","c3b8110d80","48b008ddc2","48bf9dcf0b","4fb7eaeace","1053f0d899","d9c6de2fa4","7959488a94","769494bf25","a5bcf94934","48bf9dcf0b","4fb7eaeace","1053f0d899","d9c6de2fa4","7959488a94","769494bf25","a5bcf94934","4b3cd74c04","e0f446b71b","d729d9c11a","a87492cd70","96f50b105b","0db7659e8b","d5ffa7ba98","53ee4f78e1","129ef6b60a","c815863934","611052e459","6bc0c54517","5593f544b9","1d23b6df9f","86f91b0740","3924a80de5","91079f83c2","c51ea1c520","556e0e83ff","06db924f08","b40fa60770","999f57380b","ca408af756","f878eebd8d","8f5e612381","0183b988d6","75a4552f26","44583ab0cf","999f57380b","ca408af756","f878eebd8d","8f5e612381","0183b988d6","75a4552f26","44583ab0cf","1887463439","6aa8178771","ea18e219a6","911f8ccf07","b526f921ef","bf1b06e6a1","6366045d59","f3eda8ff4e","2e16c934ff","2d6d1b65ed","4d79baa915","005fc175cf","ef2f921657","dfc41a5efc","1887463439","6aa8178771","ea18e219a6","911f8ccf07","b526f921ef","bf1b06e6a1","6366045d59","53495de666","e1304da497","0a12ecf2e7","51c5e96b42","231c151e47","6128292e81","b4d514720a","d6590e92e4","b4a1e55963","16097ca738","01090f4ce3","56d429fb8c","12ef2de6b4","c531bff55a","2ea673de74","bfcb3b5d5a","cd626184b6","91db063a0a","522b2361f5","1375fb903a","a6cc4788a6","283d4414fd","39b31f77a1","f67a642906","652ab885ac","3278cc5c54","f65908e26f","60c651b938","3f4e671b95","8d6f80de14","04ba694600","3fa22a1ae9","d9c538f8b4","839aeb3876","34dafd8e6b","e07910e552","d6288b76ad","67a6ea3014","49ad9c6118","2041af91df","8c3a9eb554","afdc720318","2ea673de74","bfcb3b5d5a","cd626184b6","91db063a0a","522b2361f5","1375fb903a","a6cc4788a6","97e2709de5","a6ca4949b6","68a51c1b11","0db5516aaa","6fce0d533f","3f653c4d4c","26a2eaf845","3124f6fc26","6fc8556c3a","7fd420785e","5986a19018","cf0f1b351b","aaa9f38e4d","81475dc228","65f5c64546","977583717f","9c08e842b4","96eab1a192","5624e869c6","8e98bcdb6d","a6cedf7d67","19a9c4617b","994d1acf89","526bc37cdd","588ce9ce21","5f89b21aca","14c3888a38","be74ad000e","e729b19901","c5170df878","e32b00f4f3","7d148981f6","bb84902e86","88d22f5bb9","31353f6914","100661ce96","86ea96c51a","914b2301cf","6ff73af381","dfca6aafd8","4f56a2b2c3","e675ad7370","100661ce96","86ea96c51a","914b2301cf","6ff73af381","dfca6aafd8","4f56a2b2c3","e675ad7370","c696c21895","ce1a6255a3","a06dafeea5","a5543dc7ca","bf135d0bc9","ffb9ff449c","65723f1772","8c3b913d0c","748fcc3f02","326a2b96c4","0e933f888d","53be6cf32d","f3d1bf5781","0f892cb9e2","8c3b913d0c","748fcc3f02","326a2b96c4","0e933f888d","53be6cf32d","f3d1bf5781","0f892cb9e2","551ee894a2","54aebd74b6","a54ebedf9b","c2a3261cf3","d9fdd194f1","aef10f3425","93b64b10dc","551ee894a2","54aebd74b6","a54ebedf9b","c2a3261cf3","d9fdd194f1","aef10f3425","93b64b10dc","860e45ed35","bc1b7af516","b316697d79","35d0894a3e","e45528c87e","7cef618ebb","099f577200","62f366e300","af7fb6f63a","7eef37a163","5058ae869a","f041d9707e","b96fc7ba70","d107875b7c","62f366e300","af7fb6f63a","7eef37a163","5058ae869a","f041d9707e","b96fc7ba70","d107875b7c","35ccd498f2","ef96a941c3","3cce18c98e","00b832b0b6","cdeab7c339","69533e8f0e","e8453530bd","97beed1ce4","889434c37f","9440f3fb59","3aa0d01e3b","49fa4ef4fa","8324a21dd7","96845c7257","831740bc9f","4116cc5344","d586c82f48","43ae3b5cca","1f4c659113","acf134f967","c73e91fa33","e8c5925d33","fc8b0cc091","e609c1d411","1d911e1729","d9176647a7","369ab0aa59","31a0b1f8cc","e8c5925d33","fc8b0cc091","e609c1d411","1d911e1729","d9176647a7","369ab0aa59","31a0b1f8cc","78836dfb71","26ce0d1d21","6debe3c0e1","5a6b8d066f","077a16c8fa","0855e22914","57fe2a47d0","e5b736518e","4d725fef34","036e105157","88debba93d","c1beed80b5","32299b53fd","586ab6721e","3b233541d2","d86d1b18b3","36a2433727","c0c64cf5ae","6cd5d6cc3b","fafb3099e1","ad7f44d412","4c6509fac9","568e097832","8d7cd887fe","f8f1dab2d5","406ff7ccbc","783af246a2","8467efcfc3","8074d574f3","83766326bb","aa9ccd7989","04158dcc2e","af4ca1ce31","5e66b8b8b1","f7cae4733a","b0e2646d91","6501c1abe2","b122c62e9b","e0faa7e0d6","f1c1299efc","b953a88dc1","95e8c97134","ae392413f2","389f04d9d2","bfe997264f","42ef30c76e","e19a71798a","e21431143a","403922c09e","59e44f87c9","5ffe633c54","44d3adefd8","3f7b67f6aa","940f988bde","0cadffc566","6ecf984d71","5b8774cac5","1d512e54e1","15196d7df1","6012c7b5a5","36acf6f846","c8abe353b9","fbc04a0d2a","1f3830d537","f0bc446860","69fa429954","981044b3f8","adc1c89c79","b20a860fd5","10a988b6c1","2d37debfa8","28cfd3fc51","a2d2af304c","b7cc1d861c","76c099d39c","9f11514831","9f58517a1a","1562cef8c1","fc8943375b","73e39e270e","eb461a2658","26efc82be0","d7b8ec2b6a","d2eb7d8171","15c3a2cd22","644194f643","9d04254a92","2356febbda","2eab8f1273","a1957759f2","49527debfa","4f4a155d06","c4f858a36f","bdb0255ace","6834e2712d","e4aa870382","17274f7e63","9d825fb874","6b22533aaf","a54bdc4747","4e2607b0b0","d438c00f50","d25e883b37","f6194f90ca","43925f21ff","6b22533aaf","a54bdc4747","4e2607b0b0","d438c00f50","d25e883b37","f6194f90ca","43925f21ff","4d3bb5fe37","f404c38151","135a6790e9","f50237b8a1","8f97b39cc7","e7e537696f","2b1b69687f","4d3bb5fe37","f404c38151","135a6790e9","f50237b8a1","8f97b39cc7","e7e537696f","2b1b69687f","588c54c8f6","a9ae96e05f","ccd1133d19","784ea92fac","8334872f4d","c1e438cd5d","71c941448f","caf9ea7f12","819c4fb19e","042689a498","3a80b5285d","0a9ef573d9","a0c664354a","fb76d08690","caf9ea7f12","819c4fb19e","042689a498","3a80b5285d","0a9ef573d9","a0c664354a","fb76d08690","40d18e845b","3db932c904","37e49ab2ba","fb0adef11f","d3f7be5826","10492fab15","f14846eb0a","bd5c09a927","d7b9df1267","2de528c1de","6b70d50534","8bbf218341","d6be459867","9bcd308684","bd5c09a927","d7b9df1267","2de528c1de","6b70d50534","8bbf218341","d6be459867","9bcd308684","d04f35c62f","d9ebb0c087","84ff16df82","237b8bb9ab","c6f33bf390","8b59bee5c8","5d14af9e68","ed015f5d00","06db591f90","7e22017fbe","a72931f1b6","dc6a60ea99","439a3fe186","eed1833cae","c97f55f5ce","aa2884f6aa","f4cdc4a6ef","825d2812e5","841ddbe6bb","5837e0529a","234e6e3b03","1f6867aa7c","d6b49a16f7","60a601a74e","0740185cff","eed982bffc","4d606dda70","0f8fc08a18","dc9d912c2b","b922bb5ece","2400d04fdc","4935dcce83","d8009b0d70","4db30541a4","dbf436073e","dc9d912c2b","b922bb5ece","2400d04fdc","4935dcce83","d8009b0d70","4db30541a4","dbf436073e","80115d1234","bcfce7b392","5547581acf","e6a336692a","7041708e69","e13b63b50a","03f74ab862","4cc5916ae8","52366392f2","8990d11d93","61513ee920","072934e7c5","8e0dcf9782","948d0ac5c2","d2ac87336a","f87946c800","b093c956b7","657e0235d2","b1efa7470d","e5266922c3","ef443e862c","08352d5c9b","4f41a1cf43","6c9cbf4993","e65817dfb0","f0ee6e9e67","f71445b294","374555fda0","3df112fff7","8b9847c5b5","e21a51f590","67fa70708c","e0a1928d99","ee33781c5b","1b91f0ccfd","107bd1c7bd","e8a5eeef2b","a805e3d9b5","b193063a1d","af2239b964","64605ecbad","d94ef48243","4455732b1a","1ef3699937","276a425e88","5614540178","578978e93e","5a00253197","808fcb7f85","b2dc045009","6d72dbc5b4","39a8b99663","6cfc4d1cc4","6f0dc68f5d","b767a97b7a","b90a79d986","0ec870acea","1e45e6b23e","813dbd93b0","84cd471b02","782384242e","0e9ddfad3f","763ea7635d","1cef9f840e","5d80aea9ec","23c1132bda","a8ab1983f7","4e0f0986ab","3598d626df","ee2cc31d4e","1cef9f840e","5d80aea9ec","23c1132bda","a8ab1983f7","4e0f0986ab","3598d626df","ee2cc31d4e","bd809362e5","d580680b31","9d443f5056","f0ee8685b9","6e4a807d83","e75e93adb8","bfe7ba7024","6fa9d36815","80408c5463","520aa336a4","78d5f65e72","256639a22c","66268a213b","abe0055541","a0563b44cb","9d13ad4410","f9744738bd","e42550e3cd","cd4cc6d657","58b5f08717","00381bc136","74efbd3bff","6f009a0451","42eb78529b","1780b84266","46d107dc80","77c5fcfbba","36cb5d30f1","d2ac87336a","f87946c800","b093c956b7","657e0235d2","b1efa7470d","e5266922c3","ef443e862c","ff9e421c4f","69328d56fa","1d9e03c186","540d11790a","f22d67b808","8f7b656207","5748c34cde","3d0eb25068","e97d25c7d0","248a89388d","3caeb0fe0a","a4e8c28e92","46bd93b8af","ddd681f78f","3d0eb25068","e97d25c7d0","248a89388d","3caeb0fe0a","a4e8c28e92","46bd93b8af","ddd681f78f","8be9812ae2","bcbd31e897","3ee12925df","d10ad03b25","b93a91d102","2d567958a6","60549c6b99","009790766c","e4eb673548","4d9ce12758","efea87d06a","2e21c94225","a8e992ac19","60e6b582ff","009790766c","e4eb673548","4d9ce12758","efea87d06a","2e21c94225","a8e992ac19","60e6b582ff","009790766c","e4eb673548","4d9ce12758","efea87d06a","2e21c94225","a8e992ac19","60e6b582ff","3fd4b08d4f","7d7d9b67e2","890d4dc1e1","91116cb290","51ea976ac1","a246fced4d","3e68bda8c7","91fe3a2927","7a3660f6d6","b8d0176495","07ad0e5e74","5f50662ab2","a90c3b486a","b66270759f","d052b20a80","1ccb193ea3","75fc16bb17","e178931303","effbab0868","358037330a","75cb5bbfd7","c3d546583f","fb43996cfa","e0577f8a98","8abf432215","6b2db6f358","0cc923de3c","d431b39062","6a316cf41c","57864285c8","067f83cf6a","f56f6d55e8","f3c6150d53","a79fe5d5fc","8eb4a77d16","d6bafd701f","b649777e5e","e662faa388","1741abaf28","568526f6db","cd9bc1122d","290a53153c","f05c8401d2","c4134d1d64","4b373232fa","359502718d","471619d826","4799b7f38d","40152672cc","f05c8401d2","c4134d1d64","4b373232fa","359502718d","471619d826","4799b7f38d","40152672cc","5c131b502b","3b44667a9b","025dbf1deb","edc4d27997","583b51268e","aa3e511ae2","d745ca2db3","a8d1fc6fb7","54378729a2","5a00a3970b","bec67e8fde","00984dccfa","c8dac99ee9","7c23520e52","a8d1fc6fb7","54378729a2","5a00a3970b","bec67e8fde","00984dccfa","c8dac99ee9","7c23520e52","a8d1fc6fb7","54378729a2","5a00a3970b","bec67e8fde","00984dccfa","c8dac99ee9","7c23520e52","6d91942ab6","efb287751b","aaad3bcc5d","5c865dd910","e3208ea9a2","1631591460","47c752e93c","6d91942ab6","efb287751b","aaad3bcc5d","5c865dd910","e3208ea9a2","1631591460","47c752e93c","187a143a50","6b867bc184","efe789d483","1081f7f447","72e0b225d0","d733edb668","eb0c27ee5a","0f93a5d2ec","28d7d1a186","8b1109f9b8","45000abce1","dd5f798713","ec6a66be22","4983934d96","04fdcff3f6","a9b15320d3","698bbbe535","e87d82788a","02bb94355a","b6ae5f18a5","a78a63b091","bba08e93f1","bb8b1af137","3e515e73a1","e447875836","6ef659a859","b3e00bd4f1","c1940e20b2","cfb9ba13f6","72ae1bc860","303fffd531","1b327b2844","c76b504fd6","1a973c3c66","9924b1ec5c","cfb9ba13f6","72ae1bc860","303fffd531","1b327b2844","c76b504fd6","1a973c3c66","9924b1ec5c","b19c4d964e","18be654b8c","0ec84894ed","02fe062147","c36c71897c","7e7b523a18","e9064127da","36c2eaf411","4c2a612504","2ffd9a0ee3","85a2ba199f","dba56523a0","2d429203b8","dc63a5722a","9dd97df8f6","ae1d8eacc0","b51e6b6b50","2452a2f29a","7e010924a0","4e7c1a6ac5","2696a993b1","8419654bf0","4df619f7f7","3b3b36de21","6604ee3c9b","cd07306baa","9c5f93de81","cf688a3a24","c09dff119c","5c583126af","6f2e61ae76","d6f2fa2298","0d485d9610","8128a9e3fd","8aa4fe9783","eb931b6c67","524d5834d9","0d1e4ffb41","1ae3accc80","797a93d65f","fec6e52efd","bf5d7f255a","c09dff119c","5c583126af","6f2e61ae76","d6f2fa2298","0d485d9610","8128a9e3fd","8aa4fe9783","79c4775e9f","1d3beb7145","0ce05e870d","08b275744a","47c4440e2e","238b540441","89cf650f3c","8dfadc460d","285c2d706d","6119b580ce","c2fce7c01e","fb51af7f68","09b4970ea6","29c67ed967","8dfadc460d","285c2d706d","6119b580ce","c2fce7c01e","fb51af7f68","09b4970ea6","29c67ed967","076e087e6e","fc27291313","183faff175","d5aac9af81","8768e77386","40b885472d","a04e81e72a","076e087e6e","fc27291313","183faff175","d5aac9af81","8768e77386","40b885472d","a04e81e72a","28638d25f2","7ed0684aa0","9b830d776d","d1de70ffee","de9024a09f","2e0708cdd8","a8cf51839d","00b79c3d59","7dd2228ff5","1eb9236349","f5b23461d4","baf1de8d99","321fb732d0","428c237e4d","076e087e6e","fc27291313","183faff175","d5aac9af81","8768e77386","40b885472d","a04e81e72a","39866cac92","17c82cd2ea","1e3d2e55bb","de7eac6a2e","cbc7e9db55","8da2fa8507","886f15b498","8a11aa36d7","61e4172aba","c458c34b3d","9eda90f040","9e2d893d0a","80bb7bd3a4","3726747274","8a11aa36d7","61e4172aba","c458c34b3d","9eda90f040","9e2d893d0a","80bb7bd3a4","3726747274","2b22b7eb3f","083f775549","9613e880bc","4296fcde70","3a64d67a5b","108a56426f","029c289cf2","076e087e6e","fc27291313","183faff175","d5aac9af81","8768e77386","40b885472d","a04e81e72a","93a9d02e20","b6545dd6bc","9a2a06dfeb","2820f19ac6","20fd8c43aa","dea6b8a5d9","e842a4ccbf","2888eb4a66","91255ddb84","b22680b33a","03a1aeff9c","726bb95486","4c65b339aa","bed5cbe0d4","83a325628b","52a76ce35f","8f5aa6f5d7","8e796d74f1","515a72cf30","5df60ece18","c8d763b23d","00d096f7f4","88ec702118","6d94bdb821","743e1d9d73","b497fd87e5","3abf331d11","59094d684a","00d096f7f4","88ec702118","6d94bdb821","743e1d9d73","b497fd87e5","3abf331d11","59094d684a","c4888325db","f462940e02","07a7280fe5","fe1426279e","bc245c855e","3df7216fbf","ee4627c8b1","3039904502","70b3cf40e1","f0d4f772db","a48044908a","4d1b9bc105","3f8335b48b","43d8608621","f7f2c04fe7","a19d61b05c","9cf38bca50","6c6255d538","45ab9046ef","2da5b0a187","d7f8a00b65","9e32441a21","46b911f876","b555635634","86ff0cdbcf","0c01df3528","b3709f1970","cac3ea377d","9e32441a21","46b911f876","b555635634","86ff0cdbcf","0c01df3528","b3709f1970","cac3ea377d","11303f978e","77d49d3d0a","4fb21e8df0","c7d8287084","d1f807c941","681d74d68d","d1b7d55d5f","5398c7bf8d","6bc12269a5","41985053ec","9e94ff2f58","55428fefdc","1b96fbee64","143d7de914","86aa90a212","0e734f3181","9772c2e519","0bfe946f1d","abe33b70c4","62511dc035","5a0141aab2","9d3fa727e8","d86a1d8566","89e9036b17","8bc3be9842","ccc9705ee6","3dc51de08b","02fc283a59","27a3ef0585","a9f5f53591","d84d40e87f","f39f7ef4a2","dc88d67a55","18f8ab2ff5","992168bf27","5398c7bf8d","6bc12269a5","41985053ec","9e94ff2f58","55428fefdc","1b96fbee64","143d7de914","11303f978e","77d49d3d0a","4fb21e8df0","c7d8287084","d1f807c941","681d74d68d","d1b7d55d5f","7344edab0d","8d0ad74980","4da56500f4","fbc271f4d8","edfc2e3e28","4b236b8851","9d96a584b4","5398c7bf8d","6bc12269a5","41985053ec","9e94ff2f58","55428fefdc","1b96fbee64","143d7de914","5398c7bf8d","6bc12269a5","41985053ec","9e94ff2f58","55428fefdc","1b96fbee64","143d7de914","52a8429273","490179f5e2","c9f54f564c","a349dbff8e","5d718e3bd6","9cdff8d65e","9f2fa81b34","8689799ad5","c8ae164805","0382f85106","855b51f397","5b2600e929","76cfa7e80d","bec2f7d9a5","be626317df","88c7e6e4db","b1357006c7","a9b9ee755f","09981007c6","995d23866f","9a05b520d8","786922bb61","4f0bc876e9","dc3e9d2d01","08441f9b23","cac7f746e1","f452926b00","20fcab3299","28f1c51e97","2902b81472","6109cc16a1","bfd93bdf4a","a0bbaf6e8d","519dee7ce3","7d1d95768c","2badcbfeaf","6f886b844c","db419636b1","09f9a31ebe","584c8d7008","c650ecd62b","836230f5c6","2badcbfeaf","6f886b844c","db419636b1","09f9a31ebe","584c8d7008","c650ecd62b","836230f5c6","4dbf897166","8b1addaa32","09a7f64775","860dcfd4a5","84610fd339","72173bcffe","abe6016b00","4dbf897166","8b1addaa32","09a7f64775","860dcfd4a5","84610fd339","72173bcffe","abe6016b00","ce1d20e438","d6808ef1ec","8fb4704adc","37c4c1b4a8","4c294a234e","dbfa52b105","5c5c36800d","2a54b65d0f","9b78cdaa9d","2a2675b575","aa703ad073","ca7fac6fd9","29f7f13ed4","3b01ef5ca4","2a54b65d0f","9b78cdaa9d","2a2675b575","aa703ad073","ca7fac6fd9","29f7f13ed4","3b01ef5ca4","3b99db7867","404c611503","685a3a3713","4fbee742e1","e59cf3fdf9","ac4aa24d9b","6e65c53e5d","5f49163c64","298341dab9","87c03e06e3","08bb935655","48d653ddad","0ab71363b1","a1133b785a","55128ee219","7cfddbf5a2","90b7bf8d7c","7ef3ed7a32","d7a7d8a53f","da16e475c7","b4a59cb168","3b99db7867","404c611503","685a3a3713","4fbee742e1","e59cf3fdf9","ac4aa24d9b","6e65c53e5d","99685372ef","4dccc5c1dc","a35e5e6f36","5a94f5d24e","c0cf878c9c","fd1420ce4c","c5092c7cf1","8384cfbd02","73de0498d8","1eb7d1a486","1b991c37bd","6f27d64253","bb489400af","811d8d6e94","8f77a363b2","8e118aab27","e9455278ee","c5c5d26d4a","56f4d11f8b","9e1b49a761","e42f325977","0e92f82985","51eb94ed2f","1d25223e6d","6efd71d514","2b06fab142","9b0c840f4e","77330305eb","0e92f82985","51eb94ed2f","1d25223e6d","6efd71d514","2b06fab142","9b0c840f4e","77330305eb","b947013d8d","db259f00ce","c27033f682","87377b4bd5","35f03a7565","77d4bd518b","b94c3b16b9","eb49c987cc","e23c3506a7","14039cf3e8","62e9912a25","3ddf58e64e","d6931ab574","55dcb62107","292a263dbc","b6332af3e9","54c032f814","933209ee19","b7d1caf3fc","ec1b7b40cd","d1e3d29cf0","4145a4dd19","ad5f281154","a16ec10257","d08d4cb3fa","9a65471cbd","b91649913a","f9a91eb66e","c80ebb3902","dabbd98843","4a6df2503f","03648c11b6","ca91b421d1","368dc2bba8","65aeaf70be","04331d0aae","7c0713aba8","6d0cd85ea7","8e739506c0","654236dc57","f274aacd0e","7607eb3a39","c17af3e9d2","1c73728d41","5efea71462","f9fe95306b","09c8354dc9","45928228f2","61771a3bcb","c17af3e9d2","1c73728d41","5efea71462","f9fe95306b","09c8354dc9","45928228f2","61771a3bcb","48cea11f7c","81edffd1d1","931e092ac5","fe03e81999","1942bfccdb","2ae3f9cbfb","c426d0137f","dd091e8003","9ad49673c1","449d251927","45c16e7ee3","346356f2c1","f98485c2c7","689e0417ba","dd091e8003","9ad49673c1","449d251927","45c16e7ee3","346356f2c1","f98485c2c7","689e0417ba","9cc2234a43","d3002cbfa7","fae04f15d2","54938de175","359ee3477c","466c6c1613","f39df81d9f","6ceb7b8c92","add3ad1ab5","9272ae64db","3622db2b91","ad217decab","e0732b279e","5c297aeac1","6b37652fb0","ae5ce0eb51","f05cbc2cdd","8cd8cc966a","e3ff9d77c1","7323da48ff","89316fb6f0","d8bfd694fc","5c7d15f2fb","48e9a466eb","cdc8b1df6d","bc9934c7a8","c6030fcebc","75853146b6","115d211340","545878e602","48aae945b7","bb358a350f","ce6a124b83","36dd951645","aed7531599","b08aae32a8","ac13f43b39","c04c3bd8b5","291cdaa86f","315ca1e7ca","0097b0c9ef","979b3a0e99","6baa18a656","d3c77c8755","1533ded215","3b15c88556","40e4af0303","31a96b97d9","36914cd656","df30e78763","bb58192018","aee258fe91","16b63f47bc","074763a3a7","88a118d5ef","327e0283eb","cd166387a6","daae133dfb","1b8309dc11","4f843d150c","88767880cf","97af894b90","d46b0c54c2","6ceb7b8c92","add3ad1ab5","9272ae64db","3622db2b91","ad217decab","e0732b279e","5c297aeac1","c5ce8fc79b","cbd6936311","5b6cc6bd1c","2c2d26c345","1f0d02a820","94e8b66992","6b64c0f075","c5ce8fc79b","cbd6936311","5b6cc6bd1c","2c2d26c345","1f0d02a820","94e8b66992","6b64c0f075","02cb03d74a","a2cc45cee0","cb8d4cba7b","d47cfdd8c0","d177fa305b","542b3367b0","8dc7c06b71","918b311557","26285c3e6c","21ecc06eac","cfb6cae0b2","c455706d81","3aff5b2c8d","112d4f8218","3461f3f72a","dd4c611e62","bc87c0ffa3","200e630791","5c5a2b47e2","8408fa958e","2b8e1c005a","3461f3f72a","dd4c611e62","bc87c0ffa3","200e630791","5c5a2b47e2","8408fa958e","2b8e1c005a","c14cc0a09e","3ed4cc1437","999041d3bd","109e639492","4abf415aae","1818fd862a","baa88b083e","dc0046ee82","c91922fcbe","bdddc8a9c1","5980b609ce","62e6969912","992fb17ea1","c2f64ec70b","7b39df28f0","a6e07d2b63","a4f3eae08c","a32294b5fb","6e064c9fda","0231487286","65694e274b","50354eca4a","34081b4e0d","74a9ce61ff","b7618330d6","0320b4b622","c3432c07e7","76f7eeb3c6","50354eca4a","34081b4e0d","74a9ce61ff","b7618330d6","0320b4b622","c3432c07e7","76f7eeb3c6","71dda07470","07674559fb","d52518a18f","2a49fdcc88","9c7fb63a83","4c2122508a","913a3b7d70","3c5e926c68","3cae46dc54","bd96100744","9e7c35963e","2fdd69ebf1","57299af292","2af3ddd4e1","71dda07470","07674559fb","d52518a18f","2a49fdcc88","9c7fb63a83","4c2122508a","913a3b7d70","469308a186","55da62d764","edfa145be8","800a9055ac","9e99e5090b","73f4c76475","35a7af82c7","432c42166a","463c1b8543","f6264e9b42","7f08dff61a","4cc8810a6e","601eaaeae2","df98abb713","041cfdcd60","cec9877765","a76c839f68","1130f3fa5d","1501945fba","a12d871900","2f88e3b243","71dda07470","07674559fb","d52518a18f","2a49fdcc88","9c7fb63a83","4c2122508a","913a3b7d70","e4090b5d6c","765175c388","1a8b59f438","982813fd3b","5185aadad2","f5738f2af7","5e65d06979","cba04060a6","5abae31e5d","e4db396770","e990d8b706","00d144e64a","a7fdc0df46","f80d86210e","ab476a97ab","4970e60bf5","2dd94bcc5d","512701c938","cebe661beb","66553174ab","3fb2e30224","8f345e0552","b181f4c22d","52d43683bc","6ba02270a1","3f3de48026","39c8613674","218ab60dfe","21483fc950","a9bf7ae74b","a6fbadae80","9e22c424ae","0b0a1cc405","abaa96414d","ba5f15f39b","e8f3653191","52ce837dd8","e78182f8be","1bb99e47f1","ab618d4dd2","a9aef372c6","bd1861e7b5","21483fc950","a9bf7ae74b","a6fbadae80","9e22c424ae","0b0a1cc405","abaa96414d","ba5f15f39b","6ca40b27cc","1bd75527d6","259cc0f5a6","d8ebfa15cb","63fdb1fc37","a8d030752a","a484606617","89e7da528f","b5bf4d0942","e2411f6279","3127ac4dc6","197b6864e5","b71f0055ec","57c137e85a","b959af6323","6d50a83296","fd29a4abb0","daf5df6151","b66b7a2a12","191d929c51","dd08ea7796","225c740e9c","550b790e56","487145dc6f","b5b25fef9d","d79bc7650d","f77c4915b7","29e1c812e5","02a93c0bf0","8dca57290d","2ccd270ec9","e735a2a8c0","414d8de0f9","46ecdaa4a7","a9df56b5d2","ceb51ee395","aad202d592","45e0216dfb","589bbda055","5ad1e98796","b55a17221e","0e7d914cb6","ceb51ee395","aad202d592","45e0216dfb","589bbda055","5ad1e98796","b55a17221e","0e7d914cb6","b8b22778c9","41712a62a8","485a163118","228749c73e","6a5a18afbf","f7062e9398","7b490709b8","29c9188d56","075d31ae7a","8fae5ec085","e34dd56607","69a4c862b2","25362e6f6c","b33ecb3f93","29c9188d56","075d31ae7a","8fae5ec085","e34dd56607","69a4c862b2","25362e6f6c","b33ecb3f93","5bb7f9d25e","02eb09609c","30d1fe4408","59fbce7921","8400807319","89614555d8","183113d907","c4f1cd4fa5","70787bd25c","d5e1b8c3de","14b0aa33b3","c81161aad3","ae22589d15","fc8d306210","df4746b185","53891e77ae","c83d901344","0a3fa321f2","f332d6cbd6","69397b3436","b225421814","aee3cb039a","17903970d5","f95722b760","33b5945636","1529d9fa7b","5049a4f4be","817b6bc8e4","e7f53ad985","486966049e","46546c7472","2dfab24b89","2f7ac12de4","ff0bf0ff25","1bf15a3292","e7f53ad985","486966049e","46546c7472","2dfab24b89","2f7ac12de4","ff0bf0ff25","1bf15a3292","fd8982213a","83bb62d89a","5657aac4ad","46749e8c98","347c6a9d97","b45d4e2baa","682e67a1fd","4169dc6dfd","f2cc37dff3","ee2e7b57d3","bf50399087","f9e64e7970","f8d29ea478","2f35f22b1b","64d1a13048","4e58e95340","02b5a0e418","fa33bb410f","8351f2a415","b323fa0dcb","bc4b6a6770","50f13090ed","52f6c6e4b2","d429325d87","790b84715c","bc8e931fac","228fa3d93a","f6b5aaa32a","6b4a983d0d","da87e58706","33e2cda53c","3cf8792dc4","98f94bcf38","94ea2fc211","1dc2462dd7","4169dc6dfd","f2cc37dff3","ee2e7b57d3","bf50399087","f9e64e7970","f8d29ea478","2f35f22b1b","b49e8db68c","cd7020bbb4","53910c5a9b","090b204589","08f35802ce","066194a9a7","4c27aef58f","b49e8db68c","cd7020bbb4","53910c5a9b","090b204589","08f35802ce","066194a9a7","4c27aef58f","dcefcfe1f6","38e85acd38","f5fdf44335","53419ced41","313ce0671e","7e19ffd7c9","ab8f7d17df","6b233052ad","e010901a43","10d74283b8","24654d266b","4f8402a89e","f0f65c317c","665c9ae5ed","57a647be66","0ac4b90524","c484d89d11","2ce9f3c666","acea979e5a","a8f5b25687","df5b0642a4","858c9e97dd","d47ee73112","a8a3281b78","264f9d6a0e","fcbb998d42","ea43d4d211","cb42dca1e0","fe9bc53825","ab4359cd37","110892b6d1","24d76e9949","c8d1e4eda5","0124e33dcc","3ce56ae3ef","858c9e97dd","d47ee73112","a8a3281b78","264f9d6a0e","fcbb998d42","ea43d4d211","cb42dca1e0","858c9e97dd","d47ee73112","a8a3281b78","264f9d6a0e","fcbb998d42","ea43d4d211","cb42dca1e0","cc06b55a8f","a795cf8a9b","a0c4bb6a5b","019952174c","627211aa61","bf4ccd1527","a16e43e118","a876f670c6","805486fda9","0d0b77f522","0d1936ec00","8ecbc07328","cf34dd626b","64f5afcca4","cfba86dbaa","d1166b4443","bfe4293ea1","7213677c77","3beae31efe","8399e26cd7","8d78cfedef","5b42f93690","7a3881cb9c","af633e50b5","f324e8194b","ab23589234","516fdc3882","a66eee5e67","cfba86dbaa","d1166b4443","bfe4293ea1","7213677c77","3beae31efe","8399e26cd7","8d78cfedef","3b961cf8b0","f63a951b74","f214b06dcf","d0441cc471","c7c6d5d1b7","b8dfa4e715","ef8b44ba80","4e64681a42","82cef9ff39","33f4779d28","ab810e3546","8488619152","eed33e9fdf","c6e75290b7","4e64681a42","82cef9ff39","33f4779d28","ab810e3546","8488619152","eed33e9fdf","c6e75290b7","2edad91138","fde7ddfac3","3e86dd807e","91224fea7f","08d0a1adf7","66104372a6","44f09fe7f6","99f0fbd164","22218ef893","805f51bf92","dd3d10d618","e899a45b1e","11d542b27b","8492239f13","c1636840a0","cadb9617ce","a3f35dbf35","05488abc45","b1ff3eb410","0538110d98","05f135c16f","4cdb35d099","14194c3731","ee4ec6a6c3","1e18380dbb","720da7a3b2","5f2b3313c3","afb2e987de","6c7624b2c0","833c1f7713","1505faaea2","1e3a52580c","03b5d53e32","138e079bab","4b08231920","ae08eb75cd","ac2ca4bd44","a9b67ff4ba","b39076ef2f","62ea19751f","21ddd6cc1d","c3f1e7bea9","dac4b91c52","60512fea7d","00cef6ee72","6fb953fbf7","3fa4a87884","738cbc2673","2e55af8013","2edad91138","fde7ddfac3","3e86dd807e","91224fea7f","08d0a1adf7","66104372a6","44f09fe7f6","de559bd422","7e94232b21","c5004d41fd","bf837df00d","bffa74e677","9b85bfce0d","7baf153595","bb7260df21","6f0b0d4645","96154c3014","dba994bda1","2b7f76dd8d","c2710cf810","69daaeb776","31e7009070","0c9f13ccad","4a720b3308","97662d0b5c","8693d56831","c2b4ac0a90","e98afa0514","a3057b28b4","1b1faa7dd6","bf6e852748","a459c76502","c8d46e2d94","1e638126fe","3da3b6a253","84c5f8185d","309e89b8ff","737a66cae6","6af6e33349","bb11e86a0f","cd9d7f95bc","b767918e46","096f0fbe90","3b605aeba9","188099c316","31808077dc","4072b0bf9e","0881286296","e6189c3935","b7d60d8bb4","5702d75b28","70772f306c","dabe10b10f","b083f2d42c","f2200cb0cc","c65435d559","de559bd422","7e94232b21","c5004d41fd","bf837df00d","bffa74e677","9b85bfce0d","7baf153595","befc141b6f","72227f55c2","f2d2faa390","18401fe885","5f5430998a","6545b64e15","37879318a6","76e85c06a7","6b35e6574b","68166e3da1","700541a026","a11c0c2add","05c60bf9d7","79bf1c2683","8c8f6e4f23","d5ef53daf6","3ca7d042b9","6eba9188bc","44883a39ed","f789f9c942","8143c4bd38","183e60b59e","90ad8e17dc","c7294f8288","d88393409d","51e78ef7c5","17ea17a393","0128151ffb","612ba85ecb","c06a9f9e5a","186362c5dd","894e11ba92","6ce7f50a52","d1e60b684a","312a47ca99","63c1ff57de","596b239bca","23c03c6084","26dbfd6d73","9c1c98f3bb","07487d355d","c67f791387","d3dc327351","d89eb91f60","59bba7caa2","8a19bbc1c1","fb6991d38b","c5c77cc4c8","adafb005a6","befc141b6f","72227f55c2","f2d2faa390","18401fe885","5f5430998a","6545b64e15","37879318a6","78fee30a43","a4161ec574","4b4b3d7906","243b7de9bf","af5a77e37c","a9df4c5651","6d5faf29e0","21b0f36463","c572547127","9a89c2d629","3d7fdfc3fb","be7f1bd23d","e296a9b3c6","7a46fddf00","81d1ce744b","ae8b91e2c9","665602233a","89a834a525","80b1ea61ad","32fa8a6104","4f5874547b","abce677aa3","4c8103e6e8","bd7dc84fa8","972c93b620","7b5af440d3","494b013cfd","24d91dddbd","c5811061eb","4d820ea50a","7e0deba68d","61c165012a","819e0f8c9a","90dccae01a","b49393ef84","3093f541d2","b45dbf8b57","cff47eaaec","885112da9f","150393c90b","295aa1d66b","5d232b2dac","25b6395c30","1e9c506453","5e91dcb2c6","387fdd1f04","92a4bc5cb5","9f17581699","5007f62637","78fee30a43","a4161ec574","4b4b3d7906","243b7de9bf","af5a77e37c","a9df4c5651","6d5faf29e0","968215f043","0a0616e873","e96054e090","95dfe2d8fb","1c88ecd2e0","3ed9fbccd5","535d7d461c","e56e419372","878dd7e8c2","406e17cae3","19cb579a95","83044b28c1","35aeb39393","f97beb7ecc","61276c00cf","283b145fe0","b4b0beb7a1","2183bb950d","7e54cda548","243cb0717d","8a88eb0979","84b7328595","4306712cdf","1aab561e0c","3b4d2e54bc","c9a5d1468c","41f4fc768f","b4be0f9219","5900065522","c7ba9eff59","c6fad9e353","a2e47d90e1","b57c20586a","0c98a2d9ea","1c51f3f254","d5fd065bd1","fc8f3145e4","9860d41b69","7c80e1842a","579789c0f5","e74a38b09b","268f9491ca","768c8205c2","189a659fca","9e3307fde4","b0bcb68eba","f1e56230c1","4699a83034","35f192b129","933a00699b","c4bd154b4f","b5b5fb6bb8","d92d8fbca6","b38d8bed95","b5ab498545","af0df9412d","fc08676452","aa46053e95","e8a305cf98","0e0656ab70","7021da1146","ce6a749f92","352de2d3fb","fc08676452","aa46053e95","e8a305cf98","0e0656ab70","7021da1146","ce6a749f92","352de2d3fb","a254aa319a","330c5bd7a9","d8a71c534b","dba209fb37","dd04519c6e","61fbcc066f","89205f9aec","a254aa319a","330c5bd7a9","d8a71c534b","dba209fb37","dd04519c6e","61fbcc066f","89205f9aec","1187c5045a","8e9f8fa20e","2d53202bfd","9a2301fb0e","e8186cc858","9745ee8fb1","a88da37b2e","ae3412ea93","0ff073b429","f63fc98ff9","5be300bef3","7ab4801b92","58ee72444e","73a1a38edd","976c7a0b1d","c842ff3421","e4fe14f70e","40133ddeb5","b998b359ce","3f1d0f2d3a","5b7de27083","968215f043","0a0616e873","e96054e090","95dfe2d8fb","1c88ecd2e0","3ed9fbccd5","535d7d461c","cd00ff44b4","b3fd4b1837","0727d713ec","1e5080a00f","20057ea8eb","83c5ce07c8","666cd9f27a","cd00ff44b4","b3fd4b1837","0727d713ec","1e5080a00f","20057ea8eb","83c5ce07c8","666cd9f27a","3faa9e19ed","8f17b40228","08a7ab9791","45f9ac4d1a","666399bc45","e605f29a80","edd2582233","3faa9e19ed","8f17b40228","08a7ab9791","45f9ac4d1a","666399bc45","e605f29a80","edd2582233","ddd3b6ced9","bce0f0bb7e","4468cd97e6","17ff46abcd","cb727ab5a9","35bfae11cd","c0a6fde5d6","ddd3b6ced9","bce0f0bb7e","4468cd97e6","17ff46abcd","cb727ab5a9","35bfae11cd","c0a6fde5d6","febdbbfec1","dfe2730945","96ed11c9c6","c653855ee9","f161366608","ae7b27379c","e40af4bc47","c0ca31a1c3","e9dac1e136","dc4d6294b0","2a87631bb7","6300bd6227","70ba2176c4","9e55b9bb50","6c266c3615","da26be5404","2414dd98d0","df44d37b82","a1e59d06bf","eb8eea8bf2","a2de6b62c3","6d046704d6","3ba58ee3e8","ded981ba22","c8ef6a64d5","aa8e191afa","1aaa7364e5","d6ef553467","316624a6f5","debcfd5107","d3d0bbd758","366e9d11ec","0d5a1caf15","d5811ff56c","fb7bc3ea2d","b2c886b842","6cb3b67a9d","1df92098e5","5be286dc5d","f9a711dffd","aabc12bdd4","c8a180d621","6c266c3615","da26be5404","2414dd98d0","df44d37b82","a1e59d06bf","eb8eea8bf2","a2de6b62c3","6c266c3615","da26be5404","2414dd98d0","df44d37b82","a1e59d06bf","eb8eea8bf2","a2de6b62c3","1accc8735c","4459f3fd8f","4a60c4fea6","6bb71963cb","6296560ea0","16fbb2b7ce","05c0182461","6a40062593","1ed1ae21d0","3bb70a2f6d","8d91abd5b0","ad38b64ec0","d7e636ff9d","060fc0e49c","debf930e40","2d6fcabb2b","da05a09850","2901daeaba","d52a88cc20","66d67ea4b4","3f0399714a","9bfaf90c02","4d90b1d3c9","11856ae24f","dec64b072d","4eb182d0ad","daddd5a16f","3f6b444a0a","82e5f64d94","59e07687bb","43e51c5008","a252fc2c26","bda71c6b3b","e22d93e603","fd3cabb0f2","dcf9b0ea0b","082074115e","5f47c651f2","17b79f4c49","2ba4e1d798","a3aa6fe15e","fba988f648","82e5f64d94","59e07687bb","43e51c5008","a252fc2c26","bda71c6b3b","e22d93e603","fd3cabb0f2","e2a832b8e7","5ae87bef4e","7dca3ef353","2800f36892","95cffc05c6","3f16d3c0f2","1e5c4efd8c","539c9f973e","4b90339525","657ceeb96b","9ad3daa347","029ec36106","0241a21229","a9fb94aa57","5df362b00d","46b9ac513c","c206c3ad1b","2b185df079","fb228d710f","d226b98b20","f303e155b1","288084fedd","9290f16c14","7f50d28f1f","8968e58c23","1dc51b5a03","a2e040a003","a5f77f86fb","cede1acaba","64a5d05194","df29a838a8","f8fd91d675","ba9d72cf09","1eb8705652","9686598019","44937fa0cd","3ce3223e55","00962f45c6","9c97209540","e99ab3778d","6395160115","ff594bf63e","44937fa0cd","3ce3223e55","00962f45c6","9c97209540","e99ab3778d","6395160115","ff594bf63e","51745e4b62","d334c6e87c","3387df2946","fb2509df29","cf3ecbea86","bc03dfe6ab","3cb2a50bc6","5868f73400","0825234649","fb59a0a3e2","8d1fa0907a","056a0d0773","6d243c86f9","61d9f81ff0","410e914bed","1f9424c976","7ea34bfbb6","1553a6a930","4774137d0f","62b4e5374f","fd4a410e00","a741574079","b98cd4af30","cae01e5633","9b1ff1ba98","ba17977df1","0932d48049","5d04b10931","0ebace0629","08c87396db","f82e81d4c5","88e2e74728","4146a3e23f","56249163c0","6d56fa54c0","5dd8154b35","d26f6a0c95","d5f3683dd8","010a355177","fa322537d8","439d1f8a4c","b5cfbff505","638ae4c7ac","2f42aee6ee","f0dd31d4f1","5c118e2d2b","d9d9eef991","36b85cb915","ae49bc1d90","51745e4b62","d334c6e87c","3387df2946","fb2509df29","cf3ecbea86","bc03dfe6ab","3cb2a50bc6","51745e4b62","d334c6e87c","3387df2946","fb2509df29","cf3ecbea86","bc03dfe6ab","3cb2a50bc6","5ffe4f3354","e915f3b2c7","b439b363a2","ff53660619","6ff060fc85","c06f3e4ac9","655558d4fb","5ffe4f3354","e915f3b2c7","b439b363a2","ff53660619","6ff060fc85","c06f3e4ac9","655558d4fb","09cd0d00ab","091a3b9698","f99deea2bb","22738f4608","ba22a9b891","578046cb7d","1b41a23710","57a77b6448","d3e920bd52","a5fa62ffd5","858583174e","dfde4fc785","2efb1c0de2","d608ade850","56aec3da4e","a46a2e0f3a","5296b8ddcc","1acaef4260","a44670beb4","12e18defc8","7e4714d4c5","47428581b8","c7cc86ae1c","3e29b4dda7","a9b4c75915","accce92c9e","c5880ee0e3","2f558bc740","47428581b8","c7cc86ae1c","3e29b4dda7","a9b4c75915","accce92c9e","c5880ee0e3","2f558bc740","560eebf1d1","a8aa466947","a8004c794e","2c9be5532c","8a27390a37","db7786183d","47af6fbb6c","2513677c68","b138c5c9c0","c0fed42414","ecaf8e3746","531a862540","6c7b7e115f","5558ee3026","111cc2caa3","370e463385","0d3bb95093","32d87eccf4","f19b881d13","3dc9ed1af6","a75943f52b","1ca39d4023","e7b58bd1d9","3e973569dd","b216315c5a","3fba7b7de6","89aa78fcfd","24a66d1b57","445bc0b885","123f1c1f11","71d777d959","717325e8d1","e022fffc39","21e9e01527","7d0c15d4a9","b625716897","53d1187efc","751ee0d819","39a366743c","367ce42cc1","a97b4588b9","b281157708","9dc89e1ec5","221c254a8b","f1554b687e","b3030ac4fd","5f888529f4","afd16235e1","d1fea4ba2c","9dc89e1ec5","221c254a8b","f1554b687e","b3030ac4fd","5f888529f4","afd16235e1","d1fea4ba2c","974602a540","feadf5f3de","5b4af31d59","8b470d7df9","f3bb07c459","bfc65979fa","8cff7fc3d7","522202af19","304ce9c3a4","cc8c8127fc","0fb3251978","66d5f56093","0041e7ca71","6f6663dc40","522202af19","304ce9c3a4","cc8c8127fc","0fb3251978","66d5f56093","0041e7ca71","6f6663dc40","a77a668c81","1bba0c0d08","285ef41713","cc550dca06","3072125db7","92c32ceeca","42cf76ab4a","2bfe08cf87","3df8920c29","b12f4c54aa","75b1d5e236","3aff2d0718","4ac446f4d0","f3f16ccf36","da5ce6ca80","ee8901391d","5a8b6e7d10","3e1a626177","173cc05f69","8b27bb8b2a","5add7125c0","bbdcc8e3c7","62d602f7a0","6c6dfff8d8","d86bd60c7d","6d1b62a0ec","6e85422487","e59316a54b","2bfe08cf87","3df8920c29","b12f4c54aa","75b1d5e236","3aff2d0718","4ac446f4d0","f3f16ccf36","278812aa13","c8448d9775","cb5a6fce43","fabcf0db52","ba23a19285","d58f24665b","dad639dc22","0c0d14a002","a5c76ac7be","74d65d55a6","8cc1e2e3fb","d37ccdf27d","6c4c5d3897","a45da1bf57","7483a88b45","13303f8558","97d26db851","2f7445e63f","11e673e81c","4e5ed3113b","6770d571ab","7483a88b45","13303f8558","97d26db851","2f7445e63f","11e673e81c","4e5ed3113b","6770d571ab","648b315b38","5971959eb3","a959fce26e","f3c3f178da","f10dbc3210","b3686cb971","44d26f894b","648b315b38","5971959eb3","a959fce26e","f3c3f178da","f10dbc3210","b3686cb971","44d26f894b","d7ad211a97","c649171ff2","9b803f0192","8ebdaff4a5","0400b583db","6da8df7fa8","b67cd4ddfe","d7ad211a97","c649171ff2","9b803f0192","8ebdaff4a5","0400b583db","6da8df7fa8","b67cd4ddfe","b5991f6cd9","e68d409dd9","d499fd16a8","5804c7d127","b5a04f4417","1f48e76aa5","0b72175fdf","b5991f6cd9","e68d409dd9","d499fd16a8","5804c7d127","b5a04f4417","1f48e76aa5","0b72175fdf","e0c16ab3fd","31abf257f3","644eeca374","da25d8372d","a123579951","d29cd0459b","e2e1aab04d","86e12d6fcf","abe04cbadc","3c6617dfec","ca22dc9672","5f5c8d9a3a","f3160308ca","096b760ab1","63dc4711ae","59f42be48d","322f86e53c","f35c4f5f52","2a33ffc4f0","e83563f138","e9386cb222","15c85adffe","77c4404b12","ee66ad0aaf","3c45f664b7","92554bc31f","d08a6d5b5d","5ea1fb6c1b","f5021e3ac6","c80dead9f3","f1618212fd","41684ed849","e32f330f56","66417dde0a","a22ad8663f","86e12d6fcf","abe04cbadc","3c6617dfec","ca22dc9672","5f5c8d9a3a","f3160308ca","096b760ab1","9492c32e47","c65002adff","29499d9f7b","8c8ba30bca","a4ad4955f8","ccd5f0edbb","4762e335d7","86e12d6fcf","abe04cbadc","3c6617dfec","ca22dc9672","5f5c8d9a3a","f3160308ca","096b760ab1","ea1be18540","1eecb5a54b","397ee9ab74","5d99f08396","73b5c6dc32","7ba9d39cc7","fa650e5329","ea1be18540","1eecb5a54b","397ee9ab74","5d99f08396","73b5c6dc32","7ba9d39cc7","fa650e5329","29eca6d52d","3b98049072","a14f0aac02","7b57aeea9d","158852bb6a","6a9bf2e6f0","0cf82cc629","b7b7160869","f5ca1ea1ff","1376ead942","d3b630060d","9a2ab9f646","e17906b6b5","7030630865","de0548c635","da0ed0087f","092bca3bd6","7da2c18395","74094be0a1","9f93b7b500","a56948ffe8","3b939213ba","58c216e8d5","359ee50136","f40a2e0e39","267c849f91","4d100837d6","f5dae86b20","cf89b92f84","fde828fc9e","f564701359","d2811966a7","781d587b34","17bdcee580","238426027a","eafcdf1ffb","99730ca277","ad7afb137e","975db6e345","ed9cccaf1c","c7b72c8cb2","629673964e","5bfc4bfcd1","c6219de536","aa6e909a9f","2b1b6e2598","ce53fb9b91","a1df28be4a","bcdea4fe42","ed9c3d67f6","4c2bf80933","a9c2c82a7a","dcdf21d3b3","b239c28b56","6d55ee12fa","37b0c8dcbf","816534d9f1","f74cb25324","80e0efd45c","83ac8100aa","b39d4ccaaf","8f8923967e","44527f6141","1a499d1665","04c66c0c68","66f0b0f42b","4a9f5aba6b","bea52b7f9d","a779ecc86b","9f8ae4c75a","d510e08d4a","7cfdec2cb5","fdfe1ce645","68a5f7a202","fc4327de0f","4d11ab2ddc","43edaccbe9","de0548c635","da0ed0087f","092bca3bd6","7da2c18395","74094be0a1","9f93b7b500","a56948ffe8","572388ae25","b1be121b2e","7d76623b0b","80dead26a6","a9dee52b75","ae7b420dd1","780d05e79b","95063e4852","719d532425","094aad8dc8","e08acc03b8","4e11d21825","aab27ef84c","a12d7084eb","95063e4852","719d532425","094aad8dc8","e08acc03b8","4e11d21825","aab27ef84c","a12d7084eb","a41d38f39d","a047a0127f","40ffa58700","1f893fae67","884b9ab841","b795ecfb01","c978fbc43b","6447c4e325","21c3509b20","25b48adbf0","fb79323ed3","8a7c0e8588","d244e2c490","12af17b29b","6447c4e325","21c3509b20","25b48adbf0","fb79323ed3","8a7c0e8588","d244e2c490","12af17b29b","ed8fdfa6fd","2b8cd9c253","05e74f7e9f","fd9e76ca9e","1bd14fe5af","bdb7b5985a","d5f3fa9aac","b228d6d580","e997993b94","db89cca19d","21e75b7c63","458bf8e6c4","521f08cb1c","0e09a8ce3a","b228d6d580","e997993b94","db89cca19d","21e75b7c63","458bf8e6c4","521f08cb1c","0e09a8ce3a","f2446aa4d5","21c6fba496","d746a307ae","ca56796e63","210ec10565","168ebaf15a","b62136bb42","a3dfb600aa","5f719bbcdd","dbd96041d2","d244ee91aa","16fe330e16","3cd71f2f13","f0b18150ff","e790d24b21","13033f493c","1e4b75b0e5","1980b54331","97885a4578","79fb13b73e","5d276c5c22","6df52c3bef","eeee5f085e","40a69c4824","9d1a46b6ba","4fff412f66","7c92841df8","8aa4d3ea67","57564dd9be","9a5f567fd7","a9ba50c1a6","d22f0d9311","b98574d269","043e804642","a788e6ffab","6df52c3bef","eeee5f085e","40a69c4824","9d1a46b6ba","4fff412f66","7c92841df8","8aa4d3ea67","8a2fb9139d","c4094c72ab","e9c41563ee","27d91266a1","1a04c6ade7","e256e224bc","7bc1ac9630","d854870da4","913a087879","878116d4af","82b95b5c7a","21e0895c4d","c02b1251f2","4c3bd1b10f","d854870da4","913a087879","878116d4af","82b95b5c7a","21e0895c4d","c02b1251f2","4c3bd1b10f","6b71241cc9","76fe052abf","e3fbed4ddb","51b827d098","b52982f2d8","b8d26d6b32","04b0586845","6b71241cc9","76fe052abf","e3fbed4ddb","51b827d098","b52982f2d8","b8d26d6b32","04b0586845","2d83c87275","428232d4ef","c1de2c9f2b","e7024a4b5d","2b11fcff93","4462915890","12e696e063","535a27c26f","17eb0a35cc","085a78382c","649c9e00aa","02bfc7d2a1","8e0fa0a3f7","ca50dceb95","248c2c31e7","e216aa419b","815bbae7f0","cc0f030526","84409b2a78","6f7c719c6d","9a7e39d747","0d19e77dea","8bb65ad37e","de744579db","24524a3fd0","a8901b547f","4cee88b010","01c3ff45b2","697cbf10f7","b08d778ca1","35f0058676","f81ad454fc","bda64c699a","7f95559e53","c40de9d2b9","d617e76223","365218ace2","ca2bd0a25f","99d39fe125","ffaeb21861","fac9ecea5a","0e12590163","ea96ae14a8","54ec48b6c9","a508364f40","ee4aab5398","d52d6f9b4a","ea38de77dc","e4b0e4cdab","efb61aa870","137c8783e5","603fe7ac10","c6788bf612","d6e521f048","9cf8274cb7","560287e128","248c2c31e7","e216aa419b","815bbae7f0","cc0f030526","84409b2a78","6f7c719c6d","9a7e39d747","e99a1dace7","763b0691bf","1c7064ab57","cc2498f340","cd631ae7a7","1e7e4230be","b03e3969ec","e99a1dace7","763b0691bf","1c7064ab57","cc2498f340","cd631ae7a7","1e7e4230be","b03e3969ec","371640f1df","206e880714","8d5ae80072","4c0eab4552","55eab7c86d","446c742eb8","4350e322b2","01fd2e7392","3a46766c8d","f9fb587185","471c5aa4b3","2dd6b906fa","f5c8d6853d","f4e5bb195c","01fd2e7392","3a46766c8d","f9fb587185","471c5aa4b3","2dd6b906fa","f5c8d6853d","f4e5bb195c","55985719f0","fd12643cf0","68f449a6e9","7adacf0004","34822e687e","8f2fd65781","b9e21b4358","a280dfbea5","bc6104b606","2982f92138","bdc6f696c0","14908b00af","01bd9e2330","77b72be12a","8e3b51692f","378e6f5f92","8ed05fb24b","fbd6de2c6c","045890993d","87e5629d3b","3a1cd5fb4b","d7a7566540","d4f398e332","045a8bf8f8","e571bef398","a9322c05b0","501ffd9f1c","8a09579df6","8e3b51692f","378e6f5f92","8ed05fb24b","fbd6de2c6c","045890993d","87e5629d3b","3a1cd5fb4b","bc31d9667d","e87f95e508","c1a6853e03","434008bd49","e8a4b0aca1","d004d18ac8","1c2bf0d0dd","522401df3e","72d46c47a6","98199cf2bb","7f00ca1c26","023190af29","0d8e2c83ac","10d502ed78","a3aa00488f","4a48adeaeb","954bcce34a","efbd4d96b5","74731b9c63","5c9dc0a074","8a6888525f","a3aa00488f","4a48adeaeb","954bcce34a","efbd4d96b5","74731b9c63","5c9dc0a074","8a6888525f","75cf709ce6","596a40f410","92773f5de6","2e3823b77c","286e93c1da","1004e5d538","c4f32401bf","2df32ff6c6","2aaa75ae65","5437708074","449d562b02","7a79c94292","e65eeab820","208e0cd597","2df32ff6c6","2aaa75ae65","5437708074","449d562b02","7a79c94292","e65eeab820","208e0cd597","f419952874","1088e3ac43","c0924af452","3bad4a1eb3","5c6037aee5","cba37e7c2a","227a5c9fda","32b22be2fb","155f830eab","3bd887bb7a","5dd6a17773","23f33f5b1b","41c07fc6c9","cbb0b00aca","f8bd7f7153","c464846400","556a66d0d4","3434fc7df9","fdc8ca2c35","47a70b7da3","bf94cfb254","12863c9c6c","e771358ff5","fddeb2dcaf","e827290757","7758bf715c","ad7110ef35","9c8bf3dce0","f8bd7f7153","c464846400","556a66d0d4","3434fc7df9","fdc8ca2c35","47a70b7da3","bf94cfb254","bd4332f1d2","b7d68348a6","43a02ba663","b7e4a21915","e06ecda7db","fa2bd0a76c","9b7c2a1997","3be80fe3b5","f6aa9a7663","4806f7f041","a8c7b1b54e","34b67b95f6","b1fd2c8e31","f5c6742473","f8bd7f7153","c464846400","556a66d0d4","3434fc7df9","fdc8ca2c35","47a70b7da3","bf94cfb254","2b8a2e21fd","a8feb15b6a","70fc710cf9","c2b084a6ed","39dd31bc50","c29e243234","d760903747","2b8a2e21fd","a8feb15b6a","70fc710cf9","c2b084a6ed","39dd31bc50","c29e243234","d760903747","8087f87cdd","bcff03e833","08b004e41e","3b6e51f978","ffc2a98a29","b84031e296","6b09c884e7","7ea112ba89","2a5e088817","ec220f0cdc","fad0c37922","e84225db81","0c4c4445b1","841def70c2","4862e41e9f","805d0fa3c8","5a55c106a1","5811bb7571","eefdfd5d07","1d797e857d","6fb026a4c6","a133f83abe","4a264c0438","6053fb87a0","8010d46a55","8872ef77a2","d1f39f96ec","bd5c0bae32","35db6ae072","4675c7a266","a667a6f1a6","19e2f51b14","2303abae47","2186424275","0bde6387a0","e83f2a8787","12ff277690","6d207a37bc","5864f80f95","11a55cd376","7fd124c7fd","fedca5d933","7f0bf195b8","39e6df71b1","0b55342094","ea4143ea9a","0a552e3fee","d158ae438e","5592ce89ad","35db6ae072","4675c7a266","a667a6f1a6","19e2f51b14","2303abae47","2186424275","0bde6387a0","cd4326c018","7bd37801c8","149a32fcd3","411fe04028","1ef782f003","39646bba5b","7a8f9492ec","cd4326c018","7bd37801c8","149a32fcd3","411fe04028","1ef782f003","39646bba5b","7a8f9492ec","452e714efa","40b6a8f47a","65501a2bc0","6401fdc74a","28c5d5fc44","1184f4cd35","8ab442ca20","b1591085b6","0e59eb6c9a","78cb7a350d","cef70811f2","b22c9f37ae","c1c139878d","eaaae5614d","96894df262","e98a7ff3b3","0046be0f3d","450552ca32","4fe32c304d","4ec28e9e26","2bfcbb3a63","452e714efa","40b6a8f47a","65501a2bc0","6401fdc74a","28c5d5fc44","1184f4cd35","8ab442ca20","14efc692b8","4530a78377","2622dc12ef","9f122989d9","40da107786","611c7c96f8","8b32d926df","f4b74e4ab5","ba6ccaf0bd","5fad9a6e66","ec5d0d350f","31d216cdc5","d5007272ed","27a07a5ca7","ae1d224630","4894d54457","da541158da","339eaccd93","ce6577eda7","07dbf67fe8","25efd9e0d2","b46327826a","2a2fb43866","dfe0d80d23","9a59200f32","f943798246","c98ec42c3f","62e6c74b10","63f9912103","2a2c92e6c8","61f014619b","dafc5ef0b1","5b1904d251","88c3a8a20f","a74a456007","e4668499b6","7c09423f19","7d65027a2a","05eefff6a3","868acc9940","915791244e","c76f1b36e6","c3a3a95169","36fc837264","27f3821382","255aae4e47","9d15397c60","061a4139c0","cf37acafae","4212e1ac17","d3d34c52ce","1b2dde643c","d969fdda1c","c3a717b021","5cfdc6ba74","2892312157","c5c95420b2","4dd9614648","c4d7ba81a9","def244cf6a","e8f4c050cb","68db375ba1","cba858c1c5","d733090037","e6fac31a0c","0dcc13c467","2be897773a","f12a0d1cda","799718f913","8b8ba7a69d","e961acd1dc","1c5b671f83","b830c01fbe","24d235a7a1","b30c056026","c6913bf05d","ea5b9dbcbb","e961acd1dc","1c5b671f83","b830c01fbe","24d235a7a1","b30c056026","c6913bf05d","ea5b9dbcbb","7070eb274f","976f94d8bd","6bd34c0a3d","3871e6b160","c6ae91c8d2","829f4bc11d","c3910f714e","9308268d34","b551b2957a","88b0d8d0e4","e5e087aab9","54b19d20f4","864d2139cf","33184abfcc","9308268d34","b551b2957a","88b0d8d0e4","e5e087aab9","54b19d20f4","864d2139cf","33184abfcc","1c477eb148","cf7bb74649","d169338e86","b4b578d303","4fae08c676","959035b191","192620a553","c28067235d","53375843cc","f89f13d08d","185aba087e","37ce48d504","51ea4b2499","479be14829","b2975d27ab","46683238f6","f5cbb9ad2c","69c903e44e","c3517d3e08","6e04509125","9e4a733f71","c28067235d","53375843cc","f89f13d08d","185aba087e","37ce48d504","51ea4b2499","479be14829","8e0d0e1160","34189a2e35","ca89efbfff","e0d4e9968a","b78ac3e3ed","b76737848f","c203a81366","be49c6014a","773fe43bda","11bd4914d4","2a9fdee0e0","d388bc059b","20009ee76e","b5a000738a","be49c6014a","773fe43bda","11bd4914d4","2a9fdee0e0","d388bc059b","20009ee76e","b5a000738a","be49c6014a","773fe43bda","11bd4914d4","2a9fdee0e0","d388bc059b","20009ee76e","b5a000738a","e043215149","be5cf06806","6fb618e652","b048b531de","6eaafafdf1","19700fbb6c","39f837b615","2f378dd6bf","8f9ac8b0d2","46894ef95f","fb20f83ca9","ceea1c73ee","ad7ca80c78","d48764619f","a74bc25f9c","2638869edd","d8543c8c99","875564bfa5","91aaf6f419","bd16567880","409e31dc91","52c79c4c8c","f7b52db180","472690cd1c","d1921c2d3f","80418cc709","319b72ed72","c3f623394d","ff9739704e","d79af0dcdf","009cf02c78","9ebf26ac2c","5aa770c813","f30b328e51","9025247e71","ff9739704e","d79af0dcdf","009cf02c78","9ebf26ac2c","5aa770c813","f30b328e51","9025247e71","2c2d154809","dc2f1e843b","7207339fc1","2eca8496b5","d59ad805e5","051e926cc9","f03de00d36","d1761319fc","8950b77ced","55668478a7","f250f8853e","d00cf74895","f9ffdeea31","f36b4c4474","6261d8ed9c","02bfd2f855","cd1c2cea0a","36266bd5ac","b34233ac96","298a5a02ef","117309accc","6261d8ed9c","02bfd2f855","cd1c2cea0a","36266bd5ac","b34233ac96","298a5a02ef","117309accc","64d12ac392","462a44428a","6e80bd61d8","2658deaf6e","93e519b2c5","d384fb2bef","4bbe0f91a5","64d12ac392","462a44428a","6e80bd61d8","2658deaf6e","93e519b2c5","d384fb2bef","4bbe0f91a5","578113bd00","5cc8124e0a","5085cef41a","c3767fd405","690c02ec6b","1ce46dbe2e","4d5f014a0c","578113bd00","5cc8124e0a","5085cef41a","c3767fd405","690c02ec6b","1ce46dbe2e","4d5f014a0c","e5e9d29767","48b29c4a16","1997983b02","880a4b5d25","c978890122","175c2d11d9","759440a316","2cc4131250","b073c58555","3f7f57ffc7","ba9137c47b","362d1520a7","b020fbf05a","49a3f458ac","a29dc380eb","c1a834ea0b","97e188e360","a906fd9f42","20f1738251","297347b250","f67ee874b1","2e328a0374","f13fe12a67","1b46133f94","92c1bd9222","9055c2bec4","e8caabe789","f7254904c3","0443d68c43","d2c2785045","c00de5c056","f8511d86d7","ebcbb23335","ded2854bf8","fa18dccb36","84706bfa75","0032718452","c2cf16e78f","c71f3a4dc3","aa66966dd3","287790ebec","5dde21bd15","19f26db363","5ecf22bd18","ac2d60bbb5","eb4b7bff8d","336ec7818d","2850c9c78e","39f54d82b9","e5e9d29767","48b29c4a16","1997983b02","880a4b5d25","c978890122","175c2d11d9","759440a316","c6da05c9e8","ee35f405a2","ce93618ebb","1916d1202c","63cd168d10","6218595caf","db81074f63","d3d584d122","364139f7e1","f11e3a1c87","6978ec93b7","71c1412edd","871bcf6775","c9080e9ac2","2f91cc8b77","187753e7e6","37c1b97a29","4924b03dec","fb3234b8de","f7f32388a2","a74b7a3320","1cd0938415","152c004ca2","670cfdefe5","2c27fe89b4","06f137974e","af7ee3104e","429dc98ee9","abe7e56a76","ac8676fd3b","922b344c1b","a9a53688fe","89b8a48f29","45ef19d633","067a4739b7","20f15918f1","59f29909f4","4edc5238c7","5549212625","bd4d31bd42","c82f79687d","4b3e9991a2","b444f0d92b","e4f2c0263a","143ebcf949","6cf181f479","e3b42dbeb3","d11c9cb739","44c3b305ab","c6da05c9e8","ee35f405a2","ce93618ebb","1916d1202c","63cd168d10","6218595caf","db81074f63","4c00266ca9","95300fe961","87ca8a1b0e","a706d3130b","ef1c70dba3","535ab5911f","61d604e852","76410e6e27","fa318d65dd","e5e953e11c","f926203aad","ea8466b4b5","fb63c7b3ca","395ae7e347","6bb5cdfa66","80fa96062d","d292fa0c3d","b45dfd0d75","b9d5313ba6","e769dce5f1","47b712a41d","aa07393be7","cbf44bbecb","59e3f670a9","d8e21bd63a","212e55dad7","a2ef363e60","7f2266a197","960d7371d7","7986bc0717","91186a16f9","ea10ec47d7","9422e67491","1fd8b44682","d25b7feee9","914571ab77","050267f709","03857df53d","6df06f31bc","b3a43dc22b","c3af9c686c","58f61d571a","5549ac5a1b","1c542fc675","674293663a","097e84e3c2","7f972293a9","e8932a1d35","6509b58e22","66fee975f8","f74d55d4b9","454cfa5d85","4c374a1dc9","01e141075f","624f7f66b7","09ed33341d","6bb5cdfa66","80fa96062d","d292fa0c3d","b45dfd0d75","b9d5313ba6","e769dce5f1","47b712a41d","d9c3d38558","a6cae6317b","f4b248bbe5","5035e54d19","0888d6ab93","8d3dc033b4","b52c5de806","14f99114bc","a92a394ebe","cc0489f560","cd41b71249","368f636551","75efc3daba","518c9e36f6","37822f41ad","9e9a1add89","af6c67ce2d","8c94b1d687","03b7c748dc","f2beede72a","553450b76b","13d41c795e","cfa3d5130b","634b950475","6ae5001a8e","f80164c089","b9c1ec7ccc","c770782bd4","a88a53bb8a","d3db73e2c2","cf55bab225","44185afd23","f54c445a3d","6ddc722e41","a1b3341271","a88a53bb8a","d3db73e2c2","cf55bab225","44185afd23","f54c445a3d","6ddc722e41","a1b3341271","232a62f051","923b06d92a","33c44ce039","280aae4f1b","e79eec3f92","55b291206e","0c1e4e4a96","ee3d7a0a35","582adddecc","3ba9d8a0d2","d64f298e2b","efa02e5ed8","9d39b99935","3000db1f09","37fcbb4e18","8caf4797a0","ab19141211","4e805ffb64","f697651b0e","400a0a99c7","4249930a01","f279c127c2","082720b4eb","25ea743e02","8e961f5b7d","f0ddfbf62c","1a832cbf25","36de771431","459ec20e36","5fb5f0f5f1","a2c2774494","a25a38522c","9d3a528b25","5959e1c3f8","0978dbc8f0","459ec20e36","5fb5f0f5f1","a2c2774494","a25a38522c","9d3a528b25","5959e1c3f8","0978dbc8f0","b33bb5b1af","92c49fc12c","df7db21e33","d5784b576b","f03199ec64","fdde055123","e5aa676aea","b33bb5b1af","92c49fc12c","df7db21e33","d5784b576b","f03199ec64","fdde055123","e5aa676aea","8a0c52947f","b580b4d4b0","de2089b464","e6e433abbe","eed6d8c2d7","c4694c7fdd","4edf2e0ca1","8a0c52947f","b580b4d4b0","de2089b464","e6e433abbe","eed6d8c2d7","c4694c7fdd","4edf2e0ca1","9bb7486b03","9375ff07d0","d4639ec4ec","2bb37e8a83","d818c67212","5f0fc51799","141d7ececc","44342ade4c","84201231bb","da91511e5b","cc0cd6ff93","b9314ae144","28cd2e74a6","b684e44645","16325ef8be","d454efdb6e","63a03244c3","d2564d0809","293380741f","cf4269d2c5","09db657a59","0eaadfccf2","4970744d73","140e1483fe","0c3b59ab39","4f4c5db4b8","82855389f0","98856379c0","f4b87a58e8","4c4243c7df","b854bb6687","2339c8b274","a07a86c80e","757225b90d","8f87fcbd23","b9337fd2a4","3d0bad740e","30e795aeb2","2aa5e094f9","f6d55acf0a","9b90406fdf","8861fd540e","b9337fd2a4","3d0bad740e","30e795aeb2","2aa5e094f9","f6d55acf0a","9b90406fdf","8861fd540e","c0e73a2daf","0ebb17f17e","f637236236","3561b369c7","562187d1a0","11f0154e12","6bf0029539","0fa8106272","bccd997031","7a0db6bc2a","2c5b3c8f15","bc7544a9cd","d95c1adcb1","da7218ff5d","a36459d2c1","5125f29311","b01781b456","5ab8d34d98","544b795bac","c7a613778f","34d8bc6571","47e1ed5b8d","ed987c0bfe","99d7d4470f","74ed3d88aa","57b7c4cb93","1849163594","673e24b17f","8bcab6c965","30dfdbb065","3f0b43f28a","babbd951fa","6f3b6c5dd1","de5129923c","75d45be210","440a4dc216","012e8c4580","f6e4de3835","9cfaf2a67e","82f8ff9931","1f3e374de9","63b77a2976","8330eb53db","b7f7221bc1","80c3d6d45c","ddce26514f","b8cf43148b","4a8c2549f5","13027d0dca","8330eb53db","b7f7221bc1","80c3d6d45c","ddce26514f","b8cf43148b","4a8c2549f5","13027d0dca","d2cc24f374","ccf4dee087","33738c6d57","fbc01bef74","d5f0c324b4","9672932ede","fed95a6c5a","0c3817eace","bd058d59f8","552b6b7f43","a7add8a827","ae52347db4","044020c2f3","85ab881851","fa061b0d37","a02bcd1651","054f2f0832","6b8b0d66b4","cd9f2489ef","71f0d32391","802fab17e2","c18af02cce","596e0babe4","967812027a","0234722f60","d7cc79a378","a6f209ba1c","388868c0b2","ca81412410","910ddc76ae","ccca8bba85","a931e67633","7141ade197","52d5fa5f09","9d03eff8ec","19c19d25ab","26f2b6f9da","a948287e68","f25e07009b","7051630da5","5295d259ae","4e0a387bc3","05cd70f3af","5ce2281fd3","94ae6a1327","d3759df01f","714dad6767","4aa88fe053","7d3a5a99f8","05cd70f3af","5ce2281fd3","94ae6a1327","d3759df01f","714dad6767","4aa88fe053","7d3a5a99f8","9e73396a75","9db3ce400b","11e3193e54","9901170530","aaed481bc4","ee700a3b10","ce20409393","d44022169a","2cb01141bc","4246a4a409","33f3d127a4","b1d145d67e","0b146d8a25","312a829bd8","95575ea196","7778e5472e","e9955d8d89","6d5eefbaf6","dd08fccc9c","c05c325df9","b6f5a84cf0","49044ea6e2","18140502cc","80ace355b9","d092a6a1ee","5db7881bb2","36b224d474","af1b79483f","898b2f1189","af0ed6fac7","c42cf92710","301e2ffd5d","2c13554a82","2d932e234a","ecf1685ed8","6d870e5a35","c76353a610","16d94ba62d","9093f51941","0dd8744894","68d8d5197b","aebdff1eb1","81c2727f92","a19546e4ee","93cd577b36","1b9f2a1e8e","0014bab440","033e8068d4","cc7b7f3397","81c2727f92","a19546e4ee","93cd577b36","1b9f2a1e8e","0014bab440","033e8068d4","cc7b7f3397","d7c922e68c","9952aa47b5","b2613cc3f2","9c02cbf473","284fcdb8c6","9731cb8a21","2349c0925c","d7c922e68c","9952aa47b5","b2613cc3f2","9c02cbf473","284fcdb8c6","9731cb8a21","2349c0925c","8c9cb6ce10","24ef4f5ae3","68df4b0be2","6bd84378c2","ef9ad4fc29","062d7ac1ad","8afebce18e","d7c922e68c","9952aa47b5","b2613cc3f2","9c02cbf473","284fcdb8c6","9731cb8a21","2349c0925c","d7c922e68c","9952aa47b5","b2613cc3f2","9c02cbf473","284fcdb8c6","9731cb8a21","2349c0925c","f917da5ee9","6d360d4b47","493ef15f63","1f9f815fd9","b59c5da137","4ee203adbc","6a4dfe9823","f917da5ee9","6d360d4b47","493ef15f63","1f9f815fd9","b59c5da137","4ee203adbc","6a4dfe9823","deacc279f5","1efd617427","47a8433ba0","d1eb0fa81d","a39fd4be34","f3fe99f7c8","a30672cffd","e22d747a64","a922b45d06","1d544ff290","39ea8d74ed","c8d82b867f","a3289ed22f","eeb48da4a9","bcb2d733e6","3afa62fd73","2d238524bc","2fe7bb0026","99efe2f6de","c8920cec14","2d903ad061","37b0dea4c5","b5f56065c6","dbbf72f614","9e579d925a","c6b60194d7","2ca06dd9f1","786eabf41a","6d77fce7e5","5d04246e4f","7b2157f934","c765a7021e","0bd8155ffd","a9069342b2","8a6f738aed","8b0d186967","8ff27357e7","db2ab8dbed","06c843f080","1261ec0b13","70853ab005","e7b69a6c4c","cd4bed1f92","0fbd88664f","792bb695ac","bd777f8277","1a67dcfca2","6997ae6783","2ee9484596","70147754d9","7ce558c730","a1548a152c","3c67527e0b","6517aabec9","656066d08d","8d1c08e96b","2a637d493b","6791dc8825","6de7c58924","e36c640ab8","77dc6a8013","6325ee54c1","dbc3e82c5d","90b26fa2f0","7494d8a729","a0a2a08dc7","3e8775716c","3854076030","9de72e94cd","966972d455","de69217a2b","83de927638","d36540817f","7727fa481a","912802fe41","c54330889b","2430451af8","00d0a3b91f","2761f4ba68","eaaddcd089","e7da5cecd2","8361fb0812","3b848af81d","ffdd9ad9f3","b071f3cc86","c1b0208da1","88eeb3317f","676e8cfe77","c777fdf1ec","2cc1c6aea2","83e949bcc9","b071f3cc86","c1b0208da1","88eeb3317f","676e8cfe77","c777fdf1ec","2cc1c6aea2","83e949bcc9","7b75d67fb5","44e71f435d","7981e02e5c","caa2d7407a","cbe2d32d37","e8503ec514","b42cab3b79","3af6a2c242","48b7e27795","525da0257a","a80422b18b","2fe6df709a","f37ef93bb8","365edd3734","3af6a2c242","48b7e27795","525da0257a","a80422b18b","2fe6df709a","f37ef93bb8","365edd3734","85c4b758f3","7b0d19dc08","378b331107","4e3e5d93ef","45953950ed","447cb3d5cc","551be0072a","81d16ec1bd","08e1a503e3","37b9f485bd","32f1537c0b","4a3da679c1","44eb819b78","b3936ada18","81d16ec1bd","08e1a503e3","37b9f485bd","32f1537c0b","4a3da679c1","44eb819b78","b3936ada18","88124472da","897803044a","2bb2eb2698","e1dad8f86a","5b52f98085","818c6f269d","26de945dfa","6cb24d0649","718893d47e","1cfcd7c046","d04787a126","9907e7af54","924d792b87","d5f8523245","53eaa03d2d","0b1be69ea6","5b8df3920a","88b0294379","fddb67969a","809f59dbb9","cc6147b101","1b09dc2b36","61b1f35924","8cb63a69c4","ed0612a19c","2c9791d57a","63e60e4c94","3cad924171","42d9b28b7e","c0b2733a9b","3fbfadfb0b","7110489a6b","8310253cd2","1e599e53ce","f0dfa86116","84dd22ea6a","4d3d7cfba9","f8fd599d18","474f85d2b0","d48b895fde","94918e89c6","1c38366156","078dc65ab2","36b0c15aed","6cf5c90cc3","f2cc49b605","10572d023f","3b6815e336","ba376b54d2","8c8fd31bbd","26c8614b47","cfead1fcb7","50d31d840d","c932f49472","c2e8da5a28","1989dcbd4e","6cb24d0649","718893d47e","1cfcd7c046","d04787a126","9907e7af54","924d792b87","d5f8523245","571cff36ed","31d9e3b33b","1e485b8990","5826f7fe71","df64b96ea7","801347ea93","5e8067c6fc","14dedb6a89","f9d20de7c2","cf431fd0ae","1054335a19","75e2ebe9cc","56958b2c0e","878b9b730d","fb823e13b1","1f09de3dbf","dd6532e1a6","76cc688d57","0007901aca","f7c1f40359","2e7a7ad2e0","59e70ea502","4da1b4df05","018daf5a28","678c1e9fd3","f948f4fa1c","4db49d4e46","0301b12c53","13fde04c16","45e45f9f43","09d7cf9aba","1974d41a2e","2498272f52","4b3aa27c93","8f5b37014c","08922d1703","e8c538fa0c","e56fd66d26","5967023bb6","093e103ee1","cbc42fcd4d","05d680952c","e65e35d108","a271b67fba","de6985eb09","66238eff22","c3b6dca504","91e7d29ad8","c9c8223cef","66f1c4cb8f","08004b294d","aac9f66689","4e98335655","7a8c735fcc","531dbb0ef6","2691e30981","9c91fa96e5","45febdb82e","b15545ae1a","70870da2a2","bcd13bfaa6","9b7f6569b2","5bbdbe6d8d","571cff36ed","31d9e3b33b","1e485b8990","5826f7fe71","df64b96ea7","801347ea93","5e8067c6fc","8b6f94e384","0d95b2c37f","5f9b87faec","8a795160bf","0e7c57e39c","b893f26c71","d90b5fbeff","1c5dd92740","3c0de70b83","8af5fd1c74","875b114e0c","55fe5227c2","b64f45fae6","e60e011509","6c0fce4b9c","6a67062d48","4e2a15b162","c5247ad888","b6f88dc86f","297b1ee4c4","0d98839d51","8b6f94e384","0d95b2c37f","5f9b87faec","8a795160bf","0e7c57e39c","b893f26c71","d90b5fbeff","76730e1b76","67dac13090","e30321e131","21249379da","7f9617d67f","26ac864022","030da60c59","6ef7e5af7e","775a0fb7ea","612232c6e1","ca2f3a05cb","f706a28f0a","18d19c896f","3904afcc12","5898bae598","b2f5adceb1","dd62555cf1","75fa028b41","5a1c01dd38","27f4b03547","255b4eba2f","6ef7e5af7e","775a0fb7ea","612232c6e1","ca2f3a05cb","f706a28f0a","18d19c896f","3904afcc12","0f467fd300","7ea8591dac","4be92529ef","dfa0b6e86d","051d618195","7d92f70b8e","fb0c5f0753","c5fcd7f7f9","50f29a032b","051f979d69","ef6bc2dc65","d0d286be51","78b8997ca4","ad220ead8b","c5fcd7f7f9","50f29a032b","051f979d69","ef6bc2dc65","d0d286be51","78b8997ca4","ad220ead8b","a21cd4a6ba","e4be5e0972","9c8b72ebd3","5d16ca809f","6021e50a43","c3ce51411f","13a29c4b2c","a21cd4a6ba","e4be5e0972","9c8b72ebd3","5d16ca809f","6021e50a43","c3ce51411f","13a29c4b2c","3415b62bb3","0f8e322304","0fc8e91996","8e0a22ea39","972904e65d","ff9d1f443d","45cdce0171","3415b62bb3","0f8e322304","0fc8e91996","8e0a22ea39","972904e65d","ff9d1f443d","45cdce0171","7acb67400f","162b74725d","9d1533f9d4","ceda943b6c","595fa0b26d","8120fdb0ad","b7b3310906","7acb67400f","162b74725d","9d1533f9d4","ceda943b6c","595fa0b26d","8120fdb0ad","b7b3310906","d84367ed83","dc01a2b115","af9ae24200","b4cce575be","eb16cde620","f6ac2e5ee5","99595d5093","514d5bb76f","a425cd5cd6","169318f4d0","6cd893dac3","b900e7711b","5ce7c27747","5c2b27d337","514d5bb76f","a425cd5cd6","169318f4d0","6cd893dac3","b900e7711b","5ce7c27747","5c2b27d337","b797c43ec8","6d3c54564a","fbf3f6d28e","6683a88433","0f93d80e9d","3082f48642","05e64a4693","b797c43ec8","6d3c54564a","fbf3f6d28e","6683a88433","0f93d80e9d","3082f48642","05e64a4693","ef7e14b3b1","c1b464bab2","8d8a680f08","10f59a37f7","57a6f1da4f","fe06793cff","8a524526f0","ef7e14b3b1","c1b464bab2","8d8a680f08","10f59a37f7","57a6f1da4f","fe06793cff","8a524526f0","203661a6e4","d4d4f92413","84fe08818c","9d724f5dc3","4266a9d747","964ebe22b9","1ce4cf04b7","e6f09403c0","bd3f40560b","bb69d1da04","1a33a9cf51","86aa27fde1","4c7e0b4a41","de2e11df3b","e6f09403c0","bd3f40560b","bb69d1da04","1a33a9cf51","86aa27fde1","4c7e0b4a41","de2e11df3b","ca8031bab4","656ae9e9c3","0177d6afd8","2f98a77b4b","62e3fb70be","9c92d56bfe","3084fe23df","ffc7ca118c","d620e6b453","e27ee1d2a9","cc39e0a952","5d3a6393c9","20b0ff356d","9ded623cf2","ffc7ca118c","d620e6b453","e27ee1d2a9","cc39e0a952","5d3a6393c9","20b0ff356d","9ded623cf2","fa05be9876","26a9e8a025","cf9172c3c3","eda300d6bf","44b2676b88","bb2f5926e1","f15abfabf2","2dd566b155","30a7046b1d","a326f65230","ada1a14155","8298c2e44f","4c79efe1ac","27ff6a3456","6a68382ecc","290db9a598","65b1a5b863","b4688e5d65","84b9c5b4a5","4dc3184822","c64452653e","6ea5582a49","39a03639fe","8b377296b4","77a1986806","661e70c473","7f985955ca","a9c6400286","6a68382ecc","290db9a598","65b1a5b863","b4688e5d65","84b9c5b4a5","4dc3184822","c64452653e","e0dc42c18b","89fd1c2885","19af726c6c","917f94a588","d13d3f2523","dd65bb6ef8","4c3f43d001","32569364a9","81f47e615a","d9d7c687b6","bdd57a295f","efbb04ce1f","60445d7d4d","01958fff96","32569364a9","81f47e615a","d9d7c687b6","bdd57a295f","efbb04ce1f","60445d7d4d","01958fff96","c1ef387511","1b31f94a44","6c5c90a25e","abf535bf4f","b3feaf9bc6","b0b9632173","2c2d7bad49","2f04bebfc6","a5053f2a08","958764b88b","373ccb6fa7","81bcafaf5c","ab71691737","0e71598d82","6686d02f22","380aa5a8bb","7a33e4f505","ee8a3f2c33","63b2ddcd22","96ba4165e9","5ef4000ed9","d9d32e9d9d","528f7f9ad9","51aaf8eadc","38b9dba5c1","c22ba2d5d7","4f1e24fc9e","89c7e7ca0a","ae4a3a5309","c92eef9356","67dcea0197","2aa828a9d1","2e4f172a4a","04a84c9a90","8051bb8454","d9d32e9d9d","528f7f9ad9","51aaf8eadc","38b9dba5c1","c22ba2d5d7","4f1e24fc9e","89c7e7ca0a","99dbf9563b","d8141f5fa2","e43e56fde2","59bfd58149","8e38014486","066d435359","b9802e01f5","59649d026c","63ba3ecf11","3da3c765fe","667efaed48","a35ff46c15","c4f26b6134","20175ad1b0","80595a0487","561aecfe06","5580f4eef5","d32671f797","b4e965774f","343641e058","75c0687e42","3f5737e7ec","4b6408e220","032a0015ad","562142d8cb","df6c0f65bf","c316525e81","c5b43899b8","223bd38ab0","78e2638d84","5ed2aeaa15","251d0f9035","2cf9ce0ceb","9d873b8269","e82638cf8c","15eb550657","ce449ccef6","88f7fdb9da","b4a3af30f1","ab8b588403","0a269dfcfb","d7d855f0b4","2f04bebfc6","a5053f2a08","958764b88b","373ccb6fa7","81bcafaf5c","ab71691737","0e71598d82","a140793d6a","1c86ba0799","bcdcea7fb8","f8b8223fc0","e684309365","6d2ea89924","3f64847960","722f98d768","511d5b1557","7527b0cc42","ce05797f60","fe6eb91b3f","ef84f31c8a","6fadfc8478","b650e6185b","89a3e97c33","5db6210c0c","af84dc176c","3dd523c6ea","582f760b8c","1d9eb761c6","1f7c07d015","0260c0cada","77906294de","7ec6c6e877","94280d52eb","55525806c0","d1a2bf2e93","caa4c56ab3","11118f2e51","3b7cce0d37","63bd7591c7","0c9321aa05","98f405cbaa","6ac4936bd5","cb0504831d","de510b9982","cda06ec616","f6440705a7","57daf8e078","d986f6abf7","aff5b73690","888310f8e1","cdefe4e4da","82ff73de70","fd6247c114","f606ddd972","91b63c5e3a","95fd68551e","9ec6cee040","70ab2484be","b0c93f328b","d7a1fb7ff2","a49d4d0330","aa20148aae","d0293f865f","3fcff2826f","54f3a27213","6878a3cb0d","b4c8e6fc45","df4adde845","42175296a5","51e79f6d7d","3fcff2826f","54f3a27213","6878a3cb0d","b4c8e6fc45","df4adde845","42175296a5","51e79f6d7d","0e9c6e6759","4274d99942","34b90b5546","cdbf531287","e8cc35b0c8","730d5c5698","fdd217acea","025453168a","a4064072ef","2a2b430575","a6672d7b52","40a169fac7","ab55f04e94","07eec2fb8c","494135ce41","26d21cf630","747a6d9ab3","a2734e9779","f571a0000f","b77b903e37","b1bb8d1a32","cc4f10a629","f9c02c7cfc","afa4f4984a","799e374fe5","52466e482e","73f9865654","c869e60954","9a28528860","46f784db70","d5694ea797","77ae8ec416","ff9b6e06ad","934b497af8","7ac31118d0","3f924ca2fb","04e6ec256f","978651dfff","2e5cefc6fa","41ab6d376b","4e3e94e085","af90263987","14b901c288","a13175893b","60c137b034","f3faec9f8e","969b3334f7","609560dcb6","4602ff3d0d","14b901c288","a13175893b","60c137b034","f3faec9f8e","969b3334f7","609560dcb6","4602ff3d0d","b28c38e82b","8cd77e0462","857f0ecf20","dcf39ed136","d33a77d7bc","aa2a6488a2","d68ddf0f29","9ed8bad5d0","6753e755bf","2b1a103001","d7fe4f2960","2ef8faffe8","8bf81c5371","9e72f57d0c","824a707df6","89da9bb75c","dad3b94ea8","f139768477","5c926f99f0","c4a57c223c","2ddab01ccf","824a707df6","89da9bb75c","dad3b94ea8","f139768477","5c926f99f0","c4a57c223c","2ddab01ccf","c453f83a5f","f45e43c9fe","573313a3b5","eb23558b33","ed6200a531","79dc7d39fa","01c3e9c693","24f75cb6e6","e5a75a91e0","5ddf7b1300","2325ea0813","543c9b8b0f","d950afd731","acaf30a26c","7a38894a62","16c0518fa3","44e90ec29f","9bc940caa1","11f49ac4f3","d275684854","e9f3ad2e7f","2721befe68","ebb3b3bc66","0086379293","2ef98be037","e811e7061b","78388dda8b","6e1f87c689","daeac81e2e","1d019401d7","f3f68eb154","cacfb0c721","7df8f6884a","b619389333","a538686eef","9542116384","caa4471d9e","cad6ce493d","a6532487a3","797856e294","9b6fd3e946","c20cc35c23","0cbe93f2ad","40c7405ded","16e5a9874d","05b85fcf63","733f8f4437","48f9216536","f59bbb3090","bd4fe0fb61","e0dff9df83","e9aa603525","a8e1429803","b0af56aa0e","e480861701","4587a68c2b","61c5bf5c71","1b65eb5e00","71b08e5951","70bb7f0ef5","0e12fed2a7","85eb4393f1","dcd6b4ef66","61c5bf5c71","1b65eb5e00","71b08e5951","70bb7f0ef5","0e12fed2a7","85eb4393f1","dcd6b4ef66","1326f1ad8a","2607640319","5552174c3f","35e37e3687","a2e0963919","72a263d97a","c7282a7c86","6f026a042f","f42fba557e","da32f84763","438686d2d5","b5d60f7094","2672aadb34","22f3d40df8","6f026a042f","f42fba557e","da32f84763","438686d2d5","b5d60f7094","2672aadb34","22f3d40df8","6d45d0ab8d","c50340f41c","623cf8d4da","0df8fd42a3","48223817e0","d1ba9e32ec","74781af51a","6b8d31c6de","01176aaaa9","c0639ea561","ea3d162dc7","b0eb6f8a43","a11cd6b4c3","69e33645cc","6b8d31c6de","01176aaaa9","c0639ea561","ea3d162dc7","b0eb6f8a43","a11cd6b4c3","69e33645cc","1ceb08bb28","f747d9a6ff","9bffc817a4","88f3a0f99a","074141343f","281aa2ddbd","e55eebaa2d","b84e20096a","59432657ab","d483140b73","b36b081b59","e4d3e10dda","32e52df155","fbc1a5adb1","136bde05b5","b354183455","b8e7c305ce","4730d5c3e3","7035dde5fd","d6295d2b99","42083f8503","f5653dc833","75af928db3","2b6be46d5d","d716429345","344f78f0ba","cdc5115178","0f0371784e","136bde05b5","b354183455","b8e7c305ce","4730d5c3e3","7035dde5fd","d6295d2b99","42083f8503","37308ced5b","3dba4dab6e","500042575b","2087a7c25b","963f90be3c","551568a9a3","3fb6dcc160","37308ced5b","3dba4dab6e","500042575b","2087a7c25b","963f90be3c","551568a9a3","3fb6dcc160","a57a2df35c","e2493bc850","e55c7216a1","a17de1d341","56cab2c2df","e92aa89d58","5f031570b5","a57a2df35c","e2493bc850","e55c7216a1","a17de1d341","56cab2c2df","e92aa89d58","5f031570b5","218b9297da","855ca59c82","39e0ababd6","a79588cd76","22c602f2dd","cd14d8cb75","392a5ff2cc","79163ae9c2","8bd376fd3d","eb8bd8d806","7b92428223","346ee45aa4","8e984c6168","a61d305202","218b9297da","855ca59c82","39e0ababd6","a79588cd76","22c602f2dd","cd14d8cb75","392a5ff2cc","218b9297da","855ca59c82","39e0ababd6","a79588cd76","22c602f2dd","cd14d8cb75","392a5ff2cc","9094bb3b1f","313d982bb0","1c5f1acf77","a92bfca896","27d3c0a9b0","6dfd1bf6be","61db28c20e","f71b74e028","692e3c677d","0e19be76a0","ab18dde17e","96f4cb1144","3e908f1e20","6d6cb130b5","2a77335357","5bdadba5d1","9cdc8e487a","9c07b22919","3158789c89","7160871c26","c64ae3c3b8","0146810614","b175831ce2","6b514ad0b1","2527640f8a","d8400be88d","a0f88071f8","f1cc31e212","0146810614","b175831ce2","6b514ad0b1","2527640f8a","d8400be88d","a0f88071f8","f1cc31e212","106368df19","ff8530b3e7","63189b6df2","4dee8279a1","44d3ea7204","1bace8f9f8","48c97d3426","106368df19","ff8530b3e7","63189b6df2","4dee8279a1","44d3ea7204","1bace8f9f8","48c97d3426","54e0494aba","be3167033b","3a5a83906d","ea05c28e14","986815e0d9","60d19fa8a6","226d1ae48b","b456e6d855","8f9f3d8397","6cc450dc05","a7ef80358d","f3270c25cb","5293560565","424e706d0c","1844ca18d5","096343f160","f0de4d5883","b906e2d01e","7d64327093","bdd9c9d69d","4ba5382928","a0d5ffd929","3bac119d6f","62d297e851","8509a72499","6a33a38d0a","820166288b","b8af005cd1","8f896ca14f","07963acf28","11338e409e","076ada990c","b218512b05","e7610f1841","423b2b92f4","bbd242314c","fc2ebaeacb","f761b587c2","8d7a75b50b","67d4ddbcaa","bb45d36a79","c6d9223643","3b46064247","80aa8aac11","01b88e9bf2","5e09ec5ace","7e3ea501fd","5d0aebacaf","1bb8e93b1b","9433721cad","5370472343","20fbfe9e3a","9fca87194a","4a13b207c6","58703181df","aa93aed388","3fd1717166","81f156692f","6a98c29833","f719e79cc8","d8ccd51494","c4e00d7e43","2104060775","7fe3959982","2f45c4f75e","ae442daa9e","5c422ee471","fed4979b0f","0e7b5c0288","b9dd639940","7fe3959982","2f45c4f75e","ae442daa9e","5c422ee471","fed4979b0f","0e7b5c0288","b9dd639940","7a277051f9","8c3c907e16","2acfd3e2da","4d64418efa","acd83455f4","ea1e6b93b6","2c78976faa","252b37b5ba","98202ef902","606c34b4a8","a62585a978","118bc15338","18370ef514","cf89f3d2e2","97d9f09ad8","c7e8bbff59","169fc4b3ae","177e6f5e11","ba0bbc57df","3fcbb3497d","10c30c15d6","7497d6afc2","2032bfc055","dd0ad0f8e2","1ac2a35bb4","4a5c75dcd1","4f1245d51a","786f58b977","4c0dba6787","2d91cf9033","5105d5261f","75d6b00a05","d0701d5f60","27a36f10a5","5db1b8d2ac","72572a447e","81e3e7a804","934d46c190","4bd7843664","57d831be02","604175c511","d39fa95321","97d9f09ad8","c7e8bbff59","169fc4b3ae","177e6f5e11","ba0bbc57df","3fcbb3497d","10c30c15d6","af844af21d","fecbe64999","2bc52e0414","23300b2ce9","b82c04235f","c66410c2e3","33cf9b5d15","209fc09d94","2664078ea9","54897ee955","ffcdf490c1","dc19b29fc1","dba05a2e90","0510c0083e","5ea96ba155","becdc49666","69e0d28040","882fb110b4","b5ad73582e","b1d89b1f2e","a47aed5690","3e05048f1f","d0de7086aa","57621cf248","7eeab4a501","47d5c78223","9d4d4f5ab9","9461188405","5ea96ba155","becdc49666","69e0d28040","882fb110b4","b5ad73582e","b1d89b1f2e","a47aed5690","12b868a959","f3922ad1c0","6ff38310fa","2741ea7bb6","8244ec55d5","eaa4898dbf","21b213866f","a86860c136","e322277a14","2faf810340","f976c6ad7b","9e1056a6f1","8b06dfe9fa","f42867a326","ae55cada72","31792a1a7d","4a7e7bb41d","27ee920dd5","57282d8b0a","3f96b66edc","cc3a4dc862","83ce8bd936","9b027af9ba","d24916c2d0","c19801c7b2","7e98f1363a","92ddf97b3a","9efa198a42","f82ea49ff9","f2af03d3e1","6c7217e2a9","adcc7592f3","c232bc6481","ac9272fd16","6cafde9258","48d128e5e6","dec36b4073","a51da18b19","f5e2765ac0","029c1d7303","7fc4dada07","30d2328180","48d128e5e6","dec36b4073","a51da18b19","f5e2765ac0","029c1d7303","7fc4dada07","30d2328180","9d73a64dfe","a6d7ce9320","3512857a13","8ae05e9dab","e145df5f89","d3150df3ad","0c96361285","3235a7121f","272eb7e2a2","d02089130e","ba08efa296","70693a7060","80f61c9f6a","22f4271ede","09a570d356","eca294228e","695e73181d","70be19f5e7","18fc39d4b0","7dcf261eda","aa90b25490","425de23efa","e71dcf1c5c","88faeec8de","8b7b7e7f79","2e8b0e5c05","b02f2647f3","f5ec9eb37a","adeeb75d9d","177e2385f6","8347f889a3","773e837fcf","db54d0083c","0f719f0d78","02af9d2414","1786be8b2a","4fd903b980","2e6976914d","9b538ebfba","f9f69fc810","d0fb0d7a21","d618a30252","1786be8b2a","4fd903b980","2e6976914d","9b538ebfba","f9f69fc810","d0fb0d7a21","d618a30252","3d4a6df65d","29fc5d7dd0","e2ef355594","642188bfb0","476eb43385","7a92c11344","a5e1d128c2","557e509b38","11cad9f25b","7353502dae","9c32036c16","fc43cab5c8","2b14b4a3bd","f1f36eca61","c24248b0d6","b23e4658ec","2bc2c15225","bcfb1cd689","f3d7047c76","1a24da245b","e12917d346","7f5db0e624","84771d941d","4e8aeff81d","31efe54337","44b0783f2c","61088dd00f","7b24272126","7f5db0e624","84771d941d","4e8aeff81d","31efe54337","44b0783f2c","61088dd00f","7b24272126","39ff7a3cd0","68da587ef9","bbc385db1a","6ee810fc40","499fb5f851","8bb8d24c21","3d33fca3fd","c5fe803a6b","05fbb27635","b71979ffac","ae2f3dbef7","ade2bdf550","271e3ffd2c","db5d7ca1f7","c5fe803a6b","05fbb27635","b71979ffac","ae2f3dbef7","ade2bdf550","271e3ffd2c","db5d7ca1f7","456c196ca7","e7d403c59e","6828d9b997","756f2a9b7c","40cd645109","191cba54ac","477e01b693","1a3d1b568a","ca30fb4270","e8d22d03ca","d7d03b1e66","8b68fe7a4c","c0e5c441b7","1f213d8896","6227843ed1","3a762e6221","abce939ae9","5330d58f5a","0a9a8875c4","bd737621a5","f92c9de483","466e9005b9","3125a78bf1","ed22612e6b","3563d68671","00718faefa","58ca7c510b","89014daa65","456c196ca7","e7d403c59e","6828d9b997","756f2a9b7c","40cd645109","191cba54ac","477e01b693","ba199a092e","d296de284f","ffe7a4f571","ccd814273f","7f3cb33e3c","191a77d0d0","89746439a6","41a474fbb1","db79b91fb4","c55ed54bc2","40654adbca","e3c34b4372","db3075d307","ae8ad64cb7","41a474fbb1","db79b91fb4","c55ed54bc2","40654adbca","e3c34b4372","db3075d307","ae8ad64cb7","d0d92f04a1","1cbf141490","4531be4572","49834db71b","2c6cf1ffdc","946ef247f6","f13b21500b","d0d92f04a1","1cbf141490","4531be4572","49834db71b","2c6cf1ffdc","946ef247f6","f13b21500b","bcf2c2af74","c8bb02b942","ad51f0d229","5c585310e6","69d2672668","5136e3ddf7","b1f259bd6a","bcf2c2af74","c8bb02b942","ad51f0d229","5c585310e6","69d2672668","5136e3ddf7","b1f259bd6a","c0a7c5bf90","d8d865c654","9130966458","96dbcd98c3","f570a1619a","c1b29a3c50","e8f87b52ae","c0a7c5bf90","d8d865c654","9130966458","96dbcd98c3","f570a1619a","c1b29a3c50","e8f87b52ae","3148ef16c9","3b18a0def2","5a6c35d4d0","f4dc7fa85d","4f7c03294c","d40183b357","d0f286ba60","264fce5c9a","1f6e527333","ee433f9bef","3f5638fef5","1da8ba4cac","467ebaa737","9a591d7338","aa428ac41a","0246b18d1d","dc6ecf8e98","922f59cb7d","ea5d55e250","e42fc75ba2","ace3bd1125","aa428ac41a","0246b18d1d","dc6ecf8e98","922f59cb7d","ea5d55e250","e42fc75ba2","ace3bd1125","c0a7c5bf90","d8d865c654","9130966458","96dbcd98c3","f570a1619a","c1b29a3c50","e8f87b52ae","c437aba4c3","7011d9c867","f1e2dbb8e4","1ad2d9d648","750c940cef","b12cc80993","9df6205d72","cf0a385ded","88bda7c143","d64f1f0387","e20b652d86","8b4295ffe2","595c324259","577683c620","d199a79af7","41e2bbbbaf","f31de3fe52","21c1b78f2c","454b9b6f96","5552f8df28","2281fa913e","d199a79af7","41e2bbbbaf","f31de3fe52","21c1b78f2c","454b9b6f96","5552f8df28","2281fa913e","477bf43d15","47a07cfb62","f0b2879a4d","e9350a5962","93a445f7e0","53bd214036","700e0ef0ff","0128660745","d510c68667","b2cab34d79","37234855d8","f0f7b15f73","ed7bbad42c","4676fb5164","0128660745","d510c68667","b2cab34d79","37234855d8","f0f7b15f73","ed7bbad42c","4676fb5164","0128660745","d510c68667","b2cab34d79","37234855d8","f0f7b15f73","ed7bbad42c","4676fb5164","b5697585b4","caadb8b029","641e7a486f","0523d35e7d","1c7cb1a652","ab3a9b38da","9a028856ca","e6ab8340c4","4bcbbf7a36","2b60dfbb5c","4df3bec0dd","8797165cb3","38a92d40c0","7e5ec25045","985bb91638","61220fc655","5f5f03919d","48db1016af","5ef44c64be","cd033bd050","6e6b457283","088d13be4e","1b410969af","2a7d83685a","1500b0625a","6313d9b296","a9087d45a5","ee43addab2","9cf3933ed0","3d3ed60996","0d3a4068f8","3f5a579f6b","bd83d2a646","95b4c80592","e74871a1bf","ff236f34ff","0ed7d33fd8","4af39339d5","3cbf489fed","3b81ac677c","782a7b4d71","c35121c99e","ae2b9d1881","c30b12073b","464f6d5219","b64fe6305b","aabbd90b61","4f7d95a045","f72b4c1b0e","1591177bf2","73ddfe09c9","f09ab61892","2ce8589b53","3f87e34f1d","cb9f36b07d","3153b751f5","7c39df0de0","f97ffefac2","9e1772beab","5c9ac15a1b","feedbc3efe","ffe75425c8","37d9089f17","fa241eb29b","dc88500cfc","6571de1c91","7f7e4705fe","8cf4c02b65","38f3fd352c","92e43d4e45","fa241eb29b","dc88500cfc","6571de1c91","7f7e4705fe","8cf4c02b65","38f3fd352c","92e43d4e45","550eab2058","38a3150cb3","d927d5cab9","7c2e20d275","a8ca289c06","966b157b2d","6ed574eb64","d955d8e8e1","d96ad66a66","d6490c25f7","cf60e893b7","c663029698","cd7d9398bf","fa148cb935","7551a78758","aba336c8c7","6ce999e461","b5f6ada6a8","2320b035c8","5a6596b2fd","c0a10f0b6d","8342638654","4261ccb2d3","a77dd5d251","0e9b0b5be4","a32cc940f1","a830a61687","78560be0b1","9cf3933ed0","3d3ed60996","0d3a4068f8","3f5a579f6b","bd83d2a646","95b4c80592","e74871a1bf","9cf3933ed0","3d3ed60996","0d3a4068f8","3f5a579f6b","bd83d2a646","95b4c80592","e74871a1bf","ee3f0bfe8f","6cc0d5c3e4","32db31e190","505737bcf7","6a43cc589f","43361849d1","552195e45f","0baa872f9e","42ebef481e","783f900380","6c4e9f0a94","d912296c85","9974fc6a7e","77efb3d14f","fadc7e1afc","a80e143b1b","192c58281a","be16763dc5","0dda37c773","fdbfa9883c","f2eb6a9ac8","30020c1f2d","988573cf60","9defe7f3d2","be6b4f7c60","045392e281","3667dda595","1ff83f00f1","ee3f0bfe8f","6cc0d5c3e4","32db31e190","505737bcf7","6a43cc589f","43361849d1","552195e45f","870fc9ce09","157c41c030","40cc1425d4","8fdf652953","5f26bdad4c","b80d2d1ea4","b9f6791dc9","9549934d75","20eba93761","57902c5021","35ea98301f","89fef05397","d07c05b8f5","2742c5cfba","0cfbf09169","83d5e21838","deb0540601","d9b34d692f","872e5510ec","873cda1453","956a4486b3","3aa0f91a1f","c53862fe1b","3a6506ccc9","1b62fee320","76932a22bb","c06626b9e3","0be2a77a57","aa7bff0b90","485d5b776f","90568eb69a","ea0e8040fe","45a64fae68","ac011b38b5","a5e462101c","37df413569","94c751bc4b","e5d4d7df9d","7674969f63","e392910c9b","a7e1b75aff","e2cb7cec93","7f9c30aefd","d4adff65f0","30051049d9","f2c4bdf5be","14f7861249","11098d1a6b","d7fea04442","77d0764a47","416886b096","c503083c2b","adf524a166","3309c19f8e","d3ca4c9947","fcc2916f15","ad5f78726e","ad3426461b","6f1fa649bd","a6bb072c2d","83b7339224","6ac335adcd","6d2de096a1","ee156fa30e","6e6ffd1915","c003c5c7b2","e1cf62d788","0589037975","614fcaaa15","56ec7b59b3","ad5f78726e","ad3426461b","6f1fa649bd","a6bb072c2d","83b7339224","6ac335adcd","6d2de096a1","5962382a83","899119f84a","30b492e2ba","9f26bd4701","27db9e1724","0d816b91da","dea04802a6","da1553184b","b8e5422e53","96c59d6b4e","64d923f36e","be06f95914","36ef15b7d6","a2cbc312f3","a14ebeb62f","dbdd894300","7ab894f55c","3124af03bb","74d757a975","e2826437ba","9b92207c04","1169eee497","21651e1d63","7528194fcb","2b67eedfc0","3d8ed887ef","0102454beb","b919ad2f83","1a28dcf98c","a3d684cc60","4672deed4d","f46ddac348","542d67c3c4","df675fb67b","b42a745b20","1169eee497","21651e1d63","7528194fcb","2b67eedfc0","3d8ed887ef","0102454beb","b919ad2f83","768f1c99e5","56b7686bf6","dfbfdf1659","a57385c782","8d4a768511","3ed5d53379","fdd6d15749","768f1c99e5","56b7686bf6","dfbfdf1659","a57385c782","8d4a768511","3ed5d53379","fdd6d15749","d94d708e05","9150d7dfcd","7818fd4aa8","dc12de8477","26372ae0fc","13e5a84f43","de8dacb430","16e84848c2","74834ec58e","a4c93e87de","d210a9f424","b46bda0dce","191384ff0e","c80b59dc62","772ae69d3e","25f15d124d","921df12369","a6feabd242","02880e9cb5","f8a5e43252","56c2deba2e","6738175137","ae5865752e","ed666ea249","fe63ad675b","cee155c476","45d5e3ac9a","654147af77","6738175137","ae5865752e","ed666ea249","fe63ad675b","cee155c476","45d5e3ac9a","654147af77","13b5a95c0a","f9b76b352b","a916365f43","d66e648098","2ebc0563b5","1b7b504f53","3976fbc5e1","346331bd14","a57daed4c3","ef21d02569","988b263611","afde9330a1","6219b19395","6fa60e6368","346331bd14","a57daed4c3","ef21d02569","988b263611","afde9330a1","6219b19395","6fa60e6368","05a5d74861","f8a2a40459","352356033d","9db6027531","717eb3eea6","0fab0de3bd","5c7b61419b","006490a9ce","9e2558ea11","122caba63d","769b0f65ba","ff13930bea","6bbea58f42","79f4128701","006490a9ce","9e2558ea11","122caba63d","769b0f65ba","ff13930bea","6bbea58f42","79f4128701","006490a9ce","9e2558ea11","122caba63d","769b0f65ba","ff13930bea","6bbea58f42","79f4128701"]}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment