Erc-721

ERC 721 鑄幣過程中是否需要重入保護,為什麼需要?

  • February 7, 2022
我正在嘗試編寫 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,您可能(我沒有測試過,如果我錯了,請糾正我)每個戰利品箱獲得更多物品。

所以,在你跳躍之前先看看。

引用自:https://ethereum.stackexchange.com/questions/117793