FabledFunks
0x17fe7bc0781864eb5772e1f464d621a9b2ac9ac6
Verification
Verified
v0.8.24+commit.e11b9ed9
Type
Contract
16,412 bytes
ABI entries
46
17 read · 10 write
License
none
Contract information
- Address
- 0x17fe7bc0781864eb5772e1f464d621a9b2ac9ac6
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.24+commit.e11b9ed9
- Optimization
- Enabled
- Creator
- 0x7fda2D5945…A43BF214Bf
- Creation tx
- 0xaa2416cb4f…4c29a24451
Token
- Name
- Fabled Funks
- Symbol
- FUNK
- Decimals
- —
- Holders
- 192
- Market
- View token page →
Read contract (17)
MAX_PER_WALLET() → uint256
MAX_SUPPLY() → uint256
RESERVE() → uint256
balanceOf(address) → uint256
getApproved(uint256) → address
isApprovedForAll(address, address) → bool
mintedBy(address) → uint256
name() → string
owner() → address
ownerOf(uint256) → address
publicMinted() → uint256
reserveMinted() → uint256
royaltyInfo(uint256, uint256) → address, uint256
supportsInterface(bytes4) → bool
symbol() → string
tokenURI(uint256) → string
totalMinted() → uint256
Events (4)
ApprovalApprovalForAllOwnershipTransferredTransfer
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "royaltyReceiver",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "numerator",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "denominator",
"type": "uint256"
}
],
"name": "ERC2981InvalidDefaultRoyalty",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "receiver",
"type": "address"
}
],
"name": "ERC2981InvalidDefaultRoyaltyReceiver",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "numerator",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "denominator",
"type": "uint256"
}
],
"name": "ERC2981InvalidTokenRoyalty",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "receiver",
"type": "address"
}
],
"name": "ERC2981InvalidTokenRoyaltyReceiver",
"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"
}
],
"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_PER_WALLET",
"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": "RESERVE",
"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": [
{
"internalType": "uint256",
"name": "qty",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "mintedBy",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"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": "publicMinted",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "reserveMinted",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "salePrice",
"type": "uint256"
}
],
"name": "royaltyInfo",
"outputs": [
{
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"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": "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": "address",
"name": "receiver",
"type": "address"
},
{
"internalType": "uint96",
"name": "bps",
"type": "uint96"
}
],
"name": "setDefaultRoyalty",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "iid",
"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": "id",
"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"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Base64} from "@openzeppelin/contracts/utils/Base64.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
/// @title Fabled Funks
/// @notice 1,000 fully on-chain glitched pixel fox punks on Robinhood Chain.
/// 900 free public mint + 100 den reserve. Art is a 24x24 sprite stored
/// as a 288-byte constant; per-token seed drives palettes, GAN-style
/// corruption (row melts, dead pixels, scanlines, FRIED hue-rotate),
/// a ~7% party hat drop, and a procedurally generated on-chain FABLE.
/// Exactly ONE purple party hat exists: token #1. Homage to BASTARD
/// GAN PUNKS. No IPFS. No server. Oo-de-lally.
contract FabledFunks is ERC721, ERC2981, Ownable {
using Strings for uint256;
uint256 public constant MAX_SUPPLY = 1000;
uint256 public constant RESERVE = 100;
uint256 public constant MAX_PER_WALLET = 5;
uint256 public totalMinted;
uint256 public publicMinted;
uint256 public reserveMinted;
mapping(uint256 => uint256) private _seed;
mapping(address => uint256) public mintedBy;
// 24x24 sprite, 2 cells/byte. 0=bg 1=black 2=fur 4=white 5=hood 6=hoodDark 7=eye 8=nose 9=innerEar
bytes private constant SPRITE =
hex"000000000000000000000000000110000000000000011000001221000000000000122100001292100000000001292100012992100000000001299210012992211111111112299210012255555555555555552210001555555555555555555100015562222222222226551000015622222222222222651000015622222222222222651000015627712222221772651000015627712222221772651000015622222222222222651000015644222222222244651000015644422444422444651000015644444488444444651000015564444488444446551000015556444444444465551000015555664444446655551000015555556611665555551000155555555555555555555510155555555555555555555510156655555555555555566510";
constructor(address royaltyReceiver) ERC721("Fabled Funks", "FUNK") Ownable(msg.sender) {
_setDefaultRoyalty(royaltyReceiver, 500);
}
// ---- mint ----------------------------------------------------------------
function mint(uint256 qty) external {
require(qty > 0 && qty <= MAX_PER_WALLET, "bad qty");
require(publicMinted + qty <= MAX_SUPPLY - RESERVE, "public sold out");
require(mintedBy[msg.sender] + qty <= MAX_PER_WALLET, "wallet cap");
mintedBy[msg.sender] += qty;
publicMinted += qty;
_mintN(msg.sender, qty);
}
function ownerMint(address to, uint256 qty) external onlyOwner {
require(reserveMinted + qty <= RESERVE, "reserve gone");
reserveMinted += qty;
_mintN(to, qty);
}
function _mintN(address to, uint256 qty) internal {
for (uint256 i = 0; i < qty; i++) {
uint256 id = ++totalMinted;
_seed[id] = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), to, id)));
_safeMint(to, id);
}
}
// ---- trait tables --------------------------------------------------------
function _furName(uint256 i) internal pure returns (string memory) {
return ["EMBER", "RUST", "GOLDEN", "ARCTIC", "SHADOW", "TOXIC"][i];
}
function _furCol(uint256 i) internal pure returns (string memory) {
return ["#e8622a", "#b0431a", "#f0913b", "#e9edf2", "#3a3d44", "#7ee23b"][i];
}
function _hoodName(uint256 i) internal pure returns (string memory) {
return ["LINCOLN GREEN", "OXBLOOD", "CHARCOAL", "ROYAL", "ACID", "HOT PINK"][i];
}
function _hoodCol(uint256 i) internal pure returns (string memory) {
return ["#2f6b34", "#6e1f22", "#2b2b2b", "#33417a", "#b8d432", "#e0369b"][i];
}
function _hoodDark(uint256 i) internal pure returns (string memory) {
return ["#224d26", "#4d1315", "#1a1a1a", "#232d59", "#8fa71f", "#a82273"][i];
}
function _eyeName(uint256 i) internal pure returns (string memory) {
return ["AMBER", "EMERALD", "ICE", "BLOOD"][i];
}
function _eyeCol(uint256 i) internal pure returns (string memory) {
return ["#ffb02e", "#39d353", "#67e8f9", "#ff3b3b"][i];
}
function _calm(uint256 i) internal pure returns (string memory) {
return ["#5b7a8c", "#7a6a5b", "#6a7a5b", "#8c7a9a", "#9a8a6a", "#708090"][i];
}
function _loud(uint256 i) internal pure returns (string memory) {
return ["#ff2d95", "#39ff14", "#00e5ff", "#ffe600", "#ff5e00", "#b967ff"][i];
}
function _glitchCol(uint256 i) internal pure returns (string memory) {
return ["#ff2d95", "#39ff14", "#00e5ff", "#ffe600", "#ff0044", "#b967ff", "#ffffff", "#0b0b0e"][i];
}
function _glitchName(uint256 g) internal pure returns (string memory) {
return ["CLEAN", "GLITCHED", "CORRUPTED", "FRIED AF"][g];
}
// RuneScape-style party hats. Purple (index 5) is a 1/1: token #1 only.
function _phatName(uint256 i) internal pure returns (string memory) {
return ["BLUE", "RED", "GREEN", "YELLOW", "WHITE", "PURPLE 1/1"][i];
}
function _phatCol(uint256 i) internal pure returns (string memory) {
return ["#4a5cff", "#e23b3b", "#3ddc55", "#ffe148", "#f2f2f2", "#b04ddb"][i];
}
function _phatDark(uint256 i) internal pure returns (string memory) {
return ["#3242c9", "#a82424", "#27a03b", "#d4b52a", "#c9c9c9", "#7e2fa8"][i];
}
// ---- fable ---------------------------------------------------------------
function _opener(uint256 i) internal pure returns (string memory) {
return [
"THE FOX", "A BASTARD FOX", "THE HOODED ONE", "A FERAL DEGEN",
"THE OUTLAW", "A GLITCHED FOX", "THE TRICKSTER", "AN ONCHAIN FOX"
][i];
}
function _deed(uint256 i) internal pure returns (string memory) {
return [
"ROBBED THE SHERIFF'S LIQUIDITY POOL",
"SOLD THE KING'S ARROWS FOR GAS",
"APED THE ROYAL TREASURY INTO A MEMECOIN",
"STOLE THE PRINCE'S PRIVATE KEYS",
"FARMED THE FOREST AND DUMPED ON NOBLES",
"MINTED 900 FREE AND KEPT 100",
"FRONTRAN THE ARCHERY TOURNAMENT",
"BRIDGED OUT OF NOTTINGHAM AT 3AM"
][i];
}
function _moral(uint256 i) internal pure returns (string memory) {
return [
"NEVER TRUST A CLEAN WALLET",
"THE HOOD STAYS ON",
"EVERY FOX IS A FABLE",
"FORTUNE FAVORS THE FERAL",
"OO-DE-LALLY MEANS OO-DE-LALLY",
"RICH STAY RICH UNTIL THEY MEET A FOX",
"GAS IS TEMPORARY, LORE IS FOREVER",
"MORALS ARE FOR THE UNHOODED"
][i];
}
// ---- derivation ----------------------------------------------------------
struct T {
uint256 fur;
uint256 hood;
uint256 eye;
uint256 bgKind; // 0 calm, 1 loud, 2 trippy, 3 void
uint256 bgA;
uint256 bgB;
uint256 glitch; // 0..3
bool phat;
uint256 phatIdx;
}
function _traits(uint256 id) internal view returns (T memory t) {
uint256 s = _seed[id];
t.fur = s % 6; s /= 6;
t.hood = s % 6; s /= 6;
t.eye = s % 4; s /= 4;
uint256 b = s % 100; s /= 100;
if (b < 30) { t.bgKind = 0; t.bgA = s % 6; }
else if (b < 70) { t.bgKind = 1; t.bgA = s % 6; }
else if (b < 95) { t.bgKind = 2; t.bgA = s % 6; t.bgB = (t.bgA + 1 + (s / 6) % 5) % 6; }
else { t.bgKind = 3; }
s /= 36;
uint256 g = s % 100;
t.glitch = g < 20 ? 0 : g < 65 ? 1 : g < 90 ? 2 : 3;
// party hat: token #1 is THE purple phat; ~7% of the rest get one of 5 colors
if (id == 1) {
// curated 1/1 grail — the "#013" look + the only purple party hat
t.fur = 5; // TOXIC
t.hood = 3; // ROYAL
t.eye = 3; // BLOOD
t.bgKind = 0; // CALM AF
t.bgA = 5; // navy slate (matched to #013)
t.glitch = 2; // CORRUPTED
t.phat = true;
t.phatIdx = 5;
} else {
uint256 p = uint256(keccak256(abi.encodePacked(_seed[id], "phat")));
if (p % 100 < 7) {
t.phat = true;
t.phatIdx = (p / 100) % 5;
}
}
}
function _cell(uint256 x, uint256 y) internal pure returns (uint256) {
uint256 i = y * 24 + x;
uint8 b = uint8(SPRITE[i >> 1]);
return (i & 1 == 0) ? (b >> 4) : (b & 0x0f);
}
function _symCol(uint256 sym, T memory t) internal pure returns (string memory) {
if (sym == 1) return "#0b0b0e";
if (sym == 2) return _furCol(t.fur);
if (sym == 4) return "#f4f1ea";
if (sym == 5) return _hoodCol(t.hood);
if (sym == 6) return _hoodDark(t.hood);
if (sym == 7) return _eyeCol(t.eye);
if (sym == 8) return "#141518";
return "#1c1f24"; // 9 inner ear
}
// ---- svg -----------------------------------------------------------------
function _svg(uint256 id, T memory t) internal view returns (string memory) {
uint256 s = _seed[id];
uint256[24] memory shift;
uint256 nShift = [uint256(0), 2, 4, 5][t.glitch];
for (uint256 j = 0; j < nShift; j++) {
uint256 h = uint256(keccak256(abi.encodePacked(s, "shift", j)));
shift[4 + (h % 18)] = 1 + (h / 18) % 4;
}
bytes memory corr = new bytes(576);
uint256 nCorr = [uint256(0), 10, 26, 40][t.glitch];
for (uint256 j = 0; j < nCorr; j++) {
uint256 h = uint256(keccak256(abi.encodePacked(s, "corr", j)));
corr[h % 576] = bytes1(uint8(1 + (h / 576) % 8));
}
string memory body = "";
for (uint256 y = 0; y < 24; y++) {
string memory rowStr = "";
uint256 x = 0;
while (x < 24) {
uint256 code = _code(x, y, shift[y], corr);
if (code == 0) { x++; continue; }
uint256 x2 = x;
while (x2 + 1 < 24 && _code(x2 + 1, y, shift[y], corr) == code) x2++;
rowStr = string.concat(
rowStr,
'<rect x="', (x * 20).toString(),
'" y="', (y * 20).toString(),
'" width="', ((x2 - x + 1) * 20).toString(),
'" height="20" fill="',
code >= 256 ? _glitchCol(code - 256) : _symCol(code, t),
'"/>'
);
x = x2 + 1;
}
body = string.concat(body, rowStr);
}
if (t.phat) body = string.concat(body, _phatSvg(t.phatIdx));
return string.concat(_svgOpen(s, t), body, _svgClose(t));
}
/// RuneScape-style zigzag party hat, drawn over the hood crown (cells 8-16, rows 1-4)
function _phatSvg(uint256 i) internal pure returns (string memory) {
string memory c = _phatCol(i);
return string.concat(
'<rect x="180" y="20" width="20" height="20" fill="', c, '"/>',
'<rect x="240" y="20" width="20" height="20" fill="', c, '"/>',
'<rect x="300" y="20" width="20" height="20" fill="', c, '"/>',
'<rect x="160" y="40" width="60" height="20" fill="', c, '"/>',
'<rect x="220" y="40" width="60" height="20" fill="', c, '"/>',
'<rect x="280" y="40" width="60" height="20" fill="', c, '"/>',
'<rect x="160" y="60" width="180" height="20" fill="', c, '"/>',
'<rect x="160" y="80" width="180" height="20" fill="', _phatDark(i), '"/>'
);
}
function _code(uint256 x, uint256 y, uint256 dx, bytes memory corr) internal pure returns (uint256) {
uint8 c = uint8(corr[y * 24 + x]);
if (c > 0) return 256 + (c - 1);
return _cell((x + 24 - dx) % 24, y);
}
function _svgOpen(uint256 s, T memory t) internal pure returns (string memory) {
string memory open =
'<svg xmlns="http://www.w3.org/2000/svg" width="480" height="480" viewBox="0 0 480 480">';
if (t.glitch == 3) {
open = string.concat(
open,
'<filter id="f"><feColorMatrix type="hueRotate" values="',
(40 + (s % 280)).toString(),
'"/></filter><g filter="url(#f)">'
);
}
if (t.bgKind == 2) {
return string.concat(
open,
'<defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="',
_loud(t.bgA), '"/><stop offset="1" stop-color="', _loud(t.bgB),
'"/></linearGradient></defs><rect width="480" height="480" fill="url(#g)"/>'
);
}
string memory bg = t.bgKind == 0 ? _calm(t.bgA) : t.bgKind == 1 ? _loud(t.bgA) : "#000000";
return string.concat(open, '<rect width="480" height="480" fill="', bg, '"/>');
}
function _svgClose(T memory t) internal pure returns (string memory) {
string memory close = "";
if (t.glitch >= 2) {
close =
'<defs><pattern id="s" width="20" height="20" patternUnits="userSpaceOnUse"><rect width="20" height="10" fill="#000"/></pattern></defs><rect width="480" height="480" fill="url(#s)" opacity="0.14"/>';
}
if (t.glitch == 3) close = string.concat(close, "</g>");
return string.concat(close, "</svg>");
}
// ---- metadata ------------------------------------------------------------
function _bgName(T memory t) internal pure returns (string memory) {
return t.bgKind == 0 ? "CALM AF" : t.bgKind == 1 ? "LOUD" : t.bgKind == 2 ? "TRIPPY" : "VOID";
}
function _fable(uint256 id) internal view returns (string memory) {
uint256 h = uint256(keccak256(abi.encodePacked(_seed[id], "fable")));
return string.concat(
"FABLE #", id.toString(), ": ", _opener(h % 8), " ", _deed((h / 8) % 8),
". MORAL: ", _moral((h / 64) % 8), "."
);
}
function tokenURI(uint256 id) public view override returns (string memory) {
_requireOwned(id);
T memory t = _traits(id);
string memory json = string.concat(
'{"name":"Fabled Funk #', id.toString(),
'","description":"', _fable(id),
' || 1000 FULLY ONCHAIN GLITCHED FOX PUNKS ON ROBINHOOD CHAIN. 900 FREE, 100 KEPT BY THE DEN. ONE PURPLE PARTY HAT EXISTS.",',
'"image":"data:image/svg+xml;base64,', Base64.encode(bytes(_svg(id, t))),
'","attributes":[{"trait_type":"Fur","value":"', _furName(t.fur),
'"},{"trait_type":"Hood","value":"', _hoodName(t.hood),
'"},{"trait_type":"Eyes","value":"', _eyeName(t.eye),
'"},{"trait_type":"Background","value":"', _bgName(t),
'"},{"trait_type":"Glitch","value":"', _glitchName(t.glitch),
'"},{"trait_type":"Party Hat","value":"', t.phat ? _phatName(t.phatIdx) : "NONE", '"}]}'
);
return string.concat("data:application/json;base64,", Base64.encode(bytes(json)));
}
// ---- admin / overrides ---------------------------------------------------
function setDefaultRoyalty(address receiver, uint96 bps) external onlyOwner {
_setDefaultRoyalty(receiver, bps);
}
function supportsInterface(bytes4 iid) public view override(ERC721, ERC2981) returns (bool) {
return super.supportsInterface(iid);
}
}
Chain explorer4224msChain node85ms