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