Digital items with Ethereum contract
Credits goes to Cryptozombies
Basic
pragma solidity ^0.4.19;
contract HelloWorld {
}
State variable
State variables permanently write on to the Ethereum blockchain.
pragma solidity ^0.4.19;
contract HelloWorld {
uint dnaDigits = 16;
}
Math operations
Addition: x + y Subtraction: x - y, Multiplication: x * y Division: x / y Modulus / remainder: x % y
pragma solidity ^0.4.19;
contract HelloWorld {
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
}
Struct and Array
To store data in a custom data structure, use the combination of Struct and Arrays
struct Zombie {
string name;
uint dna;
}
// declare a dynamic array of Zombie
// Zombie[4] is a static fix length array
Zombie[] public zombies;
Function, private, public, view and pure
All functions are public by default
function createZombie(string _name, uint _dna) {
zombies.push(Zombie(_name, _dna));
}
```
By convention, use `_` as prefix for private functions. Function declaration will also
have `private` keyword follow the parameters.
```
function _createZombie(string _name, uint _dna) private {
zombies.push(Zombie(_name, _dna));
}
```
When accessing an internal state, this function is `view` as to say read-only.
While `pure` functions do not use any state and only return the calculation.
function _generateRandomDna(string _str) private view returns (uint) {
uint rand = uint(keccak256(_str));
return rand % dnaModulus;
}
function createRandomZombie(string _name) public {
uint randDna = _generateRandomDna(_name);
_createZombie(_name, randDna);
} ```
Events
Events are notify by the contract to the corresponding watcher.
event NewZombie(uint zombieId, string name, uint dna);
Final program with events
pragma solidity ^0.4.19;
contract ZombieFactory {
event NewZombie(uint zombieId, string name, uint dna);
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
…
}
pragma solidity ^0.4.19;
contract ZombieFactory {
event NewZombie(uint zombieId, string name, uint dna);
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies;
function _createZombie(string _name, uint _dna) private {
uint id = zombies.push(Zombie(_name, _dna));
NewZombie(id, _name, _dna);
}
function _generateRandomDna(string _str) private view returns (uint) {
uint rand = uint(keccak256(_str));
return rand % dnaModulus;
}
function createRandomZombie(string _name) public {
uint randDna = _generateRandomDna(_name);
_createZombie(_name, randDna);
}
}
Frontend with web3.js
// Here's how we would access our contract:
var abi = /* abi generated by the compiler */
var ZombieFactoryContract = web3.eth.contract(abi)
var contractAddress = /* our contract address on Ethereum after deploying */
var ZombieFactory = ZombieFactoryContract.at(contractAddress)
// `ZombieFactory` has access to our contract's public functions and events
// some sort of event listener to take the text input:
$("#ourButton").click(function(e) {
var name = $("#nameInput").val()
// Call our contract's `createRandomZombie` function:
ZombieFactory.createRandomZombie(name)
})
// Listen for the `NewZombie` event, and update the UI
var event = ZombieFactory.NewZombie(function(error, result) {
if (error) return
generateZombie(result.zombieId, result.name, result.dna)
})
// take the Zombie dna, and update our image
function generateZombie(id, name, dna) {
let dnaStr = String(dna)
// pad DNA with leading zeroes if it's less than 16 characters
while (dnaStr.length < 16)
dnaStr = "0" + dnaStr
let zombieDetails = {
// first 2 digits make up the head. We have 7 possible heads, so % 7
// to get a number 0 - 6, then add 1 to make it 1 - 7. Then we have 7
// image files named "head1.png" through "head7.png" we load based on
// this number:
headChoice: dnaStr.substring(0, 2) % 7 + 1,
// 2nd 2 digits make up the eyes, 11 variations:
eyeChoice: dnaStr.substring(2, 4) % 11 + 1,
// 6 variations of shirts:
shirtChoice: dnaStr.substring(4, 6) % 6 + 1,
// last 6 digits control color. Updated using CSS filter: hue-rotate
// which has 360 degrees:
skinColorChoice: parseInt(dnaStr.substring(6, 8) / 100 * 360),
eyeColorChoice: parseInt(dnaStr.substring(8, 10) / 100 * 360),
clothesColorChoice: parseInt(dnaStr.substring(10, 12) / 100 * 360),
zombieName: name,
zombieDescription: "A Level 1 CryptoZombie",
}
return zombieDetails
}