1、ERC20 / ERC721 / ERC1155 有什么区别?
-
ERC20 ------ 可替代代币(Fungible Token)
- 用途:代表
可互换的资产
,比如 USDT、ETH 衍生代币、游戏货币 - 特性:每个代币单位是相同的(1 USDT = 1 USDT);支持转账、批准、余额查询等标准接口
- 应用场景:稳定币、代币经济、DeFi 抵押、交易所交易
- 典型接口:
jsfunction totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
- 用途:代表
-
ERC721 ------ 非同质化代币(NFT, Non-Fungible Token)
- 用途:代表 独一无二的资产,每个代币有唯一标识
- 特性:不可互换(每个 NFT ID 唯一);支持拥有者查询、转移、批准交易
- 应用场景:艺术品 NFT、游戏道具、域名、收藏品
- 典型接口:
jsfunction ownerOf(uint256 tokenId) external view returns (address); function transferFrom(address from, address to, uint256 tokenId) external; function approve(address to, uint256 tokenId) external;
-
ERC1155 ------ 多类型代币(Semi-Fungible / Batchable)
- 场景:同时管理可替代 + 非替代 资产
- 游戏道具:同类道具堆叠、稀有道具独一无二
- 活动票券或卡牌
- 收藏品市场
- 特点:
- 单个合约管理多种
token ID
- 支持批量转账、批量铸造
- 节省
Gas
,方便资产组合管理
- 单个合约管理多种
- 场景:同时管理可替代 + 非替代 资产
2、什么是 Gas?为什么前端需要关注 Gas 消耗?
答:Gas 是以太坊(Ethereum)和类似区块链平台中执行交易或智能合约操作所需的计算费用单位。前端需要关注Gas消耗
,因为用户在发起交易时必须支付Gas
,如果Gas
设置不合理:太低 → 交易可能失败或一直挂起;太高 → 用户成本增加,体验不佳。
Gas
的作用- 区块链网络上每个修改链上状态的操作(如存储数据、计算函数)都需要消耗计算资源。
Gas
是衡量这些资源消耗的单位,保证用户为使用网络支付合理费用,同时防止滥用网络资源。
Gas
与前端的关系- 前端通常通过
Web3.js
、Ethers.js
等库与区块链交互,用户点击"执行交易"或"调用智能合约函数"时,需要指定Gas Limit
(最多愿意消耗的Gas
)和Gas Price
(每单位Gas
的价格)。 - 前端可以预估
Gas
消耗,优化用户体验,防止交易失败或费用过高。
- 前端通常通过
Gas
消耗差异- 前端在展示交易确认界面时,通常会显示预计
Gas
消耗和对应费用,让用户知情。
- 前端在展示交易确认界面时,通常会显示预计
3、区块链中的 nonce 是什么?在前端交易提交中如何处理?
答:在区块链(尤其是以太坊或EVM
系列链)中,nonce
是每个账户发送交易的计数器,用于保证交易的唯一性和顺序。
nonce 的定义和作用
- 定义:每个账户的
nonce
是一个递增的整数,表示该账户已经发出的交易数量。 - 作用:
- 防止交易重复:即使交易内容相同,
nonce
不同,交易哈希也不同,网络不会重复执行。 - 保证交易顺序:区块链按照
nonce
从小到大处理交易,保证先发的交易先被打包。
- 防止交易重复:即使交易内容相同,
- 示例:
text
"账户 A 已发出 3 笔交易,nonce 分别是 0、1、2"
"新交易 nonce 必须是 3,否则网络会拒绝或排队"
获取当前账户nonce
js
// ethers.js 库为例;获取账户最新 nonce
const nonce = await provider.getTransactionCount(address);
getTransactionCount
返回最新的nonce
- 如果有未确认交易,
nonce
会顺延 - 对于并行交易或重发交易,可手动指定
nonce
保证顺序
发送交易时使用 nonce
js
const tx = await signer.sendTransaction({
to: '0xRecipientAddress',
value: ethers.utils.parseEther('0.01'),
nonce,
gasLimit: 21000,
gasPrice: ethers.utils.parseUnits('20', 'gwei')
});
- 如果不指定
nonce
,ethers.js
会自动使用最新nonce
- 手动指定
nonce
可用于:多笔并行交易、重发失败交易;
注意事项
- 并行交易:需手动管理
nonce
,避免重复或跳号。 - 交易失败:可以用相同
nonce
重发覆盖旧交易。 - 顺序确认:网络优先处理
nonce
小的交易,保证顺序执行。
4、Web3.js / Ethers.js 的区别?你在项目中用过哪一个?
答:Web3.js
历史最悠久,功能全,但 API 笨重,包体积大,更新慢。Ethers.js
轻量、现代化、文档友好,社区推荐度高,更适合React / Vue
前端项目。
-
Web3.js
- 以太坊最早的
JavaScript SDK
,最经典的"入门库"。 - 目标是「一个库搞定所有」,功能比较大而全(RPC、合约交互、钱包管理、utils 等)。
- 以太坊最早的
-
Ethers.js
- 后来出现的轻量化库,设计更现代、更模块化。
- 强调安全、简洁、易于和前端框架结合。
-
包大小
- Web3.js → 较大(几百 KB),加载速度偏慢。
- Ethers.js → 更轻量,打包后更适合前端应用。
-
API 风格
- 基于
eth、personal、shh
等命名空间。 - 方法命名偏传统,不太直观。
jsconst Web3 = require('web3'); const web3 = new Web3('https://rpc-url'); const balance = await web3.eth.getBalance('0xAddress'); console.log(balance);
Ethers.js
基于Provider
/Signer
/Contract
三大核心概念。- 更清晰,现代
Promise
风格 API。
jsimport { ethers } from 'ethers'; const provider = new ethers.JsonRpcProvider('https://rpc-url'); const balance = await provider.getBalance('0xAddress'); console.log(ethers.formatEther(balance));
- 基于
-
合约交互:
Ethers
更简洁,而且返回值就是tx
对象,不需要.methods.xxx.send()
这种嵌套。
js
// Web3.js
const contract = new web3.eth.Contract(abi, address);
await contract.methods.transfer(to, amount).send({ from });
js
// Ethers.js
const contract = new ethers.Contract(address, abi, signer);
await contract.transfer(to, amount);
- 钱包与签名
- Web3.js → 钱包相关 API 偏复杂,还依赖 web3-provider。
- Ethers.js → 原生支持钱包对象(Wallet),同时和 MetaMask、Ledger 等无缝结合。
- 社区与生态
- Web3.js → 历史悠久,文档相对老旧,更新速度偏慢。
- Ethers.js → 目前主流,几乎所有新的以太坊前端项目都推荐用 Ethers。