Solidity汇编代码出现execution reverted错误,寻求问题排查
问题分析与修复
你的汇编代码触发execution reverted主要是因为内存布局错误导致路由器合约无法识别函数调用,以下是具体问题和修复方案:
函数选择器存储位置错误
构造合约调用数据时,函数选择器必须放在内存起始位置(0x00),你将其存在0x7c,导致路由器无法匹配目标函数,直接触发回滚。
修正:把函数选择器写入0x00:mstore(0x00, SWAP_ETH_FOR_TOKEN)参数内存布局完全错误
Uniswap V2的swapExactETHForTokens(对应你用的SWAP_ETH_FOR_TOKEN选择器)参数的内存布局有严格要求:- 函数选择器(4字节,
0x00-0x03) amountOutMin(uint256,32字节,0x04-0x23)path数组的偏移量(uint256,0x24-0x43)—— 动态数组需指定其在内存中的起始位置to地址(uint256,0x44-0x63)deadline(uint256,0x64-0x83)
此外,你直接存储path的calldata指针是错误的,必须将数组内容复制到内存:
// 把calldata中的address[2]数组复制到内存(0x84起始) calldatacopy(0x84, path.offset, mul(2, 32)) // 设置path数组在call data中的偏移量 mstore(0x24, 0x84)- 函数选择器(4字节,
call指令的输入范围错误
你当前call的起始位置是0x7c、长度0x100,完全指向错误的内存区域。修正后,call的起始应为0x00,长度需覆盖函数选择器+所有参数+数组内容的总长度(示例中为0xC4)。to参数逻辑错误(可选优化)address()获取的是当前合约地址,若要让代币转到调用者账户,应使用caller()(对应Solidity的msg.sender):mstore(0x44, caller())revert指令无效
revert(3,3)的长度为0,无法传递错误信息,建议改为回滚时返回路由器的错误数据:if iszero(success) { returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) }
修正后的完整代码
function swapEthForToken( address router, uint256 minAmount, address[2] calldata path ) public payable { assembly { let deadline := add(timestamp(), 300) // 确保SWAP_ETH_FOR_TOKEN是swapExactETHForTokens的正确选择器(0x7ff36ab5) let swapSelector := SWAP_ETH_FOR_TOKEN // 构造call data内存布局 mstore(0x00, swapSelector) // 函数选择器 mstore(0x04, minAmount) // amountOutMin mstore(0x24, 0x84) // path数组的偏移量 mstore(0x44, caller()) // 接收代币的地址(msg.sender) mstore(0x64, deadline) // deadline // 复制path数组到内存 calldatacopy(0x84, path.offset, mul(2, 32)) // 调用路由器合约 let success := call(gas(), router, callvalue(), 0x00, 0xC4, 0x00, 0x00) // 处理调用失败 if iszero(success) { returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } } }
内容的提问来源于stack exchange,提问作者Mehul Singh Rathore
相关产品推荐
相关产品推荐

