import { MockUSDT__factory, ControlledERC20__factory,IPancakePair__factory } from "../typechain-types" import { IPancakeRouter02__factory, IPancakeFactory__factory } from "../typechain-types" import { config as dotenvConfig } from "dotenv" import { ethers } from "ethers" import fs from "fs" // BSC Testnet PancakeSwap V2 合约地址 const PANCAKE_ROUTER_ADDRESS = "0xD99D1c33F9fC3444f8101754aBC46c52416550D1" const PANCAKE_FACTORY_ADDRESS = "0x6725F303b657a9451d8BA641348b6761A6CC7a17" const WBNB_ADDRESS = "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd" /** * @dev PancakeSwap流动性添加脚本 * 在PancakeSwap V2上为MockUSDT和ControlledERC20创建交易对并添加流动性 * 包含交易对创建、代币授权、流动性添加等功能 */ async function main() { dotenvConfig() const rpcUrl = process.env.BSC_TESTNET_RPC_URL const privateKey = process.env.PRIVATE_KEY if (!rpcUrl || !privateKey) { throw new Error("请在.env中配置BSC_TESTNET_RPC_URL和PRIVATE_KEY") } const provider = new ethers.JsonRpcProvider(rpcUrl) const wallet = new ethers.Wallet(privateKey, provider) console.log("🚀 开始添加PancakeSwap流动性...") console.log("📝 操作账户:", wallet.address) console.log("💰 账户余额:", ethers.formatEther(await provider.getBalance(wallet.address)), "BNB") // 读取部署信息文件(包含合约地址) let deploymentInfo try { deploymentInfo = JSON.parse(fs.readFileSync("deployment-bsc-testnet.json", "utf8")) } catch (error) { console.error("❌ 无法读取部署信息文件,请先运行部署脚本") process.exit(1) } const mockUSDTAddress = deploymentInfo.contracts.mockUSDT const controlledERC20Address = deploymentInfo.contracts.controlledERC20 console.log("📄 MockUSDT地址:", mockUSDTAddress) console.log("📄 ControlledERC20地址:", controlledERC20Address) // 获取合约实例 const mockUSDT = MockUSDT__factory.connect(mockUSDTAddress, wallet) const controlledERC20 = ControlledERC20__factory.connect(controlledERC20Address, wallet) const pancakeRouter = IPancakeRouter02__factory.connect(PANCAKE_ROUTER_ADDRESS, wallet) const pancakeFactory = IPancakeFactory__factory.connect(PANCAKE_FACTORY_ADDRESS, wallet) // 检查代币余额 const mockUSDTBalance = await mockUSDT.balanceOf(wallet.address) const controlledERC20Balance = await controlledERC20.balanceOf(wallet.address) console.log("\n💰 代币余额:") console.log("MockUSDT余额:", ethers.formatUnits(mockUSDTBalance, 6), "mUSDT") console.log("ControlledERC20余额:", ethers.formatEther(controlledERC20Balance), "CTRL") // 检查或创建交易对(如果不存在则创建新的交易对) console.log("\n🔍 检查交易对...") let pairAddress = await pancakeFactory.getPair(mockUSDTAddress, controlledERC20Address) if (pairAddress === ethers.ZeroAddress) { console.log("📦 创建新的交易对...") const tx = await pancakeFactory.createPair(mockUSDTAddress, controlledERC20Address) await tx.wait() pairAddress = await pancakeFactory.getPair(mockUSDTAddress, controlledERC20Address) console.log("✅ 交易对已创建:", pairAddress) } else { console.log("✅ 交易对已存在:", pairAddress) } // 授权Router使用代币(允许Router合约转移用户的代币) console.log("\n🔐 授权Router使用代币...") const mockUSDTAllowance = await mockUSDT.allowance(wallet.address, PANCAKE_ROUTER_ADDRESS) if (mockUSDTAllowance < mockUSDTBalance) { console.log("授权MockUSDT...") const approveTx = await mockUSDT.approve(PANCAKE_ROUTER_ADDRESS, ethers.MaxUint256) await approveTx.wait() console.log("✅ MockUSDT授权完成") } const controlledERC20Allowance = await controlledERC20.allowance(wallet.address, PANCAKE_ROUTER_ADDRESS) if (controlledERC20Allowance < controlledERC20Balance) { console.log("授权ControlledERC20...") const approveTx = await controlledERC20.approve(PANCAKE_ROUTER_ADDRESS, ethers.MaxUint256) await approveTx.wait() console.log("✅ ControlledERC20授权完成") } // 添加流动性到PancakeSwap交易对 console.log("\n💧 添加流动性...") // 计算添加的流动性数量(使用余额的一半,确保流动性充足) const mockUSDTAmount = mockUSDTBalance / 2n const controlledERC20Amount = controlledERC20Balance / 2n console.log("添加流动性数量:") console.log("MockUSDT:", ethers.formatUnits(mockUSDTAmount, 6), "mUSDT") console.log("ControlledERC20:", ethers.formatEther(controlledERC20Amount), "CTRL") // 设置最小数量(允许1%的滑点保护) const mockUSDTMin = (mockUSDTAmount * 99n) / 100n const controlledERC20Min = (controlledERC20Amount * 99n) / 100n // 添加流动性(设置5分钟的交易截止时间) const deadline = Math.floor(Date.now() / 1000) + 300 // 5分钟后过期 const addLiquidityTx = await pancakeRouter.addLiquidity( mockUSDTAddress, controlledERC20Address, mockUSDTAmount, controlledERC20Amount, mockUSDTMin, controlledERC20Min, wallet.address, deadline ) console.log("⏳ 等待交易确认...") const receipt = await addLiquidityTx.wait() console.log("✅ 流动性添加成功!") console.log("交易哈希:", receipt!.hash) // 获取LP代币余额 const pairContract = IPancakePair__factory.connect(pairAddress, wallet) const lpBalance = await pairContract.balanceOf(wallet.address) console.log("🪙 LP代币余额:", ethers.formatEther(lpBalance)) // 保存流动性信息 const liquidityInfo = { pairAddress: pairAddress, mockUSDTAmount: mockUSDTAmount.toString(), controlledERC20Amount: controlledERC20Amount.toString(), lpBalance: lpBalance.toString(), transactionHash: receipt!.hash, timestamp: new Date().toISOString(), } fs.writeFileSync("liquidity-info.json", JSON.stringify(liquidityInfo, null, 2)) console.log("\n💾 流动性信息已保存到 liquidity-info.json") console.log("\n🎉 流动性添加完成!") console.log("📊 交易对地址:", pairAddress) console.log( "🔗 PancakeSwap链接: https://testnet.pancakeswap.finance/add/" + mockUSDTAddress + "/" + controlledERC20Address ) } main() .then(() => process.exit(0)) .catch((error) => { console.error("❌ 添加流动性失败:", error) process.exit(1) })