cryptozombies全攻略一
第二章.合约
我们要建立最基本的合约
首先要写版本指令
然后写合约
pragma solidity ^0.4.19
contract ZombieFactory{
}
第三章.状态变量和整数
状态变量会被永久保存在合约中
也就是说他们会被写入到以太坊区块链中
我们的僵尸DNA将由一个十六位数字组成
所以我们来一个状态变量
contract ZombieFactory {
uint dnaDigits = 16;
}
第四章.数学运算
我们的每一个僵尸的DNA都是16个字符
所以我们需要来一个uint,让它等于10^16
这样的话,
之后我们可以用%来把一个整数变成16位
contract ZombieFactory {
uint dnaDigits = 16;
uint dnaModulus = 10**dnaDigits;
}
第五章.结构体
我们要创建一些僵尸
每个僵尸都有属性
所以我们要创建一个结构体
struct Zombie{
string name;
uint dna;
}
第六章.数组
我们需要一个僵尸数组,
然后我们需要让外部APP能够看到
所以我们需要一个公共数组
Zombie[] public zombies;
第七章.定义函数
我们需要来一个函数来创建僵尸Zombie
function createZombie(string _name, uint _dna){
}
第八章.结构体和数组
刚刚只写了一个空函数
现在来真正的创建僵尸Zombie
Zombie zombie = Zombie(_name, _dna);
zombies.push(zombie);
我们可以改成一行
zombies.push(Zombie(_name, _dna));
第九章.私有/公共函数
solidity定义的函数默认为公共
这就意味着任何一方(或者其他合约)都可以调用这个函数
很明显
不是什么时候都需要这样做,而且这样的合约很容易受到攻击
所以把自己的函数定义为私有private是一个好的习惯
只有当一个函数需要外部调用它的时候,才可以把它设置为public公共
我们把createZombie方法改成private
function _createZombie(string _name, uint _dna) private {
zombies.push(Zombie(_name, _dna));
}
第十章.函数的更多属性
string hello = "hello";
function sayHello() public returns(string){
return hello;
}
我们来看这段代码
这段代码实际上没有修改solidity的状态
也就是说
它没有改变任何值或者写任何东西
这种情况,
我们可以把这个函数定义为view,
意思就是只能读取数据,
而不能更改数据
function sayHello() public view returns(string){
return hello;
}
再来说一下pure函数
function _add(uint a, uint b) private pure returns(uint){
return a + b;
}
function _multiply(uint a, uint b) private pure returns(uint){
return a * b;
}
function sayHello() public pure returns(string){
return "hello";
}
我们看这三个函数
甚至都没有读取应用里面的状态
返回值只和参数有关系,和其他变量没有关系
现在我们来写一个函数,
根据一个字符串随机生成一个dna数据
function _generateRandomDna(string _str) private view returns(uint){
}
第十一章.keccak256和类型转换
function _generateRandomDna(string _str) private view returns(uint){
}
这个函数,参数是_str,是一个string字符串
我们根据这个字符串,来生成一个uint
function _generateRandomDna(string _str) private view returns(uint){
uint rand= uint(keccak256(_str));
return rand % dnaModulus;
}
第十二章.结合
我们把刚刚的方法结合起来
刚刚一共写了两个方法
一个是根据字符串生成随机的dna
一个是根据name和dna创建僵尸
那么我们结合一下
function createRandomZombie(string _name) public{
uint randDna = _generateRandomDna(_name);
_createZombie(_name,randDna);
}
参数是_name,是字符串
然后我们根据这个_name字符串,生成一个随机的dna
然后根据这里的名字和dna,来创建僵尸
_createZombie(_name, randDna);
第十三章.事件
事件就是当一个事件发生的时候,我们就做什么
比如这样
event IntegerAdded(uint x, uint y, uint result);
function add(uint _x, uint _y) public{
uint result= _x + _y;
//触发了整数加法事件
IntegerAdded(_x, _y, result);
return result;
}
如果是普通的加法方法,那么就是返回结果就好了
但是我们现在监听了整数加法这个事件
那么就调用IntegerAdded这个事件
我们来一个事件叫做NewZombie
意思是,每次创造出一个僵尸的时候,就会调用这个事件
event NewZombie(uint zombieId, string name, uint dna);
然后我们修改一下_createZombie方法
function _createZombie(string _name, uint _dna) private {
uint id = zombies.push(Zombie(_name, _dna)) -1;
//触发事件
NewZombie(id, _name, _dna);
}
我们把zombies.push方法返回的值-1 当做id
然后就触发NewZombie事件,传入id,_name,_dna
这一大章全部结束了
我们看一下完整代码
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)) -1;
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);
}
}