Creating some art for our NFT and going deep down the rabbit hole with web3.

After much messing around the last few days, I got some prototypes up and running.

Smart Contracts Launched:

These were all super simple to set up, I linked my coinbase wallet to the NFT, added some ETH and hit launch. Their guides will be much better than anything I show shown below.

Building the NFT's  - Lore Building

I went back and forth what kind of theme I want for this project. On one hand, we are going to have a bunch of old school brokers using this platform, so I considered just making this super dry insurance themed. The NFT's would be policies, the token dollars, and accounts or the "portfolios".

The more I thought about it though, the old school users probably wont even look at the web3 tech behind this platform and use the ACH transafers, so I might as well do something that I enjoy.

I decided to go with more of a D&D vibe, but with Aztec and Mayan Gods. I live in Mexico so I view it as a good learning opportunity into their culture, and here is a lot of great lore out here to explore for the project.

Here is the work completed using Chat GPT-4 and MidJourney, ill include some of the prompts I used to create the figures.

Gods

Core Gods

These are the simple policy representations, whenever we sell a policy, we mint a god for whatever broker is in control of the policy.

  • Quetzalcoatl - The Feathered Serpent
  • Xōchipilli: The Flower Prince
  • Tlāloc: The Rain Deity
  • Huītzilōpōchtli: The Solar War Deity
  • Patecatl: The Lord of Pulque and Healing
  • Chalchiuhtlicue: The Goddess of Water and Fertility
  • Chicomecōātl: The Goddess of Agriculture and Nourishment
  • Tezcatlipoca, the Smoking Mirror
  • Mictlāntēcutli - Lord of Mictlan
  • Xolotl: God of Twilight, Twins, and Deformities
  • Tepeyollotl: Heart of the Mountains
  • Mixcoatl: God of Hunting, War, and Storms
  • Chantico: Goddess of the Hearth and Volcanoes

Nature Gods

We will also have one time mints representing bonuses to the lands, these are quota bonuses getting hit by the affiliate.

Prompt - An X god was drawn to your land by producing XXX new energy from your gods.

  • Spring God - A spring providing your gods with minor energy
  • Stream God - A mountain spring providing your gods with energy
  • River God - A vibrant spring providing your gods with abundant energy
  • Lake God - A roaring spring your gods with massive energy
  • Ocean God - Instantly provides your new creatures with maximum energy

Unique Gods

These are one time mints

  • Water God - 150k Health Quarter - .25% - Health New Production Calendar Quarters
  • Wind God - 250k Health Quarter - .25% - Health New Production Calendar Quarters
  • Star God - 250k New Life Quarter - .25%
  • Moon God - 350k Health Quarter - .25% - Health New Production Calendar Quarters
  • God of Light - 1M New Health Year - .25%
  • God of Night - 1M Life Year - .25%→ New Production Life
  • God of Earth - 1M Total Portfolio - .25% → Total Production Annual Health + New Production Life
  • Sun God- Heaven - 5M Total Portfolio - 1% - The sun is the most vital resource, providing all life with its energy.

Owner Mints

Lastly, I want to print a card representing entropy in the system i.e. our profits, and some cards for the owners to utilize later

  • Apep - God of Chaos - An entropy seeking being - Draws all extra energy not collected out of the system if affiliates dont hit tier bonuses.
  • Justin - Samsara - Death cycle card
  • Mike -
  • Brett - Zeus

Lands

The lands represent the user ownership over the dividends produced by the asset. Anytime this land card is staked, all the god cards associated with the card will produce energy tokens. I think what we will do, is create mounment NFT's that represent the creature being "taxed" on that land owning it. I havent finalized these yet, we need to come up with a lot of unique lands people wont mind being stuck with.

Forest

 Calakmul

 Sian Ka'an

 Mirador Basin

 Lacandon Jungle

 Tikal

Valleys

 Oaxaca Valley

 Valley of Mexico

 Motagua Valley

 Sacred Valley of the Río Pánuco

 Usumacinta Valley

Civilization

 Tenochtitlán

 Palenque

 Chichen Itza

 Teotihuacan

 Copán

Empire

 Aztec

 Maya

 Zapotec

 Toltec

 Mixtec

From these, I asked ChatGPT to come up with 5 NFTS for each location, this will allow us to have a healthy amount of land cards to start, giving people unique locations.

Tikal

Temple I: The Jaguar's Throne

The Sacred Ceiba Grove

Reservoirs of Rainwater

The Howler's Canopy

Limestone Ridge Mysteries

Calakmul

Structure 2: The Serpent's Pyramid

El Laberinto Bajo: The Swamp Sanctuary

Ox Te' Tuun: The Three Stones

Kingdom of the Snake: The Kaan Dynasty

Calakmul Biosphere: The Jungle's Heart

Art Work Completed

Using midjourney, I just threw together some collections and speed ran them through discord. I worked with an employee and we picked all the best ones for launch. It took us about 4 hours to make most of the basic god characters, and started making some land cards.

What we did is created an excel sheet of the mayan or aztec gods we wanted to make, and had chat gpt help us using wikipedia to make some metadata and midjourney prompts. Once those were all there, we just played with midjourney picking all of our favorite renditions, on occassion we had to modify the prompts to get better results.

Sample Chat GPT Prompt


I am making an NFT collection and need to come up with names, descriptions, and photos using midjourney prompts for a collection of mythical aztec or mayan gods. Can you search wikipedia about Mixcoatl, to create the required content? For the midjourney prompt, please provide the best prompt we could give to midjourney.

Name: Mixcoatl

Title: God of Hunting, War, and Storms

Description: Mixcoatl, also known as Camaxtle or Camaxtli, is a significant deity in Mesoamerican cultures, particularly associated with hunting, war, and storms. He is identified with the Milky Way, stars, and the heavens. Mixcoatl was the patron deity of the Otomi, the Chichimecs, and several groups that claimed descent from the Chichimecs. He is often depicted with a black mask over his eyes and distinctive red and white pin stripes painted on his body. These features are shared with other deities like Tlahuizcalpanteuctli, the Lord of the Dawn, and Itzpapalotl, the goddess of infant mortality. Mixcoatl is typically distinguished by his hunting gear, which includes a bow, arrows, and a net or basket for carrying game. He was one of the children of Tonacatecutli, an aged creator god, and Cihuacoatl, a fertility goddess. Mixcoatl was also known as the "Red" aspect of Tezcatlipoca, the "Smoking Mirror" god. He played a pivotal role in the creation myths, particularly in the story of the birth of the sun and the moon. He was the father of 400 sons, known as the Centzon Huitznahua, who met a tragic end at the hands of Huitzilopochtli. Additionally, Mixcoatl was believed to be the father of the revered deity, Quetzalcoatl, the feathered serpent.

Midjourney Prompt for Artistic Representation: "Create a mesmerizing representation of Mixcoatl, the Aztec god of hunting, war, and storms. Depict him adorned with his distinctive black mask and red and white pin stripes, poised with his hunting gear against the backdrop of the Milky Way. Emphasize his celestial connections, perhaps with stars shimmering around him and ethereal storm clouds gathering. The overall ambiance should capture the might and mystery of this deity, blending the earthly realm of hunting with the vast expanse of the cosmos."

Sample Artwork

Gods - Mixcoatl and Xochipilli

Land - Tikal

One cool idea we had, is combining the land cards that represent affiliates, with their character cards if they have an override on someone elses sales. It like a monument built for them. Pretty cool!

Code Structure

To help plan out new projects these days, I like to ask write out my general thoughts on how I think the game should work, and then ask Chat GPT to help structure the project and write some reference code. This is great, its like having a personal stackoverflow answer for your specific use case.

I should note, I wrote these bullet points based on research I did for thirdweb over the course of an entire day. I wanted to get to know how the platform really worked before diving too deep into the code.

I would start by exploring thirdweb, understand their platform if your new to this. They really do make this an easy process. My favorite feature they have is definitely the React SDK, or the prebuilt audited contracts to ensure you dont royally screw this up. I originally deployed all our test contracts with base, but im thinking im going to switch to polygon for the cheaper fees.

Here were some of the most helpful resources I found.

And some helpful videos

Here was the prompt that helped me understand how this projects is going to be laid out.


I am creating a smart contract to represent a game using nextjs, supabase, and solidity.
- Energy token is an EC720 token, that is used as the main currency on this chain
- God NFT, is an ERC721 token, used to represent creatures that generate energy
  - The attribute listed on the card "energy potential" is the annual amount of energy can be created if the nft is staked
  - the staked amount is produced daily, or the energy listed on the card divided by 365
- Lastly we have "lands", which are token bound accounts, ERC-6551. These have a 1 to many relationship with the gods, in which they take a percentage of the gods staked energy, based on 4 different types of lands
  - Forest Land
    - Once a day claims either 15% or 30% of the total energy produced by the god
    - 15% if all the land added less than 10,000 new energy of all new minted nfts combined energy total
    - 30% if all the new god under the land, generated more than 10,000 energy for the month.
    - After 365 days of staking, the creatures contract ends, and energy staking stops.
  - Valley Land
    - Same daily staking mechanisms as forest land
    - Also includes the ability to mint new "Water God" nfts, that take over the contract of the creatures after 365 days to continue producing 25% of the energy of the original god for another 365 days.
    - A water god is only minted if the user new gods energy total exceed 30,000 for the month
  - Civilization Land
    - Same staking mechanisms as the previous lands but also includes additional staking rewards for the first 365 days of staking
    - If the user new gods energy total exceed 30,000 for the month, it doubles the daily energy produced by the non water god creatures for 30 days
- Lastly, we will have a smart contract that mints the NFT's to the user based on supabase tables. Whenever a new "policy" is added in a policy table, it will look up which supabase user is associated with that sale and premium, and mint the nft to that user, representing energy as the premium

Smart Contracts

Energy Token (EC720)

  • Standard ERC20 functions for minting, transferring, and burning tokens.

God NFT (ERC721)

  • ERC721 compatible.
  • Additional attributes like "energy potential".
  • Functions for staking and unstaking the NFT to generate Energy tokens.

Lands (ERC-6551)

  • Functions to claim percentages of energy from staked God NFTs.
  • Special rules for Forest, Valley, and Civilization lands.
  • Functions to bind and unbind God NFTs.

Minter Contract

  • Functions to mint NFTs based on data from Supabase tables.
  • Possibly an Oracle that can securely interact with your Next.js backend.

Backend (Next.js)

  1. Supabase Integration
  • Functions to read/write data from/to Supabase tables.
  • Trigger-based actions for when new rows are added (policies).
  1. Web3 Integration
  • Functions to interact with the smart contracts.
  • Could use libraries like web3.js or ethers.js.
  1. Business Logic
  • Code to enforce game rules that can't be handled directly in smart contracts.
  1. User Authentication
  • Likely via Supabase Auth or similar.

Frontend (Next.js)

  1. User Dashboard
  • View and manage God NFTs, Lands, and Energy tokens.
  1. Game Interactions
  • UI for staking NFTs, claiming energy, etc.
  1. Supabase Integration
  • If needed, direct interaction with Supabase tables for less critical data.

Things to Consider

Security

  • Properly secure the Oracle and any backend-to-smart contract interactions.

Gas Efficiency

  • Optimize smart contracts for minimal gas usage.

Upgradability

  • Consider making contracts upgradable or use a proxy pattern.

Testing

  • Thoroughly test all contracts and interactions.

Would you like to dive deeper into any of these aspects?

Land NFT

I played with chatgpt a bit more, and asked it to generate some sample code to reference for the Land NFT, as it will be a crucial aspect. This is going to be a bit different and will only be used as a reference, thirdweb has most of this functionality built in to the React SDK.

can you write the code for the lands nft contract?

The Lands contract is a crucial component of your game, responsible for managing the staking and claiming mechanisms, as well as special functionalities depending on the type of land (Forest, Valley, Civilization).

Below is an extended Solidity skeleton code for the Lands contract, focusing on some of the unique rules you mentioned for each land type:

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;
contract Lands {enum LandType { Forest, Valley, Civilization }

struct Land {
    LandType landType;
    uint256 totalEnergy;
    uint256 lastClaimed;
    // Add more attributes here
}

mapping(address => Land) public lands;

// Add a staking function here to allow God NFTs to be staked in lands
// This can be implemented in various ways depending on your overall architecture

// Function to claim energy from staked Gods
function claimEnergy() external {
    require(lands[msg.sender].lastClaimed + 1 days <= block.timestamp, "Can only claim once a day");
    
    uint256 energyToClaim = 0; // Calculate this based on staked Gods
    LandType landType = lands[msg.sender].landType;

    if (landType == LandType.Forest) {
        // Forest logic
        if (lands[msg.sender].totalEnergy < 10000) {
            energyToClaim = energyToClaim * 15 / 100;
        } else {
            energyToClaim = energyToClaim * 30 / 100;
        }
    } else if (landType == LandType.Valley) {
        // Valley logic
        // Similar to Forest but with additional rules for Water God minting
    } else if (landType == LandType.Civilization) {
        // Civilization logic
        // Additional staking rewards and other rules
    }

    // Update totalEnergy and lastClaimed
    lands[msg.sender].totalEnergy += energyToClaim;
    lands[msg.sender].lastClaimed = block.timestamp;
    
    // Transfer energy to the user (you'd call your ERC20 contract here)
}

// Add functions to bind and unbind Gods from lands
// This can be implemented in various ways depending on your overall architecture

// Other utility functions, modifiers, and events
}

Data Oracle Minter

Another code I asked for is the data oracle, this is going to be an important part of this contract. This data oracle will check supabase if we have any new sales, and if so, mint the NFT to the correct user. If this gets hacked, or there are bugs, it can break the entire structure. As a fail safe, we will only manually convert NRG tokens for USDC for people making withdrawals, we wont have many partners so our accountant can easily confirm the amounts are correct based on our internal systems for now. I will also implement some fail safes to ensure the amount of new total energy listed on the NFT mints, is equal to the amount received in our income account in fiat. This will ensure if the chain is compromised or bugged, we wont see any long term effects before we push out an update.

I did originally ask Chat GPT to use a vercel cron function, but I guess the browser plugin is disabled now and it has no data on it. This is only for reference however so it will do for the test concept.

Run scheduled jobs with Vercel Cron Jobs and Vercel Functions – Vercel
can you expand on the data oracle?
how it might calculate the nft mint drop amounts using a cron function in javascript?

An oracle in this context is an entity that provides data to a smart contract from an external source, like a database or an API. In your case, you want to mint NFTs based on data in a Supabase table. You can set up a cron job in a Node.js environment to check this table at regular intervals and then trigger the minting operation via the smart contract.

The Flow:

  1. Cron Job: A cron job runs at regular intervals to check the Supabase table for new entries.
  2. Supabase Query: The job queries the Supabase table for new policies that need NFTs to be minted.
  3. Data Processing: The cron job processes this data to determine how many and what kind of NFTs to mint.
  4. Blockchain Interaction: The processed data is then used to call the smart contract's minting function.
  5. Smart Contract: The smart contract mints the NFTs as instructed.
const cron = require('node-cron');
const ethers = require('ethers');

const provider = new ethers.providers.JsonRpcProvider('YOUR_INFURA_URL');
const wallet = new ethers.Wallet('YOUR_PRIVATE_KEY', provider);
const contractAddress = 'YOUR_CONTRACT_ADDRESS';
const abi = ['YOUR_CONTRACT_ABI'];

const contract = new ethers.Contract(contractAddress, abi, wallet);

// Function to query Supabase (simplified)
const querySupabase = async () => {
  // Use Supabase client to get data
  // Return the data
  return [
    { userId: '1', policy: 'somePolicy1', premium: 1000 },
    { userId: '2', policy: 'somePolicy2', premium: 2000 },
    // ...
  ];
};

// Function to mint NFTs
const mintNFTs = async (data) => {
  for (const entry of data) {
    const userId = entry.userId;
    const premium = entry.premium; // Used to determine the "energy" in your case

    // Call the smart contract to mint the NFT
    const tx = await contract.mintBasedOnSupabaseData(userId, premium);
    await tx.wait();
  }
};

// Schedule cron job to run every hour (or as needed)
cron.schedule('0 * * * *', async () => {
  console.log('Running the cron job');

  const data = await querySupabase();
  await mintNFTs(data);
});


Vault

Lastly, I asked it for some sample code on how we could convert tokens to real life currency down the road. Once we trust the code is working, we will stop doing this manually and automate the entire platform.

Conversion tool

  • Marketplace
  • Burns tokens if ACH paid
  • Burns tokens if USDC paid
I want to create another contract that users can use to withdrawal their energy into USDC, or optionally do an ACH trasnfer from our real life bank. We want the energy to be burned once the usdc or ACH transfer is marked received in supabase

Smart Contract for Energy to USDC/ACH Conversion

You could create a new contract that handles the withdrawal of Energy tokens. Once a withdrawal is initiated, the contract could burn the corresponding Energy tokens and notify your backend system to process the USDC transfer or ACH transfer.

Here's a simplified Solidity code snippet:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract EnergyWithdrawal {
    IERC20 public energyToken;
    IERC20 public usdcToken;

    mapping(address => uint256) public pendingWithdrawals;

    event WithdrawalRequested(address indexed user, uint256 amount, bool isACH);
    event WithdrawalProcessed(address indexed user, uint256 amount, bool isACH);

    constructor(address _energyToken, address _usdcToken) {
        energyToken = IERC20(_energyToken);
        usdcToken = IERC20(_usdcToken);
    }

    function requestWithdrawal(uint256 amount, bool isACH) external {
        // Transfer Energy tokens to this contract and burn them
        require(energyToken.transferFrom(msg.sender, address(this), amount), "Transfer failed");
        energyToken.burn(amount);

        // Log the withdrawal for backend processing
        pendingWithdrawals[msg.sender] += amount;
        emit WithdrawalRequested(msg.sender, amount, isACH);
    }

    // This could be called by your backend after it confirms the USDC or ACH transfer
    function confirmWithdrawal(address user, uint256 amount, bool isACH) external {
        // Authorization checks (only allow your backend to call this)
        
        require(pendingWithdrawals[user] >= amount, "Insufficient pending amount");
        pendingWithdrawals[user] -= amount;

        if (!isACH) {
            // Transfer USDC to the user
            require(usdcToken.transfer(user, amount), "USDC Transfer failed");
        }
        
        emit WithdrawalProcessed(user, amount, isACH);
    }
}

Subscribe to Justin's Blog

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe