铸造
基本函数
铸造使用了_mint函数,其函数定义是:
function _mint(address to,uint256 quantity)internal virtual
1
该函数规定了以下参数:
to铸造NFT接受地址
quantity铸造的NFT数量
由于ERC721A只能铸造固定数量的NFT,所以无法指定铸造NFT的tokenID
其函数的运行逻辑简单如下:
运行_beforeTokenTransfers,此函数应根据具体目的编写
设置_packedOwnerships,以方便查询NFT的拥有者
设置_packedAddressData,方便查询某一用户的所有NFT
释放Transfer事件
运行_afterTokenTransfers,此函数应根据具体目的编写
接下来,我们将结合代码进行分析。
最先运行的_beforeTokenTransfers和最后运行的
_afterTokenTransfers都是由用户自定义的函数,用于实现白名单等功能。函数具体定义如下:
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
)internal virtual{}
function _afterTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
)internal virtual{}
读者可根据自身需求,通过继承覆盖的方式定义这两个函数。
接下来,我们设置一些核心数据,这些数据的设置是_mint函数的核心。值得注意的是,这些函数都定义在unchecked代码块中,因为NFT的各个参数设置不会产生溢出情况,通过unchecked可以避免编译过程中插入溢出检查代码以减少gas消耗。
简而言之,在某些已经确定不会出现数据溢出的场景中使用unchecked包裹代码可以减少gas消耗
最开始,我们设置表示NFT所有者的_packOwnershipData数据结构,具体设置方法如下:
_packedOwnerships[startTokenId]=_packOwnershipData(
to,
_nextInitializedFlag(quantity)|_nextExtraData(address(0),to,0)
);
为方便读者理解代码,在此处,我们给出_packedOwnerships的定义:
//Bits Layout:
//-[0..159]addr
//-[160..223]startTimestamp
//-[224]burned
//-[225]nextInitialized
//-[232..255]extraData
mapping(uint256=>uint256)private _packedOwnerships;