This contract stores the DNA information for GOGOs. When GOGOs were released there was no such thing as an "on-chain view" on Tezos. The Tezos blockchain has evolved since, and making this information available on-chain is a key part of the long-term GOGOs development goals.
This repository creates a contract that provides a set of on-chain views regarding the unique DNA string associated with each GOGO.
This DNA was originally used to select the source images when generating the GOGOs and is available inside each GOGOs off-chain TZIP-21 metadata.
This contract brings additional metadata on-chain that complements and subtly augments the existing off-chain metadata.
- Mainnet: KT1A18hiVawYcKDHyZ4JzToziq1nb6XhVJ1S
- Ghostnet: KT1LR44SnJHMHs169t3A4dFR2Hp26syYfd2t
There are small differences between the "traits" shown on-chain and the ones that ended up in the final off-chain metadata.
The DNA values represents the "before" generation state of the GOGOs, and the final metadata shows their finished state.
The main difference is that the DNA shows what's in the left hand even if the left hand is out of the frame, and the off-chain meta also shows details of the "tool" which the on-chain DNA does not keep track of and represents so-called hidden traits for GOGOs where you cannot see their left hand.
GOGOs selected their own "tools" (if any) seen in the TZIP21 metadata at the end of their generation function and their input DNA did not impact their choice of tool, meaning the DNA does not show what is in the GOGOs right hand. This was intended to give each GOGO the concept of free will and choices they had to make while they were being generated.
The DNA also does not track or dictate the "background" or "stress" values as these are the results of the GOGOs lived experience while being generated and outside of the control of their input DNA. These values are available in the off-chain TZIP-21 metadata.
Meteor and UFO traits are intentionally untracked both on and off-chain to add a bit of spice.
GOGOs sometimes have intentionally duplicate trait names that differ visually, such as the "OK" hand (4 variants) and "black" or "blue" hair (multiple variants) that were designed alongside untracked visual traits like meteors and abstract traits like stress to subtly disrupt the standard rarity ranking process when they were released.
Take this into consideration when integrating.
The contract adds the following on-chain views. You pass in the ID of the GOGO you want to query along with any additional options if the view requires it.
You can interact with the views directly on BCD: https://better-call.dev/mainnet/KT1A18hiVawYcKDHyZ4JzToziq1nb6XhVJ1S/views
get_dna_config()
Returns the DNA configuration object
length:10
pieces:10 items
0:left_arm
1:left_hand
2:body
3:head
4:face
5:hat
6:bling
7:hair
8:accessory
9:aura
get_dna(1)
Returns the DNA for the specific GOGO in String format
@string_1: 0_4_9_14_13_4_3_7_1_2
There are 2 options here, the one returns integer keys and the other has the String
get_full_dna_keys(1)
Will return a trait map with integer values mapping to traits
@map_1:10 items
accessory:1
aura:2
bling:3
body:9
face:13
hair:7
hat:4
head:14
left_arm:0
left_hand:4
get_full_dna_values(1)
Will return a trait map with the String value of the trait pre-populated
@map_1:10 items
accessory:Headset
aura:Red
bling:None
body:Purple Tee
face:Disgusted
hair:Blue Punk
hat:Spikes
head:Ashen
left_arm:None
left_hand:Mace
Because left_arm is 'None' the left_hand is out of frame so it is not present in the final TZIP21 metadata in this example GOGO #1
token_has_trait(token=1,trait='body',vals={'9'})
Check if a given Token has any of the supplied Traits for a given Trait type
Will return True if the token has any of the matching values for the given trait.
There can be multiple trait values with the same name, for example hair: Blue hair has several markers, so to check if a GOGO has blue hair you should call
token_has_trait(token=1,trait='hair',vals={'2','7','12','101'})
Another example to check if a GOGO has an accessory:
token_has_trait(token=1,trait='accessory',vals={'1','2','3','106','108','109','110'})
will return true if the GOGO has any of those accessories.
You can see the trait map in the contract storage for the values you need for your use case.
trait_key_value('body','5')
will return Dinosaur
is_mythic(1)
will return False
is_mythic(786)
will return True
If you own or manage an existing Tezos FA2 collection you may use this repository to create your own on-chain DNA trait registry.
You only need to deploy this if you need to access trait information about a specific collection on-chain inside other contracts, or if you want to make this information available to other third-parties on-chain.
Priming the DNA data is a very expensive operation, and costs about 0.0075tz per DNA entry, meaning seeding the GOGOs DNA (5555 pieces) to mainnet costs around 42tz split across 7 batch operations. This only has to be done once though.
If you're deploying your own DNA library then you need to modify the contract with your specific configuration, and generate new dna.json
files that map your token traits exactly.
The traits are hard-coded at contract origination and there are no entrypoints to update this information with. If you're making a dynamic DNA bank you will need to add this functionality yourself.
When modifying this for your own collection you must make changes to the contract/dna_registry.py
file.
- Set your own metadata in the
metadata_base
value - Define the exact
length
of your DNA string - Define the trait
pieces
and their order in the DNA sequence - Define the map for each DNA trait to the available trait values
- Define your
mythic
DNA markers
You must also configure your environment with the correct wallet, key etc. and must create your own DNA mapping based on your collection traits and associated dna/dna.json
file.
The contract/tests.py
file must also be updated to match your trait configuration.
If you modify the metadata_base
value a new file will be generated and pinned to ipfs with your nft.storage STORAGE_API_KEY
and the contract will be recompiled with this new value before origination when you run compile.sh
Create a ghostnet.env
file inside the contract
folder based on the example.env
and fill in your specific values.
You need to add an admin wallet address and an NFT.storage key and set the network to a valid value like ghostnet
.
You can create a mainnet
env when you're ready to go to production.
All *.env
files are ignored by version control so you can't accidentally commit secrets.
You must have the file ~/smartpy-cli/SmartPy.sh
available in your home directory. You can follow the instructions at https://smartpy.io/docs/cli to configure.
Before you can originate you must first run npm install
in the root. This will add the required Taquito dependencies.
Pass in the value of the env you want to deploy to, if you want to deploy to ghostnet
make sure there is a properly configured ghostnet.env
file in the root directory and run ./compile.sh ghostnet
to deploy to ghostnet
.
The compile.sh
file will call the cli/originate.js
file - do not call this file yourself as it needs the environmental setup performed by compile.sh
to be in place in order to function correctly.
This will not register any DNA it just compiles and originates a new contract.
If the COMP_USE_LEDGER value is set to 0 (e.g. non-mainnet deployments like ghostnet) will use whatever the COMP_ADMIN_KEY
value in the env file is when originating. You can get this value from a testnet wallet faucet file.
If the COMP_USE_LEDGER value is set to 1 then this key is ignored during origination and you will need to check your connected ledger and approve each transaction there. You must make sure the COMP_ADMIN
wallet address matches the ledger, and the correct COMP_LEDGER_PATH
is set in your env file (default wallet for Tezos on ledger is 44'/1729'/0'/0
and subsequent wallets created in ledger live are 44'/1729'/1'/0
then 44'/1729'/2'/0
etc)
All mainnet
deployments should happen through a ledger hardware wallet only and you should deploy to ghostnet
using the same wallet you will deploy to mainnet
(i.e. through your ledger)
During the compile.sh
process the script will check if new TZIP16 metadata has been generated or not.
If new metadata is generated (i.e. you change the contract tzip16 metadata) then a new IPFS CID will be generated and pinned to ipfs and filecoin using https://nft.storage. You need to add a free key to the STORAGE_API_KEY
value in your selected .env file. See https://nft.storage/docs/quickstart/#get-an-api-token for information on how to get this key. The selected .env
file will be updated with the new COMP_TZIP16
value.
To define a mythic GOGO, such as Aukouma (#786) the DNA is set to a repeating pattern of the same number 101 with the resulting DNA being 101_101_101_101_101_101_101_101_101_101
In the case of GOGOs the threshold is '100' and any DNA trait ID above that number is considered mythic. If your collection has more than 100 traits then increase this value to 1000 and make the adjustment in the contract. All mythics must be defined in the contract.
Once the contract is deployed you can prime it with all of your DNA.
This is a very expensive operation so be sure that you've done all of your testing on ghostnet before performing this operation on mainnet.
You can call ./prime.sh <network> <contract>
to upload the contents of your dna/dna.json
file to the contract you originated.
This is a multi-step operation. If your token count is beyond a certain threshold and you're deploying with a ledger hardware wallet you will have to confirm each transaction on your device.
The file looks like this:
{
"1": [
0,
4,
9,
14,
13,
4,
3,
7,
1,
2
],
// all entries
}
where "1" is token ID 1 and the values are just the defined marker IDs in an array that matches your contract trait definition.
Deployment costs are triple to bigmaps with this contract. Instead of costing ~42 tez for the GOGOs DNA priming operation across 5555 tokens it's around ~126tz so the choice comes from deployment efficiency.
You can change it to a big_map in the contract/dna_registry.py
file if you don't mind paying extra to have the info in a big_map.