Updates Since Chainlink Fall 2021 Hackathon

Evil Club Lords

Have launched the nemesis to Matic Mike, the Evil Club Lords. This is a delayed mint using VRF to assign a random time to reveal (between 2-4 weeks) with the option to speed up the process every 24 hours by injecting with the ERC20 token $HGH. 1 hour per $HGH burned reduces amount of time until reveal, up to 10 $HGH (hours) / 24h.

Dance Royale and Analytics

I've modified the dance royale contracts to allow multi-erc721 entry from different contracts, including ones not in the Matic Mike family if we wish. I've also created a fully secure roll system that globally modifies all seeds generated for entries and determines rolls on the final chainlink call in the queue so nobody can pre-determine rolls on the chain.

I've added a Dance Analytics contract that compiles all data from multiple royale contracts and combines them in a get call.

High Stakes Royale

We've launched the WETH royale contract which is similar to the normal dance royale, however entry is with $WETH with optional $HGH burned to give a variable power level incrase.

A Quick Note

The project is now fully in production with almost 660 unique wallets holding NFTs. I listed staging environment links on the mumbai testnet, however for full user experience some updates have been pushed directly to production. If judges need a production Matic Mike and don't want to buy one on the opensea aftermarket, please let me know so I can send one of mine.


Matic Mike was inspired by other high utility NFT projects in the space that are 100% on chain. I wanted to make something special that is fully on chain with no api, but also have a full functioning and easy to use interface for everyone to enjoy. The goal here is not only to release a fun, free project, but also to show how dynamic the NFT space can be, ranging from pure artwork to a full-scale collectibles game with it's own ecosystem.

You can read a full rundown and guide of the current release here.

What it does

Full 25 minute detailed overview video

Matic Mike is a free, 100% on-chain generative ERC721 NFT game on the Polygon network with a Polygon <-> Ethereum bridge, and is accompanied by a fully compliant ERC20 Token, Matic Mike Juice ($HGH) with a Polygon <-> Ethereum bridge as well.

As stated, Matic Mike is a 100% on chain generated NFT. When I say 100%, I mean 100% as each Mike's traits are chosen on mint, and drawn out pixel by pixel on chain. Every trait has a power level associated with it, with each Mike having their own power level associated with them. Power levels are used in all the gaming functionality which I'll explain further down the line.

Problems it Solves

There's a few problems in the NFT space this project provides a resolution to. The first and most obvious is being fully on-chain. Having all metadata, including image, being stored fully on chain is basically a guarantee you will forever have access to the NFT.

The second is being able to dynamically modify metadata based on future project releases. In the data contract (which we can change the address of in the ERC721 contract if we need to make changes) I have an extension contract that queries and loops through for future contract additions. Things like fighting boss NFTs and receiving loot can be done totally on chain, and pull new data and graphics into the genesis NFT.

Another problem with high utility projects on L1 Ethereum is transaction fees. Being on Polygon with the ability to bridge over to Ethereum for certain aftermarket compatibility allows users the luxury of participating in the high utility of staking, withdrawing, token injections, minting and burn rerolls, as well as PvP battle royales without having to worry about spending more than a few pennies.

The Dance Royale specifically displays a system in which blockchain can be utilized in a fortnite style queueing system, with new queues opening as soon as the previous queue fills or is triggered via a time trigger. The actual functionality of the Dance Royale makes extreme use of Chainlink VRF.

The $HGH contract provides a new way to earn tokens by staking ERC721 tokens, with the ability to add any ERC721 Token into the ERC20 contract at different emission rates. This is something quite unique as I can add in other developers contracts for promotions or collaborations.

Finally, the major thing this project shows is the ability to integrate a full-scale collectibles game without the need for any external / centralized API. Although chainlink provides a useful resource for communicating with centralized data, being fully decentralized was the goal of this project. Utilizing Chainlink VRF for the heavy use of random number generation was a necessity in the success of this project. Chainlink VRF in the upgrade & dance royale completion also prevents against potential flashbot misuse to revert calls if desired result is not met (just learned this today).

The Minting Process

Matic Mike is now fully minted on the Polygon chain. To onboard interested users, I airdropped $1000 in MATIC to users who signed up for our whitelist for gas on the Polygon network. The mint price was as follows...

  • 1-2500: Free Mint (1 per whitelist, and once public sale was activated, up to 10 per wallet)
  • 2500-4000: 1 $HGH
  • 4000-6000: 2 $HGH
  • 6000-8000: 3 $HGH
  • 8000-10000: 4 $HGH
  • After 2500, free "Burn Rerolls" were activated, allowing users to burn their mint and generate a new mint.

$HGH and It's Uses

Let's talk a little bit about $HGH and what it is used for in-game in Matic Mike NFT's present state. Before we get into the functions of $HGH, we should talk about how to earn $HGH. As stated, Matic Mike was a 100% free mint, and after 2500 used our new ERC20 token $HGH. To earn $HGH, you must have a Mike, and he is staked "in the gym," also known as the $HGH contract, with an emissions rate of 1 $HGH over 24 hours per Matic Mike staked in the $HGH contract. The first feature was obviously the tokenized minting process, now let's take a look at the "token injections."

ERC20 -> ERC721 Token Injection

One of the unique features about the Matic Mike NFT is the ability to dynamically modify traits all on-chain at the cost of $HGH. I call this "Token Injection" and it is the process of burning off $HGH for a small chance to upgrade the tier of rarity of a random trait. This was a feature included in our initial release 2 weeks ago. The cost to inject Matic Mike for a chance to upgrade started at 1 $HGH and increases on a global scale by 3 $HGH for every successful injection. Token injections have about a 5.5% success rate, and the $HGH used per attempt is burned from the circulating supply. I'll explain how this is built in the next section.

The PvP Battle Royale

The other current use of $HGH is our player vs player battle royale contract, also known as the "Dance Royale." This is a rolling 50 man queue system done completely on-chain that costs 1 $HGH to enter, with the option of adding 0-5 additional $HGH for adding 1-10 power level per additional $HGH injected. The optional injection $HGH is burned from the circulating supply, while the entry fee is added to the pot for the current royale. Upon completion, the winner receives 70% of the royale pot, 2nd place receives 20%, and 3rd 10%.

A complete log of analytics are stored in the PvP Dance Royale contract, and our Web Interface gives a nice look at individual token stats. Analytics for wallet address data is also stored on-chain, with plans to integrate a future contract with a "name your wallet" function and a custom uri slug on the website. This will give complete analytical history for addresses even if you sell or trade your Mike in the future.

How I built it

The short answer is solidity, html, javascript, web3, jquery, select2, bootstrap 5, discordjs, and nodejs for the ethereum bridge.

The chains include Polygon, Ethereum, as well as utilizing tons of Chainlink VRF functionality specifically in the utility features of ERC20->ERC721 token injection and Battle Royale contract.

The Long Answer

The Matic Mike NFT and Matic Mike Juice ($HGH) initial release was a total of 5 smart contracts.

And the PvP Battle Royale Contract is one single contract, but 2 more contracts are planned in the near future for a more in-depth analytical look as well as the "Name your Club" contract.

The Matic Mike NFT Minting Process

Simulate Minting Here

Let's first start by getting into the minting process of the Matic Mike NFT. Every mint generates new unique metadata by looping through and generating 8 random numbers (this part does not utilize chainlink VRF so I could quickly return to the user) which are used to determine the rarity of each trait. Depending on where the number falls, it selects a number (0-9) of the trait and pieces together a "hash" or "dna code" for the token id. That DNA code and token ID is sent to the data contract when pulling the tokenURI or other read calls and the metadata is generated on demand.

I also integrated the free "burn rerolls" which essentially sent the token id being burned to a dead address, and ran the same minting process over again. This is what pushed the mint to fully mint out very quickly. There are examples of all these functions in the 5 minute overview video.

The Data & Reading From the Data Contract

Let's first start with how I populated the data. I store the data for each trait in a struct as follows...

struct Trait{
    string traitName;
    string traitType;
    string pixels;
    uint256 pixelCount;
    uint8 powerLevel;

This is pretty straight forward, but I should get into what the pixel string looks like, and how it works. Every "pixels" string is composed of each pixel by 4 characters, let's use the example ab23. The first 2 characters represent the x and y coordinates, encoded as a letter. so a = 0, and b = 1. This mean's I am plotting a pixel at 0,1. The last 2 characters represent a css class associated with the color. So I am plotting a pixel at 0,1 with a css class of "c23". I loop through each trait and plot these pixel strings during our calls. Because I do have such a large mapping of pixels, I also loaded full XML of pre-plotted data for the body and outfits.

It is worth noting, for further expansion I include this bit of code...

if(xxlAddress != nullAddress){
    IMikeExtended.Traits[] memory XxlTraits = IMikeExtended(xxlAddress).getAllPlayerLoot(_tokenId);

    for(uint256 i=0; i < XxlTraits.length; i++){
        if(XxlTraits[i].valid && XxlTraits[i].pixelCount > 0){
            svgString = string(

This is for our expansion projects, in which I'll be able to pull new graphics directly into the SVG string. Each additional trait will be plotted in 1 long string.

The ERC721 contract will call the data contract for tokenURI (which grabs the attributes and SVG, and base64 encodes for return) and power level inqueries.

It's worth noting, I drew everything out in photoshop, then mapped everything out pixel by pixel in a 24x24 SVG and wrote the style sheet that is stored on the data contract, this took over 30 hours.

The ERC20 Contract and Staking

Simulate Staking Here

The "gym" as I call it is a pretty simple mechanic. You stake your MIKE into the ERC20 contract ($HGH) and record the timestamp sent. You can claim the accumulated $HGH at any time, at an emissions rate of 1 per day per MIKE staked, with a max of 10 MIKEs per wallet staking.

Included in this is the same set of functionality, but mapped by contract addresses. This gives us the ability to add multiple contracts that can stake at different emissions rates for future projects. I plan on allowing our "Evil Club Owner" NFT to stake at an emissions rate of .25 $HGH per 24 hours.

ERC20 -> ERC721 Token Injection

Simulate Token Injection Here You must have a MIKE minted and unstaked, you can open $HGH faucet from #15 "openFaucet" on $HGH polygon mumbai contract

Our Matic Mike NFT contract allows for "injecting" Mike with the $HGH token for a chance to upgrade a random trait. I determine all randomization in this method by working off of a random number provided by a Chainlink VRF call. Let's dig in.

First, I take payment in $HGH for the injection attempt. This is burned from the total supply, and a Chainlink VRF function is called, storing the request ID to the token being attempted at upgrade.

In our fulfillRandomness call I first check to see if the modulo equation result falls in the 5.5% range required to proceed with the upgrade. If not, nothing happens, but if true, it will move onto the next call, which is determining which trait to try and upgrade. I do this by a simple modulo call to determine a 1-9 range.

Once the trait the algorithm is going to upgrade is selected, it will try to increase it's rarity by 1 or 2 rarities by subtracting from the number (if > 0), recreating the "dna code" hash with the new number, and making sure it does not exist in the hash map (all MIKEs must remain unique). If it doesn't exist, it saves the hash to the token and it is now upgraded, otherwise, it continues to move rarity positions over by 1 to until it hits a successful upgrade which the hash doesn't exist. If it steps through every combination and all hashes exist, the upgrade will also be unsuccessful.

Upon completion of a successful upgrade, the contract increases the global price of $HGH for upgrade attempts by 3. This is to preserve rarities and deflate $HGH supply.

The PvP Dance Royale Contract

First, let's list the links involved with this contract interface so you can easily jump from page to page. Make sure you have your Mike minted if you plan on sampling the queue system. Please note, if you do want to test on live environment, please send "Mike Dev" a message in discord and I'll send you some $HGH. $HGH has no max supply, and no faucet on mainnet, so I earn at the same rate as everyone else.

As mentioned in the previous section. The dance royale has a rolling 50 man queue system, which lowers to 15 man after 30 minutes if the queue hasn't filled in an effort to keep queues rolling (all numbers and times are adjustable). Lets go through a few of the requirements to enter.

  1. I have an active flag in case I ever need to freeze entries for whatever reason.
  2. The optional $HGH added to your MIKE entering battle must be a non decimal integer
  3. The optional $HGH added must be less than the maximum allowed juice (adjustable, currently 5).
  4. You must be owner of the MIKE, however the MIKE can be staked in the $HGH contract.
  5. The current Royale Rumble id does not exceed the rumble size, and the battle is not already in progress.
  6. You can only enter a unique MIKE once per content.

It is also worth noting, if you are the first in queue, you populate the analytics for the last royale. This is not done during the actual royale call due to gas limitations and ensuring Chainlink doesn't run out of gas during the callback.

Optional $HGH added is tracked and burned, before calling the Chainlink VRF function.

Here is the code for the enter royale function, it is pretty self explanatory. I make use of a lot of mappings to quickly handle all requests.

// enter battle royale
function enterRoyale(uint256 _tokenId, uint8 _hghJuice) public returns (uint256){
    require(active, "Dance Royale not currently active");
    require((_hghJuice * wagerMulti) % wagerMulti == 0, "HGH Amount cannot be a decimal");
    require(_hghJuice <= maxJuice, "Over the maximum juice amount");
    require(IHgh(hghAddress).balanceOf(msg.sender) >= (_hghJuice * wagerMulti) + currentPrice, "Not enough HGH in wallet balance");

    // check in gym as well
    require(IMaticMike(mmAddress).ownerOf(_tokenId) == msg.sender || IHgh(hghAddress).getStaker(_tokenId) == msg.sender, "Not the owner of token");
    require(royaleParticipants[_rumbleId.current()] < rumbleSize && !battleIsComplete[_rumbleId.current()], "Royale trigger currently in progress. Try again in a minute");

    // require that they are not already entered in the competition...
    require(!tokenToRumble[_tokenId][_rumbleId.current()], "Already entered in competition");

    // if new rumble populate analytics from previous rumble
    if(_rumbleId.current() != 0 && royaleParticipants[_rumbleId.current()] == 0){
        populateWinners(_rumbleId.current() - 1);

    // burn the juiced up amount
    IHgh(hghAddress).burnFrom(msg.sender, _hghJuice * wagerMulti);

    // transfer 1 HGH to contract
    IHgh(hghAddress).transferFrom(msg.sender, address(this), currentPrice);

    // begin royale entry
    royalePot[_rumbleId.current()] = royalePot[_rumbleId.current()] + wagerMulti;
    tokenToRumble[_tokenId][_rumbleId.current()] = true;

    // Chainlink VRF
    bytes32 requestId = requestRandomness(keyHash, fee);

    responseIdToBattle[requestId] = BattleType(


    return _rumbleId.current();

Once a user has entered into the competition, I need to determine their roll. This is done by first calculating their power level. The function assign a random additional powerlevel (up to the optional $HGH, multiplied by 9, plus the optional $HGH).

if(responseIdToBattle[requestId].juicedUp > 0){
    powerup = (randomness % (responseIdToBattle[requestId].juicedUp * 9)) + responseIdToBattle[requestId].juicedUp;

I then query the Matic Mike contract for power level, add it to the previous calculation, and determine the roll...

uint powerlevel = IMaticMike(mmAddress).getPowerLevel(responseIdToBattle[requestId].tokenId) + powerup;

address tokenHolder;

// check if in gym and assign accordingly
if(IMaticMike(mmAddress).ownerOf(responseIdToBattle[requestId].tokenId) != hghAddress){
    tokenHolder = IMaticMike(mmAddress).ownerOf(responseIdToBattle[requestId].tokenId);

    tokenHolder = IHgh(hghAddress).getStaker(responseIdToBattle[requestId].tokenId);

uint256 roll = randomness % powerlevel;


Once all the entries are in for the current royale, I calculate the winner by looping through all the roles, coin flipping on ties, and saving 1st, 2nd, and 3rd place. Payouts are done instantly sending the $HGH pot as follows...

  • 70% to First Place
  • 20% to Second Place
  • 10% to Third Place

The next Royale queue begins immediately, and as previously state, the analytics are stored on the first person who queues the into the next royale.

It is worth noting, I am saving wins by Token ID as well as wins by Address. This is for the future "Name Your Club" project in which I'll have full details on club wins and analytics whether they still hold the token which they won or lost with.

DiscordJS and Additional Functionality with Ethereum Bridge

I run a discord bot using discordjs running on our server using foreverjs. Some of the functionality I have implemented include...

  • /supply
    • returns circulating supply of $HGH, Matic Mikes, Unique Wallets Staking, Total Burned, and other useful info
  • /powerlevel {id}
    • Returns Powerlevel of the Token ID
  • /peek {address}
    • Returns all OpenSea links of the address, both staked and unstaked tokens
  • /snapshot {id}
    • Returns a snapshot of all the traits and an opensea link of the Token ID

The Ethereum Bridge TokenURI points to our website which runs a simple NodeJS script to query and return the polygon Matic Mike contract MetaData. For speed, we save a cached copy of the json on the server, and it is overwritten periodically with new data in case any upgrades occur or additional traits are pulled in in the future with our PvE contract.

Challenges I ran into

I had some hickups along the way as this was my first major blockchain project. I'll go over each issue individually and how it was resolved.

Gas Limit Issues on Read Functions

I ran into the problem when calling the TokenURI where if a combination of traits led to a very large amount of pixels, it would run out of gas. This is because the body and clothing portion of the SVG uses a good amount of pixels. To resolve this, instead of drawing out these attributes pixel by pixel, I loaded in the entire section of the SVG and append it to the result in one loop. I still draw out most of the smaller traits pixel by pixel, but after realizing how low cost it is to populate something like this on Polygon, I could just load more data into the contract without having to worry about a pixel by pixel drawing.

In future contracts, I'll be implementing a new algorithm for drawing out graphics in chunk in a larger map, but for the sake of time and getting multiple phases of this project out within the hackathon deadline, I did not implement this in the current data contract.

Onboarding Users to Polygon Chain

It was very hard with our whitelist explaining how to get Matic on Polygon, as well as just getting users onboarded in general. I put a guide together prior to minting that helped with this, and automatically added the polygon network to their web3 wallet.

A Small Error in the Contract Code

When a MIKE was burn rerolled, the contract modifies the "dna" hash to reflect that it has been burned, and a pitchfork type of drawing is placed on the MIKE signifying it has been sent to the dead wallet. I forgot to run this function when sending the hash to the data contract, so I had to replace the data contract mid mint to call back to the ERC721 contract to see if the token belongs to the DEAD address, and modify the hash on the data contract.

If I could go back and change it, I would probably integrate an upgradable contract to fix the error in the main contract.

OpenSea Not Refreshing MetaData and Not Having Polygon API

Instead of being able to force refresh metadata like you are able to on OpenSea with ethereum contracts, I needed to create a browser automation script that constantly runs to refresh metadata to reflect potential user upgrades from token injections, and in the future, loot from the boss contract NFTs.

Chainlink on Polygon

This was kind of a scary moment, but I had loaded some LINK onto the contract for Chainlink VRF functionality yet was getting an insufficient LINK balance. I quickly realized after re-reading the documentation that I needed to convert to the official LINK token on Polygon using the PegSwap service. This was a relief, however there is now some LINK stuck in the contract forever!

Marketing, Marketing, Marketing

I am in desperate need of marketing help for this project to gain attention and actually bring in more active users. Unfortunately due to the quick "flip" mentality on a lot of NFT projects, I have a good amount of users listing for a very low price on OpenSea and not participating in the PvP Dance Royale contract, and I'm afraid will not participate in my future PvE Evil Club Owners NFT contract I plan on releasing in December.

An update as of 11/23 - we have began to see some movement in getting a lot of the inactive users out, and I launched an update to the data contract to pull in stats to the metadata to show things like Power Level, Dance Royales entered, and Placement Percentage in those royales (top 3) for each Matic Mike. This helps potential buyers narrow down options for when they plan to buy.

My goal with this hackathon is to hopefully place, and potentially draw some attention to the work I've been putting in on really expanding what NFTs can do.

Accomplishments that I'm proud of

  • 10,000 Matic Mikes were minted over the course of 12 hours
  • 7363 of those Mikes were burn rerolled, leaving a total supply of 2637
  • Of those 2637, Matic Mike sees an average over 2200 staked (in the gym). That signifies the project has a lot of long-term holders
  • My ethereum bridge worked, although I am the only one who has used it
  • Almost 18,000 $HGH has been generated through staking over the course of this project
  • Over 648 unique wallets own a Matic Mike, which I am happy with that number
  • I was told by almost everyone on the night of minting that it was the most fun minting experience they ever had
  • The launch was relatively smooth for both the minting, and the PvP Battle Royale contract.
  • As of 11/23 we have over 70 dance royales with a minimum of 15 Matic Mikes per royale completed.

What I learned

  • Solidity, and working with blockchain in general
    • This was the first blockchain project I've worked on. I've been a big fan of Ethereum and Polygon in general but never got around to actually working with it. I now consider myself pretty up to speed with the core concepts.
  • Chainlink VRF - I had no idea until I started writing out the code I whiteboarded that true random numbers weren't technically possible on chain. Chainlink VRF was a true asset with this. I am also very excited to expand my use of Chainlink in the future, and I've got some CRAZY ideas brewing.
  • DiscordJS and Web3
    • I was very happy to find DiscordJS and it was a pleasure to work with. You can do some really cool things with it and I think it is especially useful for web3 functionality
  • Reignited my passion for coding
    • I've been a full stack developer for 12 years, but this brought me back to college and not having the robust amount of documentation I am used to today. Although a lot of documentation exists, because blockchain is still relatively "new" you can't just Google every problem and come up with a solution.
  • Learned just how much one can get done if TRULY motivated. This is the most amount of work I've done in the least amount of time I think in my entire career.

What's next for Matic Mike NFT Game

The unreleased phase of our project is our PvE Evil Club Owners NFT contract. Although I won't have time to complete this prior to the chainlink hackathon deadline, I should give a rundown so you can see more ways $HGH and the genesis Matic Mike NFT will play a role in the future of this project.

The idea is that Matic Mike will need to summon the Evil Club Owner NFT by staking in the Club contract, which will assign a randomized time period, between 1 week and 1 month, to summon out the Club Owner. You will also need to burn off 100 $HGH to start summoning the owner, and will be able to send more $HGH on a daily basis to reduce the amount of time it takes to summon the boss. My initial thought is 10 $HGH will reduce the amount of time Mike needs to be staked in the club by 1 hour.

Once the Evil Club Owner is spawned, not only will they be able to stake inside the gym and earn $HGH (at a lower emissions rate than Mike), they will also have a power level associated with themselves as well as a piece of loot. Matic Mike will be able to go into battle with his Evil Club Owner and if Mike is successful in defeating them, Mike will pull the trait and new graphic directly onto his original Matic Mike NFT. The club owner will only be able to be looted once, but will be used in future player vs player concepts. Each Matic Mike will be able to summon 2 club owners and a total of 2 new trait types with 9 different trait values will be randomly generated in the loot of the club owners.

The future of this project will be released in seasons, where the club owner and "name your club" contracts will finish up season 1, and season 2 will begin with Mike training a new apprentice, and the next chapter of PvP and PvE will revolve around Mike helping his apprentice through all walks of life in this crazy NFT space.

Updates to submission 11/23/2021 I've updated the github repository with the discordjs bot, as well as the website source code for the production site. If judges need a Matic Mike NFT on production, as well as some $HGH to use the utility functions, please reach out via discord to myself, "Mike Dev" in our discord.

I have also updated some of this documentation and replaced "we" with "I" as I developed this project solo from a code and innovation perspective. It, however, is not my intention to take away from the community help I received in promoting the project to get the amount of unique holders I currently have.

Because this is a continuously evolving product, the staging environment may not be kept as up to date as the production environment. Due to the fast-moving space I will frequently push updates directly to production.

Built With

Share this project:


posted an update

Updates to submission 11/23/2021 I've updated the github repository with the discordjs bot, as well as the website source code for the production site. If judges need a Matic Mike NFT on production, as well as some $HGH to use the utility functions, please reach out via discord to myself, "Mike Dev" in our discord.

I have also updated some of this documentation and replaced "we" with "I" as I developed this project solo from a code and innovation perspective. It, however, is not my intention to take away from the community help I received in promoting the project to get the amount of unique holders I currently have.

Because this is a continuously evolving product, the staging environment may not be kept as up to date as the production environment. Due to the fast-moving space I will sometimes push updates directly to production.

There are some times I still refer to the project as "we," and this is due purely to what is mentioned above. I built the Matic Mike MVP to create a community that owns a piece of what I've built. Moving forward I plan to reinvest any funding that comes in directly to directly benefit the project as a whole, whether that be marketing, paying additional devs to work on new releases, putting a dropshipping merch store together for Matic Mike Merch purchasable in $HGH, or anything else that may have an impact on the overall value of the project.

Log in or sign up for Devpost to join the conversation.