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
- Funding transaction
- 0xeb3fc3c1…e6a755ac in block #28429919
- 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);
}
}