前言本文主要介绍ERC721和ERC721A的特性和方法,ERC721和ERC721A都是以太坊上的非同质化代币(NFT)标准,但它们在实现方式和特性上存在一些区别:数据结构ERC721:每个tokenId都单独记录其所有者信息,逻辑清晰,但存在数据冗余。ERC721A:采用惰性初始化
本文主要介绍ERC721和ERC721A的特性和方法,ERC721和ERC721A都是以太坊上的非同质化代币(NFT)标准,但它们在实现方式和特性上存在一些区别:
tokenId
都单独记录其所有者信息,逻辑清晰,但存在数据冗余。tokenId
,只在第一个位置记录所有者信息,后续tokenId
的所有者信息通过向前查找补齐。tokenId
都需要单独记录所有者信息,导致Gas消耗较高。tokenId
的所有者信息,Gas消耗相对稳定。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract MyNFT is ERC721URIStorage { constructor() ERC721("MyNFT", "MNFT") {}
// 单个铸造
function mint(address to, uint256 tokenId, string memory tokenURI_) public {
_safeMint(to, tokenId);
_setTokenURI(tokenId, tokenURI_);
}
// 批量铸造
function mintBatch(address to, uint256[] memory tokenIds, string[] memory tokenURIs) public {
require(tokenIds.length == tokenURIs.length, "Array lengths do not match");
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
string memory tokenURI_ = tokenURIs[i];
_safeMint(to, tokenId);
_setTokenURI(tokenId, tokenURI_);
}
}
}
* **测试**
调用合约步骤:
* ### ERC721A标准
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20;
import "erc721a/contracts/ERC721A.sol"; import "@openzeppelin/contracts/utils/Strings.sol";
contract MyERC721A is ERC721A { constructor(string memory name, string memory symbol) ERC721A(name, symbol) {}
// 批量铸造函数
function mint(address to, uint256 quantity) public {
// 在实际应用中,可能需要添加权限控制,例如只有合约所有者或特定角色可以调用
_mint(to, quantity);
}
// 设置 Token URI
function _startTokenId() internal pure override returns (uint256) {
return 1; // 从 1 开始编号
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
// 使用 IPFS 哈希值生成 tokenURI
// 示例 IPFS 哈希值:QmHash...
string memory baseURI = "https://ipfs.io/ipfs/QmHash";
return string(abi.encodePacked(baseURI, Strings.toString(tokenId), ".json"));
}
}
**测试**
调用合约步骤:
### 测试截图对比
#### 铸造
**说明**:ERC721批量铸造俩个id:[1,2]url:"xxx","xxxx",ERC721A批量id:[1,2]
| ERC721(铸造) | ERC721A(铸造)|
|---------|---------|
|||
#### 铸造gas
| ERC721(铸造gas) | ERC721A(铸造gas)|
|---------|---------|
|| |
#### 转账
**说明**:ERC721转账id:2,url:"xxx","xxxx",ERC721A转账id:2
| ERC721(转账gas) | ERC721A(转账gas)|
|---------|---------|
|||
#### 转账gas
| ERC721(转账gas) | ERC721A(转账gas)|
|---------|---------|
|||
#### 交易费用对比
| 交易费用对比 | | |
| --- | --- | --- |
||批量铸造 | 转账 |
|**ERC721**| 220865(gas)| 76143 (gas)|
|**ERC721A**|60429 (gas)| 84043(gas)|
### 总结
ERC721A通过优化数据结构和存储方式,在批量铸造时显著降低了Gas消耗,但牺牲了部分转让效率。如果项目需要大量批量铸造,ERC721A是一个更好的选择;如果项目更注重单个铸造和转让效率,可以选择传统的ERC721标准。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!