CryptoKittes(加密貓,謎戀貓)智慧合約結構和原始碼解析
阿新 • • 發佈:2019-01-07
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++;
}