Skip to content

DHRUVCHARNE/dynamic-nft-forge

Repository files navigation

Foundry NFT — Basic & Mood NFT

Lightweight Foundry repository demonstrating two example ERC‑721 contracts and scripts/tests to deploy, interact, and test them.

  • BasicNft — simple ERC-721 that stores tokenURI on-chain and allows anyone to mint with a provided metadata URI.
  • MoodNft — dynamic NFT whose image (SVG) toggles between HAPPY and SAD moods. The image is stored as a data URI (fully on‑chain) and the token metadata is emitted as a data:application/json;base64, URI.

Deployed contracts (live on Sepolia)

(These are included for convenience — verify on Etherscan for transaction and ABI details.)


Table of contents


Repository structure

├── src/
│   ├── BasicNft.sol         # Simple ERC721 storing tokenURI on-chain
│   └── MoodNft.sol          # Dynamic SVG-based Mood NFT (on-chain image + JSON)
├── script/
│   ├── DeployBasicNft.s.sol
│   ├── DeployMoodNft.s.sol
│   └── Interactions.s.sol   # minting + mood flipping scripts using DevOpsTools
├── test/
│   ├── unit/                # unit tests for utilities and contracts
│   └── integrations/        # integration tests (deployment + behavior)
├── images/                  # (used by DeployMoodNft) contain `happy.svg` and `sad.svg`
├── Makefile                 # convenient commands (build, test, deploy, mint, etc.)
├── .env.example             # RPC keys and private key placeholders
└── README.md

Requirements

  • Foundryforge, anvil, cast installed.
  • make (for convenience using the provided Makefile).
  • (Optional) An RPC URL + private key if you want to deploy to a remote testnet such as Sepolia.

Quickstart

  1. Clone the repo.
  2. Copy .env.example to .env and fill in the values for SEPOLIA_RPC_URL, PRIVATE_KEY, and ETHERSCAN_API_KEY if deploying to Sepolia.
cp .env.example .env
# edit .env with your keys
  1. Install dependencies and build:
# installs dependencies listed in Makefile (forge install)
make install
make build
  1. Run tests locally:
make test
  1. Start a local anvil chain (if you want a local dev environment):
make anvil
# in another terminal: make deploy (with NETWORK_ARGS configured for local anvil)

Environment variables

Use the supplied .env.example as a template. The repo expects these variables when deploying to Sepolia via the Makefile:

SEPOLIA_RPC_URL=
PRIVATE_KEY=
ETHERSCAN_API_KEY=

Makefile / Common commands

The Makefile exposes convenient aliases. Most important:

  • make install — install repo dependencies (forge installs)
  • make build — runs forge build
  • make test — runs forge test
  • make anvil — launches anvil (local chain)

Deployment & interactions (the Makefile passes --rpc-url and --private-key using .env values when you include --network sepolia in ARGS):

  • make deploy — deploy DeployBasicNft script.
  • make deployMood — deploy DeployMoodNft script (reads images/dynamicNft/*.svg).
  • make mint — mint a BasicNft using the Interactions.s.sol script.
  • make mintMoodNft — mint a MoodNft token.
  • make flipMoodNft — flips the mood of token id 0 on the most recently deployed MoodNft.

You can inspect the Makefile for full options and NETWORK_ARGS handling.


Contracts overview

BasicNft.sol

  • Inherits from OpenZeppelin ERC721.
  • Stores a mapping s_tokenIdToUri that holds the token metadata URI (e.g. IPFS URI) on-chain.
  • mintNft(string memory _tokenURI) — mints a token to msg.sender with the provided tokenURI and increments a s_tokenCounter.
  • tokenURI(uint256 tokenId) is overridden to return the URI stored in the contract.

Use case: straight-forward example for minting NFTs whose metadata lives off-chain (IPFS), with the token URI stored on-chain.

MoodNft.sol

  • Inherits OpenZeppelin ERC721 and uses Base64 encoding.
  • Keeps an enum Mood { HAPPY, SAD } and a mapping of tokenId → Mood.
  • Constructor accepts two SVG images, converts them to data:image/svg+xml;base64,... URIs (the deploy script handles conversion) and stores them.
  • mintNft() — mints a token to msg.sender.
  • flipMood(uint256 tokenId) — toggles mood between HAPPY and SAD. Only the owner or approved address can flip the mood — otherwise the call reverts with MoodNft__CantFlipMoodIfNotOwner().
  • tokenURI(uint256 tokenId) — returns a data:application/json;base64, metadata URI with the current image URI embedded (100% on-chain metadata and image representation).

This contract demonstrates a dynamic NFT pattern where the on‑chain metadata changes based on an on‑chain state (mood).


Scripts & interactions

  • script/DeployBasicNft.s.sol — simple deploy script for BasicNft.

  • script/DeployMoodNft.s.sol — reads SVG files from ./images/dynamicNft/ and passes encoded data URIs to the MoodNft constructor.

    • svgToImageURI helper encodes an SVG string into a data:image/svg+xml;base64, URI.
  • script/Interactions.s.sol — helper scripts using DevOpsTools.get_most_recent_deployment to find the latest deployed contract address and perform actions:

    • MintBasicNft — mints a basic NFT with a hard-coded PUG metadata IPFS URI.
    • MintMoodNft — mints a Mood NFT (owner will be the signer used to broadcast).
    • FlipMoodNft — flips mood for token id 0 (useful for testing/interacting after minting).

Tests

The repo contains both unit and integration tests using forge test.

  • Unit tests cover DeployMoodNft.svgToImageURI and MoodNft basic behavior.
  • Integration tests demonstrate full deploy → mint → flip flows and assert expected tokenURI values.

Run all tests with:

make test
# or
forge test

Notes & security

  • These contracts are educational/demo-level. If you plan to adapt for production:

    • Add input validation and guardrails where appropriate.
    • Consider gas costs for storing large on-chain data (SVGs / JSON).
    • Be careful with public access — mintNft in both contracts is currently public and allows anyone to mint.
    • Add pausability, admin controls, or other access patterns as needed.

Contributing

PRs welcome. If you want to add features (metadata on-chain compression, offchain metadata pinning helper scripts, marketplace hooks, royalties) — open an issue or a PR with tests.


License

Licensed under the MIT License.


If you want, I can also generate a README-formatted quick demo showing example forge script commands to deploy and mint to Sepolia using your .env values.