2018-09-15
Learn solidity by breeding zombies 🧟
Below you’ll find my notes from the CryptoZombies game, which is a fun introduction to Solidity. It’s the first resource mentioned in my previous article about how I want to learn more about the Blockchain. I’ll try to keep the notes up-to-date as I progress through the levels. You can use it as a top-level view of what you’ll learn by playing the game, but I recommend checking out the CryptoZombies website.
// version of solidity defined on top of each file:pragma solidity ^0.4.19;// create a signle contract:contract ZombieFactory {// varaibles are stored permanently on the contractuint dnaDigits = 16;uint dnaModulus = 10 ** dnaDigits;struct Zombie {string name;uint dna;}// create dynamic arrays:Zombie[] public zombies;// by convention, fn args name's start with a _underscore// fns are public by default. A common convention is to// make all fns private by default, and only intentionally// make specific ones public later// Solidity has two additional visibility types:// - `internal` - like `private` but also accessible by// contracts inheriting from the current one// - `external` - like `public` but can't be called from// within current contractfunction private {zombies.;}// Solidity lets you define types of returned values as// well as the type of the function. A `pure` one doesn't// access the outside world, while a `view` function// only uses the outside world without modyfing itfunction pure returns (uint) {return a + b;}// `keccak256` is Ethernum's version of SHA3 has function// below we typecast the result to an `uint`function private view returns (uint) {uint rand = ;return rand % dnaModulus;}// Use `events` to inform frontend about changes:event .function pure returns (uint) {uint result = a + b;;return a + b;}// key-value stores are called `mapping`s:mapping (uint => address) public zombieToOwner;mapping (address => uint) ownerZombieCount;// `msg.sender` is a global var with caller's id (the caller can be either another contract or a person// `require` is used for input validationfunction public {uint randDna = ;;}// Solidity has no built-in string comparison so// you can do:==}// contract inheritance:contract Animal {...}contract Cow is Animal {// Cow has access to all public functions of Animal}// you can store things in storage (persistent) and// in memory (temporary). By default global scope vars// are stored permanently. You can also specify the destSomeThing storage myThing = things[1]// ^^^^ this becomes a pointer to the array of `things`// which means that `myThing.price = 100` will change the// value in permanent `storage`// analogically, using `memory` makes a copy of the value// and won't store anything persistentlySomeThing memory myThing = things[1]// Interact with third-party contract's APIs by implementing// an interface, which is just a bunch of functions// without a body mimicking the functions you want to use from// that contract:contract myInterface {function public view returns (uint);}// You can then start using the interface by instatiating// it with contrat's address:myInterface xyz = ;myInterface.;// Handle multiple returns:uint a;uint b;uint c;(a,b,c) = ;// oruint c;(,,c) = ;
A couple more notes to remember about contracts:
- Once deployed, a contract is immutable. You might want to provide functions for setting contract’s insides if you ever want to change them in the future. To prevent unauthorized usage of the functions you can for example use
Ownable
from OpenZeppelin - a Solidity library.