Robinhood MainnetChain ID: 4663
Contract detail

NeonNodes

NeonNodes is a verified Robinhood Chain smart contract at 0x539a4e52…7696b428 with 6 indexed transactions.

Address type
Smart contract
Transactions
6
First indexed block
#28428997
Latest indexed block
#28446358
Native balance
0 ETH
Balance observed at
Block #35555662
Emitted events
14
Token tracker
testing mods
Verification
Verified
Compiler
v0.8.27+commit.40a35a09
Verification match
full
Creation transaction
0xfa817e64…11ce39bb
Created at block
#28428997
Language
solidity
EVM version
cancun
License
none
Compiler optimization
Enabled · 200 runs
Related activity

Transactions

Verified contract

Contract source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import "erc721a/contracts/ERC721A.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";

contract NeonNodes is ERC721A, Ownable, ERC2981 {
    using ECDSA for bytes32;
    using MessageHashUtils for bytes32;

    // Testing deployment — 50 tokens, matches /prod/testing_42 image set.
    // Bump to 5555 for the real production deploy.
    uint256 public constant MAX_SUPPLY = 50;
    uint256 public constant MAX_PER_WALLET = 25;
    uint8   public constant MAX_BATCH = 5;
    uint256 public mintPrice = 0.00075 ether;

    address public signer;
    address public fundsReceiver;
    string  private _baseTokenURI;
    string  private _contractMetadataURI;
    bool    public mintActive;

    mapping(bytes32 => bool) public usedNonces;

    error MintNotActive();
    error MaxSupplyReached();
    error WalletLimitReached();
    error InsufficientPayment();
    error InvalidSignature();
    error NonceAlreadyUsed();
    error TransferFailed();
    error InvalidQuantity();

    constructor(
        address _signer,
        address _royaltyReceiver,
        address _fundsReceiver,
        string memory baseURI_,
        string memory contractURI_
    ) ERC721A("testing mods", "testing mods") Ownable(msg.sender) {
        signer = _signer;
        fundsReceiver = _fundsReceiver;
        _baseTokenURI = baseURI_;
        _contractMetadataURI = contractURI_;
        _setDefaultRoyalty(_royaltyReceiver, 500); // 5% (500 basis points)
    }

    function mint(
        bytes32 nonce,
        bytes calldata signature
    ) external payable {
        if (!mintActive) revert MintNotActive();
        if (_totalMinted() + 1 > MAX_SUPPLY) revert MaxSupplyReached();
        if (_numberMinted(msg.sender) + 1 > MAX_PER_WALLET) revert WalletLimitReached();
        if (msg.value < mintPrice) revert InsufficientPayment();
        if (usedNonces[nonce]) revert NonceAlreadyUsed();

        bytes32 messageHash = keccak256(
            abi.encodePacked(msg.sender, nonce, address(this), block.chainid)
        );
        bytes32 ethSignedHash = messageHash.toEthSignedMessageHash();
        if (ethSignedHash.recover(signature) != signer) revert InvalidSignature();

        usedNonces[nonce] = true;
        _mint(msg.sender, 1);

        (bool success, ) = payable(fundsReceiver).call{value: msg.value}("");
        if (!success) revert TransferFailed();
    }

    function mintBatch(
        uint8 quantity,
        bytes32 nonce,
        bytes calldata signature
    ) external payable {
        if (!mintActive) revert MintNotActive();
        if (quantity == 0 || quantity > MAX_BATCH) revert InvalidQuantity();
        if (_totalMinted() + quantity > MAX_SUPPLY) revert MaxSupplyReached();
        if (_numberMinted(msg.sender) + quantity > MAX_PER_WALLET) revert WalletLimitReached();
        if (msg.value < mintPrice * quantity) revert InsufficientPayment();
        if (usedNonces[nonce]) revert NonceAlreadyUsed();

        bytes32 messageHash = keccak256(
            abi.encodePacked(msg.sender, nonce, quantity, address(this), block.chainid)
        );
        bytes32 ethSignedHash = messageHash.toEthSignedMessageHash();
        if (ethSignedHash.recover(signature) != signer) revert InvalidSignature();

        usedNonces[nonce] = true;
        _mint(msg.sender, quantity);

        (bool success, ) = payable(fundsReceiver).call{value: msg.value}("");
        if (!success) revert TransferFailed();
    }

    function totalMinted() external view returns (uint256) {
        return _totalMinted();
    }

    function numberMinted(address wallet) external view returns (uint256) {
        return _numberMinted(wallet);
    }

    function _startTokenId() internal pure override returns (uint256) {
        return 1;
    }

    function _baseURI() internal view override returns (string memory) {
        return _baseTokenURI;
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();
        string memory base = _baseURI();
        return bytes(base).length > 0
            ? string(abi.encodePacked(base, _toString(tokenId)))
            : "";
    }

    function contractURI() external view returns (string memory) {
        return _contractMetadataURI;
    }

    function setBaseURI(string calldata baseURI) external onlyOwner {
        _baseTokenURI = baseURI;
    }

    function setContractURI(string calldata uri) external onlyOwner {
        _contractMetadataURI = uri;
    }

    function setSigner(address _signer) external onlyOwner {
        signer = _signer;
    }

    function setMintPrice(uint256 _price) external onlyOwner {
        mintPrice = _price;
    }

    function setMintActive(bool _active) external onlyOwner {
        mintActive = _active;
    }

    function setFundsReceiver(address _fundsReceiver) external onlyOwner {
        fundsReceiver = _fundsReceiver;
    }

    function withdraw() external onlyOwner {
        (bool success, ) = payable(fundsReceiver).call{value: address(this).balance}("");
        if (!success) revert TransferFailed();
    }

    function supportsInterface(
        bytes4 interfaceId
    ) public view override(ERC721A, ERC2981) returns (bool) {
        return interfaceId == 0xe8a3d485 // contractURI()
            || ERC721A.supportsInterface(interfaceId)
            || ERC2981.supportsInterface(interfaceId);
    }
}