调用initRaffle时LINK代币授权失败的问题排查与解决
问题原因分析
- 授权未完成:触发"Allowance failed"的核心原因是调用
initRaffle前,用户账户未给合约授权足够的LINK额度。LINKToken.allowance(msg.sender, address(this))返回的是用户允许合约从自己账户转走的LINK数量,该值小于ChainlinkFee,所以检查不通过。 - 缺失转账逻辑:当前代码仅做了余额和授权检查,但没有实际执行LINK转账操作,即便授权通过,合约也无法获取到用户的LINK。
可行实现方案
方案1:先授权再让合约转账(传统ERC20方式)
修改initRaffle函数,在检查通过后调用transferFrom完成LINK转账:
function initRaffle(address _tokenContract, uint256 _tokenId, uint256 _ticketPrice) external { require(_ticketPrice > 0, "Ticket price must be bigger than 0"); require(LINKToken.balanceOf(msg.sender) >= ChainlinkFee, "Insufficient LINK supplied"); require(LINKToken.allowance(msg.sender, address(this)) >= ChainlinkFee, "Allowance failed"); // 执行LINK转账,从用户账户转至合约 bool transferSuccess = LINKToken.transferFrom(msg.sender, address(this), ChainlinkFee); require(transferSuccess, "LINK transfer failed"); // 后续抽奖初始化逻辑(比如存储NFT信息、设置票价等) }
使用流程:用户需先调用LINK代币合约的approve(address(this), ChainlinkFee)(或更大额度),授权合约可从自己账户转走指定数量的LINK,再调用initRaffle。
方案2:用户直接转账+合约回调(ERC677简化流程)
利用LINK的ERC677代币特性(支持转账时触发合约回调),让用户一次性完成转账和抽奖初始化,无需单独授权:
// 实现ERC677的回调函数,接收用户转账的LINK并处理抽奖初始化 function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external { require(msg.sender == address(LINKToken), "Only LINK token is allowed"); require(amount >= ChainlinkFee, "Insufficient LINK supplied"); // 解析data中的抽奖参数 (address tokenContract, uint256 tokenId, uint256 ticketPrice) = abi.decode(data, (address, uint256, uint256)); require(ticketPrice > 0, "Ticket price must be bigger than 0"); // 后续抽奖初始化逻辑 }
使用流程:用户调用LINK代币合约的transferAndCall(address(this), ChainlinkFee, abi.encode(_tokenContract, _tokenId, _ticketPrice)),即可完成LINK转账并触发抽奖初始化。
内容的提问来源于stack exchange,提问作者gggggggggg
相关产品推荐
相关产品推荐

