How To Create a Dynamic NFT Using 3 Chainlink Services

·

Dynamic NFTs (dNFTs) are revolutionizing digital ownership by allowing non-fungible tokens to evolve based on real-world data. Unlike static NFTs, which remain unchanged after minting, dynamic NFTs can update their metadata, appearance, or attributes in response to external triggers—such as price changes, time-based events, or random generation.

In this comprehensive guide, you'll learn how to create a fully functional dynamic NFT on the Polygon Mumbai testnet using three core Chainlink services:

No prior advanced coding experience is required—just follow the step-by-step instructions and deploy your own self-updating NFT in under an hour.


Prerequisites


Step 1: Set Up a MetaMask Wallet

If you don’t already have a cryptocurrency wallet, start by installing MetaMask, one of the most widely used Ethereum-compatible wallets.

👉 Generate highly click-attractive anchor text here based on article context and anchor link characteristics; no brand names other than 'OKX' may appear here.

  1. Visit metamask.io and install the browser extension.
  2. Follow the setup wizard to create a new wallet.
  3. Securely back up your recovery phrase—this is essential for wallet recovery.

Once installed, you're ready to interact with blockchain applications like Remix and Chainlink.


Step 2: Get Testnet Funds on Polygon Mumbai

To deploy smart contracts and interact with Chainlink services, you’ll need test tokens.

  1. Go to the Chainlink Faucet for Mumbai.
  2. Click “Connect wallet” and approve the Polygon Mumbai network in MetaMask if prompted.
  3. Switch to the Mumbai network.
  4. Complete the CAPTCHA and click “Send request”.
  5. Wait a few seconds—you’ll receive test MATIC and LINK tokens.
⚠️ If MATIC runs out, use the Polygon Faucet for additional MATIC. However, only the Chainlink Faucet provides test LINK.

These funds allow you to deploy contracts and pay for Chainlink service requests without spending real money.


Step 3: Create a Chainlink VRF Subscription

Chainlink VRF generates provably fair randomness—perfect for changing your NFT’s background color securely.

  1. Visit vrf.chain.link/mumbai and connect your wallet.
  2. Click “Create Subscription” and confirm the transaction.
  3. Once created, click “Add funds” and deposit 2 test LINK.
  4. Note down your Subscription ID—you’ll need it during contract deployment.

This subscription acts as a funding source for your smart contract to request random numbers.


Step 4: Deploy the Dynamic NFT Smart Contract Using Remix

Remix is a powerful online IDE for writing, compiling, and deploying Ethereum-compatible smart contracts.

Create and Compile the Contract

  1. Open Remix IDE.
  2. Click the + icon to create a new file named demo.sol.
  3. Paste the following Solidity code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/Base64.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

contract SuperDynamicNFT is ERC721, ERC721URIStorage, VRFConsumerBaseV2 {
    int256 previousEthPrice = 0;
    string ethIndicatorUp = unicode"😀";
    string ethIndicatorDown = unicode"😔";
    string ethIndicatorFlat = unicode"😑";
    string ethIndicator;
    
    string[] public hexDigits = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];
    string public fillColor = "#000000";

    AggregatorV3Interface internal priceFeed;
    VRFCoordinatorV2Interface COORDINATOR;

    uint64 private s_subscriptionId;
    uint32 private callbackGasLimit = 2500000;
    uint16 private requestConfirmations = 3;
    uint32 private numWords = 6;
    uint256[] public s_randomWords;

    address private s_owner;

    address private vrfCoordinator = 0x7a1BaC17Ccc5b313516C5E16fb24f7659aA5ebed;
    bytes32 private keyHash = 0x4b09e658ed251bcafeebbc69400383d49f344ace09b9576fe248bb02c003fe9f;

    constructor(uint64 subscriptionId)
        ERC721("ETH Watch SVG", "ewSVG")
        VRFConsumerBaseV2(vrfCoordinator)
    {
        priceFeed = AggregatorV3Interface(0x0715A7794a1dc8e42615F059dD6e406A6594651A);
        s_owner = msg.sender;
        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
        s_subscriptionId = subscriptionId;
        _safeMint(s_owner, 0);
    }

    function requestRandomWords() public {
        COORDINATOR.requestRandomWords(
            keyHash,
            s_subscriptionId,
            requestConfirmations,
            callbackGasLimit,
            numWords
        );
    }

    function fulfillRandomWords(
        uint256,
        uint256[] memory randomWords
    ) internal override {
        s_randomWords = randomWords;
        updateFillColor();
        updateETHPrice();
    }

    function updateFillColor() internal {
        fillColor = string(abi.encodePacked("#",
            randomHexDigit(s_randomWords[0]),
            randomHexDigit(s_randomWords[1]),
            randomHexDigit(s_randomWords[2]),
            randomHexDigit(s_randomWords[3]),
            randomHexDigit(s_randomWords[4]),
            randomHexDigit(s_randomWords[5])
        ));
    }

    function updateETHPrice() internal returns (string memory) {
        int256 currentEthPrice = getETHPrice();
        if (currentEthPrice > previousEthPrice) {
            ethIndicator = ethIndicatorUp;
        } else if (currentEthPrice < previousEthPrice) {
            ethIndicator = ethIndicatorDown;
        } else {
            ethIndicator = ethIndicatorFlat;
        }
        previousEthPrice = currentEthPrice;
        return ethIndicator;
    }

    function randomHexDigit(uint256 _randomNum) internal view returns (string memory) {
        return hexDigits[_randomNum % hexDigits.length];
    }

    function getETHPrice() internal view returns (int256) {
        (, int256 price,,,) = priceFeed.latestRoundData();
        return price;
    }

    function tokenURI(uint256) public view override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        string memory imgSVG = string(abi.encodePacked(
            "<svg xmlns='http://www.w3.org/2000/svg' width='300' height='300' style='background-color:", 
            fillColor, "'><text x='50%' y='50%' font-size='40' text-anchor='middle'>",
            ethIndicator, "</text></svg>"
        ));

        string memory json = Base64.encode(bytes(string(abi.encodePacked(
            '{"name": "ETH Watching SVG",',
            '"description": "An Automated ETH tracking SVG",',
            '"image": "data:image/svg+xml;base64,', Base64.encode(bytes(imgSVG)), '"}'
        ))));

        return string(abi.encodePacked("data:application/json;base64,", json));
    }

    modifier onlyOwner() {
        require(msg.sender == s_owner);
        _;
    }

    function supportsInterface(bytes4 interfaceId)
        public view override(ERC721, ERC721URIStorage)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}
  1. Navigate to the Solidity Compiler tab and click “Compile demo.sol”.
  2. Switch to the Deploy & Run Transactions tab.
  3. Change environment to “Injected Provider – MetaMask” and connect your wallet.
  4. Enter your VRF Subscription ID in the constructor field.
  5. Click “Deploy” and confirm in MetaMask.

Once confirmed (green checkmark), your contract is live on Mumbai!


Step 5: Register Your Contract as a VRF Consumer

Now authorize your contract to use your VRF subscription:

  1. Copy your deployed contract address from Remix.
  2. Go to vrf.chain.link/mumbai and connect your wallet.
  3. Select your subscription.
  4. Click “Add consumer”, paste the contract address, and confirm.

This two-way link allows your contract to request randomness funded by your subscription.


Step 6: Automate Updates With Chainlink Automation

Let’s make your NFT update every 2 minutes using Chainlink Automation.

  1. Visit automation.chain.link/mumbai and connect your wallet.
  2. Click “Register new Upkeep” → Choose “Time-based”.
  3. Paste your contract address.
  4. When prompted with “Couldn’t fetch ABI,” go back to Remix:

    • Open Solidity Compiler
    • Click “Copy ABI”
  5. Paste the ABI into the form.
  6. Select target function: requestRandomWords
  7. Set CRON expression: */2 * * * * (runs every 2 minutes)
  8. Name your upkeep (e.g., “Dynamic NFT Demo”) and fund with 2 LINK
  9. Confirm both transactions in MetaMask.

Once active, your NFT will autonomously refresh its color and emoji every two minutes.


Step 7: View Your Dynamic NFT on OpenSea

See your live dNFT:

  1. Go to testnets.opensea.io
  2. Connect your wallet via Profile > Connect Wallet
  3. Find the NFT titled “ETH Watching SVG”
  4. Click ••• > Refresh Metadata
  5. Wait 30 seconds and reload—the background color and emoji should now reflect recent ETH price movement!

Frequently Asked Questions (FAQ)

What makes a Dynamic NFT different from a regular NFT?

A dynamic NFT can change its metadata or visual properties over time based on external data feeds, whereas traditional NFTs are immutable once minted.

Can I use this on mainnet?

Yes! Replace testnet addresses with their mainnet equivalents and use real MATIC and LINK tokens.

Why do I need Chainlink VRF?

Standard block hashes can be manipulated by miners. Chainlink VRF provides verifiable, tamper-proof randomness—critical for fair dNFT updates.

How often can I update my dNFT?

With Chainlink Automation, you control the update frequency via CRON schedules—every minute, hour, day, or custom interval.

What happens when my subscription runs out of funds?

Your dNFT will stop updating until you refill the VRF or Automation subscription with more LINK.

Is this NFT compatible with other blockchains?

The same pattern works across EVM-compatible chains like Ethereum, Avalanche, and Arbitrum—with proper configuration of Chainlink addresses.


👉 Generate highly click-attractive anchor text here based on article context and anchor link characteristics; no brand names other than 'OKX' may appear here.


Final Thoughts

You’ve just built a self-updating NFT powered by real-time market data, randomness, and automation—all decentralized and trustless thanks to Chainlink.

This project demonstrates how Web3 applications can go beyond static assets to create living digital experiences.

Whether you’re building gamified collectibles, adaptive art, or data-driven memberships, dynamic NFTs open a world of possibilities.

Core Keywords: dynamic NFT, Chainlink VRF, Chainlink Automation, Polygon Mumbai, smart contract, Remix IDE, OpenSea, ETH price tracking

Keep experimenting—your next innovation starts with a single line of code.