OpenZeppelin+Remix创建ERC20代币调用transferFrom报错超限问题排查
错误信息:Returned error: execution reverted: ERC20: transfer amount exceeds allowance
问题原因
- ERC20的
transferFrom方法设计要求:转出账户必须提前给调用transferFrom的操作地址授权对应额度的代币操作权限,你当前没有执行授权步骤,所以合约判定额度不足触发报错。 - 你代码中调用transferFrom时使用了
.call()方法,call是只读调用,不会提交交易上链修改状态,就算完成授权,用call调用transferFrom也不会真正完成转账操作。 - 额外注意:如果你的代币精度(decimals)为默认的18,代码中写的转账金额100实际对应0.0000000000000001枚代币,并非100枚代币,后续调整参数时需要做精度换算。
修复方案
方案1:先授权再调用transferFrom(适用于第三方代转场景)
先调用approve方法完成授权,再执行transferFrom,所有写操作都要用.send()方法提交上链,示例代码如下:
const Web3 = require('web3') const Apk = require('./build/contracts/APKTEST.json') // 注意Ropsten测试网已废弃,建议替换为Sepolia/Goerli测试网节点 let web3 = new Web3(new Web3.providers.HttpProvider('https://sepolia.infura.io/v3/你的infuraID')) const fromAddr = '0x6a6447CB492186a334ca2A51561D2D70659Ab0B1' const toAddr = '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4' web3.eth.defaultAccount = fromAddr const contractAbi = new web3.eth.Contract(Apk.abi, '0xc45701C31357F0b5a9a22015E2b2601C9cA59A86') // 第一步:查询余额 contractAbi.methods.balanceOf(fromAddr).call().then(res => { console.log("余额为:", res) // 第二步:给当前操作地址授权1000枚代币额度(按18位精度换算) return contractAbi.methods.approve(fromAddr, web3.utils.toWei('1000', 'ether')).send({ from: fromAddr, gas: 200000 }) }).then(approveRes => { console.log("授权成功", approveRes.transactionHash) // 第三步:调用transferFrom转账100枚代币 return contractAbi.methods.transferFrom(fromAddr, toAddr, web3.utils.toWei('100', 'ether')).send({ from: fromAddr, gas: 200000 }) }).then(transferRes => { console.log("转账成功", transferRes.transactionHash) }).catch(err => { console.log("操作失败", err) })
方案2:直接调用transfer方法(适用于自己的账户向外转账的场景)
如果转出账户就是当前发起交易的账户,不需要用transferFrom,直接调用transfer方法即可,省去授权步骤:
// 初始化代码和方案1一致 contractAbi.methods.transfer(toAddr, web3.utils.toWei('100', 'ether')).send({ from: fromAddr, gas: 200000 }).then(res => { console.log("转账成功", res.transactionHash) }).catch(err => { console.log("转账失败", err) })
内容的提问来源于stack exchange,提问作者akolol40
相关产品推荐
相关产品推荐

