pragma solidity ^0.4.21;

/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of “user permissions”.
*/
contract Ownable {
address public owner;

/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() {
owner = msg.sender;
}

/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}

/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner {
if (newOwner != address(0)) {
owner = newOwner;
}
}

}

/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens

contract ERC721 {
// Required methods
function totalSupply() public view returns (uint256 total);
function balanceOf(address _owner) public view returns (uint256 balance);
function ownerOf(uint256 _tokenId) external view returns (address owner);
function approve(address _to, uint256 _tokenId) external;
function transfer(address _to, uint256 _tokenId) external;
function transferFrom(address _from, address _to, uint256 _tokenId) external;

// Events
event Transfer(address from, address to, uint256 tokenId);
event Approval(address owner, address approved, uint256 tokenId);

}

/// @title A facet of MyFishCore that manages special access privileges.

/// @dev See the MyFishCore contract documentation to understand how the various contract facets are arranged.
contract MyFishAccessControl {
// This facet controls access control for CryptoMyFish. There are four roles managed here:
//
// – The CEO: The CEO can reassign other roles and change the addresses of our dependent smart
// contracts. It is also the only role that can unpause the smart contract. It is initially
// set to the address that created the smart contract in the MyFishCore constructor.
//
// – The CFO: The CFO can withdraw funds from MyFishCore and its auction contracts.
//
// – The COO: The COO can release genesis MyFish to auction.
//
// It should be noted that these roles are distinct without overlap in their access abilities, the
// abilities listed for each role above are exhaustive. In particular, while the CEO can assign any
// address to any role, the CEO address itself doesn’t have the ability to act in those roles. This
// restriction is intentional so that we aren’t tempted to use the CEO address frequently out of
// convenience. The less we use an address, the less likely it is that we somehow compromise the
// account.
address newContractAddress;
/// @dev Emited when contract is upgraded – See README.md for updgrade plan
event ContractUpgrade(address newContract);

// The addresses of the accounts (or contracts) that can execute actions within each roles.
address public ceoAddress;
address public cfoAddress;
address public cooAddress;

// @dev Keeps track whether the contract is paused. When that is true, most actions are blocked
bool public paused = false;

/// @dev Access modifier for CEO-only functionality
modifier onlyCEO() {
require(msg.sender == ceoAddress);
_;
}

/// @dev Access modifier for CFO-only functionality
modifier onlyCFO() {
require(msg.sender == cfoAddress);
_;
}

/// @dev Access modifier for COO-only functionality
modifier onlyCOO() {
require(msg.sender == cooAddress);
_;
}

modifier onlyCLevel() {
require(
msg.sender == cooAddress ||
msg.sender == ceoAddress ||
msg.sender == cfoAddress
);
_;
}

/// @dev Assigns a new address to act as the CEO. Only available to the current CEO.
/// @param _newCEO The address of the new CEO
function setCEO(address _newCEO) external onlyCEO {
require(_newCEO != address(0));

ceoAddress = _newCEO;
}

/// @dev Assigns a new address to act as the CFO. Only available to the current CEO.
/// @param _newCFO The address of the new CFO
function setCFO(address _newCFO) external onlyCEO {
require(_newCFO != address(0));

cfoAddress = _newCFO;
}

/// @dev Assigns a new address to act as the COO. Only available to the current CEO.
/// @param _newCOO The address of the new COO
function setCOO(address _newCOO) external onlyCEO {
require(_newCOO != address(0));

cooAddress = _newCOO;
}

/*** Pausable functionality adapted from OpenZeppelin ***/

/// @dev Modifier to allow actions only when the contract IS NOT paused
modifier whenNotPaused() {
require(!paused);
_;
}

/// @dev Modifier to allow actions only when the contract IS paused
modifier whenPaused {
require(paused);
_;
}

/// @dev Called by any “C-level” role to pause the contract. Used only when
/// a bug or exploit is detected and we need to limit damage.
function pause() public onlyCLevel whenNotPaused {
paused = true;
}

/// @dev Unpauses the smart contract. Can only be called by the CEO, since
/// one reason we may pause the contract is when CFO or COO accounts are
/// compromised.
/// @notice This is public rather than external so it can be called by
/// derived contracts.
function unpause() public onlyCEO whenPaused {
// can’t unpause if contract was upgraded
paused = false;
}
}

/// @title Base contract for CryptoMyFish. Holds all common structs, events and base variables.

/// @dev See the MyFishCore contract documentation to understand how the various contract facets are arranged.
contract MyFishBase is MyFishAccessControl {
/*** EVENTS ***/

/// @dev The Birth event is fired whenever a new MyFish comes into existence. This obviously
/// includes any time a MyFish is created through the giveBirth method, but it is also called
/// when a new MyFishis created.
event Birth(address owner, uint256 myFishId, uint8 level,uint8 quality,uint8 starlevel,uint8 growup, uint8 skill,uint8 genius, uint16 strength, uint16 agility, uint16 power);

/// @dev Transfer event as defined in current draft of ERC721. Emitted every time a MyFish
/// ownership is assigned, including births.
event Transfer(address from, address to, uint256 tokenId);

/*** DATA TYPES ***/

/// @dev The main MyFish struct. Every MyFish in CryptoMyFish 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 MyFish {
uint8 level;

uint8 quality;
uint8 starlevel;
uint8 growup;

uint8 skill;
uint8 genius;

uint16 strength;
uint16 agility;
uint16 power;

bool eated;
}

/*** CONSTANTS ***/

/*** STORAGE ***/

/// @dev An array containing the MyFish struct for all MyFishes in existence. The ID
/// of each MyFish is actually an index into this array.
MyFish[] myFishes;

/// @dev A mapping from MyFish IDs to the address that owns them. All MyFish have
/// some valid owner address
mapping (uint256 => address) public myFishIndexToOwner;

// @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 MyFishIDs to an address that has been approved to call
/// transferFrom(). Each MyFish can only have one approved address for transfer
/// at any time. A zero value means no approval is outstanding.
mapping (uint256 => address) public myFishIndexToApproved;

/// @dev Assigns ownership of a specific MyFish to an address.
function _transfer(address _from, address _to, uint256 _tokenId) internal {
// has been eated fish can not transfer
MyFish memory fish = myFishes[_tokenId];
require(fish.eated == false);
// Since the number of MyFish is capped to 2^32 we can’t overflow this
ownershipTokenCount[_to]++;
// transfer ownership
myFishIndexToOwner[_tokenId] = _to;
// When creating new MyFish _from is 0x0, but we can’t account that address.
if (_from != address(0)) {
ownershipTokenCount[_from]–;
// clear any previously approved ownership exchange
delete myFishIndexToApproved[_tokenId];
}
// Emit the transfer event.
Transfer(_from, _to, _tokenId);
}

/// @dev An internal method that creates a new MyFish 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 _owner The inital owner of this MyFish, must be non-zero
function _createMyFish(
uint8 _level,uint8 _quality,uint8 _starlevel,uint8 _growup, uint8 _skill,uint8 _genius, uint16 _strength, uint16 _agility, uint16 _power,
address _owner
)
internal
onlyCLevel whenNotPaused
returns (uint)
{
require(_owner != address(0));
// require(_level != 0);
MyFish memory _myFish = MyFish({
level: _level,
quality: _quality,
starlevel: _starlevel,
growup: _growup,
skill: _skill,
genius: _genius,
strength: _strength,
agility: _agility,
power: _power,
eated: false
});
uint256 newMyFishId = myFishes.push(_myFish) – 1;

// emit the birth event

Birth(
_owner,
newMyFishId,
_myFish.level,
_myFish.quality,
_myFish.starlevel,
_myFish.growup,
_myFish.skill,
_myFish.genius,
_myFish.strength,
_myFish.agility,
_myFish.power
);

// This will assign ownership, and also emit the Transfer event as
// per ERC721 draft
_transfer(0, _owner, newMyFishId);

return newMyFishId;
}
}

/// @title The facet of the CryptoMyFish core contract that manages ownership, ERC-721 (draft) compliant.

/// @dev Ref: https://github.com/ethereum/EIPs/issues/721
/// See the MyFishCore contract documentation to understand how the various contract facets are arranged.
contract MyFishOwnership is MyFishBase, ERC721 {

/// @notice Name and symbol of the non fungible token, as defined in ERC721.
string public constant name = “MyFish”;
string public constant symbol = “MF”;

// Internal utility functions: These functions all assume that their input arguments
// are valid. We leave it to public methods to sanitize their inputs and follow
// the required logic.

/// @dev Checks if a given address is the current owner of a particular MyFish.
/// @param _claimant the address we are validating against.
/// @param _tokenId MyFish id, only valid when > 0
function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
return myFishIndexToOwner[_tokenId] == _claimant;
}

/// @dev Checks if a given address currently has transferApproval for a particular MyFish.
/// @param _claimant the address we are confirming MyFish is approved for.
/// @param _tokenId MyFish id, only valid when > 0
function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) {
return myFishIndexToApproved[_tokenId] == _claimant;
}

/// @dev Marks an address as being approved for transferFrom(), overwriting any previous
/// approval. Setting _approved to address(0) clears all transfer approval.
/// NOTE: _approve() does NOT send the Approval event. This is intentional because
/// _approve() and transferFrom() are used together for putting MyFishes on auction, and
/// there is no value in spamming the log with Approval events in that case.
function _approve(uint256 _tokenId, address _approved) internal {
myFishIndexToApproved[_tokenId] = _approved;
}

/// @notice Returns the number of MyFishes owned by a specific address.
/// @param _owner The owner address to check.
/// @dev Required for ERC-721 compliance
function balanceOf(address _owner) public view returns (uint256 count) {
return ownershipTokenCount[_owner];
}

/// @notice Transfers a MyFish to another address. If transferring to a smart
/// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or
/// CryptoMyFish specifically) or your MyFish may be lost forever. Seriously.
/// @param _to The address of the recipient, can be a user or contract.
/// @param _tokenId The ID of the MyFish to transfer.
/// @dev Required for ERC-721 compliance.
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 MyFish .
require(_to != address(this));

// You can only send your own MyFish.
require(_owns(msg.sender, _tokenId));

// Reassign ownership, clear pending approvals, emit Transfer event.
_transfer(msg.sender, _to, _tokenId);
}

/// @notice Grant another address the right to transfer a specific MyFish via
/// transferFrom(). This is the preferred flow for transfering NFTs to contracts.
/// @param _to The address to be granted transfer approval. Pass address(0) to
/// clear all approvals.
/// @param _tokenId The ID of the MyFish that can be transferred if this call succeeds.
/// @dev Required for ERC-721 compliance.
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);
}

/// @notice Transfer a MyFish owned by another address, for which the calling address
/// has previously been granted transfer approval by the owner.
/// @param _from The address that owns the MyFish to be transfered.
/// @param _to The address that should take ownership of the MyFish. Can be any address,
/// including the caller.
/// @param _tokenId The ID of the MyFish to be transferred.
/// @dev Required for ERC-721 compliance.
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 MyFish (except very briefly
// after a MyFish 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);
}

/// @notice Returns the total number of MyFishes currently in existence.
/// @dev Required for ERC-721 compliance.
function totalSupply() public view returns (uint) {
return myFishes.length ;
}

/// @notice Returns the address currently assigned ownership of a given MyFish.
/// @dev Required for ERC-721 compliance.
function ownerOf(uint256 _tokenId)
external
view
returns (address owner)
{
owner = myFishIndexToOwner[_tokenId];

require(owner != address(0));
}

/// @notice Returns a list of all MyFish IDs assigned to an address.
/// @param _owner The owner whose MyFishes we are interested in.
/// @dev This method MUST NEVER be called by smart contract code. First, it’s fairly
/// expensive (it walks the entire MyFish array looking for MyFish belonging to owner),
/// but it also returns a dynamic array, which is only supported for web3 calls, and
/// not contract-to-contract calls.
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 totalMyFish = totalSupply();
uint256 resultIndex = 0;

// We count on the fact that all MyFish have IDs starting at 1 and increasing
// sequentially up to the totalMyFish count.
uint256 myFishId;

for (myFishId = 0; myFishId < totalMyFish; myFishId++) {
if (myFishIndexToOwner[myFishId] == _owner) {
result[resultIndex] = myFishId;
resultIndex++;
}
}

return result;
}
}

}

/// @title all functions related to creating MyFish
contract MyFishMinting is MyFishOwnership {

// Limits the number of genesis MyFish .
uint256 public constant GENESIS_CREATION_LIMIT = 100;

// Counts the number of genesis MyFish the contract owner has created.
uint256 public genesisCreatedCount = 0;

/// @dev we can create genesis MyFish, up to a limit. Only callable by COO
///
///
function createGenesisMyFish(uint myCount) public onlyCEO {
require(genesisCreatedCount < GENESIS_CREATION_LIMIT);
uint256 myFishId;

for (myFishId = 0; myFishId < myCount; myFishId++) {
require(genesisCreatedCount < GENESIS_CREATION_LIMIT);
_createMyFish(
0,
0,
0,
0,
0,0,0,0,0,
ceoAddress
);
genesisCreatedCount++;
}
}
}

/// @title CryptoMyFishes on the Ethereum blockchain.

/// @dev The main CryptoMyFishes contract, keeps track of MyFish so they don’t wander around and get lost.
contract MyFishCore is MyFishMinting {

/// @notice Creates the main MyFishes smart contract instance.
function MyFishCore() public {
// Starts paused.
// paused = true;

// the creator of the contract is the initial CEO
ceoAddress = msg.sender;

// the creator of the contract is also the initial COO
cooAddress = msg.sender;
cfoAddress = msg.sender;

}

/// @dev Used to mark the smart contract as upgraded, in case there is a serious
/// breaking bug. This method does nothing but keep track of the new contract and
/// emit a message indicating that the new address is set. It’s up to clients of this
/// contract to update to the new contract address in that case. (This contract will
/// be paused indefinitely if such an upgrade takes place.)
/// @param _v2Address new address
function setNewAddress(address _v2Address) external onlyCEO whenPaused {
// See README.md for updgrade plan
newContractAddress = _v2Address;
ContractUpgrade(_v2Address);
}

/// @notice Returns all the relevant information about a specific MyFish.
/// @param _id The ID of the MyFish of interest.
function getMyFish(uint256 _id)
external
view
returns (
uint8 level,
uint8 quality,
uint8 starlevel,
uint8 growup,
uint8 skill,
uint8 genius,
uint16 strength,
uint16 agility,
uint16 power,
bool eated
) {
MyFish storage fish = myFishes[_id];
level = fish.level;
quality = fish.quality;
starlevel = fish.starlevel;
growup = fish.growup;
skill = fish.skill;
genius = fish.genius;
strength = fish.strength;
agility = fish.agility;
power = fish.power;
eated = fish.eated;

}

// @dev Allows the CFO to capture the balance available to the contract.
function withdrawBalance() external onlyCFO {
uint256 balance = this.balance;
cfoAddress.send(balance);

}

event UpdateMyFish(uint id,uint8 level,uint8 quality,uint8 starlevel,uint8 growup, uint8 skill,uint8 genius,uint16 strength, uint16 agility, uint16 power, bool eated);

//@dev if level==0 or fish.level==0, do not change level
// if fish.level==0 ,do not eated
function updateMyFish(uint _id,uint8 _level,uint8 _quality,uint8 _starlevel,uint8 _growup, uint8 _skill,uint8 _genius, uint16 _strength, uint16 _agility, uint16 _power, bool _eated) public onlyCLevel {
require(myFishIndexToOwner[_id] != address(0));
MyFish storage fish = myFishes[_id];
require(fish.eated != true);
if( (fish.level !=0) && (_level != 0) ) {
fish.level = _level;
}
fish.quality = _quality;
fish.starlevel = _starlevel;
fish.growup = _growup;
fish.skill = _skill;
fish.genius = _genius;
fish.strength = _strength;
fish.agility = _agility;
fish.power = _power;
if (fish.level != 0) {
fish.eated = _eated;
}
UpdateMyFish(_id,_level,_quality,_starlevel,_growup,_skill,_genius,_strength,_agility,_power,_eated);
}

event SetEated(uint id);
//@dev if fish.level==0 ,do not set eated
function setEated(uint _id) public onlyCLevel {
require(myFishIndexToOwner[_id] != address(0));
MyFish storage fish = myFishes[_id];
require( (fish.level != 0) && (fish.eated != true) );
fish.eated=true;
// sub count of eatedFish owner
address tmp = myFishIndexToOwner[_id];
myFishIndexToOwner[_id] = address(0);
ownershipTokenCount[tmp]–;
SetEated(_id);
}

function checkId(uint _id,uint _eatedId) internal {
require( (myFishIndexToOwner[_id] != address(0)) && (myFishIndexToOwner[_eatedId] != address(0)) );
MyFish storage fish = myFishes[_id];
MyFish storage eatedFish = myFishes[_eatedId];
require( (fish.level != 0) && (eatedFish.level !=0) && (fish.eated==false) && (eatedFish.eated==false) );

}
function eat(uint _id,uint8 _level,uint8 _quality,uint8 _starlevel,uint8 _growup, uint8 _skill,uint8 _genius, uint16 _strength, uint16 _agility, uint16 _power,bool _eated, uint _eatedId) public onlyCLevel {
//address addr2=myFishIndexToOwner[_eatedId];
//address addr1=myFishIndexToOwner[_id];
//require((addr1 !=address(0))&&(addr2 != address(0)));
checkId(_id,_eatedId);

//require( (myFishIndexToOwner[_id] != address(0)) && (myFishIndexToOwner[_eatedId] != address(0)) );
updateMyFish(_id,_level,_quality,_starlevel,_growup,_skill,_genius,_strength,_agility,_power,_eated);
setEated(_eatedId);

}

function createMyFish(
uint8 _level,uint8 _quality,uint8 _starlevel,uint8 _growup, uint8 _skill,uint8 _genius, uint16 _strength, uint16 _agility, uint16 _power,
address _owner
) external onlyCLevel whenNotPaused returns (uint) {
require(_level != 0);
return _createMyFish(_level,_quality,_starlevel,_growup,_skill,_genius,_strength,_agility,_power,_owner);
}
}