Robinhood MainnetChain ID: 4663
Contract detail

BACONFACTORYCompanionNFT

BACONFACTORYCompanionNFT is a verified Robinhood Chain smart contract at 0xf20a2488…51bdd2ff with 0 indexed transactions.

Address type
Smart contract
Transactions
0
History coverage
No indexed activity found
Native balance
0 ETH
Balance observed at
Block #35827066
Verification
Verified
Compiler
v0.8.31+commit.fd3a2265
Verification match
full
Creation transaction
0x2d529b70…f0898709
Created at block
#28604286
Language
solidity
EVM version
osaka
License
none
Compiler optimization
Enabled · 2000 runs
Verified contract

Contract source code

// SPDX-License-Identifier: MIT
pragma solidity 0.8.31;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract BACONFACTORYCompanionNFT is ERC721, ReentrancyGuard {
    error InvalidConfiguration();
    error SaleClosed();
    error InvalidQuantity();
    error SupplyExceeded();
    error WalletLimitExceeded();
    error IncorrectPayment();
    error NothingToWithdraw();
    error NativeTransferFailed();
    error ZeroLaunchFingerprint();
    error ScheduleOverflow();
    string private _baseTokenUri;
    uint256 public immutable mintPrice;
    uint256 public immutable maxSupply;
    uint256 public immutable maxPerWallet;
    uint256 public immutable saleStart;
    uint256 public immutable saleEnd;
    address payable public immutable proceedsRecipient;
    bytes32 public immutable launchFingerprint;
    uint256 public totalMinted;
    mapping(address => uint256) public mintedBy;
    event Minted(address indexed buyer, uint256 indexed firstTokenId, uint256 quantity, uint256 paid);
    event ProceedsWithdrawn(address indexed recipient, uint256 amount);
    constructor(
        string memory name_,
        string memory symbol_,
        string memory baseTokenUri_,
        uint256 mintPrice_,
        uint256 maxSupply_,
        uint256 maxPerWallet_,
        uint256 mintStartDelay_,
        uint256 mintDuration_,
        address payable proceedsRecipient_,
        bytes32 launchFingerprint_
    ) ERC721(name_, symbol_) {
        if (bytes(name_).length == 0 || bytes(symbol_).length == 0) revert InvalidConfiguration();
        if (maxSupply_ == 0 || maxPerWallet_ == 0 || maxPerWallet_ > maxSupply_) revert InvalidConfiguration();
        if (mintDuration_ == 0 || proceedsRecipient_ == address(0)) revert InvalidConfiguration();
        if (mintStartDelay_ > type(uint256).max - block.timestamp) revert ScheduleOverflow();
        uint256 computedSaleStart = block.timestamp + mintStartDelay_;
        if (mintDuration_ > type(uint256).max - computedSaleStart) revert ScheduleOverflow();
        if (launchFingerprint_ == bytes32(0)) revert ZeroLaunchFingerprint();
        if (_composeLaunchDigest(launchFingerprint_) == bytes32(0)) revert ZeroLaunchFingerprint();
        _baseTokenUri = baseTokenUri_;
        mintPrice = mintPrice_;
        maxSupply = maxSupply_;
        maxPerWallet = maxPerWallet_;
        saleStart = computedSaleStart;
        saleEnd = computedSaleStart + mintDuration_;
        proceedsRecipient = proceedsRecipient_;
        launchFingerprint = launchFingerprint_;
    }
    function mint(uint256 quantity) external payable nonReentrant returns (uint256 firstTokenId) {
        if (block.timestamp < saleStart || block.timestamp > saleEnd) revert SaleClosed();
        if (quantity == 0) revert InvalidQuantity();
        if (totalMinted + quantity > maxSupply) revert SupplyExceeded();
        if (mintedBy[msg.sender] + quantity > maxPerWallet) revert WalletLimitExceeded();
        if (msg.value != mintPrice * quantity) revert IncorrectPayment();
        firstTokenId = totalMinted + 1;
        totalMinted += quantity;
        mintedBy[msg.sender] += quantity;
        for (uint256 i = 0; i < quantity; ++i) _safeMint(msg.sender, firstTokenId + i);
        emit Minted(msg.sender, firstTokenId, quantity, msg.value);
    }
    function withdrawProceeds() external nonReentrant {
        uint256 amount = address(this).balance;
        if (amount == 0) revert NothingToWithdraw();
        (bool sent, ) = proceedsRecipient.call{value: amount}("");
        if (!sent) revert NativeTransferFailed();
        emit ProceedsWithdrawn(proceedsRecipient, amount);
    }
    function launchId() external view returns (bytes32) {
        if (_composeLaunchDigest(launchFingerprint) == bytes32(0)) revert ZeroLaunchFingerprint();
        return launchFingerprint;
    }
    function _baseURI() internal view override returns (string memory) {
        return _baseTokenUri;
    }

    function remainingSupply() external view returns (uint256) {
        return maxSupply - totalMinted;
    }

    function quoteMint(uint256 quantity) external view returns (uint256) {
        return mintPrice * quantity;
    }

    function mintedByBatch(address[] calldata accounts) external view returns (uint256[] memory values) {
        values = new uint256[](accounts.length);
        for (uint256 i = 0; i < accounts.length; ++i) values[i] = mintedBy[accounts[i]];
    }
    function _foldByteMix(bytes32 acc) private pure returns (bytes32) {
        unchecked { uint256 v = uint256(acc); return bytes32((v & 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00) | ((v << 8) & ~uint256(0xff)) | (v >> 248)); }
    }

    function _foldMulmodPrime(bytes32 acc) private pure returns (bytes32) {
        return bytes32(mulmod(uint256(acc), 0xff51afd7ed558ccd, type(uint256).max - 188));
    }

    function _foldKeccakTagged(bytes32 acc) private pure returns (bytes32) {
        return keccak256(abi.encodePacked(acc, uint256(0x9e3779b97f4a7c15)));
    }

    function _composeLaunchDigest(bytes32 acc) private pure returns (bytes32) {
        return _foldKeccakTagged(_foldMulmodPrime(_foldByteMix(acc)));
    }
}