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

React+Solidity开发DApp调用ERC20 transfer报-32000执行回滚错误

报错核心原因
  • 调用方法使用错误:你写的await contract.transfer.call(account, 50)是只读模拟调用,不会发起真实的链上交易,且本地模拟时如果未指定发送地址,msg.sender不是你当前连接的钱包地址,直接触发合约里require(numTokens <= balances[msg.sender])的余额校验,交易回滚抛出execution reverted错误。
  • 概念理解偏差:transfer()是ERC20代币转账函数,本身不需要payable修饰符,只有需要接收链原生币(Rinkeby测试网ETH)的函数才需要加payable,你之前对函数属性的认知是错的。
  • 数值精度问题:ERC20代币默认采用18位精度,直接传整数50实际只对应0.00000000000000005个代币,如果你要转50个完整单位的代币,数值需要做精度转换,这个是后续会触发逻辑异常的隐藏问题。
修复步骤

1. 修正前端调用逻辑

完全去掉.call调用,改用发起交易的方法,根据你用的库选对应写法:

web3.js 版本

// 获取当前连接的钱包地址
const accounts = await web3.eth.getAccounts()
const currentAccount = accounts[0]
// 做精度转换,18位精度和ETH单位规则一致,直接用toWei转换即可
const transferValue = web3.utils.toWei('50', 'ether')
// 发起真实链上交易,指定发送方为当前钱包地址
await contract.methods.transfer(接收方钱包地址, transferValue).send({
  from: currentAccount
})

ethers.js 版本

// 获取当前钱包签名者
const signer = await provider.getSigner()
// 精度转换,第二个参数填你合约设置的decimals值,默认是18
const transferValue = ethers.utils.parseUnits('50', 18)
// 连接签名者后发起交易
await contract.connect(signer).transfer(接收方钱包地址, transferValue)

2. 合约侧校验

  • 确认你已经给测试用的钱包地址mint了足够数量的测试代币,余额不足的话哪怕调用方式正确,还是会触发require校验回滚。
  • 不要给transfer函数添加payable修饰符,否则用户调用时误转的ETH会永久锁在合约里,没有对应提币逻辑就无法取出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:24:35