以太坊 ABI 编码 / 解码器

把函数签名加参数转换为精确的 calldata,或粘贴交易中的 calldata 进行解码。完整支持 ABI v2:嵌套数组、元组、动态 bytes 和字符串,并逐字(32 字节)拆解展示。

整数可用十进制或 0x 十六进制(引号可选)。地址、bytes 和字符串需加引号。bytesN 接受 0x 十六进制或文本。
示例:

由浏览器中的 JavaScript 计算。地址不会被上传或存储。

什么是 ABI 编码?

ABI 编码是 Solidity 合约 ABI 规范中把函数调用转换为字节的规则:先是 4 字节选择器,随后是打包成 32 字节字的参数;静态值内联存放,动态值(bytes、字符串、动态数组)放在头部之后,头部记录其字节偏移量。ABI 编码器根据签名和取值构造这段 calldata;解码器则做逆向操作。

布局方式

以 f(uint256,uint32[],bytes10,bytes) 传入 (0x123, [0x456, 0x789], "1234567890", "Hello, world!") 为例,编码结果为:选择器 0x8be65246,然后是四个字组成的头部(uint256、指向数组的偏移量 0x80、右填充的 bytes10、指向 bytes 的偏移量 0xe0),再是尾部:数组长度 2 及其两个元素,接着是 bytes 长度 13 和填充后的数据。点击上方的“Solidity 文档 f()”可逐字查看。

规则简述

实例演示:一笔 ERC-20 转账

transfer(address,uint256),接收方为 0x1111111111111111111111111111111111111111,金额 25 USDT(原始单位 25,000,000),编码后共 68 字节:选择器 a9059cbb,然后是 12 个零字节的左填充加 20 字节地址,再是 25,000,000 = 0x17d7840 左填充为一个 32 字节字。任何区块浏览器中的每一笔 ERC-20 转账都是这个形态,所以解码器仅凭选择器就能识别函数并还原参数。

相关工具

单独计算选择器可使用函数选择器工具;把代币数量换算为原始整数可使用代币小数位换算器;查看单个 32 字节字可使用十六进制转十进制换算器。

常见问题

什么是 ABI 编码?

应用二进制接口(ABI)定义了参数在交易 data 字段中的排布方式:4 字节选择器后跟若干 32 字节字。静态类型内联存放;动态类型(bytes、string、动态数组以及包含它们的元组)在头部用偏移量引用,实际内容放在尾部。

参数应该怎么写?

按参数顺序写成 JSON 数组。整数可用十进制或 0x 十六进制,加不加引号均可;大数值应加引号或用十六进制。地址和字符串需加引号。数组和元组写成嵌套数组,例如 uint256[][] 写成 [[1,2],[3]]。

为什么解码出的数值显示为字符串?

大于 253 的整数无法用 JSON 数字精确表示,因此所有整数都以十进制字符串显示。地址以 EIP-55 校验和格式显示。

可以解码 Etherscan 上的交易吗?

可以。复制 input data,连同函数签名一起粘贴,解码前会先核对选择器与签名是否一致。如果选择器不匹配,你会得到错误提示而不是乱码。

abi.encode 和 abi.encodePacked 有什么区别?

abi.encode 遵循上述标准规则,把每个值填充到 32 字节,因此可以解码。abi.encodePacked 把各值按最小宽度直接拼接,没有填充和偏移量;它更短但存在歧义,不知道类型就无法解码。本工具仅实现标准编码。

支持自定义错误和事件吗?

编码规则完全相同,所以你可以用错误的签名来编码或解码错误数据。事件日志有所不同:非 indexed 参数以 ABI 编码存放在 data 字段,因此要用只包含非 indexed 类型的签名来解码这一部分。