APE Price: $0.95 (+0.07%)

Contract Diff Checker

Contract Name:
MintFuku

Contract Source Code:

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.28;

interface IFuku {
    function mint(
        uint32 qty,
        bytes32[] calldata proof,
        uint64 timestamp,
        bytes calldata signature
    ) external payable;
    function totalSupply() external view returns (uint256);
    function transferFrom(address from, address to, uint256 tokenId) external;
}

contract MintFuku {
    error InvalidAmount();
    error WithdrawalFailed();
    error OnePerPerson();
    error NotStarted();
    error WithdrawalsNotEnabled();
    error AlreadyStarted();
    struct Deposit {
        address user;
        uint96 balance;
    }

    uint256 public constant cost = 69 ether;
    uint256 public constant costWithFee = 80 ether;
    IFuku public constant FUKU = IFuku(0x1bcbD0D45d35BBBE514BEc8CB9e48C51835a6d8c);

    address public immutable _owner;
    uint256 public constant startTime = 1731366000;
    uint256 public constant _MAX_TOTAL_SUPPLY = 1111;

    Deposit[] public deposits;
    mapping(address => uint256) public indexToAddress;

    constructor() {
        _owner = msg.sender;
    }

    receive() external payable {
        deposit();
    }

    function deposit() public payable {
        if (block.timestamp >= startTime) revert AlreadyStarted();

        if (msg.value % costWithFee != 0) {
            revert InvalidAmount();
        }

        if (indexToAddress[msg.sender] == 0) {
            indexToAddress[msg.sender] = deposits.length;
            deposits.push(Deposit(msg.sender, uint96(msg.value)));
        } else {
            deposits[indexToAddress[msg.sender]].balance += uint96(msg.value);

            if (deposits[indexToAddress[msg.sender]].balance > costWithFee * 5) {
                revert InvalidAmount();
            }
        }
    }

    function mint() external {
        uint256 nextTokenId = FUKU.totalSupply();

        for (uint256 i = 0; i < deposits.length; i++) {
            uint256 mintCount = deposits[i].balance / costWithFee;

            if (nextTokenId + mintCount > _MAX_TOTAL_SUPPLY) {
                uint256 differenceToRefund = (nextTokenId + mintCount) - _MAX_TOTAL_SUPPLY;
                mintCount = _MAX_TOTAL_SUPPLY - nextTokenId;
                deposits[i].user.call{value: differenceToRefund * costWithFee}("");
            }

            for (uint256 j = 0; j < mintCount; j++) {
                new Minter{value: cost}(deposits[i].user, nextTokenId + j);
            }

            payable(_owner).call{value: (costWithFee - cost) * mintCount}("");
            unchecked { nextTokenId += mintCount; }

            delete deposits[i];
        }
    }

    function withdraw() external {
        uint256 balance = deposits[indexToAddress[msg.sender]].balance;
        deposits[indexToAddress[msg.sender]].balance = 0;
        payable(msg.sender).call{value: balance}("");
    }

    function ownerWithdraw() external {
        if (msg.sender != _owner) revert WithdrawalFailed();
        (bool success, ) = payable(_owner).call{value: address(this).balance }("");
        if (!success) revert WithdrawalFailed();
    }
}

contract Minter {
    uint256 public constant _COST = 69 ether;
    IFuku public constant FUKU = IFuku(0x1bcbD0D45d35BBBE514BEc8CB9e48C51835a6d8c);

    constructor(address minter, uint256 tokenIdToMint) payable {
        FUKU.mint{value: msg.value}(1, new bytes32[](0), uint64(0), new bytes(0));

        FUKU.transferFrom(address(this), minter, tokenIdToMint);
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):