ERC20代币转至未使用地址时出现0授权错误,求调试方案
ERC20InsufficientAllowance错误排查:已设置最高授权但调用transferFrom时授权额度为0
开发了一套ERC20代币系统,包含XYZtoken.sol与DiscountContract.sol两个合约,核心逻辑为:用户购买商品获得代币、使用代币兑换折扣后,将对应代币转至死地址0x000000000000000000000000000000000000dEaD。
但执行purchaseProducts函数时触发ERC20InsufficientAllowance错误,提示授权额度为0,尽管已通过合约设置最高额度授权。本人Solidity经验有限,缺乏便捷调试手段,已耗时4小时仍未解决,附上合约代码及错误详情,请求帮助排查问题。
合约代码
XYZtoken.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract XYZtoken is ERC20 { address payable public owner; constructor(uint256 initialSupply) ERC20("XYZtoken", "XYZT") { owner = payable (msg.sender); _mint(owner, initialSupply); } function mintExtraTokens(uint256 amount) public onlyOwner { _mint(owner, amount); } function approveDiscountContract(address spender, uint256 amount) public{ _approve(owner, spender, amount); } // function usedToken(address unspentaddress, uint256 amount) public { // _burn(unspentaddress, amount); // } function balanceOf() view public { balanceOf(msg.sender); } modifier onlyOwner { require(msg.sender == owner, "Only owner can access this function"); _; } }
DiscountContract.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./XYZtoken.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract DiscountContract { XYZtoken public token; address payable public companyAddress; address public unspentAddress; struct Customer { uint256 tokensEarned; // uint256 discountRate; } mapping(address => Customer) public customers; event TokensEarned(address indexed customer, uint256 amount); event DiscountAvailed(address indexed customer, uint256 discountRate); event TokensSentToCompanyAddress(address indexed customer, uint256 tokensSent); event BalanceLogged(address sender, uint256 amount); event excessPaidBack(address sender, uint256 amount); constructor(address _tokenAddress) { token = XYZtoken(_tokenAddress); companyAddress = payable(msg.sender); unspentAddress = 0x000000000000000000000000000000000000dEaD; token.approveDiscountContract(address(this), type(uint256).max); } function availDiscount(address sender) public view returns (uint256) { if (token.balanceOf(sender) < 10) { return 0; } // Calculate discount rate based on earned tokens uint256 discount = token.balanceOf(sender) / 10; if (discount > 5) { discount = 5; } // Transfer the discount tokens from the customer to the unspent address return discount; } function purchaseProducts(uint256 amount) payable external { address payable sender = payable(msg.sender); // Validate purchase, e.g., product price, availability, etc. require(amount > 0, "Amount must be greater than 0"); require(sender != companyAddress && sender != unspentAddress, "Cannot purchase product"); //Avail the discount using the tokens uint256 discount = availDiscount(sender)*10; require(discount <=10, "The balance is less than discount"); // token.approveDiscountContract(address(this), discount*2); token.approve(address(this), discount); token.transferFrom(sender, unspentAddress, discount); uint256 discountedAmount = ((100-discount)/100)*(amount); //Check whether sufficient balance is present or not in the transaction require(sender.balance >= discountedAmount*(10**18), "Insufficient ETH balance in the contract"); //Transfer ETH to the company for uint256 excessPayment = msg.value - discountedAmount * (10**18); // Refund the excess payment to the purchaser if (excessPayment > 0) { payable(sender).transfer(excessPayment); emit excessPaidBack(sender, excessPayment); } require(msg.value >= discountedAmount * (10**18), "Payment is less than the required amount"); payable(companyAddress).transfer(discountedAmount*10**18); require(msg.value == discountedAmount * (10**18), "Amount sent must match the purchase amount"); require(token.balanceOf(companyAddress) >= discountedAmount, "Insufficient tokens"); uint256 earnedTokens = discountedAmount; // Mint tokens to the customer // token.transferFrom(companyAddress, sender, earnedTokens); // token.transferFrom(sender, earnedTokens); token.transferFrom(companyAddress, sender, earnedTokens); // Update customer's token balance customers[sender].tokensEarned += earnedTokens; emit TokensEarned(sender, earnedTokens); } }
错误信息
transact to DiscountContract.purchaseProducts errored: Error occured: revert. revert The transaction has been reverted to the initial state. Error provided by the contract: ERC20InsufficientAllowance Parameters: { "spender": { "value": "0xd8b934580fcE35a11B58C6D73aDeE468a2833fa8", "documentation": "Address that may be allowed to operate on tokens without being their owner." }, "allowance": { "value": "0", "documentation": "Amount of tokens a `spender` is allowed to operate with." }, "needed": { "value": "10", "documentation": "Minimum amount required to perform a transfer." } } Debug the transaction to get more information.
内容的提问来源于stack exchange,提问作者WannaBeTechGuy
相关产品推荐
相关产品推荐

