Erc-721
ERC 721 鑄幣過程中是否需要重入保護,為什麼需要?
- 我正在嘗試編寫 ERC-721 NFT 鑄幣合約,我注意到很多使用者都在防範重入攻擊。我想知道為什麼(以及是否)需要這樣做。與我正在編寫的契約類似的契約範例:
- https
//rinkeby.etherscan.io/address/0xEF6aB0b5CD245dB057eA6eE2beb858eC81f6145d#code https://etherscan.io/address/0xf21d1b31b15282592ff0e48f7b474b57ae418361#code#F1#L1可以看到您可能能夠鑄造超過單個地址的鑄造限制,但這是唯一可以作為目標的東西。在這些情況下我什至應該包括一個可重入守衛,如果是這樣,為什麼?
TL;DR: _safeMint 不是那麼安全。因此,請確保您的
mint
過程是安全的。看一下合約程式碼
mint
這裡的方法,require(_mintAmount <= maxMint, "Cant mint more then maxmint" ); for (uint256 i = 1; i <= _mintAmount; i++) { _safeMint(msg.sender, supply + i); }
在這裡,合約在一個循環中呼叫_safeMint,
_mintAmount
其中最大值是. 實現如下,required``maxMint``_safeMint
_mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer" );
見
_checkOnERC721Received
,如下,if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { assembly { revert(add(32, reason), mload(reason)) } } } }
如果鑄幣廠是由合約發起的,則檢查合約是否能夠接收 ERC721 代幣。如果沒有可重入保護,
onERC721Received
將允許攻擊者控制的合約再次呼叫鑄幣廠,這對於某些各方來說可能是不可取的,例如允許鑄幣超過允許的數量。當事情沒有正確實施時,這可能會變得非常煩人。例如,看看這段程式碼,function unpack(uint256 _tokenId) public { require(ownerOf(_tokenId) == _msgSender()); // Insert custom logic for configuring the item here. for (uint256 i = 0; i < NUM_CREATURES_PER_BOX; i++) { // Mint the ERC721 item(s). FactoryERC721 factory = FactoryERC721(factoryAddress); factory.mint(OPTION_ID, _msgSender()); } // Burn the presale item. _burn(_tokenId); }
如果您在利用重入
unpack
之前呼叫burn
,您可能(我沒有測試過,如果我錯了,請糾正我)每個戰利品箱獲得更多物品。所以,在你跳躍之前先看看。