You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Go-ethereum解码以太坊交易输入数据遇RLP错误求助

问题根源

以太坊智能合约交易的输入数据(前4字节为函数选择器,剩余部分为函数参数)采用ABI编码,而非你使用的RLP编码。RLP仅用于以太坊底层数据(如交易本体、区块头)的序列化,不适用于合约函数参数解码,这是导致你遇到rlp: expected input list for []main.SwapFunction错误的核心原因。

解决方案

使用go-ethereum的accounts/abi包进行ABI解码,步骤如下:

1. 获取目标合约的ABI

从交易对应的合约页面导出ABI(可通过交易详情页的合约地址跳转获取),将其保存为字符串或本地文件。

2. 调整代码逻辑

替换原有的RLP解码逻辑,改用ABI解码。以下是修改后的完整代码:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"math/big"

	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"
)

// 保持原结构体定义不变,需与ABI中的函数参数结构匹配
type SwapDescription struct {
	SrcToken         common.Address
	DstToken         common.Address
	SrcReceiver      common.Address
	DstReceiver      common.Address
	Amount           *big.Int
	MinReturnAmount  *big.Int
	GuaranteedAmount *big.Int
	Flags            *big.Int
	Referrer         common.Address
	Permit           []byte
}

type CallDescription struct {
	TargetWithMandatory *big.Int
	GasLimit            *big.Int
	Value               *big.Int
	Data                []byte
}

type SwapFunction struct {
	Caller common.Address
	Desc   SwapDescription
	Calls  []CallDescription
}

func main() {
	// 连接以太坊网络
	client, err := ethclient.Dial("https://eth-mainnet.alchemyapi.io/jsonrpc/MY-API-KEY")
	if err != nil {
		fmt.Println("连接以太坊网络失败:", err)
		return
	}

	// 交易哈希
	txHash := "0xd918b14504b82d4c5334a751e0439826e682a57c6813f16a707801f89f589b90"
	hash := common.HexToHash(txHash)

	tx, isPending, err := client.TransactionByHash(context.Background(), hash)
	if err != nil {
		fmt.Println("获取交易失败:", err)
		return
	}
	if isPending {
		fmt.Println("交易处于pending状态")
		return
	}

	input := tx.Data()
	if len(input) < 4 {
		fmt.Println("输入数据长度不足")
		return
	}

	// 1. 填入目标合约的ABI字符串(从合约页面复制)
	abiStr := `[{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"struct ISwapRouter.SwapDescription","name":"desc","type":"tuple"},{"internalType":"struct ISwapRouter.CallDescription[]","name":"calls","type":"tuple[]"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"}]`

	// 2. 解析ABI
	contractABI, err := abi.JSON(json.RawMessage(abiStr))
	if err != nil {
		fmt.Println("解析ABI失败:", err)
		return
	}

	// 3. 解码函数参数
	var decodedData SwapFunction
	err = contractABI.UnpackIntoInterface(&decodedData, "swap", input[4:])
	if err != nil {
		fmt.Println("解码参数失败:", err)
		return
	}

	// 输出解码结果
	fmt.Printf("解码后的Caller: %s\n", decodedData.Caller.Hex())
	fmt.Printf("SrcToken: %s\n", decodedData.Desc.SrcToken.Hex())
	fmt.Printf("Amount: %s\n", decodedData.Desc.Amount.String())
	// 可按需输出其他字段
}

关键说明

  • 确保abiStr中的函数定义与交易调用的函数完全匹配(包括参数名称、类型、顺序),否则解码会失败。
  • 如果合约ABI包含更多函数,只需保留目标函数swap的ABI片段即可,无需完整ABI。
  • ABI解码会自动处理以太坊数据类型与Go语言类型的映射(如address对应common.Address,uint256对应*big.Int)。

内容的提问来源于stack exchange,提问作者chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 14:21:31