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 “Injected provider - Metamask” and that the network is (11155111) which is Ethereum Sepolia. If not make sure to switch your network in your Metamask extension.
CrossChainPriceNFT.sol
In the Remix File Explorer, create a new file. Name it CrossChainPriceNFT.sol.
I am providing the code for you here, there were some slight changes in this block of code from the source code used during the Recorded Workshop. Polygon's Mumbai Testnet 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 Base Sepolia test network
// SPDX-License-Identifier: MITpragmasolidity 0.8.19;// Deploy this contract on Sepolia// Importing OpenZeppelin contractsimport"@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 contractsimport"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";contractCrossChainPriceNFTisERC721, ERC721URIStorage {usingCountersforCounters.Counter;usingStringsforuint256; Counters.Counter public tokenIdCounter;// Create price feed AggregatorV3Interface internal priceFeed;uint256public lastPrice =0;string priceIndicatorUp =unicode"😀";string priceIndicatorDown =unicode"😔";string priceIndicatorFlat =unicode"😑";stringpublic priceIndicator;structChainStruct {uint64 code;string name;string color; }mapping (uint256=> ChainStruct) chain;//https://docs.chain.link/ccip/supported-networks/testnetconstructor() 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/USD0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43 );// Mint an NFTmint(msg.sender); }functionmint(address to) public {// Mint from Sepolia network = chain[0]mintFrom(to,0); }functionmintFrom(address to,uint256 sourceId) public {// sourceId 0 Sepolia, 1 Fuji, 2 Base Sepoliauint256 tokenId = tokenIdCounter.current();_safeMint(to, tokenId);updateMetaData(tokenId, sourceId); tokenIdCounter.increment(); }// Update MetaDatafunctionupdateMetaData(uint256 tokenId,uint256 sourceId) public {// Create the SVG stringstringmemory finalSVG =buildSVG(sourceId);// Base64 encode the SVGstringmemory 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 URIstringmemory finalTokenURI =string( abi.encodePacked("data:application/json;base64,", json) );// Set token URI_setTokenURI(tokenId, finalTokenURI); }// Build the SVG stringfunctionbuildSVG(uint256 sourceId) internalreturns (stringmemory) {// Create SVG rectangle with random colorstringmemory 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 pricestringmemory bodySVG =string( abi.encodePacked("<text x='50%' y='50%' font-size='128' dominant-baseline='middle' text-anchor='middle'>",comparePrice(),"</text>" ) );// Close SVGstringmemory tailSVG ="</svg>";// Concatenate SVG stringsstringmemory _finalSVG =string( abi.encodePacked(headSVG, bodySVG, tailSVG) );return _finalSVG; }// Compare new price to previous pricefunctioncomparePrice() publicreturns (stringmemory) {uint256 currentPrice =getChainlinkDataFeedLatestAnswer();if (currentPrice > lastPrice) { priceIndicator = priceIndicatorUp; } elseif (currentPrice < lastPrice) { priceIndicator = priceIndicatorDown; } else { priceIndicator = priceIndicatorFlat; } lastPrice = currentPrice;return priceIndicator; }functiongetChainlinkDataFeedLatestAnswer() publicviewreturns (uint256) { (,int256 price,,, ) = priceFeed.latestRoundData();returnuint256(price); }functiontokenURI(uint256 tokenId)publicviewoverride(ERC721,ERC721URIStorage) returns (stringmemory) {return super.tokenURI(tokenId); }// The following function is an override required by Solidity.function_burn(uint256 tokenId) internaloverride(ERC721,ERC721URIStorage) { super._burn(tokenId); }}
We will now deploy the code. Switch to Remix's DEPLOY & RUN TRANSACTIONS tab, select the CrossChainPriceNFT file and click the Deploy button.
We will now check this collection on Opensea.
Copy your CrossChainPriceNFT contract address.
Use this link testnet.opensea.io to navigate the testnet version of Opensea. In the search bar you will search your CrossChainPriceNFT.sol address that you just deployed.
Save this link to your collection so you can check on the status of your NFT's