Puzzlr is a GameFi project built on Aurora that takes inspiration from Proof of Work, gaming, and community building.
Puzzlr is a novel way to create NFT mints, do community building, and just have a fun experience with your friends!
The idea of the game is simple:
- There is a rare NFT that is a prize
- Each game can have
nnumber of prizes (1 or more)
- A jigsaw puzzle representing that prize is an active game
- Users need to collect all the pieces for that jigsaw puzzle through different possible actions
- Once a user has all the pieces and has successfully solved the jigsaw puzzle, they can win the prize.
The behind-the-scenes of this project are a lot - with a ton of moving parts to make the game enjoyable, easy, and fun.
Watch the demo video here - https://www.youtube.com/watch?v=rtv0rHFiAkc&feature=youtu.be
Community building is hard, especially in NFT communities. Typically, there's a lot of hype when the project is just starting out, members on Discord are going crazy, everybody wants that whitelist, and the collection is sold out in a few minutes.
This sets the expectations very high, and NFT community admins struggle to keep up the hype and the activity goes down.
Puzzlr brings together a fun, competitive, unique community-building approach which rewards players and is decentralized and built on the same principles as the NFT community itself.
How it Works
When a new puzzle game is active, the first step the user needs to take is gather pieces.
Pieces can be collected in a variety of ways. In the demo video, we demonstrate how you can purchase packs (with price set to $0 for the demo) where each pack contains a random assortment of 10 pieces.
Alternatively, pieces can also be airdropped to existing NFT/token holders - forcing them to try to work together and trade pieces with each other in a race to be the first to solve.
Or yet, pieces could be distributed through a scavenger hunt. Through clues dropped across social media or IRL, users could get access to a certain code that lets them claim one (or many) piece(s) required to solve the puzzle.
Once multiple users have multiple pieces, it is possible that you have a piece someone else wants, and they have a piece you want.
For this, we built a NFT<>NFT marketplace native to Puzzlr that allows for exactly this use case. This was done because middleman NFT trading websites such as OpenSea require the unnecessary step of going from NFT -> Token -> Other NFT and vice-versa.
This way, community members can work together while also competing with each other. Trading one piece for another - completely on chain.
Solving the Puzzle
Once you have all the required pieces to solve the puzzle, comes in the actual jigsaw.
With a simple drag-and-drop interface, and the prize image on the side, puzzlers need to solve the jigsaw puzzle.
In the demo, we demonstrate a 5x5 puzzle i.e. you need 25 pieces to solve it. This is not a requirement however, and the code is designed in a way you can create puzzles of any grid-size you want (NxN puzzles). We kept it 5x5 for simplicity.
This step is what we refer to as the Proof-of-Work NFT minting. You need to put in effort to collect the pieces and then also solve the puzzle (which can get quite difficult with certain images) - and it's no longer about who's the whale in the room.
Claiming the Prize
Once your puzzle is completely solved, you can go ahead and claim your prize. This will mint the prize NFT straight to your wallet, and congratulations - you now have a 1/n NFT.
To make all of this happen, there are a variety of things that are going on in the background. First, let's define our tech stack then see how the tech interoperates with each other.
- Solidity (w/ Hardhat)
- The Graph
- "Graph Worker" - a background script
- Hasura (GraphQL wrapper on Postgres)
- Lots and lots of Typescript
There are three contracts that go into making this game work.
PuzzleManager contains the core logic of the code. Starting new puzzles, marketplace listings, trading, choosing winners, selling packs, unboxing packs, generating randomness, and so on.
PrizeFactory contracts are ERC-721 implementations that mint the pieces and prizes NFTs individiually. The separation was done to allow for customization of the
Prize NFT collection page on marketplaces more easily - while keepign the hundreds, if not thousands, of pieces separate.
We created a subgraph that tracks all these three contracts and is used for a variety of things.
- Tracking Pack Purchases
- Tracking Pack Unboxes
- Tracking Piece Mints
- Tracking Transfers
- Tracking Marketplace Listings
- Tracking Winners
- Tracking Prize Mints
and so on.
Due to the number of NFTs that are being minted, and the number of pages we have to show these NFTs along with their metadata, using the Subgraph to fetch a list of NFTs owned by a user, for example, and then calling
tokenURI on each was getting very very slow.
So, we have a background worker - the Graph Worker - that polls the subgraph for new information - specifically token transfers (mints and trades) - every few seconds.
It caches this information in a Postgres database that is wrapped with Hasura GraphQL to make the website fast and be able to easily query different information around token holdings and such.
NOTE: While this introduces a centralized aspect to the game - the game is FULLY functional without this part. This is just done to speed things up - but all information is completely verifiable on-chain.
We use IPFS to store the metadata and images for each piece and prize NFT we mint. Thank Pinata for this.
We use Next.js to build the entire website and the serverless API functions.
To store cached information around all the various NFTs and metadata on puzzles and winners.
All actions in the game - buying packs, unboxing packs, solving puzzles, transfering pieces, listing on marketplace, etc - are all metatransactions. That is, we cover the gas for each and every transaction for the user.
Building this was challenging and fun, but important to the game experience and UX.
This was done so that NFT communities - even the ones not on Aurora - could play with the game without needing to first bridge tokens over - which can be complicated and intimidating for the average crypto user right now.
This is something we are very proud of.
- Getting this done on time was very hard.
- DB caching
- Complicated subgraph
- Graph worker listener
- Getting past the slow debugging due to needing to recreate puzzles, get all pieces, and such everytime something went wrong
Generally speaking, very very proud we were able to accomplish what we did.
There are a LOT of moving parts in this game - technically speaking. We came across weird issues on Aurora that were sometimes a little frustrating.
- When deploying contracts through a Hardhat script, Aurora would sometimes randomly hang up. We deploy 3 contracts in our case, and sometimes it would deploy all 3 no problem, other times it would deploy 1 and then be stuck for hours, other times it wouldn't deploy at all. We couldn't figure out the root cause for this issue.
- Getting testnet tokens on Aurora was bit of a pain. The faucet gives out very little ETH, and bridging from Goerli to Aurora Testnet, the transaction was stuck for hours. I had to message on Discord to get someone to help and they managed to un-stuck the transaction and get me the Aurora ETH I needed.
- Figuring out why our website was being slow and looking at the difference between caching token metadata in the DB vs calling contracts each time was challenging and mind blowing. It was day and night.
Puzzlr is really a community-building event that can be run by various folks. We like to think of it as the first step towards a Web3-based 'Jackbox Games' which are often used by companies and businesses to host fun events with their employees.
The codebase is designed as such that a lot of parts can be customized with ease - every thing being controlled through a central
We can pitch this as a B2B events solution with whitelabel customizations that can be designed to fit your use case with whatever sort of prizes.