You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Hardhat投票脚本中切换使用命名用户账户

问题描述

我正在开发一个简单的治理协议,跟随教程编写的代码已能正常运行。

在Hardhat配置文件中,我已在accounts字段添加了两个私钥:

const config: HardhatUserConfig = {
  defaultNetwork: "hardhat",
  networks: {
    hardhat: {
      chainId: 31337,
      allowUnlimitedContractSize: true
    },
    mumbai: {
      url: INFURA_RPC_URL,
      accounts: [PRIVATE_KEY, PRIVATE_KEY_2],
      chainId: 80001,
    },
  },
//...
}

我编写了部署脚本用于创建治理代币:

const deployGovernanceToken: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
  // @ts-ignore
  const { getNamedAccounts, deployments, network } = hre
  const { deploy, log } = deployments
  const { deployer, user } = await getNamedAccounts()
  const governanceToken = await deploy("GovernanceToken", {
    from: deployer, args: [], log: true,
    waitConfirmations: networkConfig[network.name].blockConfirmations || 1,
  })
  await delegate(governanceToken.address, deployer, user)
  //...
}

const delegate = async (governanceTokenAddress: string, delegatedAccount: string, userAccount: string) => {
  const governanceToken = await ethers.getContractAt("GovernanceToken", governanceTokenAddress)
  const transactionResponse = await governanceToken.mint(userAccount, "10000000000000000000000000");
  await transactionResponse.wait(1)
  console.log(`Checkpoints: ${await governanceToken.numCheckpoints(delegatedAccount)}`)
}

此外我还有一个用于提案投票的脚本:

export async function vote(proposalId: string, voteWay: number, reason: string) {
  console.log("Voting...")
  const signer = await ethers.getSigners()

  console.log('signers:' + signer);

  const governor = await ethers.getContract("GovernorContract")
  const voteTx = await governor.castVoteWithReason(proposalId, voteWay, reason)
  const voteTxReceipt = await voteTx.wait(1)
  console.log(voteTxReceipt.events[0].args.reason)
  const proposalState = await governor.state(proposalId)
  console.log(`Current Proposal State: ${proposalState}`)
  if (developmentChains.includes(network.name)) {
    await moveBlocks(VOTING_PERIOD + 1)
  }
}

请问如何修改投票脚本,使其使用预先配置的命名user账户进行投票?


解决方案

要让投票脚本使用预先配置的user命名账户,核心是通过Hardhat的getNamedAccounts获取该账户地址,再拿到对应签名器,最后用这个签名器连接合约发起交易。

修改后的投票脚本

import { ethers, network } from "hardhat"
import { developmentChains, moveBlocks } from "../helper-hardhat-config" // 确保导入项目依赖的工具函数

export async function vote(proposalId: string, voteWay: number, reason: string) {
  console.log("Voting...")
  
  // 获取预先配置的user命名账户地址
  const { user } = await ethers.getNamedAccounts()
  // 通过user地址获取对应的签名器(用于发起交易)
  const userSigner = await ethers.getSigner(user)

  console.log(`Using user account: ${user}`)

  // 用user签名器连接Governor合约,确保交易由user账户发起
  const governor = await ethers.getContract("GovernorContract", userSigner)
  const voteTx = await governor.castVoteWithReason(proposalId, voteWay, reason)
  const voteTxReceipt = await voteTx.wait(1)

  console.log(voteTxReceipt.events[0].args.reason)
  const proposalState = await governor.state(proposalId)
  console.log(`Current Proposal State: ${proposalState}`)

  if (developmentChains.includes(network.name)) {
    await moveBlocks(VOTING_PERIOD + 1)
  }
}

关键修改说明

  1. 获取命名账户:通过ethers.getNamedAccounts()拿到配置好的user账户地址,这要求你在Hardhat配置中提前定义namedAccounts映射。
  2. 获取对应签名器:用ethers.getSigner(user)拿到user账户的签名实例,后续交易都会由该账户签名。
  3. 签名器连接合约:在获取GovernorContract实例时传入userSigner,替代默认的部署者签名器,确保投票交易由user账户发起。

补充配置要求

如果你的Hardhat配置里还没定义namedAccounts,需要在hardhat.config.ts中添加如下配置,让user对应到你配置的第二个私钥:

// hardhat.config.ts中新增配置
namedAccounts: {
  deployer: {
    default: 0, // 对应accounts数组中的第一个私钥(PRIVATE_KEY)
  },
  user: {
    default: 1, // 对应accounts数组中的第二个私钥(PRIVATE_KEY_2)
  },
}

内容的提问来源于stack exchange,提问作者Ritzy Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 20:15:32