pxn合约的简单分析

本人纯小白,第一次尝试分析合约代码,仅供学习参考!

合约地址:

https://rinkeby.etherscan.io/address/0x3201fe090e70bd464bc93469545be5278595d1f5#code

合约类型:

ERC721A

审计分析

Reentrancy: safemint 总是发生在最后一步 √

Ownership take over: 合约继承了Ownerable

Timestamp dependency:

//Require DA started
        require(
            block.timestamp >= DA_STARTING_TIMESTAMP,
            "DA has not started!"
        );
        require(block.timestamp <= WL_STARTING_TIMESTAMP, "DA is finished");

Contract interact:

callerIsUser()这个函数要求调用者不能是其他合约

 modifier callerIsUser() {
        require(tx.origin == msg.sender, "The caller is another contract");
        _;
    }

业务逻辑分析:

(1)白单Mint

function mintWL(bytes calldata signature) public payable callerIsUser {
        require(DA_FINAL_PRICE > 0, "Dutch action must be over!");

        require(
            !userToHasMintedPublicWL[msg.sender],
            "Can only mint once during public WL!"
        );
        require(
            block.timestamp >= WL_STARTING_TIMESTAMP,
            "WL has not started yet!"
        );
        require(
            block.timestamp <= WL_STARTING_TIMESTAMP + 86400,
            "WL has finished!"
        );
        //Require max supply just in case.
        require(
            PUBLIC_WL_MINTED + 1 <= WL_QUANTITY,
            "Max supply of 6000!"
        );

        require(
            wlSigner ==
                keccak256(
                    abi.encodePacked(
                        "\x19Ethereum Signed Message:\n32",
                        bytes32(uint256(uint160(msg.sender)))
                    )
                ).recover(signature),
            "Signer address mismatch."
        );

        require(msg.value >= WLprice, "Must send enough eth for WL Mint");

        userToHasMintedPublicWL[msg.sender] = true;
        PUBLIC_WL_MINTED++;

        //Mint them
        _safeMint(msg.sender, 1);
    

必须在荷兰拍以后进行;

!userToHasMintedPublicWL[msg.sender] 是否已经mint;

到时间才能开启mint;

block.timestamp <= WL_STARTING_TIMESTAMP + 86400 mint时间;

上限为6000个;

看起来没有问题。

(2)荷兰拍函数

function mintDutchAuction(uint8 quantity) public payable callerIsUser {
        require(
            DA_ACTIVE == true,
            "DA isnt active"
        );
        
        //Require DA started
        require(
            block.timestamp >= DA_STARTING_TIMESTAMP,
            "DA has not started!"
        );
        require(block.timestamp <= WL_STARTING_TIMESTAMP, "DA is finished");
        //Require max 2 per tx
        require(quantity > 0 && quantity < 3, "Can only mint max 2 NFTs!");

        //Require max 2 per wallet
        require(balanceOf(msg.sender) + quantity < 3, "Can only mint max 2 NFTs!");

        uint256 _currentPrice = currentPrice();

        //Require enough ETH
        require(
            msg.value >= quantity * _currentPrice,
            "Did not send enough eth."
        );

        //Max supply
        require(
            totalSupply() + quantity <= DA_QUANTITY,
            "Max supply for DA reached!"
        );

        //This calculates the final price
        if (totalSupply() + quantity == DA_QUANTITY) {
            DA_FINAL_PRICE = _currentPrice;
            if (((DA_FINAL_PRICE / 100) * 50) < WLprice) {
                WLprice = ((DA_FINAL_PRICE / 100) * 50);
            }
        }

        userToTokenBatchPriceData[msg.sender].push(
            TokenBatchPriceData(uint128(msg.value), quantity)
        );

        //Mint the quantity
        _safeMint(msg.sender, quantity);
    }

需要在规定时间mint,限制了最多两个钱包,每个两次mint。totalSupply() + quantity <= DA_QUANTITY 不超过最大的荷兰拍总数。当达到最大的荷兰拍总数时,计算此时的的价格,如果此时的价格小于白名单价格,此时价格+0.5是白名单的价格。

if (((DA_FINAL_PRICE / 100) * 50) < WLprice) { WLprice = ((DA_FINAL_PRICE / 100) * 50); }

(3)项目方保留

 function devMint() external onlyOwner {
        require(
            block.timestamp >= WL_STARTING_TIMESTAMP + 86400,
            "WL hasnt finished!"
        );
        uint256 leftOver = 10000 - totalSupply();
        _safeMint(DEV_FUND, leftOver);
    }

(4)

function teamMint(uint8 quantity) public payable {
        require(
            block.timestamp >= WL_STARTING_TIMESTAMP,
            "WL has finished!"
        );
        require(_teamList[msg.sender] >= quantity, "already claimed");
        require(
            msg.value >= quantity * WLprice,
            "Must send enough eth for WL Mint"
        );
        require(totalSupply() + quantity <= 10000, "exceeds supply");
        _teamList[msg.sender] = _teamList[msg.sender] - quantity;
        _safeMint(msg.sender, quantity);
    }

数量上限是10000个,需要eth余额足够。