原创 PlatON
CryptoKitties(密码猫),是全球首款区块链游戏。密码猫是一群讨人喜欢的数字喵咪,每一只猫咪都拥有独一无二的基因组,这决定它的外观和特征。玩家可以收集和繁殖喵咪,创造出全新的喵星人并解锁珍稀属性。
基于PlatON已经全面兼容以太坊生态,本文主要讲述如何将CryptoKitties迁移到PlatON上。
| 准备工作
合约源码
https://etherscan.io/address/0x06012c8cf97bead5deae237070f9587f8e7a266d#code
迁移说明
https://devdocs.platon.network/docs/zh-CN/Solidity_Contract_Migrate
系统:ubuntu 18.04
环境安装:主要是安装platon-truffle,参考教程:
https://devdocs.platon.network/docs/zh-CN/Solidity_Dev_Manual
测试账号:准备三个开发网账号,分别记为owner,user1,user2,用于测试工作。
| 迁移流程
按照下面的步骤即可完成CryptoKitties的迁移。
创建工作目录
mkdir crypto-kitties && cd crypto-kitties
初始化工程
platon-truffle init
这里可能会报错
这个是网络原因,可以通过修改/etc/hosts解决。
| 整理代码
源码是打包放到一个文件中的,里面有很多的合约,为了使程序结构更加清晰,我们将合约拆分到不同的文件中,拆分之后的目录是这样的:
其中Migration.sol是自动生成的,实际上文件数量应该是16个。
在拆分文件的时候,需要完成以下三个操作:
- 添加版本声明—需要在每个合约开头都加上pragma solidity ^0.4.11。
- 导入依赖—由于将代码拆分到了不同的文件,因此需要在依赖其他合约的文件中添加import语句,如import “./Ownable.sol”。
- 代码兼容—需要修改address(0)为address(uint160(0))。新版本,即PlatON1.1.1及以上不需要这一步操作。
| 代码说明
为了更好地理解代码逻辑,我们接下来讲一下关键的数据结构和接口。
以下是项目的UML图,我并没有把所有的内容都加进入,只加入了个人认为比较关键的点。
KittyAccessControl
权限管理相关的功能,总共分为了三个权限,分别是CEO、CFO、COO,其中CEO具有最高的权限,即CEO可以修改所有的权限。onlyCLevel是指这三个里面的任何一个都可以。
KittyBase
这个合约提供了Kitty相关的基本数据和方法,包括Kitty列表、Auction合约、转移Kitty和创建Kitty等。
Kitty
用于记录每只猫的信息,包括基因、代数、父母、生日等。
KittyOwnerShip
Kitty所有权相关的合约,主要是实现了ERC721接口。
KittyBreeding
提供Kitty的繁殖相关的功能。
KittyAuction
提供Kitty出售和sire with的相关方法。
KittyMinting
提供Kitty生成的相关方法,只能由COO调用,而且有数量限制。
KittyCore
CryptoKitties的主合约。
可以看出,KittyCore这个合约才是核心的合约,它承担了Kitty相关的所有业务逻辑。
因为Auction部分比较复杂,因此将其单独开发了合约,便于开发和维护。Auction部分的合约是完全独立于业务的,可以用于其他的NTF相关的拍卖。
基因混合
在UML中我们可以发现,Gene算法部分的代码是没有的,只有一个接口文件,因此我们需要自行将这部分代码补上。由于我们只是测试功能,因此只是用最简单的实现方式。我们将文件命名为GeneSimple.sol,放在contracts目录下,代码如下
pragma solidity ^0.4.11;import "./GeneScienceInterface.sol";/// @title SEKRETOOOOcontract GeneSimple is GeneScienceInterface { /// @dev simply a boolean to indicate this is the contract we expect to be function isGeneScience() public pure returns (bool) { return true; } /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor /// @param genes1 genes of mom /// @param genes2 genes of sire /// @return the genes that are supposed to be passed down the child function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public returns (uint256) { bytes32 hash = keccak256(targetBlock); uint256 hash256 = uint256(hash); uint256 ret = (genes1 ^ genes2) & hash256; return ret; }}
下节我们将详述编译和部署教程,敬请期待。
(未完待续)
本文转载自https://mp.weixin.qq.com/s/ds3IHKo8UrcrP84JV5m2WA