{"content":{"title":"如何在Uniswap V3中添加新的池子","body":"![](https://img.learnblockchain.cn/2025/03/09/16.jpg)\r\n\r\n## 简介\r\n\r\n许多现有项目使用著名的Uniswap协议的第三个版本作为Oracle，以获取许多资产的当前价格。Uniswap V3还可以作为年化收益或收获策略中的一个流动性池，随着时间的推移，为你的存款创造利润。一些项目还增加了与Uniswap V3的集成，以提升用户体验，使用户的生活稍微轻松一些。在所有这些场景中，检查攻击者可能添加到uniswap的有毒池如何影响协议至关重要。为了检查这一场景，我们在hardhat环境中创建了一个测试。\r\n\r\n在PoC中向UniswapV3添加新的流动性池的示例\r\n\r\n下面展示了hardhat测试环境中的代码片段。所有必要的代码注释也一并给出。\r\n\r\n```js\r\nconst tokenFactory = await ethers.getContractFactory(\"EvilToken\");\r\nconst evilToken = await tokenFactory.connect(deployer).deploy();\r\nconst positionManager = await ethers.getContractAt('INonfungiblePositionManager', \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\");\r\nconst WETH = await ethers.getContractAt('IWETH', addresses.tokens.WETH);\r\n// 在添加新池之前，调用Token的授权\r\ncall approveawait WETH.connect(deployer).approve(positionManager.address, ethers.utils.parseEther('0.1'), {gasPrice: 0});\r\nawait evilToken.connect(deployer).approve(positionManager.address, ethers.utils.parseEther('100'), {gasPrice: 0});\r\nlet multiCallParams = [\r\n// 第一个调用\r\n\"0x13ead562\" + // 编码的函数签名 ( createAndInitializePoolIfNecessary(address, address, uint24, uint160) )\r\n\"000000000000000000000000\" + evilToken.address.toLowerCase().substring(2) + // token1 地址\r\n\"000000000000000000000000\" +  WETH.address.toLowerCase().substring(2) + // token2 地址\r\n\"00000000000000000000000000000000000000000000000000000000000001f4\" + // 费用\r\n\"000000000000000000000000000000000000000005b96aabfac7cdc4b3b58fc2\", // sqrtPriceX96\r\n// 第二个调用\r\n\"0x88316456\" + // 编码的函数签名 ( mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256)) )\r\n\"000000000000000000000000\" + evilToken.address.toLowerCase().substring(2) + // token1 地址\r\n\"000000000000000000000000\" +  WETH.address.toLowerCase().substring(2) + // token2 地址\\\r\n\"00000000000000000000000000000000000000000000000000000000000001f4\" + // 费用\\\r\n\"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89f0e\" + // tick 下限\\\r\n\"0000000000000000000000000000000000000000000000000000000000010dd8\" + // tick 上限\\\r\n\"00000000000000000000000000000000000000000000000ad5a4b6712c4647c3\" + // 期望的数量1\\\r\n\"000000000000000000000000000000000000000000000000016345785d8a0000\" + // 期望的数量2\\\r\n\"00000000000000000000000000000000000000000000000acebaf563cd50439c\" + // 最小期望数量1\\\r\n\"000000000000000000000000000000000000000000000000016261cfc3291456\" + // 最小期望数量2\\\r\n\"000000000000000000000000\" + signer3.address.toLowerCase().substring(2) + // 部署者地址 \"00000000000000000000000000000000000000000000000000000000610bb8b6\" // 截止时间\\\r\n];\r\n// 通过位置管理器添加新的流动性池\r\nawait positionManager.connect(deployer).multicall(multiCallParams, {gasPrice: 0});\r\n```\r\n\r\n在这个测试中，EvilToken是一个标准的ERC20代币，可以由部署者铸造或销毁，positionManager是Uniswap V3生态系统中的一个智能合约，提供添加新流动性池的访问权限，WETH是代表封装以太的代币。multiCallParams是一个字节数组，包含部署新流动性池所需的所有参数。值得一提的是，multiCallParams中使用的一些参数如sqrtPriceX96或tick下限并不容易计算。要计算这些参数，你可以在ropsten网络上使用Uniswap V3 dApp。通过dApp计算这些参数非常简单。首先，你在dApp中创建一个具有你希望使用的参数的新流动性池，然后只是反编译你的交易在ropsten etherscan中，并获取所需参数的字节表示值。\r\n\r\n## 结论\r\n\r\n在此，你已经了解如何在hardhat框架中使用用户创建的代币添加新的Uniswap V3池用于测试。关于审计和开发人员的有用工具的更多信息，请参阅我们即将推出的文章。\r\n\r\n## 附加阅读和教程\r\n\r\n[https://uniswap.org/whitepaper-v3.pdf](https://uniswap.org/whitepaper-v3.pdf)\r\n\r\n[https://hardhat.org/getting-started/](https://hardhat.org/getting-started/)\r\n\r\n[https://eth-brownie.readthedocs.io/en/stable/](https://eth-brownie.readthedocs.io/en/stable/)\r\n\r\n[https://www.youtube.com/watch?v=nkvIFE2QVp0&list=PLVOHzVzbg7bFUaOGwN0NOgkTItUAVyBBQ](https://www.youtube.com/watch?v=nkvIFE2QVp0&list=PLVOHzVzbg7bFUaOGwN0NOgkTItUAVyBBQ)\r\n\r\n- 谁是MixBytes？\r\n\r\n\r\n[MixBytes](https://mixbytes.io/)是一个专家区块链审计师和安全研究人员团队，专注于为EVM兼容和Substrate基础项目提供全面的智能合约审计和技术顾问服务。请关注我们在[X](https://twitter.com/MixBytes)上的动态，以获取最新的行业趋势和见解。\r\n\r\n>- 原文链接： [mixbytes.io/blog/how-to-...](https://mixbytes.io/blog/how-to-add-new-pool-uniswap-v3)\r\n>- 登链社区 AI 助手，为大家转译优秀英文文章，如有翻译不通的地方，还请包涵～"},"author":{"user":"https://learnblockchain.cn/people/24680","address":null},"history":null,"timestamp":1741490426,"version":1}