如何正确获取以太坊ERC-20代币的名称、符号及小数位数信息?
如何兼容获取所有ERC-20代币的信息(小数、名称、符号)
这个问题确实挺常见的——很多开发者都会碰到标准ERC-20接口调用在某些“非主流”代币上失效的情况。咱们一步步拆解原因和解决办法:
常规的标准ERC-20获取方法
你最开始的思路完全没问题,绝大多数合规的ERC-20合约都会实现decimals()、name()、symbol()这三个只读函数,用web3.js调用的常规代码大概是这样:
const Web3 = require('web3'); const web3 = new Web3('你的节点提供商URL,比如Infura/Alchemy'); // 标准ERC-20核心信息函数的ABI片段 const erc20BasicAbi = [ { "constant": true, "inputs": [], "name": "name", "outputs": [{"name": "", "type": "string"}], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "symbol", "outputs": [{"name": "", "type": "string"}], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "decimals", "outputs": [{"name": "", "type": "uint8"}], "payable": false, "stateMutability": "view", "type": "function" } ]; async function getStandardTokenInfo(tokenAddress) { const tokenContract = new web3.eth.Contract(erc20BasicAbi, tokenAddress); try { // 并行调用提升效率 const [name, symbol, decimals] = await Promise.all([ tokenContract.methods.name().call(), tokenContract.methods.symbol().call(), tokenContract.methods.decimals().call() ]); return { name, symbol, decimals }; } catch (error) { console.error("标准接口调用失败,可能是非标准合约:", error); return null; } }
为什么部分代币调用会失败?
你提到的那个代币地址调用失效,大概率是因为它没有严格遵循ERC-20标准规范,常见的异常场景有:
- 函数名大小写不匹配:比如把
symbol()写成Symbol()(以太坊合约对函数名大小写敏感),或者用了ticker()这类非标准函数名代替symbol() - 返回值类型不符合标准:比如
decimals()返回uint256而不是规范要求的uint8,name()/symbol()返回字节数组(bytes)而非字符串(string) - 合约根本没实现这些函数:有些早期代币或者“山寨”合约只实现了
transfer()、transferFrom()等核心转账函数,省略了辅助信息函数 - 极少数情况:合约给这些只读函数加了权限限制(完全不符合标准,但确实存在)
针对非标准代币的兼容方案
1. 提取合约完整ABI(最可靠)
直接去以太坊区块链浏览器查看该代币的合约源码(如果开源的话),提取完整的ABI文件,然后用完整ABI来初始化合约调用。比如如果发现合约用ticker()代替symbol(),就直接调用tokenContract.methods.ticker().call()即可。
2. 处理返回值类型不匹配
如果遇到返回值类型不符合标准的情况,可以手动转换:
- 若
decimals()返回uint256:const decimalsBigInt = await tokenContract.methods.decimals().call(); const decimals = Number(decimalsBigInt); // 转成普通数字 - 若
name()/symbol()返回字节数组:const nameBytes = await tokenContract.methods.name().call(); const name = web3.utils.hexToUtf8(nameBytes); // 字节转UTF8字符串
3. 静态调用兜底(极端情况)
有些完全非标准的合约会在fallback函数里返回代币信息,这种情况可以尝试发送静态调用解析返回数据,但这种方法非常依赖合约的具体实现,通用性很差,示例代码大概是:
async function tryFallbackCall(tokenAddress) { try { // 发送空调用触发fallback,获取返回数据 const result = await web3.eth.call({ to: tokenAddress }); // 根据合约逻辑解析result,这里需要具体分析合约代码 return parseFallbackResult(result); } catch (error) { console.error("Fallback调用也失败了:", error); return null; } }
4. 第三方数据源兜底
如果以上方法都失效,可以考虑用成熟的区块链数据API来获取代币信息,直接查询代币的链上元数据,但要注意选择可靠的数据源。
总结
优先用标准ERC-20接口调用,失败后先确认合约是否开源、是否符合标准,再针对性调整调用方式。对于完全非标准的合约,可能需要结合合约源码或者第三方数据来解决。
内容的提问来源于stack exchange,提问作者Alsofter
相关产品推荐
相关产品推荐

