@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.
- package/LICENSE +339 -0
- package/README.md +52 -0
- package/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json +1230 -0
- package/artifacts/contracts/NonfungibleTokenPositionDescriptor.sol/NonfungibleTokenPositionDescriptor.json +161 -0
- package/artifacts/contracts/SwapRouter.sol/SwapRouter.json +574 -0
- package/artifacts/contracts/V3Migrator.sol/V3Migrator.json +360 -0
- package/artifacts/contracts/examples/PairFlash.sol/PairFlash.json +196 -0
- package/artifacts/contracts/interfaces/IERC20Metadata.sol/IERC20Metadata.json +233 -0
- package/artifacts/contracts/interfaces/IERC721Permit.sol/IERC721Permit.json +360 -0
- package/artifacts/contracts/interfaces/IMulticall.sol/IMulticall.json +30 -0
- package/artifacts/contracts/interfaces/INonfungiblePositionManager.sol/INonfungiblePositionManager.json +998 -0
- package/artifacts/contracts/interfaces/INonfungibleTokenPositionDescriptor.sol/INonfungibleTokenPositionDescriptor.json +35 -0
- package/artifacts/contracts/interfaces/IPeripheryImmutableState.sol/IPeripheryImmutableState.json +37 -0
- package/artifacts/contracts/interfaces/IPeripheryPayments.sol/IPeripheryPayments.json +59 -0
- package/artifacts/contracts/interfaces/IPeripheryPaymentsWithFee.sol/IPeripheryPaymentsWithFee.json +120 -0
- package/artifacts/contracts/interfaces/IPoolInitializer.sol/IPoolInitializer.json +45 -0
- package/artifacts/contracts/interfaces/IQuoter.sol/IQuoter.json +137 -0
- package/artifacts/contracts/interfaces/IQuoterV2.sol/IQuoterV2.json +211 -0
- package/artifacts/contracts/interfaces/ISelfPermit.sol/ISelfPermit.json +163 -0
- package/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json +248 -0
- package/artifacts/contracts/interfaces/ITickLens.sol/ITickLens.json +52 -0
- package/artifacts/contracts/interfaces/IV3Migrator.sol/IV3Migrator.json +296 -0
- package/artifacts/contracts/interfaces/external/IERC1271.sol/IERC1271.json +35 -0
- package/artifacts/contracts/interfaces/external/IERC20PermitAllowed.sol/IERC20PermitAllowed.json +59 -0
- package/artifacts/contracts/interfaces/external/IWETH9.sol/IWETH9.json +214 -0
- package/artifacts/contracts/lens/Quoter.sol/Quoter.json +202 -0
- package/artifacts/contracts/lens/QuoterV2.sol/QuoterV2.json +276 -0
- package/artifacts/contracts/lens/TickLens.sol/TickLens.json +52 -0
- package/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json +101 -0
- package/artifacts/contracts/libraries/BytesLib.sol/BytesLib.json +10 -0
- package/artifacts/contracts/libraries/CallbackValidation.sol/CallbackValidation.json +10 -0
- package/artifacts/contracts/libraries/ChainId.sol/ChainId.json +10 -0
- package/artifacts/contracts/libraries/HexStrings.sol/HexStrings.json +10 -0
- package/artifacts/contracts/libraries/LiquidityAmounts.sol/LiquidityAmounts.json +10 -0
- package/artifacts/contracts/libraries/NFTDescriptor.sol/NFTDescriptor.json +102 -0
- package/artifacts/contracts/libraries/NFTSVG.sol/NFTSVG.json +10 -0
- package/artifacts/contracts/libraries/OracleLibrary.sol/OracleLibrary.json +10 -0
- package/artifacts/contracts/libraries/Path.sol/Path.json +10 -0
- package/artifacts/contracts/libraries/PoolAddress.sol/PoolAddress.json +10 -0
- package/artifacts/contracts/libraries/PoolTicksCounter.sol/PoolTicksCounter.json +10 -0
- package/artifacts/contracts/libraries/PositionKey.sol/PositionKey.json +10 -0
- package/artifacts/contracts/libraries/PositionValue.sol/PositionValue.json +10 -0
- package/artifacts/contracts/libraries/TokenRatioSortOrder.sol/TokenRatioSortOrder.json +10 -0
- package/artifacts/contracts/libraries/TransferHelper.sol/TransferHelper.json +10 -0
- package/contracts/base/BlockTimestamp.sol +12 -0
- package/contracts/base/ERC721Permit.sol +86 -0
- package/contracts/base/LiquidityManagement.sol +90 -0
- package/contracts/base/Multicall.sol +28 -0
- package/contracts/base/PeripheryImmutableState.sol +18 -0
- package/contracts/base/PeripheryPayments.sol +70 -0
- package/contracts/base/PeripheryPaymentsWithFee.sol +55 -0
- package/contracts/base/PeripheryValidation.sol +11 -0
- package/contracts/base/PoolInitializer.sol +32 -0
- package/contracts/base/SelfPermit.sol +63 -0
- package/contracts/interfaces/IERC20Metadata.sol +18 -0
- package/contracts/interfaces/IERC721Permit.sol +32 -0
- package/contracts/interfaces/IMulticall.sol +13 -0
- package/contracts/interfaces/INonfungiblePositionManager.sol +180 -0
- package/contracts/interfaces/INonfungibleTokenPositionDescriptor.sol +17 -0
- package/contracts/interfaces/IPeripheryImmutableState.sol +12 -0
- package/contracts/interfaces/IPeripheryPayments.sol +28 -0
- package/contracts/interfaces/IPeripheryPaymentsWithFee.sol +29 -0
- package/contracts/interfaces/IPoolInitializer.sol +22 -0
- package/contracts/interfaces/IQuoter.sol +51 -0
- package/contracts/interfaces/IQuoterV2.sol +98 -0
- package/contracts/interfaces/ISelfPermit.sol +76 -0
- package/contracts/interfaces/ISwapRouter.sol +67 -0
- package/contracts/interfaces/ITickLens.sol +25 -0
- package/contracts/interfaces/IV3Migrator.sol +34 -0
- package/contracts/interfaces/external/IERC1271.sol +16 -0
- package/contracts/interfaces/external/IERC20PermitAllowed.sol +27 -0
- package/contracts/interfaces/external/IWETH9.sol +13 -0
- package/contracts/libraries/BytesLib.sol +101 -0
- package/contracts/libraries/CallbackValidation.sol +36 -0
- package/contracts/libraries/ChainId.sol +13 -0
- package/contracts/libraries/HexStrings.sol +29 -0
- package/contracts/libraries/LiquidityAmounts.sol +137 -0
- package/contracts/libraries/NFTDescriptor.sol +477 -0
- package/contracts/libraries/NFTSVG.sol +406 -0
- package/contracts/libraries/OracleLibrary.sol +161 -0
- package/contracts/libraries/Path.sol +69 -0
- package/contracts/libraries/PoolAddress.sol +48 -0
- package/contracts/libraries/PoolTicksCounter.sol +97 -0
- package/contracts/libraries/PositionKey.sol +13 -0
- package/contracts/libraries/PositionValue.sol +167 -0
- package/contracts/libraries/TokenRatioSortOrder.sol +12 -0
- package/contracts/libraries/TransferHelper.sol +60 -0
- 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
|
+
}
|