123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- import "dotenv/config"
- import { ethers } from "ethers"
- import * as fs from "fs"
- import * as path from "path"
- import { MockUSD1__factory, Launchpad__factory, BasicERC20__factory } from "../typechain-types/factories/contracts"
- import type { MockUSD1, Launchpad, BasicERC20 } from "../typechain-types/contracts"
- async function main() {
- // 获取环境配置
- const environment = process.env.ENVIRONMENT || "bsctest"
- const rpcUrl = process.env.RPC_URL || "https://data-seed-prebsc-1-s1.binance.org:8545/"
- const outputDir = process.env.OUTPUT_DIR || "./output/bsctest"
-
- console.log(`🚀 第5步:测试代币领取和提款...`)
- console.log(`🌍 环境: ${environment}`)
- console.log(`🔗 RPC: ${rpcUrl}`)
- console.log(`📁 输出目录: ${outputDir}`)
- // 检查环境变量
- if (!process.env.PRIVATE_KEY) {
- console.error("❌ 需要设置 PRIVATE_KEY 环境变量")
- process.exit(1)
- }
- // 从之前的步骤加载数据
- const step3DataPath = path.join(outputDir, "step3-data.json")
- if (!fs.existsSync(step3DataPath)) {
- console.error(`❌ 未找到 ${step3DataPath} 文件。请先运行第4步。`)
- process.exit(1)
- }
- const step3Data = JSON.parse(fs.readFileSync(step3DataPath, "utf8"))
- console.log("📋 已从之前的步骤加载数据")
- // 设置提供者
- const provider = new ethers.JsonRpcProvider(rpcUrl)
- const deployer = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
- // 连接到合约
- const mockUSD1 = MockUSD1__factory.connect(step3Data.mockUSD1, deployer)
- const launchpad = Launchpad__factory.connect(step3Data.launchpad, deployer)
- const saleToken = BasicERC20__factory.connect(step3Data.saleToken, deployer)
- // 从JSON文件加载测试账户
- const testAccountsPath = "./scripts/testAccount/BLaunchpadTest.json"
- const testAccounts = JSON.parse(fs.readFileSync(testAccountsPath, "utf8"))
- // 从加载的账户创建测试用户(保留用于兼容性)
- const user1 = new ethers.Wallet(testAccounts[0].privateKey, provider)
- const user2 = new ethers.Wallet(testAccounts[1].privateKey, provider)
- const user3 = new ethers.Wallet(testAccounts[2].privateKey, provider)
- // 获取当前时间和销售结束时间
- const currentTime = Math.floor(Date.now() / 1000)
- const saleEndTime = step3Data.saleParams.endTime
- console.log(`\n⏰ 当前时间: ${new Date(currentTime * 1000).toLocaleString()}`)
- console.log(`⏰ 销售结束时间: ${new Date(saleEndTime * 1000).toLocaleString()}`)
- // 检测是否为Hardhat环境
- const isHardhat = rpcUrl.includes("127.0.0.1") || rpcUrl.includes("localhost") || rpcUrl.includes("8545")
-
- if (isHardhat) {
- console.log("🔧 检测到Hardhat环境,使用时间快进功能...")
-
- // 使用Hardhat快进时间到销售结束后
- const timeToAdvance = saleEndTime - currentTime + 3600 // 快进到销售结束后1小时
-
- console.log(`⏰ 快进时间 ${timeToAdvance} 秒到销售结束后...`)
- await provider.send("evm_increaseTime", [timeToAdvance])
- await provider.send("evm_mine", [])
-
- // 获取区块链当前时间
- const blockNumber = await provider.getBlockNumber()
- const block = await provider.getBlock(blockNumber)
- const newCurrentTime = block?.timestamp || Math.floor(Date.now() / 1000)
- console.log("✅ 时间已快进到:", new Date(newCurrentTime * 1000).toLocaleString())
-
- console.log("\n🔓 销售已结束,启用领取...")
- // 启用领取
- const claimStartTime = newCurrentTime + 1 // 从现在起1秒后启用领取
- await launchpad.connect(deployer).enableClaimTokens(claimStartTime)
- console.log("✅ 领取已启用,时间:", new Date(claimStartTime * 1000).toLocaleString())
- // 快进时间到领取开始后
- if (newCurrentTime < claimStartTime) {
- const waitTime = claimStartTime - newCurrentTime + 1
- console.log(`⏰ 快进 ${waitTime} 秒到领取开始后...`)
- await provider.send("evm_increaseTime", [waitTime])
- await provider.send("evm_mine", [])
-
- const finalBlockNumber = await provider.getBlockNumber()
- const finalBlock = await provider.getBlock(finalBlockNumber)
- const finalTime = finalBlock?.timestamp || newCurrentTime
- console.log("✅ 时间已快进到:", new Date(finalTime * 1000).toLocaleString())
- }
-
- // 再次检查当前时间,确保销售已结束
- const finalCheckBlock = await provider.getBlock(await provider.getBlockNumber())
- const finalCheckTime = finalCheckBlock?.timestamp || Math.floor(Date.now() / 1000)
- console.log("🔍 最终时间检查:", new Date(finalCheckTime * 1000).toLocaleString())
- console.log("🔍 销售结束时间:", new Date(saleEndTime * 1000).toLocaleString())
- console.log("🔍 销售是否已结束:", finalCheckTime > saleEndTime)
- } else {
- console.log("🌐 检测到真实网络环境,检查销售是否已结束...")
-
- // 检查销售是否已经结束
- if (currentTime < saleEndTime) {
- console.log("❌ 销售尚未结束,无法进行领取测试")
- console.log("💡 提示:在真实网络中,需要等待销售自然结束才能进行领取测试")
- console.log("💡 或者可以修改合约的endTime参数来提前结束销售")
- return
- }
-
- console.log("✅ 销售已结束,检查是否已启用领取...")
-
- // 检查是否已经启用领取
- try {
- // 尝试启用领取(如果已经启用会失败,这是正常的)
- const claimStartTime = currentTime + 60 // 1分钟后启用
- await launchpad.connect(deployer).enableClaimTokens(claimStartTime)
- console.log("✅ 领取已启用,时间:", new Date(claimStartTime * 1000).toLocaleString())
- } catch (error) {
- console.log("✅ 领取功能已经启用或正在启用中...")
- }
-
- // 等待一段时间确保领取功能完全启用
- console.log("⏳ 等待领取功能完全启用...")
- await new Promise(resolve => setTimeout(resolve, 5000)) // 等待5秒
- }
- console.log("\n🎁 测试代币领取...")
- // 获取所有测试用户
- const allTestUsers = testAccounts.map((account: any) => new ethers.Wallet(account.privateKey, provider))
-
- // 记录所有用户的代币领取情况
- const userTokensReceived: { [key: string]: bigint } = {}
- let totalTokensClaimed = BigInt(0)
- // 检查是否需要快进时间(在Hardhat环境中)
- if (isHardhat) {
- // 获取当前区块链时间
- const currentBlockNumber = await provider.getBlockNumber()
- const currentBlock = await provider.getBlock(currentBlockNumber)
- const currentBlockTime = currentBlock?.timestamp || Math.floor(Date.now() / 1000)
-
- // 检查是否已经启用了领取功能
- try {
- const isClaimEnabled = await launchpad.isClaimEnabled()
- const claimStartTime = await launchpad.getClaimStartTime()
- console.log("🔍 检查领取功能状态...")
- console.log(`- 领取功能已启用: ${isClaimEnabled}`)
- console.log(`- 领取开始时间: ${new Date(Number(claimStartTime) * 1000).toLocaleString()}`)
-
- // 如果领取功能未启用,尝试启用
- if (!isClaimEnabled) {
- console.log("🔓 领取功能未启用,正在启用...")
- const newClaimStartTime = currentBlockTime + 1
- await launchpad.connect(deployer).enableClaimTokens(newClaimStartTime)
- console.log("✅ 领取功能已启用")
-
- // 快进时间到领取开始后
- const waitTime = 2
- console.log(`⏰ 快进 ${waitTime} 秒到领取开始后...`)
- await provider.send("evm_increaseTime", [waitTime])
- await provider.send("evm_mine", [])
- }
- } catch (error) {
- console.log("⚠️ 无法检测领取功能状态,继续执行...")
- }
- }
- // 让所有用户领取代币
- for (let i = 0; i < allTestUsers.length; i++) {
- const user = allTestUsers[i]
- console.log(`\n👤 用户${i + 1} (${user.address}) 领取代币...`)
-
- // 检查用户是否参与过贡献
- let userContributed = false
- let userContributionAmount = BigInt(0)
- try {
- // 从合约获取用户的贡献信息
- userContributionAmount = await launchpad.userContributionAmount(user.address)
- userContributed = userContributionAmount > 0
- console.log(`📊 用户${i + 1} 贡献金额: ${ethers.formatEther(userContributionAmount)} USD1`)
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error)
- console.log(`⚠️ 无法检测用户${i + 1}的贡献状态: ${errorMessage}`)
- }
-
- if (!userContributed) {
- console.log(`❌ 用户${i + 1} 没有参与贡献,跳过领取`)
- userTokensReceived[user.address] = BigInt(0)
- continue
- }
-
- const userBalanceBefore = await saleToken.balanceOf(user.address)
- let userTokensReceivedAmount = BigInt(0)
-
- try {
- // 获取用户当前nonce
- const userNonce = await provider.getTransactionCount(user.address)
- await launchpad.connect(user).claimTokens({ nonce: userNonce })
- const userBalanceAfter = await saleToken.balanceOf(user.address)
- userTokensReceivedAmount = userBalanceAfter - userBalanceBefore
- totalTokensClaimed += userTokensReceivedAmount
- console.log(`✅ 用户${i + 1} 领取了 ${ethers.formatEther(userTokensReceivedAmount)} 个代币`)
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error)
- if (errorMessage.includes("No tokens to claim")) {
- console.log(`✅ 用户${i + 1} 没有代币可领取(可能已经领取过了)`)
- } else if (errorMessage.includes("Claiming not enabled")) {
- console.log(`❌ 用户${i + 1} 领取功能尚未启用`)
- } else if (errorMessage.includes("Sale has not ended")) {
- console.log(`❌ 用户${i + 1} 销售尚未结束,无法领取`)
- } else {
- console.log(`❌ 用户${i + 1} 领取失败: ${errorMessage}`)
- }
- }
-
- userTokensReceived[user.address] = userTokensReceivedAmount
- }
- // 统计实际参与贡献的用户数量
- let participatingUsersCount = 0
- for (const user of allTestUsers) {
- const userContribution = await launchpad.userContributionAmount(user.address)
- if (userContribution > 0) {
- participatingUsersCount++
- }
- }
- console.log(`\n📊 代币领取总结:`)
- console.log(`- 总领取代币数量: ${totalTokensClaimed.toString()} tokens`)
- console.log(`- 参与用户数量: ${participatingUsersCount} 个用户`)
- // 所有者提款支付
- console.log("\n💸 所有者提款支付...")
- const ownerBalanceBefore = await mockUSD1.balanceOf(deployer.address)
- const ownerNonce = await provider.getTransactionCount(deployer.address)
- await launchpad.connect(deployer).withdrawPayments({ nonce: ownerNonce })
- const ownerBalanceAfter = await mockUSD1.balanceOf(deployer.address)
- const ownerReceived = ownerBalanceAfter - ownerBalanceBefore
- console.log("✅ 所有者收到了", ethers.formatEther(ownerReceived), "USD1")
- // 所有者提款剩余代币
- console.log("\n🏦 所有者提款剩余代币...")
- const remainingTokens = await saleToken.balanceOf(step3Data.launchpad)
- console.log("📊 合约中剩余代币:", ethers.formatEther(remainingTokens))
-
- if (remainingTokens > 0) {
- try {
- await launchpad.connect(deployer).withdrawRemainingTokens()
- console.log("✅ 所有者提款了", ethers.formatEther(remainingTokens), "个剩余代币")
- } catch (error) {
- console.log("⚠️ 无法提款剩余代币,可能合约逻辑认为所有代币已售出")
- console.log("💡 这通常发生在超额认购时,合约认为所有代币都已分配给用户")
- }
- } else {
- console.log("✅ 没有剩余代币可提款(所有代币已售出)")
- }
- // 最终总结
- console.log("\n🎉 领取和提款测试成功完成!")
- console.log("\n📋 最终总结:")
- console.log("- 总领取代币数量:", ethers.formatEther(totalTokensClaimed), "个代币")
- console.log("- 参与用户数量:", participatingUsersCount, "个用户")
- console.log("- 所有者收到了:", ethers.formatEther(ownerReceived), "USD1")
- console.log("- 所有者提款了:", ethers.formatEther(remainingTokens), "个剩余代币")
- // Save final data
- const finalData = {
- ...step3Data,
- claiming: {
- totalTokensClaimed: totalTokensClaimed.toString(),
- participatingUsersCount: participatingUsersCount,
- userTokensReceived: Object.fromEntries(
- Object.entries(userTokensReceived).map(([key, value]) => [key, value.toString()])
- ),
- ownerReceivedUSD1: ownerReceived.toString(),
- remainingTokens: remainingTokens.toString(),
- },
- }
- const finalDataPath = path.join(outputDir, "final-data.json")
- fs.writeFileSync(finalDataPath, JSON.stringify(finalData, null, 2))
- console.log(`\n📋 All data saved to ${finalDataPath}`)
- }
- // 导出main函数供多环境脚本调用
- export { main }
- // 如果直接运行此脚本
- if (require.main === module) {
- main()
- .then(() => process.exit(0))
- .catch((error) => {
- console.error("❌ Error:", error)
- process.exit(1)
- })
- }
|