合约内执行0x API v1多order报价触发回滚问题咨询
0x API v1多订单场景quote填充失败排查原因
以下是对应问题的根因排查方向:
- 授权对象覆盖不全:多订单聚合报价对应多个流动性来源,需要授权的spender地址不止1个,你当前的
fillQuote函数仅对传入的单个spender地址做了最大额度授权,其余流动性源对应的spender没有sellToken的划转权限,会直接触发回滚。单订单场景仅需授权1个spender,因此可以正常执行。 - Gas额度不足:多订单聚合swap的执行逻辑远复杂于单订单,消耗的gas量通常是单订单的2-5倍,若调用
fillQuote时指定的gas limit不足,会直接导致执行中断回滚。你可以先将调用时的gas limit调高3倍以上做验证。 - call调用缺少value参数:部分多订单路由逻辑会涉及中间币种的wrap/unwrap操作,或部分流动性源的交互要求传递对应ETH value,你当前的调用写法
swapTarget.call(swapCallData)没有传递value值,若call data中包含需要ETH支付的逻辑就会回滚。 - 自定义ERC20授权逻辑兼容问题:你代码中使用
require(MyIERC20(sellToken).approve(spender, type(uint).max))做授权校验,若多订单场景下涉及的授权对象对应代币实现不符合标准(比如approve方法不返回布尔值),会直接触发require校验失败回滚。 - swapCallData截断问题:多订单对应的swapCallData长度远大于单订单,若你在链下传递call data时存在截断,也会导致swapTarget执行时逻辑异常回滚。
你当前使用的fillQuote函数可优化为如下版本做初步验证:
function fillQuote( address sellToken, address buyToken, address[] calldata spenders, // 传入所有需要授权的spender列表 address swapTarget, bytes calldata swapCallData, uint256 callValue // 传入call需要的ETH value ) public payable { // 增加payable修饰符支持接收ETH // 批量给所有spender授权 for (uint256 i = 0; i < spenders.length; i++) { // 兼容无返回值的ERC20实现,先授权到0再设置最大额度 MyIERC20(sellToken).approve(spenders[i], 0); MyIERC20(sellToken).approve(spenders[i], type(uint256).max); } // 传递value调用 (bool success, bytes memory returnData) = swapTarget.call{value: callValue}(swapCallData); if (!success) { console.log(Helpers._getRevertMsg(returnData)); } require(success, 'SWAP_CALL_FAILED'); }
内容的提问来源于stack exchange,提问作者dNyrM
相关产品推荐
相关产品推荐

