调用其他智能合约带参函数时require(success)校验失败问题求助
问题排查与解决方案
语法错误修正
你提供的调用方合约代码存在两处基础语法错误,是导致校验失败的常见原因:
- 变量名拼写不一致:调用返回值声明为
sucess(缺少字母c),后续require校验使用的是正确拼写的success,会直接触发校验失败 - 语句缺少右括号:
call方法的调用语句末尾少了闭合括号,会导致编译或执行异常
修正后的基础调用代码如下:
contract Caller is Owner { function callOtherContract(uint256 number) external onlyOwner { (bool success,)=contractAddress.call(abi.encodeWithSignature("doSomething(uint256,address)", number, msg.sender)); require(success, "call failed"); } }
建议给require语句添加错误提示信息,方便后续定位具体失败原因
低级别调用参数问题排查
如果修正语法后仍调用失败,可按以下方向排查低级别call的参数问题:
- 确认函数签名完全匹配:
abi.encodeWithSignature的参数字符串中,参数类型之间不能有空格,必须和目标合约的函数定义完全一致,你当前使用的"doSomething(uint256,address)"符合规范,如果之前的写法包含空格会导致函数选择器计算错误,触发调用失败 - 手动指定gas限制:低级别
call默认分配的gas可能不足以支撑目标合约函数的执行逻辑,可手动指定gas额度:(bool success, ) = contractAddress.call{gas: 100000}(abi.encodeWithSignature("doSomething(uint256,address)", number, msg.sender)); - 确认
contractAddress变量存储的是ToCall合约的正确部署地址,地址错误会调用到空合约直接返回失败
更稳妥的替代方案:接口调用
低级别call不会做参数类型、函数存在性的前置校验,很容易出现隐式错误,更推荐使用接口方式调用,编译阶段即可暴露绝大多数问题,代码也更简洁安全:
- 首先定义
ToCall合约的对应接口:
interface IToCall { function doSomething(uint256 number, address aRandomAddress) external; }
- 改造调用方合约逻辑:
contract Caller is Owner { IToCall public immutable toCallContract; // 部署时传入ToCall合约的实际地址 constructor(address _toCallAddr) { toCallContract = IToCall(_toCallAddr); } function callOtherContract(uint256 number) external onlyOwner { toCallContract.doSomething(number, msg.sender); } }
权限校验确认
你提到已经将第二个合约设置为第一个合约的所有者,可再次确认两点:
- 调用
transferOwnership时传入的是Caller合约的部署地址,而非你个人的外部账户地址 ToCall合约的onlyOwner修饰符逻辑正常,没有额外的隐藏校验规则
内容的提问来源于stack exchange,提问作者iMeaNz
相关产品推荐
相关产品推荐

