智能合约学习笔记——僵尸工厂(一)

这篇具有很好参考价值的文章主要介绍了智能合约学习笔记——僵尸工厂(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

根据CryptoZombies学solidity

Lesson 1 搭建僵尸工厂

生成僵尸的工厂,首先建立一个批量生成僵尸的合约

pragma solidity ^0.4.19;

contract ZombieFactory { //建立合约僵尸工厂  
    event NewZombie(uint zombieId, string name, uint dna); // 这里建立事件

    uint dnaDigits = 16; // 僵尸的DNA包括头部基因;眼部基因;上衣基因;皮肤基因;眼色基因;衣服颜色基因
    uint dnaModulus = 10 ** dnaDigits;//用于后续取余运算

    struct Zombie {
        string name;
        uint dna;
    }//建立一个僵尸的结构体,包括僵尸的名字和dna

    Zombie[] public zombies;//僵尸的数组,将生成的僵尸数据存储到这个数组中

    function _createZombie(string _name, uint _dna) private {//这里用的是私有函数,只能在合约中被调用,注意私有函数的名字要用_开头
        uint id = zombies.push(Zombie(_name, _dna)) -1 ;//将生成的新僵尸数据加入数组,push返回加入后数组长度,减一后是为这个新僵尸在数组中的索引
        NewZombie(id, _name, _dna); // 当将新生成的僵尸加入数组时就会触发事件
    }

    function _generateRandomDna(string _str) private view returns (uint) {//这里用到了view,只能调用合约中的变量不能改动,另一个修饰符pure甚至不能调用函数外的数据
        uint rand = uint(keccak256(_str)); //根据输入的字符生成随机数
        return rand % dnaModulus; //我们需要的随机数是长度为16的,截取我们需要的返回
    }

    function createRandomZombie(string _name) public {
        uint randDna = _generateRandomDna(_name);//根据僵尸的名字生成随机数作为僵尸的dna
        _createZombie(_name, randDna);//根据僵尸的名字和dna调用另一个函数生成僵尸
    }

}
javascript实现

当合约完成之后,就需要写一段 JavaScript 前端代码来调用这个合约。

以太坊有一个 JavaScript 库,名为Web3.js。
在后面的课程里,我们会进一步地教你如何安装一个合约,如何设置Web3.js。 但是现在我们通过一段代码来了解 Web3.js 是如何和我们发布的合约交互的吧。

这里JavaScript 所做的就是获取由zombieDetails 产生的数据, 并且利用浏览器里的 JavaScript 神奇功能 (我们用 Vue.js),置换出图像以及使用CSS过滤器。在后面的课程中,就可以看到全部的代码。

// 下面是调用合约的方式:
var abi = /* abi是由编译器生成的 */
var ZombieFactoryContract = web3.eth.contract(abi)
var contractAddress = /* 发布之后在以太坊上生成的合约地址 */
var ZombieFactory = ZombieFactoryContract.at(contractAddress)
// `ZombieFactory` 能访问公共的函数以及事件

// 某个监听文本输入的监听器:
$("#ourButton").click(function(e) {
  var name = $("#nameInput").val()
  //调用合约的 `createRandomZombie` 函数:
  ZombieFactory.createRandomZombie(name)
})

// 监听 `NewZombie` 事件, 并且更新UI
var event = ZombieFactory.NewZombie(function(error, result) {
  if (error) return
  generateZombie(result.zombieId, result.name, result.dna)
})

// 获取 Zombie 的 dna, 更新图像
function generateZombie(id, name, dna) {
  let dnaStr = String(dna)
  // 如果dna少于16位,在它前面用0补上
  while (dnaStr.length < 16)
    dnaStr = "0" + dnaStr

  let zombieDetails = {
    // 前两位数构成头部.我们可能有7种头部, 所以 % 7
    // 得到的数在0-6,再加上1,数的范围变成1-7
    // 通过这样计算:
    headChoice: dnaStr.substring(0, 2) % 7 + 1// 我们得到的图片名称从head1.png 到 head7.png

    // 接下来的两位数构成眼睛, 眼睛变化就对11取模:
    eyeChoice: dnaStr.substring(2, 4) % 11 + 1,
    // 再接下来的两位数构成衣服,衣服变化就对6取模:
    shirtChoice: dnaStr.substring(4, 6) % 6 + 1,
    //最后6位控制颜色. 用css选择器: hue-rotate来更新
    // 360度:
    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
}

可以部署这个合约,并输入僵尸的名字,生成一个僵尸
智能合约学习笔记——僵尸工厂(一)

Lesson 2 僵尸攻击人类

这里用到了两个合约,放在两个不同的文件中
首先,ZombieFactory

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;

    mapping (uint => address) public zombieToOwner;//映射,可以通过id访问地址
    mapping (address => uint) ownerZombieCount;//映射,可以通过地址询问Id

    function _createZombie(string _name, uint _dna) internal {//这里用到了internal,指这个函数是合约内部的函数,只能在合约内部被调用,但是如果一个合约继承于这个合约那么也可以调用这个函数
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        zombieToOwner[id] = msg.sender;//可以通过msg.sender调用得到当前调用者的地址,这里是将地址存入对应id的映射
        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);//这里用到了require来限制()里的语句必须是true,也就是必须没有僵尸才能调用这个函数来创造第一个僵尸
        uint randDna = _generateRandomDna(_name);
        randDna = randDna - randDna % 100;
        _createZombie(_name, randDna);
    }

}

以及一个ZombieFactory的子合约

pragma solidity ^0.4.19;

import "./zombiefactory.sol";//讲zombiefactory文件引入,方便下面继承ZombieFactory合约

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 {//ZombieFeeding合约继承于ZombieFactory合约

  address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
  KittyInterface kittyContract = KittyInterface(ckAddress);//指向接口

  function feedAndMultiply(uint _zombieId, uint _targetDna, string _species ) public {
    require(msg.sender == zombieToOwner[_zombieId]);//限制只有调用者是这个僵尸的主人才行
    Zombie storage myZombie = zombies[_zombieId];//storage类型变量是指永久存储在区块链中的变量
    _targetDna = _targetDna % dnaModulus;
    uint newDna = (myZombie.dna + _targetDna) / 2;//新生成的僵尸的dna应该是两个dna的平均值
    if (keccak256(_species) == keccak256("kitty")) {//判断一下,如果是kitty的话,dna的最后两位变成99
      newDna = newDna - newDna % 100 + 99;
    } 
    _createZombie("NoName", newDna);
  }

  function feedOnKitty(uint _zombieId, uint _kittyId) public {
    uint kittyDna;
    (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);//调用了另一个合约中的函数
    feedAndMultiply(_zombieId, kittyDna, "kitty");//
  }

}
JavaScript 实现

我们只用编译和部署 ZombieFeeding,就可以将这个合约部署到以太坊了。我们最终完成的这个合约继承自 ZombieFactory,因此它可以访问自己和父辈合约中的所有 public 方法。

我们来看一个与我们的刚部署的合约进行交互的例子, 这个例子使用了 JavaScript 和 web3.js:

var abi = /* abi generated by the compiler */
var ZombieFeedingContract = web3.eth.contract(abi)
var contractAddress = /* our contract address on Ethereum after deploying */
var ZombieFeeding = ZombieFeedingContract.at(contractAddress)

// 假设我们有我们的僵尸ID和要攻击的猫咪ID
let zombieId = 1;
let kittyId = 1;

// 要拿到猫咪的DNA,我们需要调用它的API。这些数据保存在它们的服务器上而不是区块链上。
// 如果一切都在区块链上,我们就不用担心它们的服务器挂了,或者它们修改了API,
// 或者因为不喜欢我们的僵尸游戏而封杀了我们
let apiUrl = "https://api.cryptokitties.co/kitties/" + kittyId
$.get(apiUrl, function(data) {
  let imgUrl = data.image_url
  // 一些显示图片的代码
})

// 当用户点击一只猫咪的时候:
$(".kittyImage").click(function(e) {
  // 调用我们合约的 `feedOnKitty` 函数
  ZombieFeeding.feedOnKitty(zombieId, kittyId)
})

// 侦听来自我们合约的新僵尸事件好来处理
ZombieFactory.NewZombie(function(error, result) {
  if (error) return
  // 这个函数用来显示僵尸:
  generateZombie(result.zombieId, result.name, result.dna)
})

智能合约学习笔记——僵尸工厂(一)文章来源地址https://www.toymoban.com/news/detail-430574.html

到了这里,关于智能合约学习笔记——僵尸工厂(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《区块链原理与技术》学习笔记(四) ——以太坊的基本架构、账户模型和智能合约

    《区块链原理与技术》学习笔记 第四部分 三、以太坊 1. 以太坊简介 1.1 以太坊发展的阶段 1.2 以太坊与比特币对比 2. 以太坊的基本架构及原理 2.1 基本概念 2.2 状态转移 2.3 基本架构 3. 账户模型与转账 3.1 账户模型 4. 智能合约 4.1 合约账户与数据存储 4.2 驱动智能合约 以太坊

    2024年02月13日
    浏览(49)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[25]以太坊-智能合约-5

    智能合约-1 智能合约-2 智能合约-3 智能合约-4 网上竞拍第二版:由投标者自己取回出价 (1)存在的问题         重入攻击,如果有黑客写了一个如下方程序会怎么样?         这个hack_bid跟前面的那个黑客合约hack_bid合约是一样的,通过调用拍卖bid函数参与竞拍,ha

    2024年03月11日
    浏览(66)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[22]以太坊-智能合约-2

    智能合约-1 目录 一、智能合约的创建和运行         1.智能合约的创建         2.汽油费         3.错误处理         4.嵌套调用 二、思考         1.GasLimit和GasUsed         2.以太坊中的GasLimit跟比特币的区别 1.智能合约的创建         智能合约 由一个外

    2024年02月19日
    浏览(50)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[23]以太坊-智能合约-3

    智能合约-1 智能合约-2 1.假设某个全节点要打包一些交易到一个区块里,这些交易里有一些是对智能合约的调用,那么这个全节点应该先执行完智能合约再挖矿,还是先挖矿获得记账权再执行这些智能合约?         在区块链中,如果有一笔转账交易发布上去,需要所有的全

    2023年04月23日
    浏览(45)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[21]以太坊-智能合约-1

    目录 一、什么是智能合约 二、智能合约的代码结构         1.Solidity语言         2.bid函数         3.fallback()函数  二、外部账户如何调用智能合约 三、一个合约如何调用另一个合约中的函数         1.直接调用         2.使用address类型的call()函数      

    2024年02月05日
    浏览(44)
  • 智能合约笔记

    首先了解下为什么会出现智能合约,打个比方现在有两个人A和B打赌明天会不会下雨,每个人赌注100元,如果第二天下雨则A拿走200元,否则B拿走200元,这样就有一个问题,赌注要到第二天才能见效,如果两个人是知根知底的熟人还是君子,那么可以定一个君子协定,但是这个

    2024年01月22日
    浏览(26)
  • 【论文笔记06】智能合约的合约安全和隐私安全研究综述

    计算机学报 原文作者: 胡甜媛 李泽成 李必信 包骐豪* 原文标题: 智能合约的合约安全和隐私安全研究综述* 原文链接: 智能合约的合约安全和隐私安全研究综述 - 中国知网 原文来源: 计算机学报 笔记作者:quangaoyuan 笔记小编:quangaoyu an 区块链;智能合约;合约安全;

    2024年02月06日
    浏览(52)
  • 第146篇 笔记-智能合约介绍

    定义: 当满足某些预定义条件时,智能合约是一种在区块链网络上运行的防篡改程序。 1.什么是智能合约 智能合约是在区块链网络上托管和执行的计算机程序。每个智能合约都包含指定预定条件的代码,这些条件在满足时会触发并产生结果。通过在去中心化区块链而不是集

    2024年01月16日
    浏览(34)
  • 智能合约开发笔记-hardhat入门

    Hardhat是一个编译、部署、测试和调试以太坊应用的开发环境。 先安装nodejs环境; 然后打开命令行执行以下命令, 在项目目录pj_220509下安装hardhat环境: pj_220509目录下, 执行命令 npx hardhat  然后按提示安装相关的nodejs包,如下;完成安装; 装完后呀,可以在本地启动一个区块

    2023年04月11日
    浏览(41)
  • 区块链智能合约开发学习

    最近正在肝区块链知识学习,入手学习智能合约的开发,由于网上资料实在是太少了,好不容易东拼西凑完成了智能合约的开发、编译、部署、web3js调用(网页页面)和web3j调用(java调用),赶紧趁热把重点提炼出来。 先上图,是我最近学习知识点的一个概括总结,此外还包

    2023年04月18日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包