punkkit-sdk 1.0.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 (94) hide show
  1. package/.env +47 -0
  2. package/.gitmodules +3 -0
  3. package/README.md +158 -0
  4. package/config/auction.config.ts +40 -0
  5. package/config/env.config.ts +204 -0
  6. package/config/uniswap.config.ts +107 -0
  7. package/config/voucher.config.ts +10 -0
  8. package/contracts/MutiVoucher.sol +78 -0
  9. package/contracts/auction/ChainXAuction.sol +177 -0
  10. package/contracts/auction/ChainXAuctionV2.sol +672 -0
  11. package/contracts/auction/ChainXWrappedETH.sol +80 -0
  12. package/contracts/auction/ChainYLiquidityManager.sol +57 -0
  13. package/contracts/auction/ChainYShadowETH.sol +148 -0
  14. package/contracts/auction/ChainYVault.sol +195 -0
  15. package/contracts/auction/ChainYVaultCoinbase.sol +276 -0
  16. package/contracts/auction/ChainYVaultV2.sol +318 -0
  17. package/contracts/auction/coinbase-and-stake/README.md +55 -0
  18. package/contracts/auction/coinbase-and-stake/coinbase.sol +142 -0
  19. package/contracts/auction/coinbase-and-stake/invokeCoinbase.sol +159 -0
  20. package/contracts/auction/coinbase-and-stake/invokeStake.sol +82 -0
  21. package/contracts/auction/coinbase-and-stake/stake.sol +92 -0
  22. package/contracts/auction/interfaces/IUniswapV2Factory.sol +15 -0
  23. package/contracts/auction/interfaces/IUniswapV2Pair.sol +53 -0
  24. package/contracts/auction/interfaces/IUniswapV2Router02.sol +25 -0
  25. package/contracts/auction/interfaces/IUnlockStrategy.sol +18 -0
  26. package/contracts/auction/libraries/EventParser.sol +32 -0
  27. package/contracts/auction/libraries/TransactionParser.sol +70 -0
  28. package/contracts/auction/strategies/MatchResultWithdrawnStrategy.sol +33 -0
  29. package/contracts/auction/utils/BytesLib.sol +180 -0
  30. package/contracts/auction/utils/RLPReader.sol +355 -0
  31. package/contracts/uniswap/Create2.sol +80 -0
  32. package/contracts/uniswap/DynamicFee.sol +100 -0
  33. package/contracts/uniswap/Example.sol +35 -0
  34. package/contracts/uniswap/HookMiner.sol +52 -0
  35. package/contracts/uniswap/LimitOrder.sol +486 -0
  36. package/contracts/uniswap/LiquidPool.sol +179 -0
  37. package/contracts/uniswap/MockERC20.sol +20 -0
  38. package/hardhat.config.ts +35 -0
  39. package/ignition/modules/LimitOrder.ts +33 -0
  40. package/package.json +32 -0
  41. package/scripts/auction/deploy.ts +23 -0
  42. package/scripts/auction/deployCoinbase.ts +21 -0
  43. package/scripts/auction/deployXAuction.ts +23 -0
  44. package/scripts/auction/deployYVault.ts +22 -0
  45. package/scripts/deploy_voucher.ts +20 -0
  46. package/scripts/uniswap/deploy/deploy.ts +65 -0
  47. package/scripts/uniswap/deploy/deploy_create2.ts +11 -0
  48. package/scripts/uniswap/deploy/deploy_example.ts +35 -0
  49. package/scripts/uniswap/deploy/deploy_hooks.ts +74 -0
  50. package/scripts/uniswap/deploy/deploy_mockERC20.ts +42 -0
  51. package/scripts/uniswap/deploy/help.ts +96 -0
  52. package/scripts/uniswap/deploy/init.ts +70 -0
  53. package/src/auction/chainXAuction.ts +209 -0
  54. package/src/auction/chainYVault.ts +153 -0
  55. package/src/auction/event.ts +19 -0
  56. package/src/auction/serialize.ts +162 -0
  57. package/src/auction/type.ts +71 -0
  58. package/src/lib/signer.ts +20 -0
  59. package/src/lib/unlock.ts +14 -0
  60. package/src/uniswap/1-marketprice/addLiquidity.ts +80 -0
  61. package/src/uniswap/1-marketprice/removeLiquidity.ts +63 -0
  62. package/src/uniswap/1-marketprice/swap.ts +100 -0
  63. package/src/uniswap/2-limitorder/kill.ts +70 -0
  64. package/src/uniswap/2-limitorder/place.ts +93 -0
  65. package/src/uniswap/2-limitorder/withdraw.ts +78 -0
  66. package/src/uniswap/3-dynamicfee/dynamicfee.ts +321 -0
  67. package/src/uniswap/lib/ERC20.ts +49 -0
  68. package/src/uniswap/lib/contract.ts +18 -0
  69. package/src/uniswap/lib/limitOrder.ts +40 -0
  70. package/src/uniswap/lib/liqCalculation.ts +152 -0
  71. package/src/uniswap/lib/listen.ts +57 -0
  72. package/src/uniswap/lib/pool.ts +62 -0
  73. package/src/uniswap/lib/swap.ts +8 -0
  74. package/src/uniswap/lib/types.ts +21 -0
  75. package/src/uniswap/lib/utils.ts +26 -0
  76. package/src/uniswap/playgroud/abiencode.ts +21 -0
  77. package/src/uniswap/playgroud/amount0.ts +47 -0
  78. package/src/uniswap/playgroud/errordecode.ts +54 -0
  79. package/src/uniswap/playgroud/errorsigs.ts +86 -0
  80. package/src/voucher.ts +122 -0
  81. package/test/auction/ChainXAuctionV2.test.ts +265 -0
  82. package/test/auction/ChainYVaultV2.test.js +163 -0
  83. package/test/auction/ChainYVaultV2.test.ts +183 -0
  84. package/test/auction/auction.test.ts +106 -0
  85. package/test/connect_punk.test.ts +26 -0
  86. package/test/create2.test.ts +44 -0
  87. package/test/normal.ts +43 -0
  88. package/test/test-config.ts +18 -0
  89. package/test/uniswap/example.test.ts +62 -0
  90. package/test/uniswap/limitOrder.test.ts +184 -0
  91. package/test/uniswap/mockERC20.test.ts +142 -0
  92. package/test/voucher_hardhat.test.ts +120 -0
  93. package/test/voucher_punk.test.ts +83 -0
  94. package/tsconfig.json +11 -0
@@ -0,0 +1,179 @@
1
+ // SPDX-License-Identifier: UNLICENSED
2
+ pragma solidity ^0.8.20;
3
+
4
+ import {IPoolManager} from '@uniswap/v4-core/src/interfaces/IPoolManager.sol';
5
+ import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
6
+ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
7
+ import {PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
8
+ import {BalanceDelta} from '@uniswap/v4-core/src/PoolManager.sol';
9
+ import {IUnlockCallback} from '@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol';
10
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
11
+ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
12
+ import {CurrencyDelta, Currency} from '@uniswap/v4-core/src/libraries/CurrencyDelta.sol';
13
+ import {TickMath} from '@uniswap/v4-core/src/libraries/TickMath.sol';
14
+ import {ModifyLiquidityParams, SwapParams} from "@uniswap/v4-core/src/types/PoolOperation.sol";
15
+
16
+
17
+ contract LiquidPool is IUnlockCallback {
18
+ using SafeERC20 for IERC20;
19
+ using CurrencyDelta for Currency;
20
+ using StateLibrary for IPoolManager;
21
+ using PoolIdLibrary for PoolKey;
22
+
23
+ bytes4 constant FUNCSIG_LIQUIDITY = 0x00000001;
24
+ bytes4 constant FUNCSIG_SWAP = 0x00000002;
25
+ bytes4 constant FUNCSIG_DONATE = 0x00000003;
26
+
27
+ struct LiquidityParams {
28
+ int24 tickLower;
29
+ int24 tickUpper;
30
+ int256 liquidityDelta;
31
+ }
32
+
33
+ IPoolManager public immutable poolManager;
34
+ PoolKey key;
35
+
36
+ mapping(address => BalanceDelta) rewards;
37
+
38
+ error InvalidFuncSig();
39
+
40
+ constructor(IPoolManager _poolManager, PoolKey memory _key) {
41
+ poolManager = _poolManager;
42
+ key = _key;
43
+ }
44
+
45
+ function getSlot0()
46
+ public
47
+ view
48
+ returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee)
49
+ {
50
+ return poolManager.getSlot0(key.toId());
51
+ }
52
+
53
+ function addLiquidity(
54
+ LiquidityParams calldata params,
55
+ bytes calldata hookData
56
+ ) external {
57
+ ModifyLiquidityParams memory positionParams = ModifyLiquidityParams({
58
+ tickLower: params.tickLower,
59
+ tickUpper: params.tickUpper,
60
+ liquidityDelta: params.liquidityDelta,
61
+ salt: bytes32(uint256(uint160(msg.sender)))
62
+ });
63
+
64
+ _unlock(FUNCSIG_LIQUIDITY, abi.encode(positionParams, hookData));
65
+ /*
66
+ poolManager.unlock(
67
+ abi.encodeCall(this.addLiquidity, (positionParams, hookData))
68
+ );*/
69
+ }
70
+
71
+ function executeSwap(
72
+ SwapParams memory params,
73
+ bytes calldata hookData
74
+ ) external {
75
+ _unlock(FUNCSIG_SWAP, abi.encode(params, hookData));
76
+ /*
77
+ poolManager.unlock(
78
+ abi.encodeCall(this.executeSwap, (params, hookData))
79
+ );*/
80
+ }
81
+
82
+ function donate(
83
+ uint256 amount0,
84
+ uint256 amount1,
85
+ bytes calldata hookData
86
+ ) external {
87
+ _unlock(FUNCSIG_DONATE, abi.encode(amount0, amount1, hookData));
88
+ /*
89
+ poolManager.unlock(
90
+ abi.encodeCall(this.donate, (amount0, amount1, hookData))
91
+ );*/
92
+ }
93
+
94
+ function _unlock(
95
+ bytes4 funcSig,
96
+ bytes memory args
97
+ ) private {
98
+ poolManager.unlock(abi.encode(funcSig, msg.sender, args));
99
+ }
100
+
101
+ function unlockCallback(bytes calldata data) external override returns (bytes memory) {
102
+ (bytes4 funcSig, address recipient, bytes memory args) = abi.decode(data, (bytes4, address, bytes));
103
+
104
+ if (funcSig == FUNCSIG_LIQUIDITY) {
105
+ _handleLiquidity(args, recipient);
106
+ } else if (funcSig == FUNCSIG_SWAP) {
107
+ _handleSwap(args, recipient);
108
+ } else if (funcSig == FUNCSIG_DONATE) {
109
+ _handleDonate(args, recipient);
110
+ } else{
111
+ revert InvalidFuncSig();
112
+ }
113
+
114
+ return bytes("");
115
+ }
116
+
117
+ function _handleLiquidity(bytes memory args, address recipient) private {
118
+ (ModifyLiquidityParams memory positionParams, bytes memory hookData) =
119
+ abi.decode(args, (ModifyLiquidityParams, bytes));
120
+
121
+ (BalanceDelta delta, BalanceDelta fees) = poolManager.modifyLiquidity(key, positionParams, hookData);
122
+
123
+ rewards[recipient] = rewards[recipient] + fees;
124
+
125
+ _settleCurrencyBalance(key.currency0, recipient, delta.amount0());
126
+ _settleCurrencyBalance(key.currency1, recipient, delta.amount1());
127
+ }
128
+
129
+ function _handleSwap(bytes memory args, address recipient) private {
130
+ (SwapParams memory swapParams, bytes memory hookData) = abi.decode(args, (SwapParams, bytes));
131
+
132
+ BalanceDelta delta = poolManager.swap(key, swapParams, hookData);
133
+
134
+ _settleCurrencyBalance(key.currency0, recipient, delta.amount0());
135
+ _settleCurrencyBalance(key.currency1, recipient, delta.amount1());
136
+ }
137
+
138
+ function _handleDonate(bytes memory args, address recipient) private {
139
+ (uint256 address0, uint256 address1, bytes memory hookData) = abi.decode(args, (uint256, uint256, bytes));
140
+
141
+ BalanceDelta delta = poolManager.donate(key, address0, address1, hookData);
142
+
143
+ _settleCurrencyBalance(key.currency0, recipient, delta.amount0());
144
+ _settleCurrencyBalance(key.currency1, recipient, delta.amount1());
145
+ }
146
+
147
+ // [Mark] ref: https://learnblockchain.cn/article/6984
148
+ /*
149
+ * 根据 poolManager 返回的余额变动 deltaAmount,把资金在池(poolManager)和调用者/接收者(recipient)之间结算清算
150
+ */
151
+ function _settleCurrencyBalance(
152
+ Currency currency,
153
+ address recipient,
154
+ int128 deltaAmount
155
+ ) private {
156
+ if (deltaAmount > 0) {
157
+ // send deltaAmount of token to recipient
158
+ poolManager.take(currency, recipient, uint128(deltaAmount));
159
+ } else if (deltaAmount < 0) {
160
+ uint128 amount = uint128(-deltaAmount);
161
+ // isAdressZero() checks if the currency is the native Ethereum token (ETH)
162
+ if (currency.isAddressZero()) {
163
+ // ETH don't need call ERC20 interface to transfer.
164
+ currency.transfer(address(poolManager), amount);
165
+ // todo: is {value: uint128(deltaAmount)} correct?
166
+ poolManager.settle{value: uint128(deltaAmount)}();
167
+ } else {
168
+ IERC20(Currency.unwrap(currency)).safeTransferFrom(
169
+ recipient,
170
+ address(this),
171
+ amount
172
+ );
173
+ poolManager.sync(currency);
174
+ currency.transfer(address(poolManager), amount);
175
+ poolManager.settle();
176
+ }
177
+ }
178
+ }
179
+ }
@@ -0,0 +1,20 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5
+
6
+ contract MockERC20 is ERC20 {
7
+ constructor(
8
+ string memory name_,
9
+ string memory symbol_,
10
+ uint256 initialSupply
11
+ ) ERC20(name_, symbol_) {
12
+ _mint(msg.sender, initialSupply);
13
+ }
14
+
15
+ function mint(address to , uint256 amount) external {
16
+ _mint(to, amount);
17
+ }
18
+
19
+
20
+ }
@@ -0,0 +1,35 @@
1
+ import type { HardhatUserConfig } from "hardhat/config";
2
+ import "@nomiclabs/hardhat-ethers" // ethers v5, conflict with
3
+ import "@nomicfoundation/hardhat-chai-matchers"; // Test chai matchers
4
+ import * as dotenv from "dotenv";
5
+
6
+ // 加载环境变量
7
+ dotenv.config();
8
+
9
+ const config: HardhatUserConfig = {
10
+ networks: {
11
+ punk: {
12
+ url: process.env.RPC_URL || "http://127.0.0.1:8545",
13
+ accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
14
+ }
15
+ },
16
+ solidity: {
17
+ version: "0.8.26",
18
+ settings: {
19
+ evmVersion: "cancun",
20
+ optimizer: {
21
+ enabled: true,
22
+ runs: 200
23
+ },
24
+ viaIR: true
25
+ }
26
+ },
27
+ paths: {
28
+ sources: "./contracts",
29
+ tests: "./test",
30
+ cache: "./cache",
31
+ artifacts: "./artifacts"
32
+ },
33
+ };
34
+
35
+ export default config;
@@ -0,0 +1,33 @@
1
+ import { ethers } from "hardhat";
2
+ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
3
+ import { CONTRACT_ADDRESSES, CONTRACTS } from "../../config/uniswap.config";
4
+
5
+ function encoder(types: string[], values: any[]): string {
6
+ const abiCoder = ethers.AbiCoder.defaultAbiCoder();
7
+ const encodedParams = abiCoder.encode(types, values);
8
+ return encodedParams.slice(2);
9
+ }
10
+
11
+ // ref: https://hardhat.org/ignition/docs/guides/create2
12
+ // use "@nomicfoundation/hardhat-ignition-ethers" in config
13
+ // npx hardhat ignition deploy ignition/modules/LimitOrder.ts --strategy create2
14
+ export default buildModule("LimitOrder", (m) => {
15
+ // Load the contract artifact
16
+ const contractArtifact = CONTRACTS["LimitOrder"];
17
+ const types = ["address"];
18
+ const params = [CONTRACT_ADDRESSES.PoolManager];
19
+ const artifact = {
20
+ _format: "hh-sol-artifact-1",
21
+ contractName: "LimitOrder",
22
+ sourceName: "contracts/LimitOrder.sol",
23
+ abi: contractArtifact.abi, // Populate with ABI array
24
+ bytecode: contractArtifact.bytecode.object,
25
+ deployedBytecode: contractArtifact.bytecode.object,
26
+ linkReferences: {},
27
+ deployedLinkReferences: {},
28
+ };
29
+
30
+ // Deploy the contract
31
+ const limitOrder = m.contract("LimitOrder", artifact, params);
32
+ return { limitOrder };
33
+ });
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "punkkit-sdk",
3
+ "version": "1.0.0",
4
+ "devDependencies": {
5
+ "@nomicfoundation/hardhat-chai-matchers": "1.0.2",
6
+ "@nomicfoundation/hardhat-network-helpers": "^1.1.2",
7
+ "@nomiclabs/hardhat-ethers": "^2.2.3",
8
+ "@openzeppelin/contracts": "5.4.0",
9
+ "@types/chai": "^4.2.0",
10
+ "@types/mocha": "^10.0.10",
11
+ "@uniswap/v4-core": "1.0.2",
12
+ "chai": "^4.2.0",
13
+ "ethers": "5.7.2",
14
+ "hardhat": "2.26.3",
15
+ "solmate": "^6.8.0",
16
+ "ts-node": "^10.9.2"
17
+ },
18
+ "dependencies": {
19
+ "dotenv": "^16.4.5",
20
+ "solc": "^0.8.25"
21
+ },
22
+ "description": "In [Uniswap V4 core](https://github.com/Uniswap/v4-core) repo:",
23
+ "main": "index.js",
24
+ "directories": {
25
+ "test": "test"
26
+ },
27
+ "scripts": {
28
+ "test": "mocha"
29
+ },
30
+ "author": "",
31
+ "license": "ISC"
32
+ }
@@ -0,0 +1,23 @@
1
+ import{ ethers } from "hardhat";
2
+ import { RPC_URL, PRIVATE_KEY} from "../../config/auction.config";
3
+ import { deployCoinbase } from "./deployCoinbase";
4
+ import { deployXAuction } from "./deployXAuction";
5
+ import { deployYVault } from "./deployYVault";
6
+
7
+ async function main(){
8
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
9
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
10
+
11
+
12
+ const coinbaseAddr = await deployCoinbase(wallet);
13
+ const yVaultAddr = await deployYVault(wallet, coinbaseAddr);
14
+ const xAuctionAddr = await deployXAuction(wallet, yVaultAddr);
15
+ console.log("Deployment Summary:");
16
+ console.log(`Coinbase Address: ${coinbaseAddr}`);
17
+ console.log(`ChainYVaultV2 Address: ${yVaultAddr}`);
18
+ console.log(`ChainXAuctionV2 Address: ${xAuctionAddr}`);
19
+ };
20
+
21
+ if (require.main === module) {
22
+ main();
23
+ }
@@ -0,0 +1,21 @@
1
+ import{ ethers } from "hardhat";
2
+ import { RPC_URL, PRIVATE_KEY} from "../../config/auction.config";
3
+ import { Wallet } from "ethers";
4
+
5
+ export async function deployCoinbase(wallet:Wallet): Promise<string> {
6
+ const CoinBaseFactory=await ethers.getContractFactory("Coinbase", wallet);
7
+ const coinbase=await CoinBaseFactory.deploy();
8
+ await coinbase.deployed();
9
+ return coinbase.address;
10
+ }
11
+
12
+ async function main(){
13
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
14
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
15
+ const coinbaseAddr = await deployCoinbase(wallet);
16
+ console.log(`Coinbase deployed at: ${coinbaseAddr} by ${wallet.address}`);
17
+ };
18
+
19
+ if (require.main === module) {
20
+ main();
21
+ }
@@ -0,0 +1,23 @@
1
+ import{ ethers } from "hardhat";
2
+ import { RPC_URL, PRIVATE_KEY, AUCTION_ADDR} from "../../config/auction.config";
3
+ import { Wallet } from "ethers";
4
+
5
+ export async function deployXAuction(wallet:Wallet,chainYVaultV2Addr:string) : Promise<string> {
6
+ const ChainXAuctionFactory=await ethers.getContractFactory("ChainXAuctionV2", wallet);
7
+ const chainXAuction=await ChainXAuctionFactory.deploy(chainYVaultV2Addr);
8
+ await chainXAuction.deployed();
9
+
10
+ return chainXAuction.address;
11
+ }
12
+
13
+
14
+ async function main(){
15
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
16
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
17
+ const xAuctionAddr = await deployXAuction(wallet,AUCTION_ADDR.chainYVault);
18
+ console.log(`ChainXAuctionV2 deployed at: ${xAuctionAddr} by ${wallet.address}`);
19
+ };
20
+
21
+ if (require.main === module) {
22
+ main();
23
+ }
@@ -0,0 +1,22 @@
1
+ import{ ethers } from "hardhat";
2
+ import { RPC_URL, PRIVATE_KEY, AUCTION_ADDR } from "../../config/auction.config";
3
+ import { Wallet } from "ethers";
4
+
5
+ export async function deployYVault(wallet: Wallet, coinbaseAddr: string) {
6
+ const ChainYVaultV2Factory = await ethers.getContractFactory("ChainYVaultV2", wallet);
7
+ const contract = await ChainYVaultV2Factory.deploy(coinbaseAddr);
8
+ await contract.deployed();
9
+ return contract.address;
10
+ }
11
+
12
+
13
+ async function main(){
14
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
15
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
16
+ const yVaultAddr = await deployYVault(wallet, AUCTION_ADDR.coinbase);
17
+ console.log("ChainYVaultV2 deployed to:", yVaultAddr);
18
+ };
19
+
20
+ if (require.main === module) {
21
+ main();
22
+ }
@@ -0,0 +1,20 @@
1
+ import { ethers } from "hardhat";
2
+ import { RPC_URL, PRIVATE_KEY } from "../config/env.config";
3
+
4
+ // 事实上在punk链上不需要部署Voucher,其是创世块部署的.
5
+ async function main() {
6
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
7
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
8
+ const walletAddress = await wallet.getAddress();
9
+
10
+ // Normal deploy
11
+ const MutiVoucherFactory = await ethers.getContractFactory("MutiVoucher", wallet);
12
+ const Voucher = await MutiVoucherFactory.deploy();
13
+ await Voucher.deployed();
14
+ console.log(`MutiVoucher contract is deployed at: ${Voucher.address} by account(${walletAddress})`);
15
+ };
16
+
17
+ main().catch(error => {
18
+ console.error(error);
19
+ process.exit(1);
20
+ });
@@ -0,0 +1,65 @@
1
+ import { ethers } from "hardhat";
2
+ import type { Contract } from "ethers";
3
+ import { POOL_KEYS, RPC_URL, PRIVATE_KEY, CONTRACT_ADDRESSES, INITIAL_SUPPLY } from "../../../config/uniswap.config";
4
+ import { isDeployed, bigintToBytes32, abiEncode } from "../../../src/uniswap/lib/utils";
5
+ import { mintERC20 } from "../../../src/uniswap/lib/ERC20";
6
+ import { create2Deploy, deployHookWithFlags } from "./help";
7
+ import { deployMockERC20 } from "./deploy_mockERC20";
8
+ import { deployDynamic, deployLimitOrder } from "./deploy_hooks";
9
+ import { deployCreate2 } from "./deploy_create2";
10
+
11
+ async function main() {
12
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
13
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
14
+ const walletAddress = await wallet.getAddress();
15
+
16
+ // 1. Deploy Create2 factory
17
+ const create2Address = await deployCreate2(wallet);
18
+ if (!await isDeployed(provider, create2Address)) throw new Error("Factory is not deployed");
19
+ const factory = await ethers.getContractAt("Create2", create2Address, wallet);
20
+ // console.log("Factory address:", await factory.getAddress());
21
+
22
+ const salt: bigint = BigInt(0);
23
+ const initialSupply = INITIAL_SUPPLY;
24
+
25
+ // 1. Deploy ERC20 tokens
26
+ let token0Addr = await deployMockERC20("bitcoin", "btc", initialSupply);
27
+ let token1Addr = await deployMockERC20("ethereum", "eth", initialSupply);
28
+
29
+ // ensure token0Addr < token1Addr, for poolmanager poolkey check
30
+ if (token0Addr > token1Addr) {
31
+ const temp = token0Addr;
32
+ token0Addr = token1Addr;
33
+ token1Addr = temp;
34
+ }
35
+
36
+ // 2. Deploy poolManager.sol
37
+ const poolManagerAddr = await create2Deploy(factory, "PoolManager", ["address"], [walletAddress], salt);
38
+ // 3. Deploy DynamicFee Hook and limit order hook.
39
+ let dynamicAddress = await deployDynamic(wallet,create2Address, poolManagerAddr);
40
+ let limitOrderAddress = await deployLimitOrder(wallet,create2Address, poolManagerAddr);
41
+
42
+ // 4. Deploy liquidity
43
+ let key = POOL_KEYS.limitOrderPoolKey; // old poolkey, need to update.
44
+ key.currency0 = token0Addr;
45
+ key.currency1 = token1Addr;
46
+ key.hooks = limitOrderAddress;
47
+
48
+ const liquidityPoolAddr = await create2Deploy(factory, "LiquidPool", ["address", "(address,address,uint24,int24,address)"], [poolManagerAddr, Object.values(key)], salt);
49
+
50
+ // 5. Output deployed addresses
51
+ console.log("---- Deployed Addresses ----");
52
+ console.log("create2Factory = ", create2Address);
53
+ console.log("token0 = ", token0Addr);
54
+ console.log("token1 = ", token1Addr);
55
+ console.log("poolManager = ", poolManagerAddr);
56
+ console.log("liquidityPool = ", liquidityPoolAddr);
57
+ console.log("limitOrder Hook = ", limitOrderAddress);
58
+ console.log("dynamicFee Hook = ", dynamicAddress);
59
+ console.log("\nPlease update the CONTRACT_ADDRESSES in .env!\n");
60
+ }
61
+
62
+ main().catch(error => {
63
+ console.error(error);
64
+ process.exit(1);
65
+ });
@@ -0,0 +1,11 @@
1
+ import { ethers } from "hardhat"; // Import ethers from
2
+ import type { Wallet } from "ethers";
3
+ import { ContractFactory, Contract } from "ethers";
4
+
5
+ export async function deployCreate2(wallet : Wallet): Promise<string> {
6
+ const Create2Factory : ContractFactory = await ethers.getContractFactory("Create2", wallet);
7
+ const create2 : Contract = await Create2Factory.deploy();
8
+ await create2.deployed();
9
+ console.log("Factory deployed to:", create2.address);
10
+ return create2.address;
11
+ }
@@ -0,0 +1,35 @@
1
+ import{ethers} from "hardhat";
2
+ import { RPC_URL, PRIVATE_KEY,CONTRACT_ADDRESSES } from "../../../config/uniswap.config";
3
+ import { isDeployed } from "../../../src/uniswap/lib/utils";
4
+ import { create2Deploy } from "./help";
5
+ import { getContract } from "../../../src/uniswap/lib/contract";
6
+
7
+ async function main(){
8
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
9
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
10
+ const walletAddress = await wallet.getAddress();
11
+
12
+
13
+ // Normal deploy
14
+ const ExampleFactory = await ethers.getContractFactory("Example", wallet);
15
+ const example = await ExampleFactory.deploy(0);
16
+ await example.deployed();
17
+ console.log(`normally deployed at: ${example.address} by ${walletAddress}`);
18
+
19
+
20
+ // Create2 deploy
21
+ const factoryAddr = CONTRACT_ADDRESSES["Create2"]
22
+ if (!await isDeployed(provider, factoryAddr)) throw new Error("Factory is not deployed");
23
+ const create2Contract = await getContract(wallet,"Create2");
24
+ const salt: bigint = BigInt(111);
25
+ let exampleAddr = await create2Deploy(create2Contract, "Example", ["uint256"], [0], salt);
26
+ console.log(`create2 deployed at: ${exampleAddr} by ${walletAddress}`);
27
+ };
28
+
29
+
30
+ main()
31
+ .then(() => process.exit(0))
32
+ .catch((err) => {
33
+ console.error(err);
34
+ process.exit(1);
35
+ });
@@ -0,0 +1,74 @@
1
+ import { ethers } from "hardhat";
2
+ import { deployHookWithFlags } from "./help";
3
+ import { CONTRACT_ADDRESSES, RPC_URL, PRIVATE_KEY } from "../../../config/uniswap.config";
4
+ import { Wallet } from "ethers";
5
+
6
+ // Define the extended flags
7
+ const ALL_HOOK_MASK = BigInt((1 << 14) - 1);
8
+ const BEFORE_INITIALIZE_FLAG = BigInt(1 << 13);
9
+ const AFTER_INITIALIZE_FLAG = BigInt(1 << 12);
10
+ const BEFORE_ADD_LIQUIDITY_FLAG = BigInt(1 << 11);
11
+ const AFTER_ADD_LIQUIDITY_FLAG = BigInt(1 << 10);
12
+ const BEFORE_REMOVE_LIQUIDITY_FLAG = BigInt(1 << 9);
13
+ const AFTER_REMOVE_LIQUIDITY_FLAG = BigInt(1 << 8);
14
+ const BEFORE_SWAP_FLAG = BigInt(1 << 7);
15
+ const AFTER_SWAP_FLAG = BigInt(1 << 6);
16
+ const BEFORE_DONATE_FLAG = BigInt(1 << 5);
17
+ const AFTER_DONATE_FLAG = BigInt(1 << 4);
18
+ const BEFORE_SWAP_RETURNS_DELTA_FLAG = BigInt(1 << 3);
19
+ const AFTER_SWAP_RETURNS_DELTA_FLAG = BigInt(1 << 2);
20
+ const AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = BigInt(1 << 1);
21
+ const AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = BigInt(1 << 0);
22
+
23
+ // Deploy DynamicFee hooks to pool manager
24
+ export async function deployDynamic(wallet:Wallet,Create2Addr: string, poolManagerAddr:string) : Promise<string>{
25
+ const factory=await ethers.getContractAt("Create2", Create2Addr,wallet);
26
+ const factoryAddr=factory.address;
27
+
28
+ const flagFee: bigint = AFTER_SWAP_FLAG | AFTER_INITIALIZE_FLAG;
29
+ const dynamicFeeHook = await deployHookWithFlags(
30
+ factory,
31
+ factoryAddr,
32
+ "DynamicFee",
33
+ ["address"],
34
+ [poolManagerAddr],
35
+ flagFee
36
+ );
37
+ return dynamicFeeHook;
38
+ }
39
+
40
+ export async function deployLimitOrder(wallet:Wallet, Create2Addr: string, poolManagerAddr:string) : Promise<string>{
41
+ const factory=await ethers.getContractAt("Create2", Create2Addr,wallet);
42
+ const factoryAddr=factory.address;
43
+
44
+ // Deploy LimitOrder Hook
45
+ const flagLimit: bigint = AFTER_INITIALIZE_FLAG | AFTER_SWAP_FLAG; // | AFTER_SWAP_RETURNS_DELTA_FLAG;
46
+ const limitOrderHook = await deployHookWithFlags(
47
+ factory,
48
+ factoryAddr,
49
+ "LimitOrder",
50
+ ["address"],
51
+ [poolManagerAddr],
52
+ flagLimit
53
+ );
54
+ return limitOrderHook;
55
+ }
56
+
57
+ async function deployDemo(){
58
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
59
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
60
+
61
+ const dynamicAddress=await deployDynamic(wallet,CONTRACT_ADDRESSES.Create2, CONTRACT_ADDRESSES.PoolManager);
62
+ const limitOrderAddress=await deployLimitOrder(wallet,CONTRACT_ADDRESSES.Create2, CONTRACT_ADDRESSES.PoolManager);
63
+
64
+ if (await provider.getCode(dynamicAddress) === "0x") {
65
+ console.error("DynamicFee hook deployment failed");
66
+ }
67
+ if (await provider.getCode(limitOrderAddress) === "0x") {
68
+ console.error("LimitOrder hook deployment failed");
69
+ }
70
+ }
71
+
72
+ if (require.main === module) {
73
+ deployDemo();
74
+ }
@@ -0,0 +1,42 @@
1
+ import { ethers } from "hardhat";
2
+
3
+ import { CONTRACT_ADDRESSES, RPC_URL, PRIVATE_KEY } from "../../../config/uniswap.config";
4
+ import { create2Deploy } from "./help";
5
+
6
+
7
+ async function deployDemo() {
8
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
9
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
10
+ const walletAddress = await wallet.getAddress();
11
+
12
+ const name: string = "MockDaiToken";
13
+ const symbol: string = "MOCKDAI";
14
+ const initialSupply = BigInt(1);
15
+
16
+ console.log(`Deployer: ${walletAddress}, Deployer balance: ${ethers.utils.formatEther(await wallet.getBalance())} ETH`);
17
+ // 1. Contract factory deploy, normally deploy
18
+ // const MockERC20 = await ethers.getContractFactory("MockERC20", wallet);
19
+ // const mockERC20 = await MockERC20.deploy(name, symbol, initialSupply);
20
+ // await mockERC20.deployed();
21
+ // const tokenAddress = mockERC20.address;
22
+ // console.log("deploy to address:", tokenAddress);
23
+ // const deployerBalance = await mockERC20.balanceOf(wallet.address);
24
+ // console.log(`deployer ${symbol} balance: ${ethers.utils.formatUnits(deployerBalance, 18)}`);
25
+
26
+ // 2. Deploy with create2
27
+ deployMockERC20(name,symbol,initialSupply);
28
+ }
29
+ // Deploy MockERC20 contract using Create2
30
+ export async function deployMockERC20(name:string,symbol:string,initialSupply:bigint) : Promise<string> {
31
+ const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
32
+ const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
33
+ const create2Contract=await ethers.getContractAt("Create2",CONTRACT_ADDRESSES.Create2, wallet);
34
+ let deployAddress=await create2Deploy(create2Contract,"MockERC20",["string","string","uint256"],[name,symbol,initialSupply],BigInt(123456789));
35
+ console.log(`MockERC20Custom deployed by Create2 to: ${deployAddress}`);
36
+ return deployAddress;
37
+ }
38
+
39
+
40
+ if (require.main === module) {
41
+ deployDemo();
42
+ }