An interactive ERC721 NFT that stores both SVG graphics and MP3 audio files entirely on-chain using advanced compression and gas-efficient storage techniques. Features a hot-reloading development environment for rapid iteration on generative on-chain art.
This project implements a "Rick Roll" NFT collection where each token displays generative artwork that transforms into Rick Astley's "Never Gonna Give You Up" when clicked. Unlike traditional NFTs that store metadata and assets off-chain, everything is stored permanently on the blockchain using SSTORE2 and gzip compression.
Key Features:
- Fully On-Chain Storage: SVG graphics and MP3 audio stored directly on Ethereum using SSTORE2
- Compression: Gzip compression reduces storage costs by ~60-70% for SVG assets
- Interactive NFTs: HTML/SVG/JavaScript embedded in tokenURI for dynamic, clickable experiences
- Generative Art: Pseudo-random color schemes and animations based on token ID and viewer address
- Hot-Reloading Dev Server: Live-reload browser during Solidity development (rare in Web3!)
- Multi-Network Support: Deploy to Ethereum mainnet, Goerli, Polygon, Mumbai
Install dependencies and start the development server:
yarn install
yarn devOpen http://localhost:9901/ to see your NFT render with hot-reloading enabled. Any changes to contracts/Token.sol will automatically recompile and refresh your browser.
Token.sol - ERC721 NFT contract with embedded rendering logic
- Generates complete HTML/SVG/audio as data URIs
- Implements public sale, whitelist minting, and airdrops
rollState()function allows permanent token transformation
Storage.sol - On-chain file system using SSTORE2Map
- Stores assets in 24KB chunks across multiple storage slots
- Automatic gzip decompression for SVG assets
- Gas-efficient retrieval using CREATE2-based storage
- Place SVG/MP3 files in
buffer/directory - SVGs are minified to
buffer/minified-svgs/ - Deployment script compresses SVGs with gzip (level 9)
- Assets uploaded to Storage contract in chunks
- Token contract retrieves and Base64-encodes on-demand
yarn testyarn compileyarn chain --network hardhatyarn prettynode --require esm ./node_modules/.bin/hardhat coverage --network hardhatNote: Manual node invocation required as Hardhat doesn't natively support ESM.
Create a .env file with the following variables:
INFURA_API_KEY=your_infura_key
ALCHEMY_MUMBAI_API_KEY=your_alchemy_mumbai_key
ALCHEMY_MATIC_API_KEY=your_alchemy_matic_key
PRIVATE_KEY=your_wallet_private_key_without_0x
ETHERSCAN_API_KEY=your_etherscan_key
REPORT_GAS=yes
AUDIO_FILENAME=rickRoll.mp3 # Optional: custom audio filenpx hardhat deploy --network <network>Supported networks: hardhat, goerli, mainnet, mumbai, matic
The deployment process:
- Deploys Storage contract
- Uploads all assets from
buffer/(MP3 + minified SVGs) - Deploys Token contract
- Auto-verifies contracts on Etherscan (mainnet/Goerli only)
Resume Failed Deployments: Deployment state is saved to scripts/<network>.json. If deployment fails, simply re-run the command to resume from where it stopped.
npx hardhat --network <network> etherscan-verifyEach NFT has multiple states:
- Default State: Colorful Merkaba geometric pattern with optional spinning animation
- Rolled State: Displays a "PLAY" button that reveals Rick Astley animation and plays audio
- Pseudo-Random Trigger: Some tokens randomly show the button based on
(tokenId + viewer_address) % 19
Users can pay 0.005 ETH to permanently "roll" a token into the Rick Roll state via rollState().
- Max Supply: 5,000 tokens
- Public Sale Price: 0.04 ETH (10 per tx, 15 per wallet max)
- Whitelist Price: 0.01 ETH (25 per wallet max, requires merkle proof)
- Roll Fee: 0.005 ETH to permanently enable Rick Roll state
- Uses SSTORE2 for ~10x cheaper storage reads compared to contract storage
- Gzip compression reduces SVG storage costs by 60-70%
- Chunked uploads handle large files within block gas limits
Token URIs return complete data URLs containing:
{
"name": "RickRoll No. X",
"description": "On-chain Rick Astley Rick Roll MP3 SVG NFT",
"audio": "data:audio/mp3;base64,...",
"image": "data:image/svg+xml;base64,...",
"animation_url": "data:text/html;base64,..."
}The animation_url contains a complete HTML page with embedded JavaScript for interactivity.
This project was inspired by w1nt3r's hot-chain-svg but rewritten from scratch with TypeScript support and additional features for handling audio assets and complex interactive NFTs.
MIT