Hoodlums
0xdd6168df16fa89c5285227c4585d2a5de438b4ca
Verification
Verified
v0.8.17+commit.8df45f5f
Type
Contract
7,339 bytes
ABI entries
39
19 read · 15 write
License
none
Contract information
- Address
- 0xdd6168df16fa89c5285227c4585d2a5de438b4ca
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.17+commit.8df45f5f
- Optimization
- Enabled
- Creator
- 0x47EC2E5646…56A88696Aa
- Creation tx
- 0x1622f95b52…a8f298462d
Token
- Name
- Hoodlums
- Symbol
- HOOD
- Decimals
- —
- Holders
- 184
- Market
- View token page →
Read contract (19)
MAX_PER_TX() → uint256
MAX_SUPPLY() → uint256
SALT() → bytes32
balanceOf(address) → uint256
getApproved(uint256) → address
isApprovedForAll(address, address) → bool
mintActive() → bool
name() → string
owner() → address
ownerOf(uint256) → address
placeholderURI() → string
price() → uint256
renderer() → address
rendererFrozen() → bool
seedOf(uint256) → uint256
supportsInterface(bytes4) → bool
symbol() → string
tokenURI(uint256) → string
totalMinted() → uint256
Events (4)
ApprovalApprovalForAllOwnershipTransferredTransfer
ABI
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "approved",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [],
"name": "MAX_PER_TX",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "SALT",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "freezeRenderer",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "operator",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "qty",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "mintActive",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "qty",
"type": "uint256"
}
],
"name": "ownerMint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "placeholderURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "price",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renderer",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "rendererFrozen",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "seedOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "setApprovalForAll",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "active",
"type": "bool"
}
],
"name": "setMintActive",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "uri",
"type": "string"
}
],
"name": "setPlaceholderURI",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newPrice",
"type": "uint256"
}
],
"name": "setPrice",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "r",
"type": "address"
}
],
"name": "setRenderer",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalMinted",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "withdraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { ERC721 } from "openzeppelin-contracts/token/ERC721/ERC721.sol";
import { Ownable } from "openzeppelin-contracts/access/Ownable.sol";
import { ReentrancyGuard } from "openzeppelin-contracts/security/ReentrancyGuard.sol";
import { Strings } from "openzeppelin-contracts/utils/Strings.sol";
interface IHoodlumsRenderer {
function tokenURI(uint256 tokenId, uint256 seed) external view returns (string memory);
}
/**
* @title Hoodlums
* @notice 3333 on-chain hooded archers for Robinhood Chain (chainId 4663) or any EVM chain.
* - Public mint: price 0.0005 ETH (owner-changeable), MAX 10 per tx, NO per-wallet cap
* (mint more by sending another tx). Token ids start at #1.
* - Mint proceeds auto-forward to owner each mint (no withdraw needed; withdraw kept
* only as a safety fallback for stray ETH).
* - Art is fully on-chain: tokenURI delegates to an external renderer (settable, then
* freezable for permanence). seed = keccak256(SALT, id). Placeholder until renderer set.
*/
contract Hoodlums is ERC721, Ownable, ReentrancyGuard {
using Strings for uint256;
uint256 public constant MAX_SUPPLY = 3333;
uint256 public constant MAX_PER_TX = 10;
bytes32 public constant SALT = keccak256("hoodlums-v1");
uint256 public price = 0.0005 ether; // owner-changeable
uint256 public totalMinted;
bool public mintActive;
address public renderer; // on-chain SVG renderer
bool public rendererFrozen;
string public placeholderURI; // renderer set edilene kadar
constructor() ERC721("Hoodlums", "HOOD") {}
// ---------------- mint ----------------
/// @notice Public mint. 1..10 per tx, pays price*qty; extra tx'lerle devam edilebilir.
function mint(uint256 qty) external payable nonReentrant {
require(mintActive, "mint not active");
require(qty > 0 && qty <= MAX_PER_TX, "qty must be 1-10");
require(totalMinted + qty <= MAX_SUPPLY, "sold out");
require(msg.value >= price * qty, "underpaid");
for (uint256 i = 0; i < qty; i++) {
_safeMint(msg.sender, ++totalMinted); // ids #1..
}
// mint parasi otomatik owner'a (withdraw gerekmez)
(bool ok, ) = payable(owner()).call{ value: msg.value }("");
require(ok, "forward failed");
}
/// @notice Owner reserve/team mint, no payment.
function ownerMint(address to, uint256 qty) external onlyOwner {
require(totalMinted + qty <= MAX_SUPPLY, "sold out");
for (uint256 i = 0; i < qty; i++) {
_safeMint(to, ++totalMinted);
}
}
// ---------------- admin ----------------
function setMintActive(bool active) external onlyOwner { mintActive = active; }
function setPrice(uint256 newPrice) external onlyOwner { price = newPrice; }
function setPlaceholderURI(string calldata uri) external onlyOwner { placeholderURI = uri; }
function setRenderer(address r) external onlyOwner {
require(!rendererFrozen, "renderer frozen");
renderer = r;
}
function freezeRenderer() external onlyOwner { rendererFrozen = true; }
// ---------------- views ----------------
function seedOf(uint256 tokenId) public pure returns (uint256) {
return uint256(keccak256(abi.encodePacked(SALT, tokenId)));
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_exists(tokenId), "nonexistent token");
if (renderer != address(0)) {
return IHoodlumsRenderer(renderer).tokenURI(tokenId, seedOf(tokenId));
}
return bytes(placeholderURI).length > 0
? string(abi.encodePacked(placeholderURI, tokenId.toString(), ".json"))
: "";
}
// ---------------- safety fallback (normalde gereksiz; oto-forward var) ----------------
function withdraw() external onlyOwner {
(bool ok, ) = payable(owner()).call{ value: address(this).balance }("");
require(ok, "withdraw failed");
}
}
Chain explorer2321msChain node80ms