Solidity合约applyReferralCode函数跳转无关函数致授权失败问题
问题核心
用非owner地址调用applyReferralCode时触发!NOTAUTHORIZED错误,调试显示跳转到带onlyOwner/authorized修饰器的无关函数,但owner地址调用正常,且所有require条件均满足。
可能原因
removeRefWhitelistWallet函数的权限限制
你的applyReferralCode最后调用了removeRefWhitelistWallet(msg.sender),如果这个函数被添加了onlyOwner之类的权限修饰器,非owner地址执行到这一步时必然触发权限错误,这是最可能的根源。函数选择器冲突
Solidity通过函数签名的前4字节(选择器)识别要执行的函数,如果applyReferralCode的选择器和某个带权限修饰器的函数选择器完全一致,就会导致调用时跳转到错误的函数。调试器显示误解
Remix调试时的"跳转"可能是revert后的栈回溯,并非真的执行了无关函数,实际错误可能来自当前函数调用的子函数(比如上述的removeRefWhitelistWallet)。
排查步骤
检查
removeRefWhitelistWallet的权限修饰器
直接查看这个函数的定义,确认是否带有onlyOwner或类似限制。如果有,临时注释掉applyReferralCode里的removeRefWhitelistWallet(msg.sender)调用,再用非owner地址测试,若调用成功,即可锁定问题。验证函数选择器是否冲突
在Remix控制台或测试合约中计算并对比函数选择器:// 计算applyReferralCode的选择器 bytes4 applySelector = bytes4(keccak256("applyReferralCode(string)")); console.logHex(applySelector); // 计算带权限修饰器的函数(比如removeRefWhitelistWallet)的选择器 bytes4 removeSelector = bytes4(keccak256("removeRefWhitelistWallet(address)")); console.logHex(removeSelector);如果两个选择器相同,说明存在冲突。
查看完整调用栈
在Remix调试时,展开调用栈面板,追踪错误触发的具体位置,确认是哪个函数抛出了!NOTAUTHORIZED。
解决办法
调整
removeRefWhitelistWallet的权限逻辑
如果业务逻辑允许用户自己移除白名单,去掉该函数的onlyOwner修饰器;如果需要保留权限,就修改applyReferralCode的逻辑,比如让owner在后台处理白名单移除,或者添加特定权限允许用户执行此操作。解决函数选择器冲突
修改冲突函数的名称或参数列表,比如把applyReferralCode(string)改成applyReferralCode(string calldata)(仅修改参数位置不影响功能),或者重命名函数为applyUserReferralCode(string),重新生成唯一的选择器。
内容的提问来源于stack exchange,提问作者AJPete

