BSC测试网ERC20互换授权异常:调用deposit后未收到对应RAHI代币
问题核心原因
- 授权逻辑完全错误:你在
deposit函数内调用BUSD.approve(address(this), _amount)属于无效操作。ERC20的approve方法是代币持有者主动调用,授予第三方操作自己代币的权限,你在合约代码中调用该方法时,发起方是合约地址,相当于合约给自己授权操作合约本身的BUSD,和用户持有的BUSD没有任何关系,自然不会触发Metamask的授权弹窗。正确操作是用户在调用deposit方法前,需要先在钱包侧手动调用fakeBUSD合约的approve方法,传入你的合约地址和要存入的BUSD额度,完成授权后再调用deposit。 - 额度未做校验:你调用
BUSD.allowance(msg.sender, address(this))仅做了查询操作,没有对返回的授权额度做判断,哪怕用户实际授权额度小于要存入的_amount,代码还是会继续执行后续的safeTransferFrom,必然会调用失败。 - RAHI转账逻辑冗余错误:合约自身持有RAHI代币的前提下,不需要走
approve+transferFrom的流程,直接调用RAHI.safeTransfer(msg.sender, payout)即可完成转账,你现有的逻辑是合约给自己授权允许用户转走RAHI,完全没必要还容易触发不必要的错误。 - 兑换计算逻辑存疑:注释标注1个RAHI兑换2BUSD,按两个代币均为18位小数的常规设计,
payout = _amount.mul(1e18).div(price)即可得到对应RAHI数量,你额外多除以1e9的操作如果不是对应RAHI为9位小数的特殊设计,会导致你实际收到的RAHI数量仅为预期的十亿分之一。
修复后的deposit函数参考代码
function deposit(uint256 _amount) external checkIfPaused { require(started, 'Sale has not started'); require(!ended, 'Sale has ended'); // 校验用户给合约的BUSD授权额度足够 require(BUSD.allowance(msg.sender, address(this)) >= _amount, "Insufficient BUSD allowance"); // 计算兑换数量,如果你确认RAHI是9位小数可以保留div(1e9),否则删掉该行 uint256 payout = _amount.mul(1e18).div(price).div(1e9); // 直接转用户的BUSD到合约,不需要在合约内重复做approve BUSD.safeTransferFrom(msg.sender, address(this), _amount); // 直接从合约转RAHI给用户,不需要approve+transferFrom组合操作 RAHI.safeTransfer(msg.sender, payout); emit Deposit(msg.sender, _amount); }
操作步骤调整
- 部署修复后的合约,给合约转入足够的RAHI代币
- 调用
start方法开启兑换 - 用户侧操作:先调用fakeBUSD的
approve方法,授权你的合约地址对应数量的BUSD,Metamask会弹出授权确认窗口,授权完成后再调用合约的deposit方法传入对应数量即可完成兑换
内容的提问来源于stack exchange,提问作者Tryneed
相关产品推荐
相关产品推荐

