@huuduynvc/v3-periphery 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/LICENSE +339 -0
  2. package/README.md +52 -0
  3. package/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json +1230 -0
  4. package/artifacts/contracts/NonfungibleTokenPositionDescriptor.sol/NonfungibleTokenPositionDescriptor.json +161 -0
  5. package/artifacts/contracts/SwapRouter.sol/SwapRouter.json +574 -0
  6. package/artifacts/contracts/V3Migrator.sol/V3Migrator.json +360 -0
  7. package/artifacts/contracts/examples/PairFlash.sol/PairFlash.json +196 -0
  8. package/artifacts/contracts/interfaces/IERC20Metadata.sol/IERC20Metadata.json +233 -0
  9. package/artifacts/contracts/interfaces/IERC721Permit.sol/IERC721Permit.json +360 -0
  10. package/artifacts/contracts/interfaces/IMulticall.sol/IMulticall.json +30 -0
  11. package/artifacts/contracts/interfaces/INonfungiblePositionManager.sol/INonfungiblePositionManager.json +998 -0
  12. package/artifacts/contracts/interfaces/INonfungibleTokenPositionDescriptor.sol/INonfungibleTokenPositionDescriptor.json +35 -0
  13. package/artifacts/contracts/interfaces/IPeripheryImmutableState.sol/IPeripheryImmutableState.json +37 -0
  14. package/artifacts/contracts/interfaces/IPeripheryPayments.sol/IPeripheryPayments.json +59 -0
  15. package/artifacts/contracts/interfaces/IPeripheryPaymentsWithFee.sol/IPeripheryPaymentsWithFee.json +120 -0
  16. package/artifacts/contracts/interfaces/IPoolInitializer.sol/IPoolInitializer.json +45 -0
  17. package/artifacts/contracts/interfaces/IQuoter.sol/IQuoter.json +137 -0
  18. package/artifacts/contracts/interfaces/IQuoterV2.sol/IQuoterV2.json +211 -0
  19. package/artifacts/contracts/interfaces/ISelfPermit.sol/ISelfPermit.json +163 -0
  20. package/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json +248 -0
  21. package/artifacts/contracts/interfaces/ITickLens.sol/ITickLens.json +52 -0
  22. package/artifacts/contracts/interfaces/IV3Migrator.sol/IV3Migrator.json +296 -0
  23. package/artifacts/contracts/interfaces/external/IERC1271.sol/IERC1271.json +35 -0
  24. package/artifacts/contracts/interfaces/external/IERC20PermitAllowed.sol/IERC20PermitAllowed.json +59 -0
  25. package/artifacts/contracts/interfaces/external/IWETH9.sol/IWETH9.json +214 -0
  26. package/artifacts/contracts/lens/Quoter.sol/Quoter.json +202 -0
  27. package/artifacts/contracts/lens/QuoterV2.sol/QuoterV2.json +276 -0
  28. package/artifacts/contracts/lens/TickLens.sol/TickLens.json +52 -0
  29. package/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json +101 -0
  30. package/artifacts/contracts/libraries/BytesLib.sol/BytesLib.json +10 -0
  31. package/artifacts/contracts/libraries/CallbackValidation.sol/CallbackValidation.json +10 -0
  32. package/artifacts/contracts/libraries/ChainId.sol/ChainId.json +10 -0
  33. package/artifacts/contracts/libraries/HexStrings.sol/HexStrings.json +10 -0
  34. package/artifacts/contracts/libraries/LiquidityAmounts.sol/LiquidityAmounts.json +10 -0
  35. package/artifacts/contracts/libraries/NFTDescriptor.sol/NFTDescriptor.json +102 -0
  36. package/artifacts/contracts/libraries/NFTSVG.sol/NFTSVG.json +10 -0
  37. package/artifacts/contracts/libraries/OracleLibrary.sol/OracleLibrary.json +10 -0
  38. package/artifacts/contracts/libraries/Path.sol/Path.json +10 -0
  39. package/artifacts/contracts/libraries/PoolAddress.sol/PoolAddress.json +10 -0
  40. package/artifacts/contracts/libraries/PoolTicksCounter.sol/PoolTicksCounter.json +10 -0
  41. package/artifacts/contracts/libraries/PositionKey.sol/PositionKey.json +10 -0
  42. package/artifacts/contracts/libraries/PositionValue.sol/PositionValue.json +10 -0
  43. package/artifacts/contracts/libraries/TokenRatioSortOrder.sol/TokenRatioSortOrder.json +10 -0
  44. package/artifacts/contracts/libraries/TransferHelper.sol/TransferHelper.json +10 -0
  45. package/contracts/base/BlockTimestamp.sol +12 -0
  46. package/contracts/base/ERC721Permit.sol +86 -0
  47. package/contracts/base/LiquidityManagement.sol +90 -0
  48. package/contracts/base/Multicall.sol +28 -0
  49. package/contracts/base/PeripheryImmutableState.sol +18 -0
  50. package/contracts/base/PeripheryPayments.sol +70 -0
  51. package/contracts/base/PeripheryPaymentsWithFee.sol +55 -0
  52. package/contracts/base/PeripheryValidation.sol +11 -0
  53. package/contracts/base/PoolInitializer.sol +32 -0
  54. package/contracts/base/SelfPermit.sol +63 -0
  55. package/contracts/interfaces/IERC20Metadata.sol +18 -0
  56. package/contracts/interfaces/IERC721Permit.sol +32 -0
  57. package/contracts/interfaces/IMulticall.sol +13 -0
  58. package/contracts/interfaces/INonfungiblePositionManager.sol +180 -0
  59. package/contracts/interfaces/INonfungibleTokenPositionDescriptor.sol +17 -0
  60. package/contracts/interfaces/IPeripheryImmutableState.sol +12 -0
  61. package/contracts/interfaces/IPeripheryPayments.sol +28 -0
  62. package/contracts/interfaces/IPeripheryPaymentsWithFee.sol +29 -0
  63. package/contracts/interfaces/IPoolInitializer.sol +22 -0
  64. package/contracts/interfaces/IQuoter.sol +51 -0
  65. package/contracts/interfaces/IQuoterV2.sol +98 -0
  66. package/contracts/interfaces/ISelfPermit.sol +76 -0
  67. package/contracts/interfaces/ISwapRouter.sol +67 -0
  68. package/contracts/interfaces/ITickLens.sol +25 -0
  69. package/contracts/interfaces/IV3Migrator.sol +34 -0
  70. package/contracts/interfaces/external/IERC1271.sol +16 -0
  71. package/contracts/interfaces/external/IERC20PermitAllowed.sol +27 -0
  72. package/contracts/interfaces/external/IWETH9.sol +13 -0
  73. package/contracts/libraries/BytesLib.sol +101 -0
  74. package/contracts/libraries/CallbackValidation.sol +36 -0
  75. package/contracts/libraries/ChainId.sol +13 -0
  76. package/contracts/libraries/HexStrings.sol +29 -0
  77. package/contracts/libraries/LiquidityAmounts.sol +137 -0
  78. package/contracts/libraries/NFTDescriptor.sol +477 -0
  79. package/contracts/libraries/NFTSVG.sol +406 -0
  80. package/contracts/libraries/OracleLibrary.sol +161 -0
  81. package/contracts/libraries/Path.sol +69 -0
  82. package/contracts/libraries/PoolAddress.sol +48 -0
  83. package/contracts/libraries/PoolTicksCounter.sol +97 -0
  84. package/contracts/libraries/PositionKey.sol +13 -0
  85. package/contracts/libraries/PositionValue.sol +167 -0
  86. package/contracts/libraries/TokenRatioSortOrder.sol +12 -0
  87. package/contracts/libraries/TransferHelper.sol +60 -0
  88. package/package.json +68 -0
@@ -0,0 +1,86 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity =0.7.6;
3
+
4
+ import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
5
+ import '@openzeppelin/contracts/utils/Address.sol';
6
+
7
+ import '../libraries/ChainId.sol';
8
+ import '../interfaces/external/IERC1271.sol';
9
+ import '../interfaces/IERC721Permit.sol';
10
+ import './BlockTimestamp.sol';
11
+
12
+ /// @title ERC721 with permit
13
+ /// @notice Nonfungible tokens that support an approve via signature, i.e. permit
14
+ abstract contract ERC721Permit is BlockTimestamp, ERC721, IERC721Permit {
15
+ /// @dev Gets the current nonce for a token ID and then increments it, returning the original value
16
+ function _getAndIncrementNonce(uint256 tokenId) internal virtual returns (uint256);
17
+
18
+ /// @dev The hash of the name used in the permit signature verification
19
+ bytes32 private immutable nameHash;
20
+
21
+ /// @dev The hash of the version string used in the permit signature verification
22
+ bytes32 private immutable versionHash;
23
+
24
+ /// @notice Computes the nameHash and versionHash
25
+ constructor(
26
+ string memory name_,
27
+ string memory symbol_,
28
+ string memory version_
29
+ ) ERC721(name_, symbol_) {
30
+ nameHash = keccak256(bytes(name_));
31
+ versionHash = keccak256(bytes(version_));
32
+ }
33
+
34
+ /// @inheritdoc IERC721Permit
35
+ function DOMAIN_SEPARATOR() public view override returns (bytes32) {
36
+ return
37
+ keccak256(
38
+ abi.encode(
39
+ // keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)')
40
+ 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f,
41
+ nameHash,
42
+ versionHash,
43
+ ChainId.get(),
44
+ address(this)
45
+ )
46
+ );
47
+ }
48
+
49
+ /// @inheritdoc IERC721Permit
50
+ /// @dev Value is equal to keccak256("Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)");
51
+ bytes32 public constant override PERMIT_TYPEHASH =
52
+ 0x49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad;
53
+
54
+ /// @inheritdoc IERC721Permit
55
+ function permit(
56
+ address spender,
57
+ uint256 tokenId,
58
+ uint256 deadline,
59
+ uint8 v,
60
+ bytes32 r,
61
+ bytes32 s
62
+ ) external payable override {
63
+ require(_blockTimestamp() <= deadline, 'Permit expired');
64
+
65
+ bytes32 digest =
66
+ keccak256(
67
+ abi.encodePacked(
68
+ '\x19\x01',
69
+ DOMAIN_SEPARATOR(),
70
+ keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, _getAndIncrementNonce(tokenId), deadline))
71
+ )
72
+ );
73
+ address owner = ownerOf(tokenId);
74
+ require(spender != owner, 'ERC721Permit: approval to current owner');
75
+
76
+ if (Address.isContract(owner)) {
77
+ require(IERC1271(owner).isValidSignature(digest, abi.encodePacked(r, s, v)) == 0x1626ba7e, 'Unauthorized');
78
+ } else {
79
+ address recoveredAddress = ecrecover(digest, v, r, s);
80
+ require(recoveredAddress != address(0), 'Invalid signature');
81
+ require(recoveredAddress == owner, 'Unauthorized');
82
+ }
83
+
84
+ _approve(spender, tokenId);
85
+ }
86
+ }
@@ -0,0 +1,90 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity =0.7.6;
3
+ pragma abicoder v2;
4
+
5
+ import '@huuduynvc/v3-core/contracts/interfaces/IUniswapV3Factory.sol';
6
+ import '@huuduynvc/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';
7
+ import '@huuduynvc/v3-core/contracts/libraries/TickMath.sol';
8
+
9
+ import '../libraries/PoolAddress.sol';
10
+ import '../libraries/CallbackValidation.sol';
11
+ import '../libraries/LiquidityAmounts.sol';
12
+
13
+ import './PeripheryPayments.sol';
14
+ import './PeripheryImmutableState.sol';
15
+
16
+ /// @title Liquidity management functions
17
+ /// @notice Internal functions for safely managing liquidity in Uniswap V3
18
+ abstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {
19
+ struct MintCallbackData {
20
+ PoolAddress.PoolKey poolKey;
21
+ address payer;
22
+ }
23
+
24
+ /// @inheritdoc IUniswapV3MintCallback
25
+ function uniswapV3MintCallback(
26
+ uint256 amount0Owed,
27
+ uint256 amount1Owed,
28
+ bytes calldata data
29
+ ) external override {
30
+ MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));
31
+ CallbackValidation.verifyCallback(factory, decoded.poolKey);
32
+
33
+ if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);
34
+ if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);
35
+ }
36
+
37
+ struct AddLiquidityParams {
38
+ address token0;
39
+ address token1;
40
+ uint24 fee;
41
+ address recipient;
42
+ int24 tickLower;
43
+ int24 tickUpper;
44
+ uint256 amount0Desired;
45
+ uint256 amount1Desired;
46
+ uint256 amount0Min;
47
+ uint256 amount1Min;
48
+ }
49
+
50
+ /// @notice Add liquidity to an initialized pool
51
+ function addLiquidity(AddLiquidityParams memory params)
52
+ internal
53
+ returns (
54
+ uint128 liquidity,
55
+ uint256 amount0,
56
+ uint256 amount1,
57
+ IUniswapV3Pool pool
58
+ )
59
+ {
60
+ PoolAddress.PoolKey memory poolKey =
61
+ PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});
62
+
63
+ pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
64
+
65
+ // compute the liquidity amount
66
+ {
67
+ (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();
68
+ uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);
69
+ uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);
70
+
71
+ liquidity = LiquidityAmounts.getLiquidityForAmounts(
72
+ sqrtPriceX96,
73
+ sqrtRatioAX96,
74
+ sqrtRatioBX96,
75
+ params.amount0Desired,
76
+ params.amount1Desired
77
+ );
78
+ }
79
+
80
+ (amount0, amount1) = pool.mint(
81
+ params.recipient,
82
+ params.tickLower,
83
+ params.tickUpper,
84
+ liquidity,
85
+ abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))
86
+ );
87
+
88
+ require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');
89
+ }
90
+ }
@@ -0,0 +1,28 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity =0.7.6;
3
+ pragma abicoder v2;
4
+
5
+ import '../interfaces/IMulticall.sol';
6
+
7
+ /// @title Multicall
8
+ /// @notice Enables calling multiple methods in a single call to the contract
9
+ abstract contract Multicall is IMulticall {
10
+ /// @inheritdoc IMulticall
11
+ function multicall(bytes[] calldata data) public payable override returns (bytes[] memory results) {
12
+ results = new bytes[](data.length);
13
+ for (uint256 i = 0; i < data.length; i++) {
14
+ (bool success, bytes memory result) = address(this).delegatecall(data[i]);
15
+
16
+ if (!success) {
17
+ // Next 5 lines from https://ethereum.stackexchange.com/a/83577
18
+ if (result.length < 68) revert();
19
+ assembly {
20
+ result := add(result, 0x04)
21
+ }
22
+ revert(abi.decode(result, (string)));
23
+ }
24
+
25
+ results[i] = result;
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,18 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity =0.7.6;
3
+
4
+ import '../interfaces/IPeripheryImmutableState.sol';
5
+
6
+ /// @title Immutable state
7
+ /// @notice Immutable state used by periphery contracts
8
+ abstract contract PeripheryImmutableState is IPeripheryImmutableState {
9
+ /// @inheritdoc IPeripheryImmutableState
10
+ address public immutable override factory;
11
+ /// @inheritdoc IPeripheryImmutableState
12
+ address public immutable override WETH9;
13
+
14
+ constructor(address _factory, address _WETH9) {
15
+ factory = _factory;
16
+ WETH9 = _WETH9;
17
+ }
18
+ }
@@ -0,0 +1,70 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity >=0.7.5;
3
+
4
+ import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
5
+
6
+ import '../interfaces/IPeripheryPayments.sol';
7
+ import '../interfaces/external/IWETH9.sol';
8
+
9
+ import '../libraries/TransferHelper.sol';
10
+
11
+ import './PeripheryImmutableState.sol';
12
+
13
+ abstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {
14
+ receive() external payable {
15
+ require(msg.sender == WETH9, 'Not WETH9');
16
+ }
17
+
18
+ /// @inheritdoc IPeripheryPayments
19
+ function unwrapWETH9(uint256 amountMinimum, address recipient) public payable override {
20
+ uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));
21
+ require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');
22
+
23
+ if (balanceWETH9 > 0) {
24
+ IWETH9(WETH9).withdraw(balanceWETH9);
25
+ TransferHelper.safeTransferETH(recipient, balanceWETH9);
26
+ }
27
+ }
28
+
29
+ /// @inheritdoc IPeripheryPayments
30
+ function sweepToken(
31
+ address token,
32
+ uint256 amountMinimum,
33
+ address recipient
34
+ ) public payable override {
35
+ uint256 balanceToken = IERC20(token).balanceOf(address(this));
36
+ require(balanceToken >= amountMinimum, 'Insufficient token');
37
+
38
+ if (balanceToken > 0) {
39
+ TransferHelper.safeTransfer(token, recipient, balanceToken);
40
+ }
41
+ }
42
+
43
+ /// @inheritdoc IPeripheryPayments
44
+ function refundETH() external payable override {
45
+ if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);
46
+ }
47
+
48
+ /// @param token The token to pay
49
+ /// @param payer The entity that must pay
50
+ /// @param recipient The entity that will receive payment
51
+ /// @param value The amount to pay
52
+ function pay(
53
+ address token,
54
+ address payer,
55
+ address recipient,
56
+ uint256 value
57
+ ) internal {
58
+ if (token == WETH9 && address(this).balance >= value) {
59
+ // pay with WETH9
60
+ IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay
61
+ IWETH9(WETH9).transfer(recipient, value);
62
+ } else if (payer == address(this)) {
63
+ // pay with tokens already in the contract (for the exact input multihop case)
64
+ TransferHelper.safeTransfer(token, recipient, value);
65
+ } else {
66
+ // pull payment
67
+ TransferHelper.safeTransferFrom(token, payer, recipient, value);
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,55 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity >=0.7.5;
3
+
4
+ import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
5
+ import '@huuduynvc/v3-core/contracts/libraries/LowGasSafeMath.sol';
6
+
7
+ import './PeripheryPayments.sol';
8
+ import '../interfaces/IPeripheryPaymentsWithFee.sol';
9
+
10
+ import '../interfaces/external/IWETH9.sol';
11
+ import '../libraries/TransferHelper.sol';
12
+
13
+ abstract contract PeripheryPaymentsWithFee is PeripheryPayments, IPeripheryPaymentsWithFee {
14
+ using LowGasSafeMath for uint256;
15
+
16
+ /// @inheritdoc IPeripheryPaymentsWithFee
17
+ function unwrapWETH9WithFee(
18
+ uint256 amountMinimum,
19
+ address recipient,
20
+ uint256 feeBips,
21
+ address feeRecipient
22
+ ) public payable override {
23
+ require(feeBips > 0 && feeBips <= 100);
24
+
25
+ uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));
26
+ require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');
27
+
28
+ if (balanceWETH9 > 0) {
29
+ IWETH9(WETH9).withdraw(balanceWETH9);
30
+ uint256 feeAmount = balanceWETH9.mul(feeBips) / 10_000;
31
+ if (feeAmount > 0) TransferHelper.safeTransferETH(feeRecipient, feeAmount);
32
+ TransferHelper.safeTransferETH(recipient, balanceWETH9 - feeAmount);
33
+ }
34
+ }
35
+
36
+ /// @inheritdoc IPeripheryPaymentsWithFee
37
+ function sweepTokenWithFee(
38
+ address token,
39
+ uint256 amountMinimum,
40
+ address recipient,
41
+ uint256 feeBips,
42
+ address feeRecipient
43
+ ) public payable override {
44
+ require(feeBips > 0 && feeBips <= 100);
45
+
46
+ uint256 balanceToken = IERC20(token).balanceOf(address(this));
47
+ require(balanceToken >= amountMinimum, 'Insufficient token');
48
+
49
+ if (balanceToken > 0) {
50
+ uint256 feeAmount = balanceToken.mul(feeBips) / 10_000;
51
+ if (feeAmount > 0) TransferHelper.safeTransfer(token, feeRecipient, feeAmount);
52
+ TransferHelper.safeTransfer(token, recipient, balanceToken - feeAmount);
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,11 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity =0.7.6;
3
+
4
+ import './BlockTimestamp.sol';
5
+
6
+ abstract contract PeripheryValidation is BlockTimestamp {
7
+ modifier checkDeadline(uint256 deadline) {
8
+ require(_blockTimestamp() <= deadline, 'Transaction too old');
9
+ _;
10
+ }
11
+ }
@@ -0,0 +1,32 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity =0.7.6;
3
+
4
+ import '@huuduynvc/v3-core/contracts/interfaces/IUniswapV3Factory.sol';
5
+ import '@huuduynvc/v3-core/contracts/interfaces/IUniswapV3Pool.sol';
6
+
7
+ import './PeripheryImmutableState.sol';
8
+ import '../interfaces/IPoolInitializer.sol';
9
+
10
+ /// @title Creates and initializes V3 Pools
11
+ abstract contract PoolInitializer is IPoolInitializer, PeripheryImmutableState {
12
+ /// @inheritdoc IPoolInitializer
13
+ function createAndInitializePoolIfNecessary(
14
+ address token0,
15
+ address token1,
16
+ uint24 fee,
17
+ uint160 sqrtPriceX96
18
+ ) external payable override returns (address pool) {
19
+ require(token0 < token1);
20
+ pool = IUniswapV3Factory(factory).getPool(token0, token1, fee);
21
+
22
+ if (pool == address(0)) {
23
+ pool = IUniswapV3Factory(factory).createPool(token0, token1, fee);
24
+ IUniswapV3Pool(pool).initialize(sqrtPriceX96);
25
+ } else {
26
+ (uint160 sqrtPriceX96Existing, , , , , , ) = IUniswapV3Pool(pool).slot0();
27
+ if (sqrtPriceX96Existing == 0) {
28
+ IUniswapV3Pool(pool).initialize(sqrtPriceX96);
29
+ }
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,63 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity >=0.5.0;
3
+
4
+ import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
5
+ import '@openzeppelin/contracts/drafts/IERC20Permit.sol';
6
+
7
+ import '../interfaces/ISelfPermit.sol';
8
+ import '../interfaces/external/IERC20PermitAllowed.sol';
9
+
10
+ /// @title Self Permit
11
+ /// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route
12
+ /// @dev These functions are expected to be embedded in multicalls to allow EOAs to approve a contract and call a function
13
+ /// that requires an approval in a single transaction.
14
+ abstract contract SelfPermit is ISelfPermit {
15
+ /// @inheritdoc ISelfPermit
16
+ function selfPermit(
17
+ address token,
18
+ uint256 value,
19
+ uint256 deadline,
20
+ uint8 v,
21
+ bytes32 r,
22
+ bytes32 s
23
+ ) public payable override {
24
+ IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s);
25
+ }
26
+
27
+ /// @inheritdoc ISelfPermit
28
+ function selfPermitIfNecessary(
29
+ address token,
30
+ uint256 value,
31
+ uint256 deadline,
32
+ uint8 v,
33
+ bytes32 r,
34
+ bytes32 s
35
+ ) external payable override {
36
+ if (IERC20(token).allowance(msg.sender, address(this)) < value) selfPermit(token, value, deadline, v, r, s);
37
+ }
38
+
39
+ /// @inheritdoc ISelfPermit
40
+ function selfPermitAllowed(
41
+ address token,
42
+ uint256 nonce,
43
+ uint256 expiry,
44
+ uint8 v,
45
+ bytes32 r,
46
+ bytes32 s
47
+ ) public payable override {
48
+ IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s);
49
+ }
50
+
51
+ /// @inheritdoc ISelfPermit
52
+ function selfPermitAllowedIfNecessary(
53
+ address token,
54
+ uint256 nonce,
55
+ uint256 expiry,
56
+ uint8 v,
57
+ bytes32 r,
58
+ bytes32 s
59
+ ) external payable override {
60
+ if (IERC20(token).allowance(msg.sender, address(this)) < type(uint256).max)
61
+ selfPermitAllowed(token, nonce, expiry, v, r, s);
62
+ }
63
+ }
@@ -0,0 +1,18 @@
1
+ // SPDX-License-Identifier: UNLICENSED
2
+ pragma solidity ^0.7.0;
3
+
4
+ import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
5
+
6
+ /// @title IERC20Metadata
7
+ /// @title Interface for ERC20 Metadata
8
+ /// @notice Extension to IERC20 that includes token metadata
9
+ interface IERC20Metadata is IERC20 {
10
+ /// @return The name of the token
11
+ function name() external view returns (string memory);
12
+
13
+ /// @return The symbol of the token
14
+ function symbol() external view returns (string memory);
15
+
16
+ /// @return The number of decimal places the token has
17
+ function decimals() external view returns (uint8);
18
+ }
@@ -0,0 +1,32 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity >=0.7.5;
3
+
4
+ import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
5
+
6
+ /// @title ERC721 with permit
7
+ /// @notice Extension to ERC721 that includes a permit function for signature based approvals
8
+ interface IERC721Permit is IERC721 {
9
+ /// @notice The permit typehash used in the permit signature
10
+ /// @return The typehash for the permit
11
+ function PERMIT_TYPEHASH() external pure returns (bytes32);
12
+
13
+ /// @notice The domain separator used in the permit signature
14
+ /// @return The domain seperator used in encoding of permit signature
15
+ function DOMAIN_SEPARATOR() external view returns (bytes32);
16
+
17
+ /// @notice Approve of a specific token ID for spending by spender via signature
18
+ /// @param spender The account that is being approved
19
+ /// @param tokenId The ID of the token that is being approved for spending
20
+ /// @param deadline The deadline timestamp by which the call must be mined for the approve to work
21
+ /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
22
+ /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
23
+ /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
24
+ function permit(
25
+ address spender,
26
+ uint256 tokenId,
27
+ uint256 deadline,
28
+ uint8 v,
29
+ bytes32 r,
30
+ bytes32 s
31
+ ) external payable;
32
+ }
@@ -0,0 +1,13 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity >=0.7.5;
3
+ pragma abicoder v2;
4
+
5
+ /// @title Multicall interface
6
+ /// @notice Enables calling multiple methods in a single call to the contract
7
+ interface IMulticall {
8
+ /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed
9
+ /// @dev The `msg.value` should not be trusted for any method callable from multicall.
10
+ /// @param data The encoded function data for each of the calls to make to this contract
11
+ /// @return results The results from each of the calls passed in via data
12
+ function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
13
+ }