什么是代币精度换算器?
代币精度换算器利用代币的 decimals 值,在代币合约存储的原始整数与钱包显示的可读金额之间换算:金额 = 原始值 ÷ 10decimals。ERC-20 和 TRC-20 合约通过 decimals() 暴露该值;SPL 代币则存储在 Mint 账户中。USDT 和 USDC 使用 6,WBTC 使用 8,类 ETH 代币使用 18。
常见代币的小数位数
| 代币 | 小数位 | 1 个代币的原始整数 |
|---|---|---|
| USDT(以太坊、Tron、Solana、Polygon、Arbitrum) | 6 | 1,000,000 |
| USDC(所有主流链) | 6 | 1,000,000 |
| BNB Smart Chain 上的 USDT(Binance-Peg) | 18 | 1,000,000,000,000,000,000 |
| WBTC、cbBTC | 8 | 100,000,000 |
| ETH、WETH、DAI、LINK、UNI、AAVE | 18 | 1,000,000,000,000,000,000 |
| SOL 及大多数 SPL 代币 | 9 | 1,000,000,000 |
| GUSD | 2 | 100 |
换算原理
可读金额 = 原始值 ÷ 10decimals,原始值 = 可读金额 × 10decimals。难点在于精度:18 位小数的值超出了浮点数的表示范围,因此本页使用任意精度整数。输入的小数位数超过代币支持范围会被拒绝,因为链上无法表示该金额。
示例
一个 ERC-20 Transfer 事件显示 value = 2500000。如果代币是 USDC(6 位小数),那就是 2.5 USDC。如果同样的数字来自 DAI 转账(18 位小数),则是 0.0000000000025 DAI,一笔粉尘金额。反过来,要发送 0.0025 WBTC(8 位小数),transfer 的参数必须是 0.0025 × 108 = 250,000;发送 1 LINK(18 位小数)则需要 1,000,000,000,000,000,000。
常见错误
- 默认 18 位。硬编码 1018 会把 100 USDC 的付款变成 0.0000000001 USDC。请从合约读取
decimals()。 - 只看代币符号。同一代号的跨链桥代币在不同链上可能使用不同的小数位数。请检查你实际交互的合约。
- 先舍入再相乘。先把可读金额转换为原始整数,再用整数做运算;浮点数可能得出 2499999.9999 而不是 2500000。
代码示例
- ethers.js:
ethers.parseUnits("1.5", 6)→1500000n;ethers.formatUnits(1500000n, 6)→"1.5"。 - web3.py:
int(Decimal("1.5") * 10**6);避免使用float。 - Solana web3.js:
createTransferInstruction中的金额是原始整数;用 BigInt 乘以10 ** mint.decimals。
原生币请参见以太坊单位换算器、聪换算器、lamports 换算器和 sun 换算器。