CryptoKitties
ERC20
This contract is an ERC20 token.
Name
CryptoKitties
Symbol
CK
Decimals
Total Supply
NaN CK
About
Stats
Public Functions
36
Event Types
5
Code Size
82,025 bytes
Events (5) keyboard_arrow_up
Constants (8) keyboard_arrow_up
State Variables (20) keyboard_arrow_up
Functions
totalSupply keyboard_arrow_up
balanceOf keyboard_arrow_up
ownerOf keyboard_arrow_up
Source Code
function ownerOf(uint256 _tokenId) external view returns (address owner) {
owner = kittyIndexToOwner[_tokenId];
require(owner != address(0));
}
approve keyboard_arrow_up
Requirements help
null
Source Code
function approve(address _to, uint256 _tokenId) external whenNotPaused {
// Only an owner can grant transfer approval.
require(_owns(msg.sender, _tokenId));
// Register the approval (replacing any previous approval).
_approve(_tokenId, _to);
// Emit approval event.
Approval(msg.sender, _to, _tokenId);
}
transfer keyboard_arrow_up
Requirements help
Source Code
function transfer(address _to, uint256 _tokenId) external whenNotPaused {
// Safety check to prevent against an unexpected 0x0 default.
require(_to != address(0));
// Disallow transfers to this contract to prevent accidental misuse.
// The contract should never own any kitties (except very briefly
// after a gen0 cat is created and before it goes on auction).
require(_to != address(this));
// Disallow transfers to the auction contracts to prevent accidental
// misuse. Auction contracts should only take ownership of kitties
// through the allow + transferFrom flow.
require(_to != address(saleAuction));
require(_to != address(siringAuction));
// You can only send your own cat.
require(_owns(msg.sender, _tokenId));
// Reassign ownership, clear pending approvals, emit Transfer event.
_transfer(msg.sender, _to, _tokenId);
}
transferFrom keyboard_arrow_up
Requirements help
Source Code
function transferFrom(
address _from,
address _to,
uint256 _tokenId
) external whenNotPaused {
// Safety check to prevent against an unexpected 0x0 default.
require(_to != address(0));
// Disallow transfers to this contract to prevent accidental misuse.
// The contract should never own any kitties (except very briefly
// after a gen0 cat is created and before it goes on auction).
require(_to != address(this));
// Check for approval and valid ownership
require(_approvedFor(msg.sender, _tokenId));
require(_owns(_from, _tokenId));
// Reassign ownership (also clears pending approvals and emits Transfer event).
_transfer(_from, _to, _tokenId);
}
supportsInterface keyboard_arrow_up
Source Code
function supportsInterface(bytes4 _interfaceID) external view returns (bool) {
// DEBUG ONLY
//require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d));
return ((_interfaceID == InterfaceSignature_ERC165) ||
(_interfaceID == InterfaceSignature_ERC721));
}
setCEO keyboard_arrow_up
Modifiers help
onlyCEO checks for the following:
Source Code
function setCEO(address _newCEO) external onlyCEO {
require(_newCEO != address(0));
ceoAddress = _newCEO;
}
setCFO keyboard_arrow_up
Modifiers help
onlyCEO checks for the following:
Source Code
function setCFO(address _newCFO) external onlyCEO {
require(_newCFO != address(0));
cfoAddress = _newCFO;
}
setCOO keyboard_arrow_up
Modifiers help
onlyCEO checks for the following:
Source Code
function setCOO(address _newCOO) external onlyCEO {
require(_newCOO != address(0));
cooAddress = _newCOO;
}
pause keyboard_arrow_up
Parameters help
This function has no parameters.
Modifiers help
onlyCLevel checks for the following:
One or more of the following:
-
cfoAddress
must be equal to
the sender's address
- OR
ceoAddress
must be equal to
the sender's address
- OR
cooAddress
must be equal to
the sender's address
whenNotPaused checks for the following:
Source Code
function pause() external onlyCLevel whenNotPaused {
paused = true;
}
unpause keyboard_arrow_up
Parameters help
This function has no parameters.
Modifiers help
onlyCEO checks for the following:
whenPaused checks for the following:
paused must be true
Requirements help
Source Code
function unpause() public onlyCEO whenPaused {
require(saleAuction != address(0));
require(siringAuction != address(0));
require(geneScience != address(0));
require(newContractAddress == address(0));
// Actually unpause the contract.
super.unpause();
}
setSecondsPerBlock keyboard_arrow_up
Modifiers help
onlyCLevel checks for the following:
One or more of the following:
-
cfoAddress
must be equal to
the sender's address
- OR
ceoAddress
must be equal to
the sender's address
- OR
cooAddress
must be equal to
the sender's address
Source Code
function setSecondsPerBlock(uint256 secs) external onlyCLevel {
require(secs < cooldowns[0]);
secondsPerBlock = secs;
}
setMetadataAddress keyboard_arrow_up
Modifiers help
onlyCEO checks for the following:
Source Code
function setMetadataAddress(address _contractAddress) public onlyCEO {
erc721Metadata = ERC721Metadata(_contractAddress);
}
tokensOfOwner keyboard_arrow_up
Source Code
function tokensOfOwner(address _owner)
external
view
returns (uint256[] ownerTokens)
{
uint256 tokenCount = balanceOf(_owner);
if (tokenCount == 0) {
// Return an empty array
return new uint256[](0);
} else {
uint256[] memory result = new uint256[](tokenCount);
uint256 totalCats = totalSupply();
uint256 resultIndex = 0;
// We count on the fact that all cats have IDs starting at 1 and increasing
// sequentially up to the totalCat count.
uint256 catId;
for (catId = 1; catId <= totalCats; catId++) {
if (kittyIndexToOwner[catId] == _owner) {
result[resultIndex] = catId;
resultIndex++;
}
}
return result;
}
}
tokenMetadata keyboard_arrow_up
Requirements help
Source Code
function tokenMetadata(uint256 _tokenId, string _preferredTransport)
external
view
returns (string infoUrl)
{
require(erc721Metadata != address(0));
bytes32[4] memory buffer;
uint256 count;
(buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport);
return _toString(buffer, count);
}
setGeneScienceAddress keyboard_arrow_up
Modifiers help
onlyCEO checks for the following:
Source Code
function setGeneScienceAddress(address _address) external onlyCEO {
GeneScienceInterface candidateContract = GeneScienceInterface(_address);
// NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117
require(candidateContract.isGeneScience());
// Set the new contract address
geneScience = candidateContract;
}
approveSiring keyboard_arrow_up
Requirements help
null
Source Code
function approveSiring(address _addr, uint256 _sireId) external whenNotPaused {
require(_owns(msg.sender, _sireId));
sireAllowedToAddress[_sireId] = _addr;
}
setAutoBirthFee keyboard_arrow_up
Modifiers help
onlyCOO checks for the following:
Source Code
function setAutoBirthFee(uint256 val) external onlyCOO {
autoBirthFee = val;
}
isReadyToBreed keyboard_arrow_up
Source Code
function isReadyToBreed(uint256 _kittyId) public view returns (bool) {
require(_kittyId > 0);
Kitty storage kit = kitties[_kittyId];
return _isReadyToBreed(kit);
}
isPregnant keyboard_arrow_up
Source Code
function isPregnant(uint256 _kittyId) public view returns (bool) {
require(_kittyId > 0);
// A kitty is pregnant if and only if this field is set
return kitties[_kittyId].siringWithId != 0;
}
canBreedWith keyboard_arrow_up
Source Code
function canBreedWith(uint256 _matronId, uint256 _sireId)
external
view
returns (bool)
{
require(_matronId > 0);
require(_sireId > 0);
Kitty storage matron = kitties[_matronId];
Kitty storage sire = kitties[_sireId];
return
_isValidMatingPair(matron, _matronId, sire, _sireId) &&
_isSiringPermitted(_sireId, _matronId);
}
breedWithAuto keyboard_arrow_up
Requirements help
Source Code
function breedWithAuto(uint256 _matronId, uint256 _sireId)
external
payable
whenNotPaused
{
// Checks for payment.
require(msg.value >= autoBirthFee);
// Caller must own the matron.
require(_owns(msg.sender, _matronId));
// Neither sire nor matron are allowed to be on auction during a normal
// breeding operation, but we don't need to check that explicitly.
// For matron: The caller of this function can't be the owner of the matron
// because the owner of a Kitty on auction is the auction house, and the
// auction house will never call breedWith().
// For sire: Similarly, a sire on auction will be owned by the auction house
// and the act of transferring ownership will have cleared any oustanding
// siring approval.
// Thus we don't need to spend gas explicitly checking to see if either cat
// is on auction.
// Check that matron and sire are both owned by caller, or that the sire
// has given siring permission to caller (i.e. matron's owner).
// Will fail for _sireId = 0
require(_isSiringPermitted(_sireId, _matronId));
// Grab a reference to the potential matron
Kitty storage matron = kitties[_matronId];
// Make sure matron isn't pregnant, or in the middle of a siring cooldown
require(_isReadyToBreed(matron));
// Grab a reference to the potential sire
Kitty storage sire = kitties[_sireId];
// Make sure sire isn't pregnant, or in the middle of a siring cooldown
require(_isReadyToBreed(sire));
// Test that these cats are a valid mating pair.
require(_isValidMatingPair(matron, _matronId, sire, _sireId));
// All checks passed, kitty gets pregnant!
_breedWith(_matronId, _sireId);
}
giveBirth keyboard_arrow_up
Requirements help
null
Source Code
function giveBirth(uint256 _matronId) external whenNotPaused returns (uint256) {
// Grab a reference to the matron in storage.
Kitty storage matron = kitties[_matronId];
// Check that the matron is a valid cat.
require(matron.birthTime != 0);
// Check that the matron is pregnant, and that its time has come!
require(_isReadyToGiveBirth(matron));
// Grab a reference to the sire in storage.
uint256 sireId = matron.siringWithId;
Kitty storage sire = kitties[sireId];
// Determine the higher generation number of the two parents
uint16 parentGen = matron.generation;
if (sire.generation > matron.generation) {
parentGen = sire.generation;
}
// Call the sooper-sekret gene mixing operation.
uint256 childGenes = geneScience.mixGenes(
matron.genes,
sire.genes,
matron.cooldownEndBlock - 1
);
// Make the new kitten!
address owner = kittyIndexToOwner[_matronId];
uint256 kittenId = _createKitty(
_matronId,
matron.siringWithId,
parentGen + 1,
childGenes,
owner
);
// Clear the reference to sire from the matron (REQUIRED! Having siringWithId
// set is what marks a matron as being pregnant.)
delete matron.siringWithId;
// Every time a kitty gives birth counter is decremented.
pregnantKitties--;
// Send the balance fee to the person who made birth happen.
msg.sender.send(autoBirthFee);
// return the new kitten's ID
return kittenId;
}
setSaleAuctionAddress keyboard_arrow_up
Modifiers help
onlyCEO checks for the following:
Source Code
function setSaleAuctionAddress(address _address) external onlyCEO {
SaleClockAuction candidateContract = SaleClockAuction(_address);
// NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117
require(candidateContract.isSaleClockAuction());
// Set the new contract address
saleAuction = candidateContract;
}
setSiringAuctionAddress keyboard_arrow_up
Modifiers help
onlyCEO checks for the following:
Source Code
function setSiringAuctionAddress(address _address) external onlyCEO {
SiringClockAuction candidateContract = SiringClockAuction(_address);
// NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117
require(candidateContract.isSiringClockAuction());
// Set the new contract address
siringAuction = candidateContract;
}
createSaleAuction keyboard_arrow_up
Parameters help
Requirements help
null
Source Code
function createSaleAuction(
uint256 _kittyId,
uint256 _startingPrice,
uint256 _endingPrice,
uint256 _duration
) external whenNotPaused {
// Auction contract checks input sizes
// If kitty is already on any auction, this will throw
// because it will be owned by the auction contract.
require(_owns(msg.sender, _kittyId));
// Ensure the kitty is not pregnant to prevent the auction
// contract accidentally receiving ownership of the child.
// NOTE: the kitty IS allowed to be in a cooldown.
require(!isPregnant(_kittyId));
_approve(_kittyId, saleAuction);
// Sale auction throws if inputs are invalid and clears
// transfer and sire approval after escrowing the kitty.
saleAuction.createAuction(
_kittyId,
_startingPrice,
_endingPrice,
_duration,
msg.sender
);
}
createSiringAuction keyboard_arrow_up
Parameters help
Requirements help
null
null
Source Code
function createSiringAuction(
uint256 _kittyId,
uint256 _startingPrice,
uint256 _endingPrice,
uint256 _duration
) external whenNotPaused {
// Auction contract checks input sizes
// If kitty is already on any auction, this will throw
// because it will be owned by the auction contract.
require(_owns(msg.sender, _kittyId));
require(isReadyToBreed(_kittyId));
_approve(_kittyId, siringAuction);
// Siring auction throws if inputs are invalid and clears
// transfer and sire approval after escrowing the kitty.
siringAuction.createAuction(
_kittyId,
_startingPrice,
_endingPrice,
_duration,
msg.sender
);
}
bidOnSiringAuction keyboard_arrow_up
Requirements help
Source Code
function bidOnSiringAuction(uint256 _sireId, uint256 _matronId)
external
payable
whenNotPaused
{
// Auction contract checks input sizes
require(_owns(msg.sender, _matronId));
require(isReadyToBreed(_matronId));
require(_canBreedWithViaAuction(_matronId, _sireId));
// Define the current price of the auction.
uint256 currentPrice = siringAuction.getCurrentPrice(_sireId);
require(msg.value >= currentPrice + autoBirthFee);
// Siring auction will throw if the bid fails.
siringAuction.bid.value(msg.value - autoBirthFee)(_sireId);
_breedWith(uint32(_matronId), uint32(_sireId));
}
withdrawAuctionBalances keyboard_arrow_up
Parameters help
This function has no parameters.
Modifiers help
onlyCLevel checks for the following:
One or more of the following:
-
cfoAddress
must be equal to
the sender's address
- OR
ceoAddress
must be equal to
the sender's address
- OR
cooAddress
must be equal to
the sender's address
Source Code
function withdrawAuctionBalances() external onlyCLevel {
saleAuction.withdrawBalance();
siringAuction.withdrawBalance();
}
createPromoKitty keyboard_arrow_up
Modifiers help
onlyCOO checks for the following:
Requirements help
0
must be equal to
UNKNOWN VALUE
0
must be equal to
UNKNOWN VALUE
0
must be equal to
UNKNOWN VALUE
Source Code
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);
}
createGen0Auction keyboard_arrow_up
Modifiers help
onlyCOO checks for the following:
Requirements help
Source Code
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++;
}
setNewAddress keyboard_arrow_up
constructor keyboard_arrow_up
Parameters help
This function has no parameters.
Requirements help
One or more of the following:
-
the sender's address
must be equal to
UNKNOWN VALUE
- OR
the sender's address
must be equal to
UNKNOWN VALUE
Source Code
function() external payable {
require(
msg.sender == address(saleAuction) || msg.sender == address(siringAuction)
);
}
getKitty keyboard_arrow_up
Source Code
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
)
{
Kitty storage kit = kitties[_id];
// if this variable is 0 then it's not gestating
isGestating = (kit.siringWithId != 0);
isReady = (kit.cooldownEndBlock <= block.number);
cooldownIndex = uint256(kit.cooldownIndex);
nextActionAt = uint256(kit.cooldownEndBlock);
siringWithId = uint256(kit.siringWithId);
birthTime = uint256(kit.birthTime);
matronId = uint256(kit.matronId);
sireId = uint256(kit.sireId);
generation = uint256(kit.generation);
genes = kit.genes;
}
withdrawBalance keyboard_arrow_up
Parameters help
This function has no parameters.
Modifiers help
onlyCFO checks for the following:
Source Code
function withdrawBalance() external onlyCFO {
uint256 balance = this.balance;
// Subtract all the currently pregnant kittens we have, plus 1 of margin.
uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee;
if (balance > subtractFees) {
cfoAddress.send(balance - subtractFees);
}
}
Internal Functions
Internal functions are parts of the contract that can't be used directly, but instead are used by the public functions listed above.
internal KittyMinting._computeNextGen0Price keyboard_arrow_up
Parameters help
This function has no parameters.
Source Code
function _computeNextGen0Price() internal view returns (uint256) {
uint256 avePrice = saleAuction.averageGen0SalePrice();
// Sanity check to ensure we don't overflow arithmetic
require(avePrice == uint256(uint128(avePrice)));
uint256 nextPrice = avePrice + (avePrice / 2);
// We never auction for less than starting price
if (nextPrice < GEN0_STARTING_PRICE) {
nextPrice = GEN0_STARTING_PRICE;
}
return nextPrice;
}
internal KittyBreeding._isReadyToBreed keyboard_arrow_up
Source Code
function _isReadyToBreed(Kitty _kit) internal view returns (bool) {
// In addition to checking the cooldownEndBlock, we also need to check to see if
// the cat has a pending birth; there can be some period of time between the end
// of the pregnacy timer and the birth event.
return
(_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number));
}
internal KittyBreeding._isSiringPermitted keyboard_arrow_up
Source Code
function _isSiringPermitted(uint256 _sireId, uint256 _matronId)
internal
view
returns (bool)
{
address matronOwner = kittyIndexToOwner[_matronId];
address sireOwner = kittyIndexToOwner[_sireId];
// Siring is okay if they have same owner, or if the matron's owner was given
// permission to breed with this sire.
return (matronOwner == sireOwner ||
sireAllowedToAddress[_sireId] == matronOwner);
}
internal KittyBreeding._triggerCooldown keyboard_arrow_up
Source Code
function _triggerCooldown(Kitty storage _kitten) internal {
// Compute an estimation of the cooldown time in blocks (based on current cooldownIndex).
_kitten.cooldownEndBlock = uint64(
(cooldowns[_kitten.cooldownIndex] / secondsPerBlock) + block.number
);
// Increment the breeding count, clamping it at 13, which is the length of the
// cooldowns array. We could check the array size dynamically, but hard-coding
// this as a constant saves gas. Yay, Solidity!
if (_kitten.cooldownIndex < 13) {
_kitten.cooldownIndex += 1;
}
}
internal KittyBreeding._isReadyToGiveBirth keyboard_arrow_up
internal KittyBreeding._isValidMatingPair keyboard_arrow_up
Parameters help
Source Code
function _isValidMatingPair(
Kitty storage _matron,
uint256 _matronId,
Kitty storage _sire,
uint256 _sireId
) private view returns (bool) {
// A Kitty can't breed with itself!
if (_matronId == _sireId) {
return false;
}
// Kitties can't breed with their parents.
if (_matron.matronId == _sireId || _matron.sireId == _sireId) {
return false;
}
if (_sire.matronId == _matronId || _sire.sireId == _matronId) {
return false;
}
// We can short circuit the sibling check (below) if either cat is
// gen zero (has a matron ID of zero).
if (_sire.matronId == 0 || _matron.matronId == 0) {
return true;
}
// Kitties can't breed with full or half siblings.
if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) {
return false;
}
if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) {
return false;
}
// Everything seems cool! Let's get DTF.
return true;
}
internal KittyBreeding._canBreedWithViaAuction keyboard_arrow_up
Source Code
function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId)
internal
view
returns (bool)
{
Kitty storage matron = kitties[_matronId];
Kitty storage sire = kitties[_sireId];
return _isValidMatingPair(matron, _matronId, sire, _sireId);
}
internal KittyBreeding._breedWith keyboard_arrow_up
Source Code
function _breedWith(uint256 _matronId, uint256 _sireId) internal {
// Grab a reference to the Kitties from storage.
Kitty storage sire = kitties[_sireId];
Kitty storage matron = kitties[_matronId];
// Mark the matron as pregnant, keeping track of who the sire is.
matron.siringWithId = uint32(_sireId);
// Trigger the cooldown for both parents.
_triggerCooldown(sire);
_triggerCooldown(matron);
// Clear siring permission for both parents. This may not be strictly necessary
// but it's likely to avoid confusion!
delete sireAllowedToAddress[_matronId];
delete sireAllowedToAddress[_sireId];
// Every time a kitty gets pregnant, counter is incremented.
pregnantKitties++;
// Emit the pregnancy event.
Pregnant(
kittyIndexToOwner[_matronId],
_matronId,
_sireId,
matron.cooldownEndBlock
);
}
internal KittyOwnership._owns keyboard_arrow_up
internal KittyOwnership._approvedFor keyboard_arrow_up
internal KittyOwnership._approve keyboard_arrow_up
internal KittyOwnership._memcpy keyboard_arrow_up
Source Code
function _memcpy(
uint256 _dest,
uint256 _src,
uint256 _len
) private view {
// Copy word-length chunks while possible
for (; _len >= 32; _len -= 32) {
assembly {
mstore(_dest, mload(_src))
}
_dest += 32;
_src += 32;
}
// Copy remaining bytes
uint256 mask = 256**(32 - _len) - 1;
assembly {
let srcpart := and(mload(_src), not(mask))
let destpart := and(mload(_dest), mask)
mstore(_dest, or(destpart, srcpart))
}
}
internal KittyOwnership._toString keyboard_arrow_up
Source Code
function _toString(bytes32[4] _rawBytes, uint256 _stringLength)
private
view
returns (string)
{
var outputString = new string(_stringLength);
uint256 outputPtr;
uint256 bytesPtr;
assembly {
outputPtr := add(outputString, 32)
bytesPtr := _rawBytes
}
_memcpy(outputPtr, bytesPtr, _stringLength);
return outputString;
}
internal KittyBase._transfer keyboard_arrow_up
Source Code
function _transfer(
address _from,
address _to,
uint256 _tokenId
) internal {
// Since the number of kittens is capped to 2^32 we can't 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);
}
internal KittyBase._createKitty keyboard_arrow_up
Parameters help
Requirements help
0
must be equal to
UNKNOWN VALUE
0
must be equal to
UNKNOWN VALUE
0
must be equal to
UNKNOWN VALUE
Source Code
function _createKitty(
uint256 _matronId,
uint256 _sireId,
uint256 _generation,
uint256 _genes,
address _owner
) internal returns (uint256) {
// 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 == uint256(uint32(_matronId)));
require(_sireId == uint256(uint32(_sireId)));
require(_generation == uint256(uint16(_generation)));
// New kitty starts with the same cooldown as parent gen/2
uint16 cooldownIndex = uint16(_generation / 2);
if (cooldownIndex > 13) {
cooldownIndex = 13;
}
Kitty memory _kitty = Kitty({
genes: _genes,
birthTime: uint64(now),
cooldownEndBlock: 0,
matronId: uint32(_matronId),
sireId: uint32(_sireId),
siringWithId: 0,
cooldownIndex: cooldownIndex,
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 == uint256(uint32(newKittenId)));
// 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;
}