# Create and deploy CCIP NFT Contracts

***

## We are going to start this workshop on Remix

{% embed url="<https://remix.ethereum.org>" %}
REMIX IDE
{% endembed %}

In Remix, switch to the DEPLOY & RUN TRANSACTIONS view. You will be very familiar with this by now!

***

Make sure you are on the fifth icon on the lefthand side of remix

* it should be titled DEPLOY & RUN TRANSACTIONS

Make sure you have selected <mark style="color:blue;">“Injected provider - Metamask”</mark> and that the <mark style="color:yellow;">network is (11155111)</mark> which is Ethereum Sepolia. If not make sure to switch your network in your Metamask extension.&#x20;

<figure><img src="/files/dZvpn3utNXFlJvQURvtp" alt=""><figcaption><p>Example showing Connection to Injected Provider - Metamask &#x26; Connection to the Sepolia Network</p></figcaption></figure>

## CrossChainPriceNFT.sol

In the Remix File Explorer,  create a new file. Name it <mark style="color:blue;">`CrossChainPriceNFT.sol`</mark>.

I am providing the code for you here, <mark style="color:yellow;">there were some slight changes in this block of code from the source code used during the Recorded Workshop</mark>. <mark style="color:purple;">Polygon's Mumbai Testnet</mark> was deprecated so I took the liberty of updating this code to exclude all references to Mumbai and instead replaced it with parameters that point towards <mark style="color:blue;">Base Sepolia</mark> test network

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

// Deploy this contract on Sepolia

// Importing OpenZeppelin contracts
import "@openzeppelin/contracts@4.6.0/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts@4.6.0/utils/Counters.sol";
import "@openzeppelin/contracts@4.6.0/utils/Base64.sol";

// Importing Chainlink contracts
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract CrossChainPriceNFT is ERC721, ERC721URIStorage {
    using Counters for Counters.Counter;
    using Strings for uint256;

    Counters.Counter public tokenIdCounter;

    // Create price feed
    AggregatorV3Interface internal priceFeed;
    uint256 public lastPrice = 0;

    string priceIndicatorUp = unicode"😀";
    string priceIndicatorDown = unicode"😔";
    string priceIndicatorFlat = unicode"😑";
    string public priceIndicator;

    struct ChainStruct {
        uint64 code;
        string name;
        string color;
    }
    mapping (uint256 => ChainStruct) chain;

    //https://docs.chain.link/ccip/supported-networks/testnet
    constructor() ERC721("CrossChain Price", "CCPrice") {
        chain[0] = ChainStruct ({
            code: 16015286601757825753,
            name: "Sepolia",
            color: "#0000ff" //blue
        });
        chain[1] = ChainStruct ({
            code: 14767482510784806043,
            name: "Fuji",
            color: "#ff0000" //red
        });
        chain[2] = ChainStruct ({
            code: 10344971235874465080,
            name: "Base Sepolia",
            color: "#4b006e" //purple
        });

        // https://docs.chain.link/data-feeds/price-feeds/addresses        
        priceFeed = AggregatorV3Interface(
            // Sepolia BTC/USD
            0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43            
        );

        // Mint an NFT
        mint(msg.sender);
    }

    function mint(address to) public {
        // Mint from Sepolia network = chain[0]
        mintFrom(to, 0);
    }

    function mintFrom(address to, uint256 sourceId) public {
        // sourceId 0 Sepolia, 1 Fuji, 2 Base Sepolia
        uint256 tokenId = tokenIdCounter.current();
        _safeMint(to, tokenId);
        updateMetaData(tokenId, sourceId);    
        tokenIdCounter.increment();
    }

    // Update MetaData
    function updateMetaData(uint256 tokenId, uint256 sourceId) public {
        // Create the SVG string
        string memory finalSVG = buildSVG(sourceId);
           
        // Base64 encode the SVG
        string memory json = Base64.encode(
            bytes(
                string(
                    abi.encodePacked(
                        '{"name": "Cross-chain Price SVG",',
                        '"description": "SVG NFTs in different chains",',
                        '"image": "data:image/svg+xml;base64,',
                        Base64.encode(bytes(finalSVG)), '",',
                        '"attributes": [',
                            '{"trait_type": "source",',
                            '"value": "', chain[sourceId].name ,'"},',
                            '{"trait_type": "price",',
                            '"value": "', lastPrice.toString() ,'"}',
                        ']}'
                    )
                )
            )
        );
        // Create token URI
        string memory finalTokenURI = string(
            abi.encodePacked("data:application/json;base64,", json)
        );
        // Set token URI
        _setTokenURI(tokenId, finalTokenURI);
    }

    // Build the SVG string
    function buildSVG(uint256 sourceId) internal returns (string memory) {

        // Create SVG rectangle with random color
        string memory headSVG = string(
            abi.encodePacked(
                "<svg xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:svgjs='http://svgjs.com/svgjs' width='500' height='500' preserveAspectRatio='none' viewBox='0 0 500 500'> <rect width='100%' height='100%' fill='",
                chain[sourceId].color,
                "' />"
            )
        );
        // Update emoji based on price
        string memory bodySVG = string(
            abi.encodePacked(
                "<text x='50%' y='50%' font-size='128' dominant-baseline='middle' text-anchor='middle'>",
                comparePrice(),
                "</text>"
            )
        );
        // Close SVG
        string memory tailSVG = "</svg>";

        // Concatenate SVG strings
        string memory _finalSVG = string(
            abi.encodePacked(headSVG, bodySVG, tailSVG)
        );
        return _finalSVG;
    }

    // Compare new price to previous price
    function comparePrice() public returns (string memory) {
        uint256 currentPrice = getChainlinkDataFeedLatestAnswer();
        if (currentPrice > lastPrice) {
            priceIndicator = priceIndicatorUp;
        } else if (currentPrice < lastPrice) {
            priceIndicator = priceIndicatorDown;
        } else {
            priceIndicator = priceIndicatorFlat;
        }
        lastPrice = currentPrice;
        return priceIndicator;
    }

    function getChainlinkDataFeedLatestAnswer() public view returns (uint256) {
        (, int256 price, , , ) = priceFeed.latestRoundData();
        return uint256(price);
    }

    function tokenURI(uint256 tokenId)
        public view override(ERC721, ERC721URIStorage) returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    // The following function is an override required by Solidity.
    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage)
    {
        super._burn(tokenId);
    }
}
```

***

We will now deploy the code. Switch to Remix's DEPLOY & RUN TRANSACTIONS tab, select the <mark style="color:blue;">`CrossChainPriceNFT`</mark> file and click the Deploy button.&#x20;

<figure><img src="/files/jo7avsXmb5XcA3owl4d3" alt=""><figcaption><p>Example of DEPLOY &#x26; RUN TRANSACTIONS TAB with CrossChainPriceNFT.sol Selected</p></figcaption></figure>

<figure><img src="/files/44lvwgcGw7hh9cEweUmG" alt=""><figcaption><p>Confirm the Transaction</p></figcaption></figure>

***

## We will now check this collection on Opensea.&#x20;

{% embed url="<https://testnets.opensea.io>" %}
Testnet Opensea
{% endembed %}

Copy your <mark style="color:blue;">CrossChainPriceNFT</mark> contract address.

<figure><img src="/files/485EozXw9chdXHx2ei4e" alt=""><figcaption><p>Example of copying the CrossChainPriceNFT address</p></figcaption></figure>

Use this link [testnet.opensea.io](https://testnet.opensea.io) to navigate the testnet version of Opensea. In the search bar you will search your <mark style="color:yellow;">CrossChainPriceNFT.sol</mark> address that you just deployed.&#x20;

* Save this link to your collection so you can check on the status of your <mark style="color:green;">NFT</mark>'s

<figure><img src="/files/PayaiT0EB8YgbNmcioMt" alt=""><figcaption><p>What your collection should look like</p></figcaption></figure>

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cll-devrel.gitbook.io/bootcamp-2024/7.-chainlink-ccip-and-cross-chain-nft-dapps/create-and-deploy-ccip-nft-contracts.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
