基于 cryptozombies.io

ZombieFactory

pragma solidity ^0.4.19;

contract ZombieFactory {

    // 事件, web3.js 可以监控它
event NewZombie(uint zombieId, string name, uint dna); uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits; // 乘方 // 定义结构体
struct Zombie {
string name;
uint dna;
} // 定义数组
Zombie[] public zombies; // 定义 mapping 结构, 可理解为 python 里面的 dict
mapping (uint => address) public zombieToOwner;
mapping (address => uint) ownerZombieCount; function _createZombie(string _name, uint _dna) internal {
uint id = zombies.push(Zombie(_name, _dna)) - 1; // 获取刚刚放到数组的元素的 id // msg.sender 为调用者的 地址。
zombieToOwner[id] = msg.sender;
ownerZombieCount[msg.sender]++; // 触发事件
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 { // 要求每个账户只能有一只僵尸,否则退出
require(ownerZombieCount[msg.sender] == 0); uint randDna = _generateRandomDna(_name);
randDna = randDna - randDna % 100;
_createZombie(_name, randDna);
} }

学到了

  • 函数的定义
  • 数组的使用
  • mapping 的使用
  • require的使用
  • 事件的使用

ZombieFeeding

pragma solidity ^0.4.19;

import "./zombiefactory.sol";

// 定义一个合约接口,通过这种方式可以调用其他合约的公开方法
contract KittyInterface {
function getKitty(uint256 _id) external view returns (
bool isGestating,
bool isReady,
uint256 cooldownIndex,
uint256 nextActionAt,
uint256 siringWithId,
uint256 birthTime,
uint256 matronId,
uint256 sireId,
uint256 generation,
uint256 genes
);
} // 继承
contract ZombieFeeding is ZombieFactory { KittyInterface kittyContract; // 使用了函数修饰符,确保只有 合约账户本身可以调用该方法
function setKittyContractAddress(address _address) external onlyOwner {
// 通过 合约地址实例化接口,以后可以通过这个接口调用该合约的方法
kittyContract = KittyInterface(_address);
} // 传输结构体指针
function _triggerCooldown(Zombie storage _zombie) internal {
_zombie.readyTime = uint32(now + cooldownTime);
} // 返回 bool 类型
function _isReady(Zombie storage _zombie) internal view returns (bool) {
return (_zombie.readyTime <= now);
} function feedAndMultiply(uint _zombieId, uint _targetDna, string species) internal {
require(msg.sender == zombieToOwner[_zombieId]);
Zombie storage myZombie = zombies[_zombieId];
require(_isReady(myZombie));
_targetDna = _targetDna % dnaModulus;
uint newDna = (myZombie.dna + _targetDna) / 2;
if (keccak256(species) == keccak256("kitty")) { // if 语句的使用
newDna = newDna - newDna % 100 + 99;
}
_createZombie("NoName", newDna);
_triggerCooldown(myZombie);
} function feedOnKitty(uint _zombieId, uint _kittyId) public {
uint kittyDna;
// 调用其他合约的方法
(,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId); // 多个返回值的获取 feedAndMultiply(_zombieId, kittyDna, "kitty");
} }

学到了

  • 调用其他合约的方法
  • 结构体传值
  • 接收多个返回值的方法
  • 函数修饰符的使用

ZombieHelper

pragma solidity ^0.4.19;

import "./zombiefeeding.sol";

contract ZombieHelper is ZombieFeeding {

  uint levelUpFee = 0.001 ether;

  // 定义修饰函数,会在被修饰函数调用前调用
modifier aboveLevel(uint _level, uint _zombieId) {
// 如果指定僵尸的 level 小于 _level 就会退出,否则继续执行被修饰的函数
require(zombies[_zombieId].level >= _level);
_;
} // 用于提出 以太坊里面的 eth
function withdraw() external onlyOwner {
owner.transfer(this.balance);
} //
function setLevelUpFee(uint _fee) external onlyOwner {
levelUpFee = _fee;
} // payable 修饰符表示,可以往这个方法发送 eth
function levelUp(uint _zombieId) external payable {
require(msg.value == levelUpFee); // 判断 eth 的值
zombies[_zombieId].level++;
} // 使用了修饰符,当级别大于 2 时才能修改名字
function changeName(uint _zombieId, string _newName) external aboveLevel(2, _zombieId) {
require(msg.sender == zombieToOwner[_zombieId]);
zombies[_zombieId].name = _newName;
} function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) {
require(msg.sender == zombieToOwner[_zombieId]);
zombies[_zombieId].dna = _newDna;
} // 返回一个列表
function getZombiesByOwner(address _owner) external view returns(uint[]) { // 定义 memory 数组,节省 gas
uint[] memory result = new uint[](ownerZombieCount[_owner]);
uint counter = 0;
for (uint i = 0; i < zombies.length; i++) {
if (zombieToOwner[i] == _owner) {
result[counter] = i;
counter++;
}
}
return result;
} }

学到了

  • 定义修饰函数,以及往修饰函数传参
  • 接收,提取 eth
  • 返回 uint[]
  • memory 变量, for 循环的使用

后面接着又了解了 SafeMath 的使用

pragma solidity ^0.4.19;

import "./zombieattack.sol";
import "./erc721.sol";
import "./safemath.sol"; contract ZombieOwnership is ZombieAttack, ERC721 { using SafeMath for uint256; mapping (uint => address) zombieApprovals; function balanceOf(address _owner) public view returns (uint256 _balance) {
return ownerZombieCount[_owner];
} function ownerOf(uint256 _tokenId) public view returns (address _owner) {
return zombieToOwner[_tokenId];
} function _transfer(address _from, address _to, uint256 _tokenId) private {
ownerZombieCount[_to] = ownerZombieCount[_to].add(1);
ownerZombieCount[msg.sender] = ownerZombieCount[msg.sender].sub(1);
zombieToOwner[_tokenId] = _to;
Transfer(_from, _to, _tokenId);
} function transfer(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
_transfer(msg.sender, _to, _tokenId);
} function approve(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
zombieApprovals[_tokenId] = _to;
Approval(msg.sender, _to, _tokenId);
} function takeOwnership(uint256 _tokenId) public {
require(zombieApprovals[_tokenId] == msg.sender);
address owner = ownerOf(_tokenId);
_transfer(owner, msg.sender, _tokenId);
}
}

solidity 语法学习的更多相关文章

  1. Golang 语法学习笔记

    Golang 语法学习笔记 包.变量和函数. 包 每个 Go 程序都是由包组成的. 程序运行的入口是包 main. 包名与导入路径的最后一个目录一致."math/rand" 包由 ...

  2. Swift高级语法学习总结(转)

    Swift高级语法学习总结 1.函数 1.1 func funcNmae()->(){} 这样就定义了一个函数,它的参数为空,返回值为空,如果有参数和返回值直接写在两个括号里就可以了 1.2 参 ...

  3. Swift基础语法学习总结(转)

    Swift基础语法学习总结 1.基础  1.1) swift还是使用// 和/* */ 来注释,并且/* */允许多行注释. 1.2) swift使用print和println打印,它的传参是一个泛型 ...

  4. Swift高级语法学习总结

    Swift基础语法学习总结Swift高级语法学习总结Swift语法总结补充(一) 1.函数 1.1 func funcNmae()->(){} 这样就定义了一个函数,它的参数为空,返回值为空,如 ...

  5. Swift基础语法学习总结

    Swift基础语法学习总结Swift高级语法学习总结Swift语法总结补充(一) 1.基础  1.1) swift还是使用// 和/* */ 来注释,并且/* */允许多行注释. 1.2) swift ...

  6. Robot Framework语法学习(一)

    Robot Framework语法学习: 一.变量的声明.赋值与使用 1.变量标识符:每个变量都可以用  变量标识符 ${变量名} 来表示. 2.变量声明:可以在TestSuite上点右键或者在Edi ...

  7. MarkDown语法 学习笔记 效果源码对照

    MarkDown基本语法学习笔记 Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式. 下面将对Markdown的基本使用做一个介绍 目 ...

  8. 毕业设计 之 五 PHP语法学习笔记

    毕业设计 之 四 PHP语法学习笔记 作者:20135216 平台:windows10 软件:XAMPP,DreamWeaver 说明:该笔记是对网站编程语言的详细学习 一.PHP基础 0. 关于环境 ...

  9. 【Python】Python-基础语法学习

    基础语法学习 果然学完 C++ 后再看其他语言的确有很多的共性,只需要熟悉一下python的独特语法和 C++ 中的差异就可以写出一些小的程序,而写得过程中也再次体会出python代码的精简和灵活: ...

随机推荐

  1. Hbuilder用ajax连接eclipse中的servlet例子以及注意事项

    今天用前端神器Hbuilder连接eclipse中的servlet,真是费了九牛二虎之力,才把问题解决 Hbuilder中的代码: test.html <!DOCTYPE html> &l ...

  2. 【xsy1147】 异或(xor) 可持久化trie

    我的脑回路可能比较奇怪. 我们对这些询问离线,将所得序列${a}$的后缀和建$n$棵可持久化$trie$. 对于一组询问$(l,r,x)$,我们在主席树上询问第$l$棵树$-$第r$+1$棵树中与$s ...

  3. expect中使用exec执行shell命令

    今天想在expect脚本中获取本机ip,执行脚本是报错,脚本如下: set localip [exec ifconfig eth0 | grep Mask | cut -d: -f2 | awk '{ ...

  4. 2018春招-今日头条笔试题-第四题(python)

    题目描述:2018春招-今日头条笔试题5题(后附大佬答案-c++版) #-*- coding:utf-8 -*- class Magic: ''' a:用于存储数组a b:用于存储数组b num:用于 ...

  5. #pragma的一些用法

    1.#pragma message message 参数:Message参数能够在编译信息输出窗口输出相应的信息,这对于源代码的信息控制特别重要,其使用方法为: #pragma message(&qu ...

  6. 如何自学计算机科学与技术(Teach Yourself Computer Science)

    如果你是一个自学成才的半吊子,或者是从培训班毕业的小菜鸟.那么,你欠自己一份计算机科学的专业知识.感谢上帝,如今你可以接受世界水平的计算机教育,但无需花费数年时间和一笔不小的金钱. 互联网上的学习资源 ...

  7. tensorflow语法笔记

    1.如何理解 tf.reduce_max或者 tf.reduce_mean中对Tensor和高维矩阵的坐标轴axis的选择的操作 tf.reduce_mean( input_tensor, axis= ...

  8. 面试题43:计算多少种译码方式(decode-ways)

    这道题是非常典型的DP问题.按照DP的套路,关键是讨论出递推表达式,遍历过程中针对当前字符是否为'0'以及前一个字符为'0',分类讨论得出到目前字符为止最多有多少种译码方式?理清了递推表达式,代码是很 ...

  9. JAVA GUID

    import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Exec ...

  10. Hive中自定义Map/Reduce示例 In Python

    Hive支持自定义map与reduce script.接下来我用一个简单的wordcount例子加以说明.使用Python开发(如果使用Java开发,请看这里). 开发环境: python:2.7.5 ...