Inspiration for Everyday Avatar

The Everyday Avatar is a profile-picture style, dynamic NFT project. (PFP-Based) The idea for the project was inspired by the Nintendo Mii Creator, and the physical paper doll toys I've been playing with recently with my daughter.

As a PFP-Based project, you can take your Avatar and use it as your profile picture on social media. Since you can swap out how your Avatar looks whenever you want, show the world how you currently feel and make your Facebook or Twitter profile picture truly expressive and dynamic!

What it does

The Everyday Avatar is an NFT version of the paper doll, where for each Avatar, you have access to the entire collection of components to choose from while playing with your Avatar! Just like a real paper doll, you start with a base character and can swap out the accessories and components to your every whim, like the clothes, accessories, hairstyles, facial expressions, etc.

All this is possible through our dApp (www.everydayavatar.com), where you can mint and modify Avatar NFTs and browse through your own collection of Avatars. Since they are ERC721-based NFTs on the Polygon network, you can also view or trade your Avatars on decentralized marketplaces like opensea.io.

demo

How we built it

The Everyday Avatar project is implemented in three parts: the React Frontend, the Solidity Smart Contracts, and the Webservice Backend.

Project Architecture

architecture

The React Frontend | Moralis & Biconomy

For the user interface we choose chakra as our UI component library, which has helped us to develop faster. We integrated our react-app with Moralis react-moralis for all our smart contract interactions. We also used the Moralis Web3 NFT API to build the Avatar cards, which simplified how to display the images and metadata. Our dApp currently only supports Metamask as the wallet provider. Lastly, we implemented gasless meta-transactions for updating our Avatars using the Biconomy SDK in our dApp.

The Solidity Smart Contracts | Polygon & Chainlink Oracle

Due to the limit on contract sizes in Solidity, we implemented two smart contracts that work together: EverydayAvatar.sol and AvatarData.sol.

EverydayAvatar.sol This contract inherits from the standard openzeppelin ERC721 contracts. Additionally, we also leveraged the EIP-3664 standard by DRepublic Labs to manage the components for each NFT token, and handle updating the attributes on-chain.

AvatarData.sol This basic datastore contract is used to store the list of components and the attribute categories they belong to. We also store all the names for the components, which are used when dynamically building the metadata json.

The Web Service Backend | IPFS & Node.js

The purpose of the API is to manage the image resources for our Avatars. The individual component images are stored on IPFS, uploaded via Pinata, and cached locally on the server. We then use the component images to dynamically generate an Avatar's complete image based on its DNA identifier and return the image for viewing or pin it programmatically to IPFS.

GET /view-avatar/${componentIDs} Dynamically builds the Avatar image using Sharp, and simply returns the image via HTTP. This is the default image URL that is included in a token's metadata.

POST /make-avatar Dynamically builds the Avatar image using Sharp, and uploads it to IPFS via infura and returns the IPFS CID to the caller. We call this function through the Chainlink Oracle, which allows us to update an Avatar's image CID on-chain in a trust-minimized way.

The API is implemented using node.js, and we hosted this backend using heroku.com

Critical Features

USD Pegged Minting Fee

With crypto naturally a volatile market, we wanted to have some financial stability and pricing that can be updated, so our Avatar's can remain affordable. We did this by using the Chainlink price feeds. In our smart contract, we have a public updateMintFee() function that anyone can call, and it will calculate a new Mint Fee based on the current market condition. In our demo, we pegged minting at $1.00 usd.

We considered using Chainlink Keepers to call this function once daily in order to keep it fresh, but we ran out of time to implement this cool feature before the end of the hackathon.

The IPFS Image Snapshot System

To overcome 100% dependence on our centralized servers for the images, we also needed to have a way to store our image resources on IPFS. As a dynamic NFT, the number of image combinations is exponentially HUGE! Since creating and storing EVERY combination is not practical, we came up with a "snapshot" system instead.

In the dApp, we have an "IPFS it" button that creates a snapshot of an Avatar NFT's components, and then, directly from the smart contract (with the help of a Chainlink Oracle), we build and publish the associated image to IPFS. The CID is returned back to the smart contract and stored for use when returning the metadata from the tokenURI() function.

This implementation allows us to balance users who require decentralized metadata and images and still have the NFT be dynamic!

snapshot

The whole point of using a Chainlink Oracle (Large Responses Job) was to create a trust-minimized way to update and store our token's images dynamically in a decentralized standard. (Thanks IPFS!) The alternative was to have our contract expose a public function to update the CID, but then we’d have to trust the function to be used properly.

This implementation still relies on some trust and centralized servers but serves as a prototype for future dynamic NFTs, and possibly a new standard itself! The next step would be to build a Distributed Oracle Network (DOM) that projects could register with in order to leverage trustless dynamic image generation with built-in IPFS integration.

Challenges we ran into

The biggest challenge was to somehow handle the competing objectives that exist within the concept of a dynamic NFT and deliver a cohesive project. Was it possible? With dynamic NFTs, we need the metadata (and ideally the image) to be, well... dynamic, which is a difficult challenge when the blockchain is designed to favor immutable data. We needed to define a standardized way to modify on-chain data and with existing smart contract conventions, doing so is easy. But trying to match dynamic NFT’s ever-changing attributes to existing conventions (which were designed for static content) became difficult very quickly.

Additionally, there were several challenges we ran into along the way while trying to develop and integrate all the parts of the software stack:

The Project Scope

From the beginning, we wanted to be able to have a functioning project by the hackathon's deadline, so we had to simplify the original scope of the idea. In the original idea, we wanted to have the base avatar ("doll") be its own NFT, and all the components and parts also be their own NFTs. This added complexity we didn't have time to address, such as how and when all the components would be minted, in addition to the base NFT.

Instead, we decided that when someone was minting or altering their Avatar, they'd have access to the full collection of the components and parts, with no restrictions.

Smart Contract

One problem we had early on was running into the upper limit of Solidity's contract code size due to all the complexity we were trying to squeeze into one contract. To overcome this we did two things: enabled compiler optimizations and broke the contract into multiple smaller contracts.

We also had a hard time figuring out how to integrate our backend with an Oracle that could provide our smart contract with the IPFS CID. Thankfully we had a node operator reach out to us and work with us on this integration directly. (Matt @ block-farms.io rocks!) Lack of documentation from Chainlink was a major hindrance, even when working with Matt, and we had to just test and try things out to get them to work.

Backend API Service

Initially, we planned on using ImageMagick for image processing, but that library turned out not to be the best for our use case. We had to find a working alternative early on or the project wouldn't have worked out. We then found and used a library called Sharp for our Avatar image generator API.

dApp Frontend

We had implemented magic login with Moralis but was not able to understand how to implement it fully for the features we needed, so we decided to move on and evaluate it later. For example, for enabling gasless transactions, how can we sign a transaction for a wallet address generated by the magic login? If it generates and relates an auto-generated wallet address to your email (or login of choice), what if the end-user actually needs his/her wallet private key, and how would they find it?

Accomplishments that we're proud of

I wanted to create a crypto project that anyone can get involved in, regardless of how or when they find us. This means a project that is NOT all about the money, rarity reveals, or the moon for that matter! Let us take a step back from all the charts and graphs (especially now that they are pointing down instead...) and let's just have some fun with NFTs for a change.

Here are some of the benefits and improvements over "Traditional" NFT projects we are proud to have included in our project:

Everyday Avatar "Traditional" NFT Projects
✔️ Unlimited Collection Limited Collection, limited owners (thanks whales)
♾️ Mintable Forever "Can" mint out quickly (usually by bots)
🧔 Choose how your Avatar looks Randomly assigned at reveal (what if the art sucks?)
🔗 Dynamic on-chain metadata Static metadata and images on IPFS (simple but effective)
😊 Stable and Low mint fee (pegged to USD) High-cost barriers on secondary market (seriously who pays those prices!?!)
💸 Long-term revenue potential (for dev team) Revenue ends when minting ends (and devs are off to the next cash cow...)

In reality, the biggest accomplishment is that we built a really cool web3 product and it works! Both Hussain and I are newer to the web3 space, so this was really a project about jumping into the web3 space; no longer being just spectators!

What we learned

We learned a crap-ton from this Hackathon, between the sessions and actually building Everyday Avatar:

  • ChainlinkClient APIs like Oracles and Price Feeds
  • How awesome Moralis is, and how easy it is to interact with the smart contract. Makes your life so much easier when Moralis is the only SDK you need!
  • How to implement gasless meta-transactions
  • How to build and deploy a backend API and front end server
  • How to use IPFS in the client code AND in our backend server

What's next for The Everyday Avatar NFT

The Everyday Avatar is destined for the Polygon Mainnet, and our next steps include:

  • Working with artists and illustrators to make some outstanding and beautiful Everyday Avatars
  • Expanding the Smart Contract back to some parts of the original concept
  • Revamping our UI's onboarding and educational elements to target a larger market
  • Hardening the backend API to support the Mainnet launch
  • Evaluating a roadmap to a full Distributed Oracle Network (DOM) for our IPFS snapshot system
  • Looking for investors to support us as we make this a stable, long-term, blue-chip project

logo

Built With

Share this project:

Updates