CryptoKittes(加密猫、谜恋猫,https://www.cryptokitties.co/)是运行在以太坊上的一个游戏。 谜恋猫是世界首款架构在区块链技术上的数字猫收集与繁殖游戏,同样的技术突破使得比特币和以太坊的运作的基础。

  具体可以参考如下两篇参考资料:

  查看代码两个地方都可以

  查看源码,我画了如下的图,主要结构如下:

  • 猫的属性
  • 主要逻辑就是从上到下继承关系
  • 拍卖合约和繁殖合约
  • 遵循ERC721协议和基因科学合约(源码未公布)

   

下面我阅读源码的笔记,没有贴源码,请参照如上地址,阅读源码:

一、合约部分
1、权限:交易需要本人账号操作,CEO/CFO/COO有特殊权限(onlyCLevel指CEO/CFO/COO皆可)
1)onyCLLevel:设置区块产生速度(多少秒一个区块);提取拍卖所佣金到CFO账号;
2)CEO:暂停、启动整个合约、指定Kitty新合约地址、销售拍卖和交配权合约地址
3)COO: 生成宣传猫、初代猫,设置生育费
4)CFO: 提取佣金
2、基因科学合约(繁殖部分)未公布源码

3、主要合约分为:ERC271协议、权限控制、权属、繁殖、拍卖(猫交易、交配权拍卖)、创造(宣传猫、初代猫)
4、下面的代码是存储各种关系的数据结构,Kitty[] kitties是所有猫的数组,mapping我理解就是key-value的哈希表

  // An approximation of currently how many seconds are in between blocks.
    uint256 public secondsPerBlock = 15;

    /*** STORAGE ***/

    /// @dev An array containing the Kitty struct for all Kitties in existence. The ID
    ///  of each cat is actually an index into this array. Note that ID 0 is a negacat,
    ///  the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre
    ///  creature that is both matron and sire... to itself! Has an invalid genetic code.
    ///  In other words, cat ID 0 is invalid... ;-)
    Kitty[] kitties;

    /// @dev A mapping from cat IDs to the address that owns them. All cats have
    ///  some valid owner address, even gen0 cats are created with a non-zero owner.
    mapping (uint256 => address) public kittyIndexToOwner;

    // @dev A mapping from owner address to count of tokens that address owns.
    //  Used internally inside balanceOf() to resolve ownership count.
    mapping (address => uint256) ownershipTokenCount;

    /// @dev A mapping from KittyIDs to an address that has been approved to call
    ///  transferFrom(). Each Kitty can only have one approved address for transfer
    ///  at any time. A zero value means no approval is outstanding.
    mapping (uint256 => address) public kittyIndexToApproved;

    /// @dev A mapping from KittyIDs to an address that has been approved to use
    ///  this Kitty for siring via breedWith(). Each Kitty can only have one approved
    ///  address for siring at any time. A zero value means no approval is outstanding.
    mapping (uint256 => address) public sireAllowedToAddress;

    /// @dev The address of the ClockAuction contract that handles sales of Kitties. This
    ///  same contract handles both peer-to-peer sales as well as the gen0 sales which are
    ///  initiated every 15 minutes.
    SaleClockAuction public saleAuction;

    /// @dev The address of a custom ClockAuction subclassed contract that handles siring
    ///  auctions. Needs to be separate from saleAuction because the actions taken on success
    ///  after a sales and siring auction are quite different.
    SiringClockAuction public siringAuction;
二、猫的属性
1、基因是256位标记,猫没有性别,既可以当母亲,也可以当父亲
2、猫出生时间戳为代码执行系统时间
3、所有猫放在数组中,宣传猫和初代猫父母ID为0,怀孕的猫记录配偶的ID,用来判断是否怀孕,小猫出生后父亲ID就是母亲配偶ID
   ID是数组的索引,猫的ID是uint32,共40亿的量,以太坊每年5亿的交易量,使用ID的地方都需要溢出检查
4、后代的代,父母的代中最大的一个加1,比如0代和1代生出的小猫代为2
5、冷却时间,1分钟-7天共14档,出生后初始值是代除以2[ floor(generation/2) ],比如2代出生后冷却就是1档,5代就是2档,以后每交配一次增加一档,最大是14档(7d)

    14档{1m,2m,5m,10m,30m,1h,2h,4h,8h,16h,1d,2d,4d,7d}

    /// @dev A lookup table indicating the cooldown duration after any successful
    ///  breeding action, called "pregnancy time" for matrons and "siring cooldown"
    ///  for sires. Designed such that the cooldown roughly doubles each time a cat
    ///  is bred, encouraging owners not to just keep breeding the same cat over
    ///  and over again. Caps out at one week (a cat can breed an unbounded number
    ///  of times, and the maximum cooldown is always seven days).
    uint32[14] public cooldowns = [
        uint32(1 minutes),
        uint32(2 minutes),
        uint32(5 minutes),
        uint32(10 minutes),
        uint32(30 minutes),
        uint32(1 hours),
        uint32(2 hours),
        uint32(4 hours),
        uint32(8 hours),
        uint32(16 hours),
        uint32(1 days),
        uint32(2 days),
        uint32(4 days),
        uint32(7 days)
    ];

    冷却时间确定了之后,会根据冷却时间除以区块的生成速度计算冷却区块索引
    冷却时间的区块索引,这个是计算生猫后小猫记录区块的位置,防止溢出

    交配后母猫冷却时间为怀孕时间,公猫也有相应的冷却时间

下面代码是Kitty的数据结构,好好理解一下

 /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy
    ///  of this structure, so great care was taken to ensure that it fits neatly into
    ///  exactly two 256-bit words. Note that the order of the members in this structure
    ///  is important because of the byte-packing rules used by Ethereum.
    ///  Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html
    struct Kitty {
        // The Kitty's genetic code is packed into these 256-bits, the format is
        // sooper-sekret! A cat's genes never change.
        uint256 genes;

        // The timestamp from the block when this cat came into existence.
        uint64 birthTime;

        // The minimum timestamp after which this cat can engage in breeding
        // activities again. This same timestamp is used for the pregnancy
        // timer (for matrons) as well as the siring cooldown.
        uint64 cooldownEndBlock;

        // The ID of the parents of this kitty, set to 0 for gen0 cats.
        // Note that using 32-bit unsigned integers limits us to a "mere"
        // 4 billion cats. This number might seem small until you realize
        // that Ethereum currently has a limit of about 500 million
        // transactions per year! So, this definitely won't be a problem
        // for several years (even as Ethereum learns to scale).
        uint32 matronId;
        uint32 sireId;

        // Set to the ID of the sire cat for matrons that are pregnant,
        // zero otherwise. A non-zero value here is how we know a cat
        // is pregnant. Used to retrieve the genetic material for the new
        // kitten when the birth transpires.
        uint32 siringWithId;

        // Set to the index in the cooldown array (see below) that represents
        // the current cooldown duration for this Kitty. This starts at zero
        // for gen0 cats, and is initialized to floor(generation/2) for others.
        // Incremented by one for each successful breeding action, regardless
        // of whether this cat is acting as matron or sire.
        uint16 cooldownIndex;

        // The "generation number" of this cat. Cats minted by the CK contract
        // for sale are called "gen0" and have a generation number of 0. The
        // generation number of all other cats is the larger of the two generation
        // numbers of their parents, plus one.
        // (i.e. max(matron.generation, sire.generation) + 1)
        uint16 generation;
    }
三、繁殖
繁殖的过程分为:
1)出售交配权(公猫),母猫主人拍卖,交配、怀孕、生产
2)相同账号的两只猫可以繁殖,只有后面三个过程

条件
1)母猫主人生育费是否够2 Finney(1 ETH=1000 Finney)
2)需要公猫的用户授权(拍卖)
3)母猫未怀孕,且双方过了冷却时间
4)是否可以交配,父母和子女,兄妹之间都不可以

怀孕
1)怀孕后,母猫和公猫都增加一档冷却时间,母猫的冷却时间就是怀孕时间

出生
1)检查怀孕时间超过冷却时间
2)新生猫的代是最大的父母代+1
3)基因由父母基因遗传+突变

4)出生的小猫归母猫主人所有

繁殖的逻辑比较复杂,我这里就不贴代码了

四、拍卖猫
价格单位
//1: wei  Wei  Dai  戴伟 密码学家 ,发表 B-money
//10^3: lovelace   Ada Lovelace 洛夫莱斯 世界上第一位程序员、诗人拜伦之女
//10^6: babbage  Charles Babbage 巴贝奇  英国数学家、发明家兼机械工程师,提出了差分机与分析机的设计概念,被视为计算机先驱。
//10^9: shannon  Claude Elwood Shannon 香农  美国数学家、电子工程师和密码学家,被誉为信息论的创始人
//10^12: szabo    Nick Szabo  尼克萨博  密码学家、智能合约的提出者
//10^15: finney   Hal Finney   芬尼  密码学家、工作量证明机制(POW)提出
//10^18: ether     以太
1)条件:猫没有在卖猫/交配权的拍卖中,没有怀孕,
2)有交易费率,交易税率以当前价格乘以税率,拍卖价格以wei为单位
3)添加拍卖后,猫的所属就交给拍卖合约了,猫不能做其他事情了
4)拍卖持续时间大于1分钟,起始价格一般(也可以低)比最后价格高,价格线性下降
5)买家出价不低于当前价格就能买下(比如初始100,最后50,100秒,在第20秒时,价格20*(100-50)/100+50=60,出价大于等于60即可)
    真正扣费时是以交易时价格为准,剩余的金额会返回给买家
6)会记录0代猫的最新5只拍卖价格

五、拍卖交配权
1)条件:猫没有在猫交易/交配权的拍卖中,可以交配;符合交配规则
2)固定交易费
3)拍卖成功了直接繁殖

六、宣传猫和初代猫(COO有权限)
1)宣传猫直接给账号,初代猫放到市场拍卖;宣传猫5000只,初代猫45000只
2)初代猫默认价格10 Finney,默认拍卖时间1天

3)下一只初代猫开始价格为前五只猫的平均拍卖价格的1.5倍,如果小于默认价格,设为默认价格,最后价格为0,开始拍卖!

    /// @dev we can create promo kittens, up to a limit. Only callable by COO
    /// @param _genes the encoded genes of the kitten to be created, any value is accepted
    /// @param _owner the future owner of the created kittens. Default to contract COO
    function createPromoKitty(uint256 _genes, address _owner) external onlyCOO {
        address kittyOwner = _owner;
        if (kittyOwner == address(0)) {
             kittyOwner = cooAddress;
        }
        require(promoCreatedCount < PROMO_CREATION_LIMIT);

        promoCreatedCount++;
        _createKitty(0, 0, 0, _genes, kittyOwner);
    }

    /// @dev Creates a new gen0 kitty with the given genes and
    ///  creates an auction for it.
    function createGen0Auction(uint256 _genes) external onlyCOO {
        require(gen0CreatedCount < GEN0_CREATION_LIMIT);

        uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this));
        _approve(kittyId, saleAuction);

        saleAuction.createAuction(
            kittyId,
            _computeNextGen0Price(),
            0,
            GEN0_AUCTION_DURATION,
            address(this)
        );

        gen0CreatedCount++;
    }

Logo

为所有Web3兴趣爱好者提供学习成长、分享交流、生态实践、资源工具等服务,作为Anome Land原住民可不断优先享受各种福利,共同打造全球最大的Web3 UGC游戏平台。

更多推荐