区块链的部分价值,早以“互联网+数据库”的形式发展了很多年。在“互联网+数据库”的模式下,“+”到一定程度,就到私有链的水平了。然后每一个私链进行合并,当私链具备了更多共通性和可交换性之后,就变成了公链。
目前区块链发展的最大掣肘,在于各个区块里的数据不统一。很多互联网是局域型的,内外网并不互通。“从私链走向公链”的过程,就是打破局域网和建立数据标准化的过程,另外,虽然发展区块链的意义重大,不是一有区块链之后,以前的商业就出现翻天覆地的变化。“区块链”要发挥巨大作用,有赖于从区块链技术发展出来的通证经济。
burn销毁的核心函数为_burn函数,由于销毁事实上相当于将NFT转移给0地址,所以其大量逻辑与transfer类似。
_burn函数定义如下:
function _burn(uint256 tokenId,bool approvalCheck)internal virtual
1
参数含义如下:
tokenId待销毁NFT的tokenId
approvalCheck是否检测函数调用者的权限
大致流程如下:
获取待销毁NFT拥有者的信息
如果设置approvalCheck为true则检测函数调用者的相关权限
清空待销毁NFT的授权approve数据
减少拥有者的balance
在_packedOwnerships中写入销毁信息
恢复代币连续性
释放事件
接下来,我们详细分析具体的代码实现:
uint256 prevOwnershipPacked=_packedOwnershipOf(tokenId);
address from=address(uint160(prevOwnershipPacked));
(uint256 approvedAddressSlot,address approvedAddress)=_getApprovedSlotAndAddress(tokenId);
此处代码与transferFrom函数的开始部分基本一致,但在from处理方面进行了简化。
接下来,我们检查调用者的相关权限并清空授权,代码如下:
if(approvalCheck){
if(!_isSenderApprovedOrOwner(approvedAddress,from,_msgSenderERC721A()))
if(!isApprovedForAll(from,_msgSenderERC721A()))_revert(TransferCallerNotOwnerNorApproved.selector);
}
assembly{
if approvedAddress{
//This is equivalent todelete _tokenApprovals[tokenId]
.
sstore(approvedAddressSlot,0)
}
}
此部分代码与transferFrom函数完全一致,不再详细介绍。
_packedAddressData[from]+=(1<<_BITPOS_NUMBER_BURNED)-1;
_packedOwnerships[tokenId]=_packOwnershipData(
from,
(_BITMASK_BURNED|_BITMASK_NEXT_INITIALIZED)|_nextExtraData(from,address(0),prevOwnershipPacked)
);
此处使用_packedAddressData[from]+=(1<<_BITPOS_NUMBER_BURNED)-1;代码将balance-=1和numberBurned+=1合并一起执行。
其中_BITPOS_NUMBER_BURNED的值为128,为方便读者理解,我们再次给出_packedAddressData的格式:
//Bits Layout:
//-[0..63]balance
//-[64..127]numberMinted
//-[128..191]numberBurned
//-[192..255]aux
mapping(address=>uint256)private _packedAddressData;
if(prevOwnershipPacked&_BITMASK_NEXT_INITIALIZED==0){
uint256 nextTokenId=tokenId+1;
if(_packedOwnerships[nextTokenId]==0){
if(nextTokenId!=_currentIndex){
_packedOwnerships[nextTokenId]=prevOwnershipPacked;
}
}
}