什么是函数选择器?
函数选择器是函数规范签名的 Keccak-256 哈希的前 4 字节。规范签名是函数名加上括号内的参数类型,不含空格和参数名,例如 transfer(address,uint256) → 0xa9059cbb。它构成每次合约调用 calldata 的前 4 字节,告诉合约要执行哪个函数;其余字节是 ABI 编码后的参数。
常见选择器
下表由本页面使用与工具相同的 Keccak 实现实时计算,因此也兼作自检。把任意选择器粘贴到上方输入框即可反查。
实例演示
以 function approve(address spender, uint256 amount) external returns (bool) 为例。去掉关键字、参数名、可见性和返回类型后得到 approve(address,uint256)。该 ASCII 字符串的 Keccak-256 以 0x095ea7b3… 开头,所以选择器是 0x095ea7b3。授权 1 USDT(6 位小数)的 calldata 由选择器、左填充到 32 字节的 spender 地址,以及作为 32 字节字的 1000000 组成:4 + 32 + 32 = 68 字节。
最常见的 ERC-20 选择器
| 签名 | 选择器 |
|---|---|
totalSupply() | 0x18160ddd |
balanceOf(address) | 0x70a08231 |
transfer(address,uint256) | 0xa9059cbb |
transferFrom(address,address,uint256) | 0x23b872dd |
approve(address,uint256) | 0x095ea7b3 |
allowance(address,address) | 0xdd62ed3e |
常见错误
- 用
uint而不是uint256来哈希。transfer(address,uint)的哈希值不同;规范形式总是写出完整位宽。 - 包含参数名或空格。
transfer(address to, uint256 amount)不是规范签名。 - 用结构体名表示元组。结构体要写成括号内的各字段类型,而不能写成
MyStruct。 - 混淆选择器和主题。函数使用 4 字节;事件使用完整的 32 字节哈希。
支持的输入格式
transfer(address,uint256):规范形式。function transfer(address to, uint256 amount) external returns (bool):Solidity 声明;参数名、可见性和 returns 会被去除。event Transfer(address indexed from, address indexed to, uint256 value):计算主题哈希时忽略indexed关键字。0xa9059cbb或 32 字节主题:在内置列表中反查。
要构造或解析完整 calldata,请继续使用 ABI 编码 / 解码器。