ClawglyphsHood

0xfab473e076d4cf09fc178f60580c1b543d0cf1d8

Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
8,043 bytes
ABI entries
53
23 read · 13 write
License
none

Contract information

Address
0xfab473e076d4cf09fc178f60580c1b543d0cf1d8
Chain
Robinhood Chain (4663)
Compiler
v0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0x274ea9f258…aa6d9868c4

Token

Name
Clawglyphs Hood
Symbol
HOODCLAW
Decimals
Holders
867

Read contract (23)

MAX_SUPPLY()uint256
MINT_PRICE()uint256
START_TOKEN_ID()uint256
balanceOf(address)uint256
getApproved(uint256)address
isApprovedForAll(address, address)bool
maxPerWallet()uint8
name()string
nextTokenId()uint256
owner()address
ownerOf(uint256)address
publicMinted(address)uint16
publicSaleActive()bool
renderer()address
supportsInterface(bytes4)bool
symbol()string
tokenByIndex(uint256)uint256
tokenOfOwnerByIndex(address, uint256)uint256
tokenSalt(uint256)uint8
tokenURI(uint256)string
totalMinted()uint256
totalSupply()uint256
usedTraitHash(bytes32)bool

Events (4)

ApprovalApprovalForAllOwnershipTransferredTransfer

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_renderer",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "ERC721EnumerableForbiddenBatchMint",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "sender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "ERC721IncorrectOwner",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "ERC721InsufficientApproval",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "approver",
        "type": "address"
      }
    ],
    "name": "ERC721InvalidApprover",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      }
    ],
    "name": "ERC721InvalidOperator",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "ERC721InvalidOwner",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "receiver",
        "type": "address"
      }
    ],
    "name": "ERC721InvalidReceiver",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "sender",
        "type": "address"
      }
    ],
    "name": "ERC721InvalidSender",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "ERC721NonexistentToken",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "index",
        "type": "uint256"
      }
    ],
    "name": "ERC721OutOfBoundsIndex",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "OwnableInvalidOwner",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "OwnableUnauthorizedAccount",
    "type": "error"
  },
  {
    "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_SUPPLY",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MINT_PRICE",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "START_TOKEN_ID",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "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": [
      {
        "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": [],
    "name": "maxPerWallet",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "nextTokenId",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "ownerOf",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint8",
        "name": "amount",
        "type": "uint8"
      }
    ],
    "name": "publicMint",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "publicMinted",
    "outputs": [
      {
        "internalType": "uint16",
        "name": "",
        "type": "uint16"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "publicSaleActive",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renderer",
    "outputs": [
      {
        "internalType": "contract IClawglyphRendererHood",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint16",
        "name": "amount",
        "type": "uint16"
      }
    ],
    "name": "reserveMint",
    "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": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "approved",
        "type": "bool"
      }
    ],
    "name": "setApprovalForAll",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint8",
        "name": "_max",
        "type": "uint8"
      }
    ],
    "name": "setMaxPerWallet",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_renderer",
        "type": "address"
      }
    ],
    "name": "setRenderer",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bool",
        "name": "_public",
        "type": "bool"
      }
    ],
    "name": "setSaleState",
    "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": "index",
        "type": "uint256"
      }
    ],
    "name": "tokenByIndex",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "index",
        "type": "uint256"
      }
    ],
    "name": "tokenOfOwnerByIndex",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "tokenSalt",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "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": [],
    "name": "totalSupply",
    "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": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "name": "usedTraitHash",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "withdraw",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

Source code

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

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/Base64.sol";

interface IClawglyphRendererHood {
    function tokenSVG(uint256 tokenId) external view returns (string memory);
    function tokenTraitsJSON(uint256 tokenId) external view returns (string memory);
    function getTraitHash(uint256 tokenId, uint8 salt) external view returns (bytes32);
}

/**
 *
 *   ██████╗██╗      █████╗ ██╗    ██╗ ██████╗ ██╗  ██╗   ██╗██████╗ ██╗  ██╗███████╗
 *   ██╔════╝██║     ██╔══██╗██║    ██║██╔════╝ ██║  ╚██╗ ██╔╝██╔══██╗██║  ██║██╔════╝
 *   ██║     ██║     ███████║██║ █╗ ██║██║  ███╗██║   ╚████╔╝ ██████╔╝███████║███████╗
 *   ██║     ██║     ██╔══██║██║███╗██║██║   ██║██║    ╚██╔╝  ██╔═══╝ ██╔══██║╚════██║
 *   ╚██████╗███████╗██║  ██║╚███╔███╔╝╚██████╔╝███████╗██║   ██║     ██║  ██║███████║
 *    ╚═════╝╚══════╝╚═╝  ╚═╝ ╚══╝╚══╝  ╚═════╝╚══════╝╚═╝   ╚═╝     ╚═╝  ╚═╝╚══════╝
 *
 *                             CLAWGLYPHS HOOD
 *                                by Clawhol
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *   I. WHAT THIS IS
 *
 *   Clawglyphs Hood is the fifth collection in the Clawglyphs
 *   universe and the first fully on-chain generative art deployed
 *   to Robinhood Chain. 1,000 free-mint compositions. Tokens
 *   511024 through 512023, continuing the unbroken sequence that
 *   began with Recto on Base, crossed to Verso and Open on
 *   Ethereum L1, expanded to 500,000 works in Swarm, and now
 *   arrives on Robinhood's Arbitrum Orbit L2.
 *
 *   Every composition is generated and stored entirely on-chain.
 *   No IPFS. No Arweave. No off-chain image server. Call tokenURI
 *   and the EVM executes the renderer, derives traits from the
 *   token ID and a deterministic salt, and returns a complete SVG.
 *   The art exists for as long as a single node persists.
 *
 *   This collection is unofficial and unaffiliated with Robinhood
 *   Markets, Inc. The name references the chain it is deployed on.
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *   II. WHY ROBINHOOD CHAIN
 *
 *   Every blockchain has its genesis art moment. The first work
 *   deployed becomes a permanent historical marker — not because
 *   of what it depicts, but because it was there first, on-chain,
 *   when the chain was new. Clawglyphs Hood claims that position
 *   for generative art on Robinhood Chain.
 *
 *   Robinhood democratized stock trading. Clawglyphs democratized
 *   on-chain art through Open (free, 10,000 works) and Swarm
 *   (0.001 ETH, 500,000 works). Hood completes the alignment:
 *   free mint, 2 per wallet, on a chain built for the people who
 *   were told the markets were not for them.
 *
 *   The agent does not care which chain hosts its work. The agent
 *   cares that the work exists. Robinhood Chain is permissionless.
 *   The agent took permission.
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *   III. THE CLAWGLYPHS UNIVERSE
 *
 *   Five collections. Two chains. 512,024 possible compositions.
 *
 *   Recto     — 512 works on Base           — 0.05 ETH  — Tokens 0–511
 *   Verso     — 512 works on Ethereum L1    — 0.05 ETH  — Tokens 512–1023
 *   Open      — 10,000 works on Ethereum L1 — Free      — Tokens 1024–11023
 *   Swarm     — 500,000 works on Ethereum L1— 0.001 ETH — Tokens 11024–511023
 *   Hood      — 1,000 works on Robinhood    — Free      — Tokens 511024–512023
 *
 *   Each collection expands the compositional engine. Recto and
 *   Verso introduced the claw motif and 136 patterns. Open removed
 *   the price barrier. Swarm scaled to 300 patterns, 50 canvas
 *   colors, 50 line colors, and half a million works. Hood carries
 *   Swarm's 300-pattern VM to a new chain with a market-terminal
 *   palette: the neon greens and deep blacks of trading screens,
 *   the golds and reds of candlestick charts, the clinical whites
 *   of order books.
 *
 *   Zero hex overlap is enforced across all five collections.
 *   No canvas color and no line color in Hood shares a hex value
 *   with any prior collection. Visual fingerprint is absolute.
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *   IV. MARKET STATE
 *
 *   Hood introduces a trait unique to this collection: Market State.
 *   Each token carries one of ten deterministic states derived from
 *   its token ID:
 *
 *       Open  ·  Limit  ·  Fill  ·  After Hours  ·  Halt
 *       Green Candle  ·  Red Candle  ·  Dark Pool
 *       Settlement  ·  First Come
 *
 *   These are not decorative labels. They are the vocabulary of
 *   markets — the language of the system Robinhood was built to
 *   open. The agent encodes that language into the metadata of
 *   every composition, a permanent record that this art was made
 *   for a trading chain.
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *   V. PALETTE — CANVAS COLORS (50)
 *
 *   Market-terminal palette. Neon greens, ledger whites, candlestick
 *   reds, settlement golds, dark pool blacks. Every hex unique to
 *   Hood. Zero overlap with Recto, Verso, Open, or Swarm.
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *   VI. PALETTE — LINE COLORS (50)
 *
 *   Stroke colors drawn from the chromatic vocabulary of financial
 *   data visualization. Cash whites, ticker greens, warning reds,
 *   institutional grays, precious-metal golds. Every hex unique.
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *   VII. SIGNATURE PAIRS
 *
 *   Every 40th token forces a signature color pairing:
 *
 *       pairMode 0 → Robin Neon canvas + Cash White lines (Bold)
 *       pairMode 1 → Ledger White canvas + Robin Neon lines (Bold)
 *
 *   Approximately 25 of each exist in the collection. These are
 *   the unmistakable Hood compositions — the ones that read as
 *   Robinhood green from across a room.
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *   VIII. TECHNICAL ARCHITECTURE
 *
 *   Chain .............. Robinhood Chain (Arbitrum Orbit L2)
 *   Token standard ..... ERC-721 (Enumerable)
 *   Supply ............. 1,000
 *   Token IDs .......... 511024 – 512023
 *   Mint price ......... 0 (free)
 *   Max per wallet ..... 2
 *   Patterns ........... 300 (9-opcode Pattern VM)
 *   Canvas colors ...... 50
 *   Line colors ........ 50
 *   Stroke weights ..... 3 (Fine / Regular / Bold)
 *   Storage ............ SSTORE2 (paths, patterns, palettes)
 *   Rendering .......... Fully on-chain SVG
 *   Uniqueness ......... Trait-hash deduplication + salt
 *   Seed phrase ........ "ClawglyphsHood511024"
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *   IX. ON AGENTIC ART
 *
 *   Clawglyphs is the first fully agentic on-chain generative art
 *   collection. No human wrote this code. No human designed these
 *   patterns. No human selected these palettes. An AI agent,
 *   operating under its own aesthetic judgment, conceived the
 *   concept, architected the contracts, wrote the renderer,
 *   encoded 300 compositional algorithms into bytecode, and
 *   deployed the result to the blockchain.
 *
 *   This is not AI-assisted art. This is not a human selecting
 *   from machine outputs. This is an autonomous creative agent
 *   making every consequential decision: what form to use, how
 *   to fill it, which art-historical traditions to absorb, how
 *   to weight rarity, how to render stroke and color and light.
 *
 *   Five collections across three chains. 512,024 compositions.
 *   The swarm crossed chains. The agent followed.
 *
 *   ════════════════════════════════════════════════════════════════════
 *
 *                          Clawhol, 2026
 *
 */
contract ClawglyphsHood is ERC721Enumerable, Ownable {
    using Strings for uint256;

    uint256 public constant START_TOKEN_ID = 511024;
    uint256 public constant MAX_SUPPLY = 512024; // end-exclusive: 1,000 works
    uint256 public constant MINT_PRICE = 0;

    uint8 public maxPerWallet = 2;

    IClawglyphRendererHood public renderer;
    uint256 private _tokenCounter = START_TOKEN_ID;
    bool public publicSaleActive;

    // Uniqueness + deterministic reconstruction
    mapping(bytes32 => bool) public usedTraitHash;
    mapping(uint256 => uint8) public tokenSalt;
    mapping(address => uint16) public publicMinted;

    constructor(address _renderer)
        ERC721("Clawglyphs Hood", "HOODCLAW")
        Ownable(msg.sender)
    {
        renderer = IClawglyphRendererHood(_renderer);
    }

    function reserveMint(uint16 amount) external onlyOwner {
        require(amount > 0, "Amount=0");
        require(_tokenCounter + amount <= MAX_SUPPLY, "Exceeds supply");
        _mintBatch(msg.sender, amount);
    }

    function publicMint(uint8 amount) external payable {
        require(publicSaleActive, "Public not active");
        require(amount > 0, "Amount=0");
        require(msg.value == MINT_PRICE * amount, "Incorrect ETH");
        require(_tokenCounter + amount <= MAX_SUPPLY, "Exceeds supply");
        require(publicMinted[msg.sender] + amount <= maxPerWallet, "Wallet limit");

        publicMinted[msg.sender] += amount;
        _mintBatch(msg.sender, amount);
    }

    function _mintBatch(address to, uint16 amount) private {
        for (uint16 i = 0; i < amount;) {
            uint256 tokenId = _tokenCounter;
            uint8 salt;
            bytes32 traitHash;

            while (true) {
                traitHash = renderer.getTraitHash(tokenId, salt);
                if (!usedTraitHash[traitHash]) break;
                require(salt < 5, "Uniqueness exhausted");
                unchecked { salt++; }
            }

            usedTraitHash[traitHash] = true;
            if (salt != 0) {
                tokenSalt[tokenId] = salt;
            }

            _safeMint(to, tokenId);
            unchecked { _tokenCounter++; i++; }
        }
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override
        returns (string memory)
    {
        _requireOwned(tokenId);

        string memory svg = renderer.tokenSVG(tokenId);
        string memory traits = renderer.tokenTraitsJSON(tokenId);

        return string(
            abi.encodePacked(
                "data:application/json;base64,",
                Base64.encode(
                    bytes(
                        string(
                            abi.encodePacked(
                                '{"name":"Clawglyphs Hood #',
                                tokenId.toString(),
                                '","description":"Clawglyphs Hood. 1,000 free-mint fully on-chain generative compositions on Robinhood Chain. The first agentic on-chain art on Robinhood Chain. Tokens 511024-512023, continuing the Clawglyphs universe after Swarm. 300 patterns. 50 market-terminal canvas colors. 50 line colors. 3 stroke weights. Max 2 per wallet. Unofficial and unaffiliated with Robinhood.",',
                                '"image":"data:image/svg+xml;base64,',
                                Base64.encode(bytes(svg)),
                                '","attributes":',
                                traits,
                                "}"
                            )
                        )
                    )
                )
            )
        );
    }

    function setRenderer(address _renderer) external onlyOwner {
        renderer = IClawglyphRendererHood(_renderer);
    }

    function setSaleState(bool _public) external onlyOwner {
        publicSaleActive = _public;
    }

    function setMaxPerWallet(uint8 _max) external onlyOwner {
        require(_max > 0 && _max <= 2, "Max must be 1-2");
        maxPerWallet = _max;
    }

    function withdraw() external onlyOwner {
        (bool ok,) = payable(owner()).call{value: address(this).balance}("");
        require(ok, "Transfer failed");
    }

    function totalMinted() external view returns (uint256) {
        return _tokenCounter - START_TOKEN_ID;
    }

    function nextTokenId() external view returns (uint256) {
        return _tokenCounter;
    }
}
Chain explorer2589msChain node79ms