本文聚焦 Ethers.js、ERC20、以太坊代币、智能合约调用、代币转账、交易记录查询 等关键词,带你一站式搞懂如何用纯前端代码轻松完成代币读写。
1. 准备工作:锁定合约地址与 ABI
ERC20 代币的核心逻辑都写进了一个智能合约,只要我们拿到两样东西 —— 合约地址 与 ABI(合约接口清单)—— 就能与链上代码“对话”。
- 合约地址:通常可在项目官网、社群公告或区块链浏览器(如 Etherscan)找到。
- ABI:一份 JSON,告诉 Ethers.js“合约里暴露了哪些函数”,可手动下载,也可通过 API 拉取。
1.1 手动获取 ABI(Etherscan 图文版)
- 打开 Etherscan 并搜索代币合约地址。
- 点进 Contract → Code 标签页。
- 找到 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. 写操作:发起代币转账
转账三步走:
provider变成signer(需私钥或钱包插件注入 MetaMask);- 调整上链数据格式;
- 调
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. 进阶:常见场景与陷阱
- 合约不提供 ABI:部分老旧项目未开源,可反编译字节码手动补齐。
- 精度误区:虽然大部分代币精度为 18,但 USDC 是 6,需动态读取
decimals()。 - 前端体验:安装
@web3modal/ethers、wagmi@2等库,Metamask 一键弹窗签名,用户更丝滑。
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:调高 gasPrice、gasLimit,或等待网络低峰排队。
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 无服务器」的世界里玩得尽兴。