Solidity学习记录

第一章 创建生产僵尸的工厂
第二章 设置僵尸的攻击功能
第三章 编写DAPP所需的基础理论
第四章 完善僵尸功能
第五章 ERC721 标准和加密资产


文章目录

  • Solidity学习记录
  • 前言
  • 一、本章主要目的
  • 二、学习过程
    • 1.本节课程知识点
    • 2.最终代码
  • 总结

前言

国庆假期,事情比较多,更新拖了两天,请见谅。


一、本章主要目的

在之前的课程,我们学习了Solidity的大部分知识,本章我们学习 payable 函数,学习如何开发可以接收其他玩家付款的DApp,并学习通过函数修饰符来完善我们的程序。

二、学习过程

1.本节课程知识点

1、payable 修饰符
payable 方法是让 Solidity 和以太坊变得如此酷的一部分 —— 它们是一种可以接收以太的特殊函数。在以太坊中, 因为钱 (Ether), 数据 (transaction payload), 以及合约代码本身都存在于以太坊。你可以在同时调用函数 并付钱给另外一个合约。如果一个函数没标记为payable, 当用户尝试发送以太时,函数将拒绝事务。

2、msg.value 是一种可以查看向合约发送了多少以太的方法,常用msg.value == XXX 来表示。如果把事务想象成一个信封,你发送到函数的参数就是信的内容。 添加一个 value 很像在信封里面放钱 —— 信件内容和钱同时发送给了接收者。

3、我们可以通过 transfer 向任何以太坊地址付钱。提现写法:

contract GetPaid is Ownable {function withdraw() external onlyOwner {owner.transfer(this.balance);}
}

4、Solidity 中最好的随机数生成器是 keccak256 哈希函数。但这个方法很容易被不诚实的节点攻击

5、Solidity 的 keccak256 被攻击原理:
在以太坊上, 当你在和一个合约上调用函数的时候, 你会把它广播给一个节点或者在网络上的 transaction 节点们。 网络上的节点将收集很多事务, 试着成为第一个解决计算密集型数学问题的人,作为“工作证明”,然后将“工作证明”(Proof of Work, PoW)和事务一起作为一个 block 发布在网络上。
一旦一个节点解决了一个PoW, 其他节点就会停止尝试解决这个 PoW, 并验证其他节点的事务列表是有效的,然后接受这个节点转而尝试解决下一个节点。
这就让我们的随机数函数变得可利用了
如果运行一个节点,可以 只对我自己的节点 发布一个事务,且 不分享它 。 如果不是我想要的结果,我就不把这个事务包含进我要解决的下一个区块中去。我可以一直运行这个方法,直到获得了我想要的结果(类似于手游弱联网(并非实时监测是否联网)游戏,通过断网的方式来不断刷新出自己想要的东西,如:抽卡,掉落的稀有的物品等)。

2.最终代码

代码如下:

ownable.sol

//this is ownable.solpragma solidity ^0.4.19;/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {address private _owner;event OwnershipTransferred(address indexed previousOwner,address indexed newOwner);/*** @dev The Ownable constructor sets the original `owner` of the contract to the sender* account.*/constructor() internal {_owner = msg.sender;emit OwnershipTransferred(address(0), _owner);}/*** @return the address of the owner.*/function owner() public view returns(address) {return _owner;}/*** @dev Throws if called by any account other than the owner.*/modifier onlyOwner() {require(isOwner());_;}/*** @return true if `msg.sender` is the owner of the contract.*/function isOwner() public view returns(bool) {return msg.sender == _owner;}/*** @dev Allows the current owner to relinquish control of the contract.* @notice Renouncing to ownership will leave the contract without an owner.* It will not be possible to call the functions with the `onlyOwner`* modifier anymore.*/function renounceOwnership() public onlyOwner {emit OwnershipTransferred(_owner, address(0));_owner = address(0);}/*** @dev Allows the current owner to transfer control of the contract to a newOwner.* @param newOwner The address to transfer ownership to.*/function transferOwnership(address newOwner) public onlyOwner {_transferOwnership(newOwner);}/*** @dev Transfers control of the contract to a newOwner.* @param newOwner The address to transfer ownership to.*/function _transferOwnership(address newOwner) internal {require(newOwner != address(0));emit OwnershipTransferred(_owner, newOwner);_owner = newOwner;}
}

zombiefactory.sol

//this is zombiefactory.solpragma solidity ^0.4.19;import "./ownable.sol";contract ZombieFactory is Ownable {event NewZombie(uint zombieId, string name, uint dna);uint dnaDigits = 16;uint dnaModulus = 10 ** dnaDigits;uint cooldownTime = 1 days;struct Zombie {string name;uint dna;uint32 level;uint32 readyTime;uint16 winCount;uint16 lossCount;}Zombie[] public zombies;mapping (uint => address) public zombieToOwner;mapping (address => uint) ownerZombieCount;function _createZombie(string _name, uint _dna) internal {uint id = zombies.push(Zombie(_name, _dna, 1, uint32(now + cooldownTime), 0, 0)) - 1;zombieToOwner[id] = msg.sender;ownerZombieCount[msg.sender]++;emit NewZombie(id, _name, _dna);}function _generateRandomDna(string _str) private view returns (uint) {uint rand = uint(keccak256(abi.encodePacked(_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);}}

zombiefeeding.sol

//this is zombiefeeding.solpragma 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;modifier ownerOf(uint _zombieId) {require(msg.sender == zombieToOwner[_zombieId]);_;}function setKittyContractAddress(address _address) external onlyOwner {kittyContract = KittyInterface(_address);}function _triggerCooldown(Zombie storage _zombie) internal {_zombie.readyTime = uint32(now + cooldownTime);}function _isReady(Zombie storage _zombie) internal view returns (bool) {return (_zombie.readyTime <= now);}function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) internal ownerOf(_zombieId) {Zombie storage myZombie = zombies[_zombieId];require(_isReady(myZombie));_targetDna = _targetDna % dnaModulus;uint newDna = (myZombie.dna + _targetDna) / 2;if (keccak256(abi.encodePacked(_species)) == keccak256(abi.encodePacked("kitty"))) {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.sol

//this is zombiehelper.solpragma solidity ^0.4.19;import "./zombiefeeding.sol";contract ZombieHelper is ZombieFeeding {uint levelUpFee = 0.001 ether;modifier aboveLevel(uint _level, uint _zombieId) {require(zombies[_zombieId].level >= _level);_;}function withdraw() external onlyOwner {address _owner = owner();_owner.transfer(address(this).balance);}function setLevelUpFee(uint _fee) external onlyOwner {levelUpFee = _fee;}function levelUp(uint _zombieId) external payable {require(msg.value == levelUpFee);zombies[_zombieId].level++;}function changeName(uint _zombieId, string _newName) external aboveLevel(2, _zombieId) ownerOf(_zombieId) {zombies[_zombieId].name = _newName;}function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) ownerOf(_zombieId) {zombies[_zombieId].dna = _newDna;}function getZombiesByOwner(address _owner) external view returns(uint[]) {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;}}

zombieattack.sol

//this is zombieattack.solpragma solidity ^0.4.19;import "./zombiehelper.sol";
contract ZombieAttack is ZombieHelper {uint randNonce = 0;uint attackVictoryProbability = 70;function randMod(uint _modulus) internal returns(uint) {randNonce++;return uint(keccak256(abi.encodePacked(now, msg.sender, randNonce))) % _modulus;}function attack(uint _zombieId, uint _targetId) external ownerOf(_zombieId) {Zombie storage myZombie = zombies[_zombieId];Zombie storage enemyZombie = zombies[_targetId];uint rand = randMod(100);if (rand <= attackVictoryProbability) {myZombie.winCount++;myZombie.level++;enemyZombie.lossCount++;feedAndMultiply(_zombieId, enemyZombie.dna, "zombie");} else {myZombie.lossCount++;enemyZombie.winCount++;_triggerCooldown(myZombie);}}
}

总结

本章知识点比较少,大部分是使用之前的知识内容,本章重点知识只有两个:

1.可以使用 payable 来付款,value 用来表示付多少钱,transfer 用来转账(可以转给任何人)。
2.keccak256 函数是不安全的,有一个随机数方法是利用 oracle 来访问以太坊区块链之外的随机数函数。

Solidity学习记录——第四章相关推荐

  1. 《SysML精粹》学习记录--第四章

    <SysML精粹>学习记录 第四章:内部模块图(Internal Block Diagram,IBD) IBD介绍 组成部分属性 引用属性 连接器 项目流 内嵌组成部分和引用 小结 第四章 ...

  2. 广义相对论-学习记录9-第四章-相对论性的引力理论2

    第四章:相对论性的引力理论 6.变分原理推导场方程   场方程的左边为IGI_GIG​,右边为IMI_MIM​,作用量I=IG+IMI=I_G+I_MI=IG​+IM​   在平直时空中,作用量为: ...

  3. C语言深度剖析书籍学习记录 第四章 指针和数组

    p 称为指针变量,p 里存储的内存地址处的内存称为 p 所指向的内存. 指针变量 p 里存储的任何数据都将被当作地址来处理 一个基本的数据类型(包括结构体等自定义类型)加上"*" ...

  4. Solidity学习记录——第二章

    Solidity学习记录 第一章 创建生产僵尸的工厂 第二章 设置僵尸的攻击功能 第三章 编写DAPP所需的基础理论 第四章 完善僵尸功能 第五章 ERC721 标准和加密资产 文章目录 Solidi ...

  5. 《Go语言圣经》学习笔记 第四章 复合数据类型

    <Go语言圣经>学习笔记 第四章 复合数据类型 目录 数组 Slice Map 结构体 JSON 文本和HTML模板 注:学习<Go语言圣经>笔记,PDF点击下载,建议看书. ...

  6. 《SysML精粹》学习记录--第七章

    <SysML精粹>学习记录 第七章:序列图 序列图简介 序列图元素 消息 约束 组合片段 交互使用 小结 第七章:序列图 序列图简介   序列图是另一种可以用来说明系统动态行为信息的Sys ...

  7. 三维荧光平行因子学习记录--(四)平行因子组件导出--(一)

    三维荧光平行因子学习记录–(四)平行因子组件导出–(一) 注:本文仅作为自己的学习记录以备以后复习查阅 本文参考博客链接: https://zhuanlan.zhihu.com/p/377996430 ...

  8. 《SysML精粹》学习记录--第六章

    <SysML精粹>学习记录 第六章:活动图 活动图简介 活动图外框 活动图的关键元素   动作   对象节点   边   动作详述   控制节点 活动分区 小结 第六章:活动图 活动图简介 ...

  9. 计算机网络(第7版)谢希仁著 学习笔记 第四章网络层

    计算机网络(第7版)谢希仁著 学习笔记 第四章网络层 第四章 网络层 4.3划分子网和构造超网 p134 4.3.1划分子网 4.3.2使用子网时分组的转发 4.3.3无分类编址CIDR(构建超网) ...

最新文章

  1. 图论 ---- F. The Shortest Statement (最短路的性质 + 任意两点间最短路 + 图转树)
  2. Netlib文件转化为mps文件
  3. 【深圳(活动)】70多场干货分享!价值899元的2018中国开源年会门票等你认领
  4. Django syncdb mysql error on localhost - (1045, Access denied for user 'ODBC'@'
  5. Web常见漏洞修复建议
  6. SpringCloud的Hystrix(二) 某消费者应用(如:ui、网关)访问的多个微服务的断路监控...
  7. 类数组的push方法
  8. 5.性能之巅 洞悉系统、企业与云计算 --- 应用程序
  9. 在Sql的where中使用case进行不同字段筛选|Case的2种使用方法和一种少为人知的用途...
  10. Excel技能培训之十五 函数使用rank,Frequency,subtotal超级表,切片器,iferor,常用错误代码
  11. 用于视觉问答的相互注意融合模型《Reciprocal Attention Fusion for Visual Question Answering》
  12. 剑指Offe6-反转链表
  13. Ubuntu18.04 同一个程序显示两个图标,收藏夹图标不合并问题解决
  14. can sdo 报文
  15. 基于C++的OpenCV(八)图像处理
  16. 基于STM32的开源简易示波器项目
  17. ps合成玫瑰花丛中漂亮美女照片
  18. WordPress php升级到7.2提示Warning: Use of undefined constant Y – assumed ‘Y’ 问题解决
  19. STM32开发实例 基于STM32单片机的蓝牙手环
  20. 哈尔滨工业大学 计算机系 张红,面向TDT的动态多文档文摘研究-哈尔滨工业大学学报.PDF...

热门文章

  1. 还在一直使用Photoshop吗?在线PS处理图片更简单方便
  2. 几个不错的国外免费虚拟主机 Free host
  3. 2022危险化学品生产单位安全生产管理人员考试模拟100题及答案
  4. 人一能之,己百之;人十能之,己千之
  5. 当马斯克打开潘多拉魔盒
  6. iOS 笔记 【经典】
  7. 【Web技术】1005- 关于 JS 与 CSS 是否阻塞 DOM 的渲染和解析
  8. 人生啊,没有过不去的坎
  9. 《信号完整性分析和印制电路板》PDF下载
  10. mysql商品表_(三)购物商城数据库设计-商品表DDL(Mysql)