使用 Ethers.js 进行 ERC20 代币操作全指南

·

本文聚焦 Ethers.jsERC20以太坊代币智能合约调用代币转账交易记录查询 等关键词,带你一站式搞懂如何用纯前端代码轻松完成代币读写。

1. 准备工作:锁定合约地址与 ABI

ERC20 代币的核心逻辑都写进了一个智能合约,只要我们拿到两样东西 —— 合约地址ABI(合约接口清单)—— 就能与链上代码“对话”。


1.1 手动获取 ABI(Etherscan 图文版)

  1. 打开 Etherscan 并搜索代币合约地址。
  2. 点进 Contract → Code 标签页。
  3. 找到 Contract ABI,一键 Copy 或 Export。

1.2 自动化获取 ABI(cURL 一行版)

curl "https://api.etherscan.io/api?module=contract&action=getabi&address=0xTokenAddress"

返回的就是完整 ABI,省掉手抖复制 JSON 的心累操作。


2. 创建 Ethers.js 合约对象

安装依赖(Node 场景):

npm i ethers

示范代码(可直接放浏览器 Console):

import { ethers } from "ethers" 

const provider = ethers.getDefaultProvider()     // 主网默认 RPC
const address   = "0x..."                       // ← 合约地址
const abi       = [...]                         // ← ABI JSON

const tokenContract = new ethers.Contract(address, abi, provider)

完成后,tokenContract 就是一个可读写链上数据的 合约句柄


3. 读操作:获取代币余额

ERC20 规范强制实现 balanceOf(address),使用极简单:

async function getBalance(userAddr) {
  const bal = await tokenContract.balanceOf(userAddr)
  return ethers.formatUnits(bal, decimals)  // 自动按代币小数位修正
}

假设返回值 1000、代币最小精度 18 位,即实际余额 1 000 * 10^-18 = 0.000000000000001 枚。
👉 想更优雅地格式化各种精度?这里给出了完整工具集


4. 写操作:发起代币转账

转账三步走:

  1. provider 变成 signer(需私钥或钱包插件注入 MetaMask);
  2. 调整上链数据格式;
  3. transfer 方法。
// signer 来自浏览器插件
const signerProvider = new ethers.BrowserProvider(window.ethereum)
const signer        = await signerProvider.getSigner()

const tokenWithSigner = tokenContract.connect(signer)
const decimals        = await tokenWithSigner.decimals()

const to    = "0xRecipient..."
const value = ethers.parseUnits("5", decimals) // 浮点→BigInt

const tx = await tokenWithSigner.transfer(to, value)
console.log("tx hash:", tx.hash)

交易成功后,可在浏览器里粘贴 tx.hash 到区块浏览器,实时追踪打包状态。


5. 查询历史交易:两招解决

5.1 通过 Etherscan 事件日志

ERC20 每次转账都会触发 Transfer() 事件。
查询示例地址 0xA…0 的转入记录:

curl "https://api.etherscan.io/api?module=logs&action=getLogs&fromBlock=0&toBlock=latest&address=0xTokenContract&topic2=0x0000...0000A"

再用脚本合并转出、转入两批数据即可得到 完整账单

5.2 一步到位的 tokentx API

同样用 Etherscan,一行搞定:

curl "https://api.etherscan.io/api?module=account&action=tokentx&address=0xA...0"

返回 JSON 中自带日期、金额、发送方、接收方,前端直接渲染,免拼接。
👉 想批量获取多币交易?教你 10 秒内搞定脚本


6. 进阶:常见场景与陷阱


7. 实战小案例:前端 20 行代码完成“查余额 + 转账”

<script type="module">
import { ethers } from "https://cdnjs.cloudflare.com/ajax/libs/ethers/6.7.1/ethers.min.js"

const RPC = "https://eth-mainnet.g.alchemy.com/v2/KEY"
const USDC_ADDR  = "0xA0b86a33E644C4db..."

async function init() {
  const provider = new ethers.JsonRpcProvider(RPC)
  const abi = ["function balanceOf(address) view returns (uint256)",
               "function transfer(address,uint256) returns (bool)",
               "function decimals() view returns (uint8)"]
  const USDC = new ethers.Contract(USDC_ADDR, abi, provider)

  const wallet = "0xYourWallet"
  const bal = await USDC.balanceOf(wallet)
  console.log(`${wallet} 持有 ${ethers.formatUnits(bal, 6)} USDC`)
}
init()
</script>

深入阅读 ERC20 合约规范,把 decimals()name()symbol() 一应用上去,前端就只替用户做两件事:读取、签名。


FAQ

Q1:testnet 如何测试转账?
A:Ethers.js 接 Goerli、Sepolia 方式一样,只需把 RPC 与合约地址换成对应网络即可。水龙头获取测试代币即可。

Q2:合约接口报错 invalid address 怎么办?
A:确认地址是否含有 0x 前缀且长 40 位,同时确保 ethers.getAddress() 返回无校验错误。

Q3:代币转账迟迟不上链?
A:调高 gasPricegasLimit,或等待网络低峰排队。

Q4:ABI 太复杂无法看懂?
A:只需保留 ERC20 的 8 个标准函数即可,其余可删;Ethers.js 懒加载功能位。

Q5:如何在 React/Vue 里优雅集成?
A:使用 vite-plugin-imp 按需引入 Ethers.js,搭配 eth-hooks 封装自定义 Hook 即可实现零感知调用。


收工!只要把 合约地址 + ABI + 私钥/签名端 三件事搞明白,Ethers.js 就能让“读区块、写交易”像调 REST API 一样简单。祝你在「Web3 无服务器」的世界里玩得尽兴。