Download contracts/FORGEART.sol from Snapkitty/forge-token: direct link, hf CLI and curl.
- Browser
- Download file 5.35 kB
-
https://huggingface.co/Snapkitty/forge-token/resolve/main/contracts/FORGEART.sol
- Command line
-
hf download hf://Snapkitty/forge-token/contracts/FORGEART.sol
-
curl -L -o FORGEART.sol https://huggingface.co/Snapkitty/forge-token/resolve/main/contracts/FORGEART.sol
5.35 kB
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.24; | |
| /** | |
| * @title FORGE ART — On-Chain SACM Agent Generative NFT | |
| * @notice Each token is a unique piece of ASCII art generated by a SnapKitty | |
| * SACM agent, sealed to the WORM chain, stored entirely on-chain. | |
| * No IPFS. No external dependencies. Art lives on Base forever. | |
| * | |
| * @dev ERC-721 with fully on-chain SVG tokenURI. | |
| * Mint is gated by MINTER_ROLE — only the FORGE settlement bridge mints. | |
| * Each mint records: agent name, WORM chain tip, SVG art, token seed. | |
| * Art is deterministically reproducible from (agent, wormTip, tokenId). | |
| * | |
| * @custom:deployed-by SnapKitty Collective LLC — EIN 41-5105572 | |
| * @custom:holding-entity Bel Esprit D'Accord Trust — EIN 41-6630640 | |
| * @custom:legal UTILITY COLLECTIBLE ONLY. Not a security or investment instrument. | |
| */ | |
| import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; | |
| import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; | |
| import "@openzeppelin/contracts/access/AccessControl.sol"; | |
| import "@openzeppelin/contracts/utils/Base64.sol"; | |
| import "@openzeppelin/contracts/utils/Strings.sol"; | |
| contract FORGEART is ERC721, ERC721Burnable, AccessControl { | |
| bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); | |
| bytes32 public constant ARCHITECT_ROLE = keccak256("ARCHITECT_ROLE"); | |
| uint256 public nextTokenId; | |
| uint256 public constant MAX_SUPPLY = 2_100; // 1/10 of FORGE cap — scarce | |
| struct ArtToken { | |
| string agent; // NOVA | ENKI | CIPHER | VAULT | |
| string wormTip; // WORM chain tip at mint time (provenance) | |
| string tokenSeed; // deterministic seed for off-chain reproduction | |
| string svgArt; // full SVG stored on-chain | |
| uint256 mintedAt; | |
| } | |
| mapping(uint256 => ArtToken) public artTokens; | |
| mapping(string => uint256) public agentMintCount; | |
| event ArtMinted( | |
| uint256 indexed tokenId, | |
| address indexed recipient, | |
| string agent, | |
| string tokenSeed, | |
| string wormTip | |
| ); | |
| constructor(address architect, address minter) ERC721("FORGE ART", "FART") { | |
| require(architect != address(0), "FORGEART: zero architect"); | |
| require(minter != address(0), "FORGEART: zero minter"); | |
| _grantRole(DEFAULT_ADMIN_ROLE, architect); | |
| _grantRole(ARCHITECT_ROLE, architect); | |
| _grantRole(MINTER_ROLE, minter); | |
| } | |
| /** | |
| * @notice Mint a new FORGE ART token with fully on-chain SVG art. | |
| * @param recipient Address receiving the NFT | |
| * @param agent Agent name — "NOVA", "ENKI", "CIPHER", or "VAULT" | |
| * @param wormTip WORM chain tip at time of sealing (provenance anchor) | |
| * @param tokenSeed Deterministic seed — keccak256(agent:wormTip:tokenId) | |
| * @param svgArt Complete SVG string to store on-chain | |
| */ | |
| function mintArt( | |
| address recipient, | |
| string calldata agent, | |
| string calldata wormTip, | |
| string calldata tokenSeed, | |
| string calldata svgArt | |
| ) | |
| external | |
| onlyRole(MINTER_ROLE) | |
| { | |
| require(nextTokenId < MAX_SUPPLY, "FORGEART: max supply reached"); | |
| require(recipient != address(0), "FORGEART: zero recipient"); | |
| require(bytes(agent).length > 0, "FORGEART: empty agent"); | |
| require(bytes(svgArt).length > 0, "FORGEART: empty art"); | |
| uint256 tokenId = nextTokenId++; | |
| artTokens[tokenId] = ArtToken({ | |
| agent: agent, | |
| wormTip: wormTip, | |
| tokenSeed: tokenSeed, | |
| svgArt: svgArt, | |
| mintedAt: block.timestamp | |
| }); | |
| agentMintCount[agent]++; | |
| _safeMint(recipient, tokenId); | |
| emit ArtMinted(tokenId, recipient, agent, tokenSeed, wormTip); | |
| } | |
| /** | |
| * @notice Returns fully on-chain tokenURI as a base64-encoded data URI. | |
| */ | |
| function tokenURI(uint256 tokenId) | |
| public | |
| view | |
| override | |
| returns (string memory) | |
| { | |
| _requireOwned(tokenId); | |
| ArtToken storage art = artTokens[tokenId]; | |
| string memory svgBase64 = Base64.encode(bytes(art.svgArt)); | |
| string memory json = string(abi.encodePacked( | |
| '{"name":"FORGE ART #', Strings.toString(tokenId), ' - ', art.agent, | |
| '","description":"On-chain generative ASCII art sealed to the SnapKitty SACM WORM chain. Agent: ', art.agent, | |
| '. Every pixel is a proof of productive work.","image":"data:image/svg+xml;base64,', svgBase64, | |
| '","attributes":[', | |
| '{"trait_type":"Agent","value":"', art.agent, '"},', | |
| '{"trait_type":"WORM Tip","value":"', art.wormTip, '"},', | |
| '{"trait_type":"Token Seed","value":"', art.tokenSeed, '"},', | |
| '{"trait_type":"Minted At","value":', Strings.toString(art.mintedAt), '}', | |
| ']}' | |
| )) ; | |
| return string(abi.encodePacked( | |
| 'data:application/json;base64,', | |
| Base64.encode(bytes(json)) | |
| )); | |
| } | |
| function remainingSupply() external view returns (uint256) { | |
| return MAX_SUPPLY - nextTokenId; | |
| } | |
| function supportsInterface(bytes4 interfaceId) | |
| public view override(ERC721, AccessControl) | |
| returns (bool) | |
| { | |
| return super.supportsInterface(interfaceId); | |
| } | |
| } | |