Pages

Minting compliments on the blockchain : Storing NFT metadata onchain






Minting compliments on the Blockchain

shloot.sol is a smart contract which mints unique Shakespearean compliment SVGs as NFT. The images are randomly generated from a list of popular words found in Shakespeare's work.

The contract is deployed on Polygon mainnet



How to use

Simply call the claim function with an id that's greater than 69. (the first 69 compliments are reserved for the contract deployer).

The NFTs are free to mint, the user only has to pay gas fees.


How it works

In this post we will see how to store NFT SVGs and metadata entirely onchain. 

Most of the NFTs minted today store their Metadata on IPFS. This is easy and convenient but comes with some 3rd party risk. 

IPFS is a peer-to-peer (p2p) storage network. Content is accessible through peers located anywhere in the world, that might relay information, store it, or do both. IPFS knows how to find what you ask for using its content address rather than its location.

IPFS allows users to pin files to a server and as long as the files are pinned by atleast one IPFS node the files are available online. As you can see this requires the users to trust in the IPFS pinning network's cryptoeconomics. Blockchain is all about getting things done in a trustless manner, so we will explore an alternative.


Any NFT marketplace like Opensea have a smart contract requirement for listing and displaying NFTs. Here's the complete list https://docs.opensea.io/docs/1-structuring-your-smart-contract But the main requirement for these NFT’s is that your smart contract contains a tokenURI() method which returns the url containing your metadata. Usually NFT smart contract return a ipfs hash containing the NFT metadata here, for example


{
"name": "Herbie Starbelly",
"description": "Friendly OpenSea Creature that enjoys long swims in the ocean.",
"image": "ipfs://bafybeict2kq6gt4ikgulypt7h7nwj4hmfi2kevrqvnx2osibfulyy5x3hu/no-time-to-explain.jpeg"
"attributes": [...]
}


The metadata itself is hosted on ipfs as well as the image.

There are a few key features that define an NFT, regardless of platform.

First, each token has a unique id that distinguishes it from all other tokens. This is in contrast to a fungible token like Ether ETH, which exists as a quantity attached to an account or wallet. There is no way to tell one ETH from another. Because each NFT is unique, they're owned and traded individually, with the smart contract keeping track of who owns what.

Another key feature of an NFT is the ability to link to data that is stored outside of a smart contract. Storing or processing data outside of a smart-contract is known as being off-chain. Because data that's stored on-chain needs to be processed, verified, and replicated across the entire blockchain network, it can be very expensive to store large amounts of data. 

But if the image is simple enough and not huge in size there are ways to return the json object containing the SVG from the tokenURI function.

shloot.sol 's tokenURI function returns the NFT data as follows

function tokenURI(uint256 id) override public view returns (string memory) {
require(_exists(id), "not exist");
string[8] memory parts;
parts[0] = '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet"
         viewBox="0 0 350 350"><style>
        .base { fill: black; font-family: serif; font-size: 17px; }</style>
        <rect width="100%" height="100%" fill="white" /><text x="10" y="20" class="base">';

parts[1] = 'Thou </text><text x="10" y="40" class="base">';
parts[2] = adjective[id%40];

parts[3] = '</text><text x="10" y="60" class="base">';

parts[4] = participle[id%39 +1];

parts[5] = '</text><text x="10" y="80" class="base">';

parts[6] = noun[id%38 +2];

parts[7] = '!</text></svg>';

string memory output = string(abi.encodePacked(parts[0], parts[1], parts[2],
        parts[3], parts[4], parts[5], parts[6], parts[7]));
string memory json = Base64.encode(bytes(string(
        abi.encodePacked('{"name": "Compliment #', toString(id), '",
        "description": "Rare compliments generator based on the work of William Shakespeare",
        "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}'))));
output = string(abi.encodePacked('data:application/json;base64,', json));
return output;
}

Here the link to the complete code of the smart contract. Link to sourcecode 


Alternatively, you may also try out the project on rinkeby network 

OpenSea : https://testnets.opensea.io/collection/the-shakespearean-compliments-generator

SmartContract: https://rinkeby.etherscan.io/address/0x6571ce37DcF0b78408686412e103432a2c134ED3#writeContract



This project is inspired by the loot project, read more about it here https://blog.coinbase.com/loot-project-the-first-community-owned-nft-gaming-platform-125fa1d5ffa8


Dark version