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

go-ethereum是否支持无需ABI的输入数据编解码操作

go-ethereum 轻量ABI编解码实现方案

go-ethereum 原生提供了和 web3.js 对等的编解码能力,无需加载完整合约ABI文件,仅需指定参数类型即可完成以太坊交易输入数据的编码、解码操作,相关能力封装在官方标准包 accounts/abi 中。


1. 参数解码(对应web3.js decodeParameters)

你只需要按参数顺序传入类型列表、待解码的十六进制数据,即可完成解码,不需要提前导入完整合约ABI。
示例代码(和web3.js示例使用完全相同的测试数据):

package main

import (
	"fmt"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"
	"math/big"
)

func main() {
	// 按顺序定义参数类型,和web3.js传入的类型数组一一对应
	paramTypes := []string{"uint256", "uint256", "address[]", "address", "uint256"}
	args := make(abi.Arguments, len(paramTypes))
	for idx, typeStr := range paramTypes {
		t, err := abi.NewType(typeStr, "", nil)
		if err != nil {
			panic(err)
		}
		args[idx] = abi.Argument{Type: t}
	}

	// 待解码原始数据(可不带0x前缀)
	rawHex := "000000000000000000000000000000000000000000000001885c663d0035bce200000000000000000000000000000000000000000000000000f5666f7fdaa62600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000c0be713b48822271b362e9fac00479f5134172e80000000000000000000000000000000000000000000000000000000060e93fa900000000000000000000000000000000000000000000000000000000000000020000000000000000000000009813037ee2218799597d83d4a5b6f3b6778218d9000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
	inputBytes := common.Hex2Bytes(rawHex)

	// 执行解码
	decodeRes := make(map[string]interface{})
	err := args.UnpackIntoMap(decodeRes, inputBytes)
	if err != nil {
		panic(err)
	}

	// 输出结果和web3.js完全一致:
	// decodeRes["0"] = 28272584972907691234(*big.Int类型)
	// decodeRes["1"] = 69073998366549542(*big.Int类型)
	// decodeRes["2"] = 长度为2的地址切片
	// decodeRes["3"] = 0xc0Be713B48822271b362e9Fac00479f5134172e8(common.Address类型)
	// decodeRes["4"] = 1625898921(*big.Int类型)
	fmt.Printf("%+v\n", decodeRes)
}

2. 函数调用编码(对应web3.js encodeFunctionCall)

仅需传入函数名、参数类型列表、待编码参数值,即可生成符合ABI规范的合约调用数据,无需完整ABI。
示例代码(和web3.js示例使用完全相同的测试参数):

package main

import (
	"fmt"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"math/big"
)

func main() {
	// 定义函数基础信息、输入参数类型
	methodName := "myMethod"
	inputParamTypes := []string{"uint256", "string"}
	inputArgs := make(abi.Arguments, len(inputParamTypes))
	for idx, typeStr := range inputParamTypes {
		t, err := abi.NewType(typeStr, "", nil)
		if err != nil {
			panic(err)
		}
		inputArgs[idx] = abi.Argument{Type: t}
	}
	method := abi.NewMethod(methodName, methodName, abi.Function, "", false, false, inputArgs, abi.Arguments{})

	// 传入待编码参数值
	params := []interface{}{
		big.NewInt(2345675643),
		"Hello!%",
	}

	// 打包参数、拼接4字节函数选择器
	packedParams, err := method.Inputs.Pack(params...)
	if err != nil {
		panic(err)
	}
	fullCallData := append(method.ID, packedParams...)

	// 输出结果和web3.js完全一致:0x24ee0097000000000000000000000000000000000000000000000000000000008bd02b7b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000748656c6c6f212500000000000000000000000000000000000000000000000000
	fmt.Printf("0x%x\n", fullCallData)
}

使用说明

  • 所有Solidity支持的类型(动态数组、结构体、嵌套类型等)都可以通过abi.NewType直接解析,不需要依赖完整ABI JSON文件
  • 解码返回值的类型映射规则:整数统一为*big.Int、地址为common.Address、动态字节为[]byte、字符串为string、数组/定长数组对应Go切片/数组
  • 如果解码带函数选择器的完整调用数据,需要先截掉前4字节的选择器部分,再传入解码方法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:09:19