02-distribute-tokens.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import "dotenv/config"
  2. import { ethers } from "ethers"
  3. import * as fs from "fs"
  4. import * as path from "path"
  5. import { MockUSD1__factory, BasicERC20__factory } from "../typechain-types/factories/contracts"
  6. import type { MockUSD1, BasicERC20 } from "../typechain-types/contracts"
  7. // NonceManager类用于管理nonce
  8. class NonceManager {
  9. private nonce: number
  10. private provider: ethers.Provider
  11. private address: string
  12. constructor(provider: ethers.Provider, address: string, initialNonce?: number) {
  13. this.provider = provider
  14. this.address = address
  15. this.nonce = initialNonce || 0
  16. }
  17. async getNextNonce(): Promise<number> {
  18. if (this.nonce === 0) {
  19. // 从网络获取当前nonce
  20. const currentNonce = await this.provider.getTransactionCount(this.address)
  21. this.nonce = currentNonce
  22. }
  23. return this.nonce++
  24. }
  25. async resetNonce(): Promise<void> {
  26. const currentNonce = await this.provider.getTransactionCount(this.address)
  27. this.nonce = currentNonce
  28. }
  29. }
  30. async function main() {
  31. // 获取环境配置
  32. const environment = process.env.ENVIRONMENT || "bsctest"
  33. const rpcUrl = process.env.RPC_URL || "https://data-seed-prebsc-1-s1.binance.org:8545/"
  34. const outputDir = process.env.OUTPUT_DIR || "./output/bsctest"
  35. console.log(`🚀 第2步:向所有账户分发测试代币...`)
  36. console.log(`🌍 环境: ${environment}`)
  37. console.log(`🔗 RPC: ${rpcUrl}`)
  38. console.log(`📁 输出目录: ${outputDir}`)
  39. // 检查环境变量
  40. if (!process.env.PRIVATE_KEY) {
  41. console.error("❌ 需要设置 PRIVATE_KEY 环境变量")
  42. process.exit(1)
  43. }
  44. // 从之前的步骤加载合约地址
  45. const contractAddressesPath = path.join(outputDir, "contract-addresses.json")
  46. if (!fs.existsSync(contractAddressesPath)) {
  47. console.error(`❌ 未找到 ${contractAddressesPath} 文件。请先运行第1步。`)
  48. process.exit(1)
  49. }
  50. const contractAddresses = JSON.parse(fs.readFileSync(contractAddressesPath, "utf8"))
  51. console.log("📋 已从之前的步骤加载合约地址")
  52. // 设置提供者和部署者
  53. const provider = new ethers.JsonRpcProvider(rpcUrl)
  54. const deployer = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
  55. // 为部署者初始化NonceManager
  56. const nonceManager = new NonceManager(provider, deployer.address)
  57. // 连接到已部署的合约
  58. const mockUSD1 = MockUSD1__factory.connect(contractAddresses.mockUSD1, deployer)
  59. // 从JSON文件加载测试账户
  60. const testAccountsPath = "./scripts/testAccount/BLaunchpadTest.json"
  61. if (!fs.existsSync(testAccountsPath)) {
  62. console.error("❌ 未找到测试账户文件:", testAccountsPath)
  63. process.exit(1)
  64. }
  65. const testAccounts = JSON.parse(fs.readFileSync(testAccountsPath, "utf8"))
  66. console.log("📋 已从", testAccountsPath, "加载", testAccounts.length, "个测试账户")
  67. // 向所有测试账户分发MockUSD1
  68. console.log("\n💰 向所有测试账户分发MockUSD1...")
  69. const usd1Amount = ethers.parseEther("20000") // 每个账户20K USD1
  70. for (let i = 0; i < testAccounts.length; i++) {
  71. const account = testAccounts[i]
  72. const userWallet = new ethers.Wallet(account.privateKey, provider)
  73. const tokenBalance = await mockUSD1.balanceOf(userWallet.address)
  74. // 如果余额不足20K,需要补充
  75. if (tokenBalance < ethers.parseEther("20000")) {
  76. const needToMint = ethers.parseEther("20000") - tokenBalance
  77. try {
  78. const nonce = await nonceManager.getNextNonce()
  79. const tx = await mockUSD1.connect(deployer).mint(userWallet.address, needToMint, { nonce })
  80. console.log(`✅ 账户 ${i + 1}: ${userWallet.address} - 补充 ${ethers.formatEther(needToMint)} USD1 (总计: ${ethers.formatEther(usd1Amount)})`)
  81. } catch (error) {
  82. console.error(`❌ 为账户 ${i + 1} 铸造USD1失败:`, error)
  83. // 出错时重置nonce
  84. await nonceManager.resetNonce()
  85. }
  86. } else {
  87. console.log(`✅ 账户 ${i + 1}: ${userWallet.address} - 已有足够余额 ${ethers.formatEther(tokenBalance)} USD1`)
  88. }
  89. }
  90. // 向所有测试账户分发真实BNB作为gas费用
  91. console.log("\n💰 向所有测试账户分发BNB作为gas费用...")
  92. const bnbGasAmount = ethers.parseEther("0.01") // 每个账户0.01 BNB用于gas
  93. for (let i = 0; i < testAccounts.length; i++) {
  94. const account = testAccounts[i]
  95. const userWallet = new ethers.Wallet(account.privateKey, provider)
  96. const balance = await provider.getBalance(userWallet.address)
  97. if (balance < bnbGasAmount) {
  98. try {
  99. const nonce = await nonceManager.getNextNonce()
  100. const tx = await deployer.sendTransaction({
  101. to: userWallet.address,
  102. value: bnbGasAmount,
  103. nonce: nonce,
  104. })
  105. await tx.wait()
  106. console.log(`✅ 账户 ${i + 1}: ${userWallet.address} - ${ethers.formatEther(bnbGasAmount)} BNB用于gas`)
  107. } catch (error) {
  108. console.error(`❌ 向账户 ${i + 1} 发送BNB失败:`, error)
  109. // 出错时重置nonce
  110. await nonceManager.resetNonce()
  111. }
  112. } else {
  113. console.log(`✅ 账户 ${i + 1}: ${userWallet.address} - ${ethers.formatEther(balance)} BNB`)
  114. }
  115. }
  116. // 分发TestBNB(使用BasicERC20作为TestBNB)给所有测试账户
  117. console.log("\n💰 向所有测试账户分发TestBNB...")
  118. // 检查前3个账户的余额(主要测试账户)
  119. console.log("\n📊 主要测试账户余额检查:")
  120. for (let i = 0; i < Math.max(3, testAccounts.length); i++) {
  121. const account = testAccounts[i]
  122. const userWallet = new ethers.Wallet(account.privateKey, provider)
  123. const usd1Balance = await mockUSD1.balanceOf(userWallet.address)
  124. const realBnbBalance = await provider.getBalance(userWallet.address)
  125. console.log(`账户 ${i + 1} (${userWallet.address}):`)
  126. console.log(` - USD1: ${ethers.formatEther(usd1Balance)}`)
  127. console.log(` - 真实BNB: ${ethers.formatEther(realBnbBalance)}`)
  128. }
  129. console.log("\n🎉 代币分发成功完成!")
  130. console.log("\n📋 总结:")
  131. console.log("- 总账户数:", testAccounts.length)
  132. console.log("- 每个账户USD1:", ethers.formatEther(usd1Amount))
  133. console.log("- 每个账户真实BNB:", ethers.formatEther(bnbGasAmount))
  134. console.log("- MockUSD1地址:", contractAddresses.mockUSD1)
  135. }
  136. // 导出main函数供多环境脚本调用
  137. export { main }
  138. // 如果直接运行此脚本
  139. if (require.main === module) {
  140. main()
  141. .then(() => process.exit(0))
  142. .catch((error) => {
  143. console.error("❌ Error:", error)
  144. process.exit(1)
  145. })
  146. }