Permalink
Cannot retrieve contributors at this time
pragma solidity ^0.4.18; | |
import "./KittyAccessControl.sol"; | |
/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. | |
/// @author Axiom Zen (https://www.axiomzen.co) | |
/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. | |
contract KittyBase is KittyAccessControl { | |
/*** EVENTS ***/ | |
/// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously | |
/// includes any time a cat is created through the giveBirth method, but it is also called | |
/// when a new gen0 cat is created. | |
event Birth(address indexed owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); | |
/// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten | |
/// ownership is assigned, including births. | |
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); | |
/*** DATA TYPES ***/ | |
/// @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 cooldownEndTime; | |
// 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; | |
} | |
/*** CONSTANTS ***/ | |
/// @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) | |
]; | |
/*** 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 Assigns ownership of a specific Kitty to an address. | |
function _transfer(address _from, address _to, uint256 _tokenId) internal { | |
// since the number of kittens is capped to 2^32 | |
// there is no way to overflow this | |
ownershipTokenCount[_to]++; | |
// transfer ownership | |
kittyIndexToOwner[_tokenId] = _to; | |
// When creating new kittens _from is 0x0, but we can't account that address. | |
if (_from != address(0)) { | |
ownershipTokenCount[_from]--; | |
// once the kitten is transferred also clear sire allowances | |
delete sireAllowedToAddress[_tokenId]; | |
// clear any previously approved ownership exchange | |
delete kittyIndexToApproved[_tokenId]; | |
} | |
// Emit the transfer event. | |
Transfer(_from, _to, _tokenId); | |
} | |
/// @dev An internal method that creates a new kitty and stores it. This | |
/// method doesn't do any checking and should only be called when the | |
/// input data is known to be valid. Will generate both a Birth event | |
/// and a Transfer event. | |
/// @param _matronId The kitty ID of the matron of this cat (zero for gen0) | |
/// @param _sireId The kitty ID of the sire of this cat (zero for gen0) | |
/// @param _generation The generation number of this cat, must be computed by caller. | |
/// @param _genes The kitty's genetic code. | |
/// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) | |
function _createKitty( | |
uint256 _matronId, | |
uint256 _sireId, | |
uint256 _generation, | |
uint256 _genes, | |
address _owner | |
) | |
internal | |
returns (uint) | |
{ | |
// These requires are not strictly necessary, our calling code should make | |
// sure that these conditions are never broken. However! _createKitty() is already | |
// an expensive call (for storage), and it doesn't hurt to be especially careful | |
// to ensure our data structures are always valid. | |
require(_matronId <= 4294967295); | |
require(_sireId <= 4294967295); | |
require(_generation <= 65535); | |
Kitty memory _kitty = Kitty({ | |
genes: _genes, | |
birthTime: uint64(now), | |
cooldownEndTime: 0, | |
matronId: uint32(_matronId), | |
sireId: uint32(_sireId), | |
siringWithId: 0, | |
cooldownIndex: 0, | |
generation: uint16(_generation) | |
}); | |
uint256 newKittenId = kitties.push(_kitty) - 1; | |
// It's probably never going to happen, 4 billion cats is A LOT, but | |
// let's just be 100% sure we never let this happen. | |
require(newKittenId <= 4294967295); | |
// emit the birth event | |
Birth( | |
_owner, | |
newKittenId, | |
uint256(_kitty.matronId), | |
uint256(_kitty.sireId), | |
_kitty.genes | |
); | |
// This will assign ownership, and also emit the Transfer event as | |
// per ERC721 draft | |
_transfer(0, _owner, newKittenId); | |
return newKittenId; | |
} | |
} |