Wolf Game Contract Analysis
The notable storage/immutable vars in the contract include:
1. tokenTraits - mapping of the token id to traits
2. existingCombinations - mapping of hashed(trait id) to token id to avoid duplications
3. rarities - 2D Array of uint type where 0-9 represent sheep charactersticks and 10-18 of wolves
4. aliases - based on walkers method having an alias array like rarities
Constructor
Besides setting some storage/immutable vars
the rarity and alias array's are initialized with random values for each column and column 0 - 8 belongs to sheeps, 9 - 17 to wolves
note for each column length of both arrays are same but these are just random values generated from a customised algorithm off-chain.
```
// I know this looks weird but it saves users gas by making lookup O(1)
// A.J. Walker's Alias Algorithm
// sheep
// fur
rarities[0] = [15, 50, 200, 250, 255];
aliases[0] = [4, 4, 4, 4, 4];
// head
rarities[1] = [190, 215, 240, 100, 110, 135, 160, 185, 80, 210, 235, 240, 80, 80, 100, 100, 100, 245, 250, 255];
aliases[1] = [1, 2, 4, 0, 5, 6, 7, 9, 0, 10, 11, 17, 0, 0, 0, 0, 4, 18, 19, 19];
// ears
rarities[2] = [255, 30, 60, 60, 150, 156];
aliases[2] = [0, 0, 0, 0, 0, 0];
// eyes
rarities[3] = [221, 100, 181, 140, 224, 147, 84, 228, 140, 224, 250, 160, 241, 207, 173, 84, 254, 220, 196, 140, 168, 252, 140, 183, 236, 252, 224, 255];
aliases[3] = [1, 2, 5, 0, 1, 7, 1, 10, 5, 10, 11, 12, 13, 14, 16, 11, 17, 23, 13, 14, 17, 23, 23, 24, 27, 27, 27, 27];
// nose
rarities[4] = [175, 100, 40, 250, 115, 100, 185, 175, 180, 255];
aliases[4] = [3, 0, 4, 6, 6, 7, 8, 8, 9, 9];
// mouth
rarities[5] = [80, 225, 227, 228, 112, 240, 64, 160, 167, 217, 171, 64, 240, 126, 80, 255];
aliases[5] = [1, 2, 3, 8, 2, 8, 8, 9, 9, 10, 13, 10, 13, 15, 13, 15];
// neck
rarities[6] = [255];
aliases[6] = [0];
// feet
rarities[7] = [243, 189, 133, 133, 57, 95, 152, 135, 133, 57, 222, 168, 57, 57, 38, 114, 114, 114, 255];
aliases[7] = [1, 7, 0, 0, 0, 0, 0, 10, 0, 0, 11, 18, 0, 0, 0, 1, 7, 11, 18];
// alphaIndex
rarities[8] = [255];
aliases[8] = [0];
// wolves
// fur
rarities[9] = [210, 90, 9, 9, 9, 150, 9, 255, 9];
aliases[9] = [5, 0, 0, 5, 5, 7, 5, 7, 5];
// head
rarities[10] = [255];
aliases[10] = [0];
// ears
rarities[11] = [255];
aliases[11] = [0];
// eyes
rarities[12] = [135, 177, 219, 141, 183, 225, 147, 189, 231, 135, 135, 135, 135, 246, 150, 150, 156, 165, 171, 180, 186, 195, 201, 210, 243, 252, 255];
aliases[12] = [1, 2, 3, 4, 5, 6, 7, 8, 13, 3, 6, 14, 15, 16, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26];
// nose
rarities[13] = [255];
aliases[13] = [0];
// mouth
rarities[14] = [239, 244, 249, 234, 234, 234, 234, 234, 234, 234, 130, 255, 247];
aliases[14] = [1, 2, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11];
// neck
rarities[15] = [75, 180, 165, 120, 60, 150, 105, 195, 45, 225, 75, 45, 195, 120, 255];
aliases[15] = [1, 9, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 14, 12, 14];
// feet
rarities[16] = [255];
aliases[16] = [0];
// alphaIndex
rarities[17] = [8, 160, 73, 255];
aliases[17] = [2, 3, 3, 3];``
```
Minting Process
```
/**
* mint a token - 90% Sheep, 10% Wolves
* The first 20% are free to claim, the remaining cost $WOOL
*/
after the mandatory checks, a random seed is generated by
the use of new token id , the block number and timestamp
once the seed is generated then the seed along with the token id are used to generate the traits for each token id
the trait generation process starts with identification of the character i.e t.isSheep = (seed & 0xFFFF) % 10 != 0; since sheep is more common than wolf
then we update seed value as the value from the 16th bit from the original value i.e seed >>= 16
then for each row we first do
selectTrait(uint16(seed & 0xFFFF), 0 + shift) where shift is uint8 shift = t.isSheep ? 0 : 9;
and then seed >>= 16
In the selectTrait method[](https://) we pass in the btiwise AND of seed & MAX UINT which i assume is to avoid common traits between to id's and the column no 0 in the case of sheep and 9 in the case of wolve
then inside selectTrait a array index named trait is calculated which is the remainder of seed and the array length of the rarity array for that column
and if the 8-16th bit value of the seed is less than than rarities[traitType][trait] then trait is returned else
aliases[traitType][trait] is returned and this is part of the logic of the offchain rarity and alias array generation
this process continues and we have a struct returned in the end
then we use the existingCombinations to check is the trait has already been assigned if yes the trait generation process is repeated
Now there is also a selectRecipient which returns random address on some occassions as part of rules of the game i.e
/**
* the first 20% (ETH purchases) go to the minter
* the remaining 80% have a 10% chance to be given to a random staked wolf
* @param seed a random value to select a recipient from
* @return the address of the recipient (either the minter or the Wolf thief's owner)
*/
function selectRecipient(uint256 seed) internal view returns (address)
the minter can select to stake the minted char in the barn it is profitable since if it is a sheep you can keep it away from wolves by paying $WOOL and for wolves they can prey on sheeps easily if they get barn access
mint cost is decide by mintCost function so once the cost is decided we burn the users wool tokens depending on various conditions
/**
* the first 20% are paid in ETH
* the next 20% are 20000 $WOOL
* the next 40% are 40000 $WOOL
* the final 20% are 80000 $WOOL
* @param tokenId the ID to check the cost of to mint
* @return the cost of the given token ID
*/
function mintCost(uint256 tokenId) public view returns (uint256)
```