totalSupply() 与 tokenID 计数器的气体效率 | ERC-721
Gas efficiency of totalSupply() vs. a tokenID counter | ERC-721
我正在为 NFT 创建一个 solidity 合约,在我的 mint
函数中,我不确定调用 totalSupply()
与使用令牌计数器并递增它是否更好。任何一种变化都会花费更多的汽油吗?是更标准的做法吗?我见过两者都被使用的例子。
变体 1:
contract MyNFT is ERC721Enumerable, PaymentSplitter, Ownable {
using Counters for Counters.Counter;
Counters.Counter private currentTokenId;
...
function mint(uint256 _count)
public payable
{
uint256 tokenId = currentTokenId.current();
require(tokenId < MAX_SUPPLY, "Max supply reached");
for(uint i = 0; i < _count; ++i){
currentTokenId.increment();
uint256 newItemId = currentTokenId.current();
_safeMint(msg.sender, newItemId);
}
}
}
变体 2:
function mint(uint256 _count)
public payable
{
uint supply = totalSupply();
require( supply + _count <= MAX_SUPPLY, "Exceeds max supply." );
for(uint i = 0; i < _count; ++i){
_safeMint(msg.sender, supply + i);
}
}
两个版本似乎都有效。我只是想确定我使用的是最有效/最安全的。感谢您的任何建议!
首先,您需要向我们展示底层实现。但是,我可以推测这些是 ERC721Enumerable and Counters.
的未修改的 openzeppelin 实现
仅针对您的情况,使用 Counter
对我来说似乎有点毫无意义。
- 它会增加您的部署成本(只是一点点),因为来自 Counter 库的冗余代码
- 你已经知道你的tokens数组的长度了,为什么要保留两次呢?计数器是为您不知道元素数量的情况创建的,例如映射。
本人不保证以下分析的正确性
调用totalSupply
(从操作码的角度来看)将:
- 跳转到总供应量(8 气)
- sload tokens.slot (200) gas
但是,在使用 Counter
时,您每次减量 sstore
(>= 5000 gas),每次阅读 sload
(200 gas)。
只要我没有误会 Counter 使用存储,因此 sstore
和 sload
操作码,第二个变体将使用更少的 gas。
我正在为 NFT 创建一个 solidity 合约,在我的 mint
函数中,我不确定调用 totalSupply()
与使用令牌计数器并递增它是否更好。任何一种变化都会花费更多的汽油吗?是更标准的做法吗?我见过两者都被使用的例子。
变体 1:
contract MyNFT is ERC721Enumerable, PaymentSplitter, Ownable {
using Counters for Counters.Counter;
Counters.Counter private currentTokenId;
...
function mint(uint256 _count)
public payable
{
uint256 tokenId = currentTokenId.current();
require(tokenId < MAX_SUPPLY, "Max supply reached");
for(uint i = 0; i < _count; ++i){
currentTokenId.increment();
uint256 newItemId = currentTokenId.current();
_safeMint(msg.sender, newItemId);
}
}
}
变体 2:
function mint(uint256 _count)
public payable
{
uint supply = totalSupply();
require( supply + _count <= MAX_SUPPLY, "Exceeds max supply." );
for(uint i = 0; i < _count; ++i){
_safeMint(msg.sender, supply + i);
}
}
两个版本似乎都有效。我只是想确定我使用的是最有效/最安全的。感谢您的任何建议!
首先,您需要向我们展示底层实现。但是,我可以推测这些是 ERC721Enumerable and Counters.
的未修改的 openzeppelin 实现仅针对您的情况,使用 Counter
对我来说似乎有点毫无意义。
- 它会增加您的部署成本(只是一点点),因为来自 Counter 库的冗余代码
- 你已经知道你的tokens数组的长度了,为什么要保留两次呢?计数器是为您不知道元素数量的情况创建的,例如映射。
本人不保证以下分析的正确性
调用totalSupply
(从操作码的角度来看)将:
- 跳转到总供应量(8 气)
- sload tokens.slot (200) gas
但是,在使用 Counter
时,您每次减量 sstore
(>= 5000 gas),每次阅读 sload
(200 gas)。
只要我没有误会 Counter 使用存储,因此 sstore
和 sload
操作码,第二个变体将使用更少的 gas。