pragma solidity ^0.6.2;
contract CryptoKitties{
mapping(uint256 => address payable) public kittyIndexToOwner; // 猫咪拥有者
mapping(uint256 => Kitty) public tokenToKitty; // token对应的猫咪
uint32 index; // 猫咪数量
NFT nft;
struct Kitty{
uint32 genes; // 256位的整数,代表猫的遗传因子。这个数值将决定猫的外表
uint64 birthTime; // 这只猫诞生时的区块时间
uint64 cooldownEndBlock; // 这只猫下一次可以进行繁殖的最快时间
uint32 matronId; // 这只猫的母亲ID
uint32 sireId; // 这只猫的父亲ID
uint32 siringWithId; // 如果这只猫现在作为母猫怀孕中,将会被设置为其对应父猫的ID,否则为0
uint16 cooldownIndex; // 这只猫在每一次繁殖后需要多久才能再一次进行繁殖
uint16 generation; // 这只猫的世代。初期通过购买蛋得到的猫为世代0,其余的猫的世代为其父母的最大世代+1
}
constructor(address _nftContractAddress) public{
nft = NFT(_nftContractAddress);
for(uint256 i=1; i<100; i++){
create(0);
}
}
// 打入ETH生产1代猫
function productKitty() public payable{
require(msg.value == 1 ether,"product payable eth is not nought");
create(1);
}
// 繁殖
function reproduction(uint256 _matronId,uint256 _sireId) public payable{
Kitty memory matronKitty = tokenToKitty[_matronId];
require(kittyIndexToOwner[matronKitty.genes] == msg.sender,"matron have to be their own"); // 繁殖时母系必须是自己的
require(matronKitty.siringWithId == 0 || (matronKitty.siringWithId>0 && matronKitty.cooldownEndBlock <= block.number),"this matron already pregnant"); // 不在孕期
Kitty memory sireKitty = tokenToKitty[_sireId];
if(kittyIndexToOwner[sireKitty.genes] == msg.sender){ // 如果繁殖时父系不是自己的,那么需要支付一笔eth费用给对方
require(msg.value == 0.1 ether,"reproduction payable value is not nought");
kittyIndexToOwner[sireKitty.genes].transfer(msg.value);
}
_reproduction(matronKitty,sireKitty); // 繁殖
matronKitty.siringWithId = sireKitty.genes; // 设置母系繁殖状态
matronKitty.cooldownEndBlock = uint64(block.number + matronKitty.cooldownIndex); // 设置母系下一次可繁殖时间
tokenToKitty[_matronId] = matronKitty; // 更新母系状态
}
function _reproduction(Kitty memory _matronKitty,Kitty memory _sireKitty) private{
index += 1;
Kitty memory kitty = Kitty({
genes: index,
birthTime: uint64(now),
cooldownEndBlock: 0,
matronId: _matronKitty.matronId,
sireId: _sireKitty.sireId,
siringWithId: 0,
cooldownIndex: uint16(7 * 86400),
generation: _matronKitty.generation + 1
});
kittyIndexToOwner[index] = msg.sender;
bool success = nft.mint();
require(success,"create is fail");
uint256 tokenId = nft.maxTokenId();
tokenToKitty[tokenId] = kitty;
}
// 生产0代创世猫咪
function create(uint16 _generation) private{
index += index;
Kitty memory kitty = Kitty({
genes: index,
birthTime: uint64(now),
cooldownEndBlock: 0,
matronId: uint32(0),
sireId: uint32(0),
siringWithId: 0,
cooldownIndex: uint16(7 * 86400),
generation: _generation
});
kittyIndexToOwner[index] = msg.sender;
bool success = nft.mint();
require(success,"create is fail");
uint256 tokenId = nft.maxTokenId();
tokenToKitty[tokenId] = kitty;
}
}
interface NFT{
// 查询token的拥有者
function ownerOf(uint256 _tokenId) external view returns (address);
// 授权
function approve(address _to,uint256 _tokenId) external;
// token代理人提币
function takeOwnership(uint256 _tokenId) external;
// 转账
function transfer(address _to, uint256 _tokenId) external;
// 铸币
function mint() external returns(bool);
// 查看最新铸出来的token ID
function maxTokenId() external view returns(uint256);
}
网友评论