Web3调用ERC20代币Approve方法时Metamask弹窗后持续加载转圈
ERC20 approve调用卡交易的修复方案
核心问题是裸调用send()方法未处理交易全生命周期的事件回调,叠加本地开发环境的常见配置错误,导致前端拿不到交易终态信号一直卡在加载状态,按以下步骤修复即可:
- 补全send方法的全流程事件监听,不要只写单行裸调用。web3.js的合约send方法返回异步promise,需要绑定对应事件才能拿到交易提交、上链、报错的状态信号,否则前端无法感知交易是否完成,参考修复后的代码:
// 建议将接收授权的地址变量重命名为spenderAddress,避免和web3内置address对象冲突 const spenderAddress = "你要授权的第三方地址" this.state.token.methods.approve(spenderAddress, '100000000000000000000') .send({ from: this.state.account, // Ganache本地链自动估gas偶尔不准,手动加6w gas限制足够覆盖approve方法的执行消耗 gas: 60000 }) .on('transactionHash', (hash) => { // 拿到交易哈希时触发,此时交易刚提交到节点,可以把加载状态改为"交易确认中" console.log('交易已提交,链上哈希:', hash) }) .on('receipt', (receipt) => { // 交易被区块打包确认时触发,在这里关闭加载器,执行授权成功后的后续业务逻辑 console.log('授权成功,交易回执:', receipt) }) .on('error', (err) => { // 用户拒签、交易执行失败时触发,在这里关闭加载器,弹出错误提示 console.error('交易执行异常:', err) })
检查参数合法性
- 确认传入的spender地址是合法的42位十六进制地址,Remix会自动做地址格式校验,但web3.js不会,格式错误的地址会导致交易在节点侧长时间卡pending
- 确认传入的授权额度是字符串格式,你当前写的
100000000000000000000对应精度18的100枚代币,格式本身没问题,但要确认你部署的ERC20合约精度确实是18,且授权额度不超过当前账户的持仓总量
检查本地链环境匹配
- 打开MetaMask确认当前选中的网络就是你部署合约的Ganache本地网络,链ID、RPC地址要和Ganache启动面板的配置完全一致,切错网络会导致交易发往其他节点,本地环境收不到交易自然不会返回回执
- 确认初始化合约实例用的合约地址,是当前Ganache网络下部署的ERC20地址,不要混用其他测试网/旧启动实例的合约地址
- 连接Ganache时关闭系统代理,代理会拦截本地RPC接口的响应,导致前端拿不到交易上链的回调
Ganache专属异常修复
如果改完代码还是卡,直接打开Ganache的交易面板看交易状态:如果面板里已经显示交易成功但前端没收到回执,打开MetaMask的设置-高级选项,点击「重置账户」清空本地缓存的nonce记录,同时重启Ganache即可。本地测试链运行久了容易出现nonce不匹配、状态不同步的问题,重置后就能正常响应。
内容的提问来源于stack exchange,提问作者Naveed Ali
相关产品推荐
相关产品推荐

