import { MockUSDT__factory, ControlledERC20__factory } from "../typechain-types" import { IPancakeRouter02__factory, IPancakeFactory__factory, IPancakePair__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信息查询脚本 * 查询交易对的流动性、价格、用户余额等信息 * 包含价格影响分析、LP代币信息、用户份额计算等功能 */ 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) // 读取部署信息 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) // 检查交易对是否存在(如果不存在则提示先添加流动性) console.log("\n🔍 检查交易对...") const pairAddress = await pancakeFactory.getPair(mockUSDTAddress, controlledERC20Address) if (pairAddress === ethers.ZeroAddress) { console.log("❌ 交易对不存在,请先添加流动性") process.exit(1) } console.log("✅ 交易对地址:", pairAddress) // 获取交易对详细信息(储备量、代币地址等) const pair = IPancakePair__factory.connect(pairAddress, wallet) const [reserve0, reserve1, blockTimestampLast] = await pair.getReserves() const token0 = await pair.token0() const token1 = await pair.token1() // 确定哪个储备量对应哪个代币(PancakeSwap按地址排序) let mockUSDTReserve: bigint let controlledERC20Reserve: bigint let mockUSDTDecimals: number let controlledERC20Decimals: number if (token0.toLowerCase() === mockUSDTAddress.toLowerCase()) { mockUSDTReserve = reserve0 controlledERC20Reserve = reserve1 mockUSDTDecimals = 6 controlledERC20Decimals = 18 } else { mockUSDTReserve = reserve1 controlledERC20Reserve = reserve0 mockUSDTDecimals = 6 controlledERC20Decimals = 18 } // 显示流动性信息 console.log("\n💧 流动性信息:") console.log("MockUSDT储备:", ethers.formatUnits(mockUSDTReserve, mockUSDTDecimals), "mUSDT") console.log("ControlledERC20储备:", ethers.formatUnits(controlledERC20Reserve, controlledERC20Decimals), "CTRL") // 计算代币价格(考虑小数位数差异) const price1 = (Number(controlledERC20Reserve) / Number(mockUSDTReserve)) * Math.pow(10, mockUSDTDecimals - controlledERC20Decimals) const price2 = (Number(mockUSDTReserve) / Number(controlledERC20Reserve)) * Math.pow(10, controlledERC20Decimals - mockUSDTDecimals) console.log("\n💰 价格信息:") console.log("1 mUSDT =", price1.toFixed(6), "CTRL") console.log("1 CTRL =", price2.toFixed(6), "mUSDT") // 获取LP代币总供应量 const totalSupply = await pair.totalSupply() console.log("\n🪙 LP代币信息:") console.log("LP代币总供应量:", ethers.formatEther(totalSupply)) // 检查用户LP代币余额 const userLPBalance = await pair.balanceOf(wallet.address) if (userLPBalance > 0n) { console.log("用户LP代币余额:", ethers.formatEther(userLPBalance)) const userShare = (Number(userLPBalance) / Number(totalSupply)) * 100 console.log("用户份额:", userShare.toFixed(4) + "%") } // 模拟不同数量的交易(分析价格影响) console.log("\n📈 价格影响分析:") const testAmounts = [ ethers.parseUnits("100", 6), // 100 mUSDT ethers.parseUnits("1000", 6), // 1000 mUSDT ethers.parseUnits("10000", 6), // 10000 mUSDT ] for (const amount of testAmounts) { try { const path = [mockUSDTAddress, controlledERC20Address] const amountsOut = await pancakeRouter.getAmountsOut(amount, path) const priceImpact = ((Number(amount) - Number(amountsOut[1]) * price1) / Number(amount)) * 100 console.log( `${ethers.formatUnits(amount, 6)} mUSDT -> ${ethers.formatUnits(amountsOut[1], 18)} CTRL (价格影响: ${priceImpact.toFixed(2)}%)` ) } catch (error) { console.log(`${ethers.formatUnits(amount, 6)} mUSDT -> 交易失败 (流动性不足)`) } } // 反向交易测试 console.log("\n📉 反向价格影响分析:") const testAmountsReverse = [ ethers.parseEther("100"), // 100 CTRL ethers.parseEther("1000"), // 1000 CTRL ethers.parseEther("10000"), // 10000 CTRL ] for (const amount of testAmountsReverse) { try { const path = [controlledERC20Address, mockUSDTAddress] const amountsOut = await pancakeRouter.getAmountsOut(amount, path) const priceImpact = ((Number(amount) - Number(amountsOut[1]) * price2) / Number(amount)) * 100 console.log( `${ethers.formatUnits(amount, 18)} CTRL -> ${ethers.formatUnits(amountsOut[1], 6)} mUSDT (价格影响: ${priceImpact.toFixed(2)}%)` ) } catch (error) { console.log(`${ethers.formatUnits(amount, 18)} CTRL -> 交易失败 (流动性不足)`) } } // 获取用户代币余额 const userMockUSDTBalance = await mockUSDT.balanceOf(wallet.address) const userControlledERC20Balance = await controlledERC20.balanceOf(wallet.address) console.log("\n👤 用户余额:") console.log("MockUSDT余额:", ethers.formatUnits(userMockUSDTBalance, 6), "mUSDT") console.log("ControlledERC20余额:", ethers.formatEther(userControlledERC20Balance), "CTRL") // 保存信息到文件 const info = { pairAddress: pairAddress, reserves: { mockUSDT: mockUSDTReserve.toString(), controlledERC20: controlledERC20Reserve.toString(), }, prices: { mUSDTtoCTRL: price1, CTRLtoMUSDT: price2, }, totalSupply: totalSupply.toString(), userLPBalance: userLPBalance.toString(), userBalances: { mockUSDT: userMockUSDTBalance.toString(), controlledERC20: userControlledERC20Balance.toString(), }, timestamp: new Date().toISOString(), } fs.writeFileSync("pancakeswap-info.json", JSON.stringify(info, null, 2)) console.log("\n💾 信息已保存到 pancakeswap-info.json") console.log("\n🔗 PancakeSwap链接:") console.log("交易页面: https://testnet.pancakeswap.finance/swap") console.log("流动性页面: https://testnet.pancakeswap.finance/liquidity") } main() .then(() => process.exit(0)) .catch((error) => { console.error("❌ 查询失败:", error) process.exit(1) })