ETH Price: $1,964.34 (-2.20%)

Transaction Decoder

Block:
6721679 at Nov-17-2018 02:13:49 PM +UTC
Transaction Fee:
0.000696501 ETH $1.37
Gas Used:
232,167 Gas / 3 Gwei

Emitted Events:

111 AdminUpgradeabilityProxy.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000fadae26458902e6eaf1415ec02151470a68f8137, 0x00000000000000000000000000000000000000000000000000000000000000c3 )
112 AdminUpgradeabilityProxy.0xef7878e56c319b18c7274f69dfa9e1fe9f0c506a36f37a6a24349f9c842f4a86( 0xef7878e56c319b18c7274f69dfa9e1fe9f0c506a36f37a6a24349f9c842f4a86, 0x000000000000000000000000fadae26458902e6eaf1415ec02151470a68f8137, 00000000000000000000000000000000000000000000000000000000000000d8, 00000000000000000000000000000000000000000000000000000000000000c3, 0000000000000000000000000000000000000000000000000000000000000003, 0000000000000000000000000000000000000000000000000000000000000006 )

Account State Difference:

  Address   Before After State Difference Code
(Spark Pool)
4,546.278951497786930781 Eth4,546.279647998786930781 Eth0.000696501
0x9db37d15...465841038
0xFaDaE264...0A68F8137
1.392033608350602067 Eth
Nonce: 4432
1.391337107350602067 Eth
Nonce: 4433
0.000696501

Execution Trace

AdminUpgradeabilityProxy.edb0d0b3( )
  • Weapons.claimWeaponOld( _chibiId=216 )
    • ChibiFighters.ownerOf( _tokenId=216 ) => ( 0xFaDaE26458902e6eaf1415ec02151470A68F8137 )
    • ChibiFighters.queryChibi( _tokenId=216 ) => ( nameChibi=Super%20Chibi, infoUrl=https://chibigame.io/chibis.php?idj=216, dna=[31, 31, 3, 31, 31, 31, 31, 6, 0, 4, 4, 5, 0], father=0, mother=0, gen=0, adult=1525127704 )
      File 1 of 3: AdminUpgradeabilityProxy
      pragma solidity ^0.4.24;
      
      // File: contracts/upgradeability/Proxy.sol
      
      /**
       * @title Proxy
       * @dev Implements delegation of calls to other contracts, with proper
       * forwarding of return values and bubbling of failures.
       * It defines a fallback function that delegates all calls to the address
       * returned by the abstract _implementation() internal function.
       */
      contract Proxy {
        /**
         * @dev Fallback function.
         * Implemented entirely in `_fallback`.
         */
        function () payable external {
          _fallback();
        }
      
        /**
         * @return The Address of the implementation.
         */
        function _implementation() internal view returns (address);
      
        /**
         * @dev Delegates execution to an implementation contract.
         * This is a low level function that doesn't return to its internal call site.
         * It will return to the external caller whatever the implementation returns.
         * @param implementation Address to delegate.
         */
        function _delegate(address implementation) internal {
          assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize)
      
            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
      
            // Copy the returned data.
            returndatacopy(0, 0, returndatasize)
      
            switch result
            // delegatecall returns 0 on error.
            case 0 { revert(0, returndatasize) }
            default { return(0, returndatasize) }
          }
        }
      
        /**
         * @dev Function that is run as the first thing in the fallback function.
         * Can be redefined in derived contracts to add functionality.
         * Redefinitions must call super._willFallback().
         */
        function _willFallback() internal {
        }
      
        /**
         * @dev fallback implementation.
         * Extracted to enable manual triggering.
         */
        function _fallback() internal {
          _willFallback();
          _delegate(_implementation());
        }
      }
      
      // File: openzeppelin-solidity/contracts/AddressUtils.sol
      
      /**
       * Utility library of inline functions on addresses
       */
      library AddressUtils {
      
        /**
         * Returns whether the target address is a contract
         * @dev This function will return false if invoked during the constructor of a contract,
         *  as the code is not actually created until after the constructor finishes.
         * @param addr address to check
         * @return whether the target address is a contract
         */
        function isContract(address addr) internal view returns (bool) {
          uint256 size;
          // XXX Currently there is no better way to check if there is a contract in an address
          // than to check the size of the code at that address.
          // See https://ethereum.stackexchange.com/a/14016/36603
          // for more details about how this works.
          // TODO Check this again before the Serenity release, because all addresses will be
          // contracts then.
          // solium-disable-next-line security/no-inline-assembly
          assembly { size := extcodesize(addr) }
          return size > 0;
        }
      
      }
      
      // File: contracts/upgradeability/UpgradeabilityProxy.sol
      
      /**
       * @title UpgradeabilityProxy
       * @dev This contract implements a proxy that allows to change the
       * implementation address to which it will delegate.
       * Such a change is called an implementation upgrade.
       */
      contract UpgradeabilityProxy is Proxy {
        /**
         * @dev Emitted when the implementation is upgraded.
         * @param implementation Address of the new implementation.
         */
        event Upgraded(address indexed implementation);
      
        /**
         * @dev Storage slot with the address of the current implementation.
         * This is the keccak-256 hash of "org.zeppelinos.proxy.implementation", and is
         * validated in the constructor.
         */
        bytes32 private constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;
      
        /**
         * @dev Contract constructor.
         * @param _implementation Address of the initial implementation.
         * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
         * It should include the signature and the parameters of the function to be called, as described in
         * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
         * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
         */
        constructor(address _implementation, bytes _data) public payable {
          assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation"));
          _setImplementation(_implementation);
          if(_data.length > 0) {
            require(_implementation.delegatecall(_data));
          }
        }
      
        /**
         * @dev Returns the current implementation.
         * @return Address of the current implementation
         */
        function _implementation() internal view returns (address impl) {
          bytes32 slot = IMPLEMENTATION_SLOT;
          assembly {
            impl := sload(slot)
          }
        }
      
        /**
         * @dev Upgrades the proxy to a new implementation.
         * @param newImplementation Address of the new implementation.
         */
        function _upgradeTo(address newImplementation) internal {
          _setImplementation(newImplementation);
          emit Upgraded(newImplementation);
        }
      
        /**
         * @dev Sets the implementation address of the proxy.
         * @param newImplementation Address of the new implementation.
         */
        function _setImplementation(address newImplementation) private {
          require(AddressUtils.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
      
          bytes32 slot = IMPLEMENTATION_SLOT;
      
          assembly {
            sstore(slot, newImplementation)
          }
        }
      }
      
      // File: contracts/upgradeability/AdminUpgradeabilityProxy.sol
      
      /**
       * @title AdminUpgradeabilityProxy
       * @dev This contract combines an upgradeability proxy with an authorization
       * mechanism for administrative tasks.
       * All external functions in this contract must be guarded by the
       * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity
       * feature proposal that would enable this to be done automatically.
       */
      contract AdminUpgradeabilityProxy is UpgradeabilityProxy {
        /**
         * @dev Emitted when the administration has been transferred.
         * @param previousAdmin Address of the previous admin.
         * @param newAdmin Address of the new admin.
         */
        event AdminChanged(address previousAdmin, address newAdmin);
      
        /**
         * @dev Storage slot with the admin of the contract.
         * This is the keccak-256 hash of "org.zeppelinos.proxy.admin", and is
         * validated in the constructor.
         */
        bytes32 private constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b;
      
        /**
         * @dev Modifier to check whether the `msg.sender` is the admin.
         * If it is, it will run the function. Otherwise, it will delegate the call
         * to the implementation.
         */
        modifier ifAdmin() {
          if (msg.sender == _admin()) {
            _;
          } else {
            _fallback();
          }
        }
      
        /**
         * Contract constructor.
         * It sets the `msg.sender` as the proxy administrator.
         * @param _implementation address of the initial implementation.
         * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
         * It should include the signature and the parameters of the function to be called, as described in
         * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
         * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
         */
        constructor(address _implementation, bytes _data) UpgradeabilityProxy(_implementation, _data) public payable {
          assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin"));
      
          _setAdmin(msg.sender);
        }
      
        /**
         * @return The address of the proxy admin.
         */
        function admin() external view ifAdmin returns (address) {
          return _admin();
        }
      
        /**
         * @return The address of the implementation.
         */
        function implementation() external view ifAdmin returns (address) {
          return _implementation();
        }
      
        /**
         * @dev Changes the admin of the proxy.
         * Only the current admin can call this function.
         * @param newAdmin Address to transfer proxy administration to.
         */
        function changeAdmin(address newAdmin) external ifAdmin {
          require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
          emit AdminChanged(_admin(), newAdmin);
          _setAdmin(newAdmin);
        }
      
        /**
         * @dev Upgrade the backing implementation of the proxy.
         * Only the admin can call this function.
         * @param newImplementation Address of the new implementation.
         */
        function upgradeTo(address newImplementation) external ifAdmin {
          _upgradeTo(newImplementation);
        }
      
        /**
         * @dev Upgrade the backing implementation of the proxy and call a function
         * on the new implementation.
         * This is useful to initialize the proxied contract.
         * @param newImplementation Address of the new implementation.
         * @param data Data to send as msg.data in the low level call.
         * It should include the signature and the parameters of the function to be called, as described in
         * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
         */
        function upgradeToAndCall(address newImplementation, bytes data) payable external ifAdmin {
          _upgradeTo(newImplementation);
          require(newImplementation.delegatecall(data));
        }
      
        /**
         * @return The admin slot.
         */
        function _admin() internal view returns (address adm) {
          bytes32 slot = ADMIN_SLOT;
          assembly {
            adm := sload(slot)
          }
        }
      
        /**
         * @dev Sets the address of the proxy admin.
         * @param newAdmin Address of the new proxy admin.
         */
        function _setAdmin(address newAdmin) internal {
          bytes32 slot = ADMIN_SLOT;
      
          assembly {
            sstore(slot, newAdmin)
          }
        }
      
        /**
         * @dev Only fall back when the sender is not the admin.
         */
        function _willFallback() internal {
          require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
          super._willFallback();
        }
      }

      File 2 of 3: Weapons
      pragma solidity ^0.4.24;
      
      /**
       * @title Initializable
       *
       * @dev Helper contract to support initializer functions. To use it, replace
       * the constructor with a function that has the `initializer` modifier.
       * WARNING: Unlike constructors, initializer functions must be manually
       * invoked. This applies both to deploying an Initializable contract, as well
       * as extending an Initializable contract via inheritance.
       * WARNING: When used with inheritance, manual care must be taken to not invoke
       * a parent initializer twice, or ensure that all initializers are idempotent,
       * because this is not dealt with automatically as with constructors.
       */
      contract Initializable {
      
        /**
         * @dev Indicates that the contract has been initialized.
         */
        bool private initialized;
      
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool private initializing;
      
        /**
         * @dev Modifier to use in the initializer function of a contract.
         */
        modifier initializer() {
      	require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
      
      	bool wasInitializing = initializing;
      	initializing = true;
      	initialized = true;
      
      	_;
      
      	initializing = wasInitializing;
        }
      
        /// @dev Returns true if and only if the function is running in the constructor
        function isConstructor() private view returns (bool) {
      	// extcodesize checks the size of the code stored in an address, and
      	// address returns the current address. Since the code is still not
      	// deployed when running a constructor, any checks on its code size will
      	// yield zero, making it an effective way to detect if a contract is
      	// under construction or not.
      	uint256 cs;
      	assembly { cs := extcodesize(address) }
      	return cs == 0;
        }
      
        // Reserved storage space to allow for layout changes in the future.
        uint256[50] private ______gap;
      }
      
      
      /**
      * @title IERC165
      * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
      */
      interface IERC165 {
      
      /**
      * @notice Query if a contract implements an interface
      * @param interfaceId The interface identifier, as specified in ERC-165
      * @dev Interface identification is specified in ERC-165. This function
      * uses less than 30,000 gas.
      */
      function supportsInterface(bytes4 interfaceId)
      	external
      	view
      	returns (bool);
      }
      
      /**
      * @title ERC165
      * @author Matt Condon (@shrugs)
      * @dev Implements ERC165 using a lookup table.
      */
      contract ERC165 is IERC165, Initializable {
      
      bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7;
      /**
      * 0x01ffc9a7 ===
      *   bytes4(keccak256('supportsInterface(bytes4)'))
      */
      
      /**
      * @dev a mapping of interface id to whether or not it's supported
      */
      mapping(bytes4 => bool) internal _supportedInterfaces;
      
      /**
      * @dev A contract implementing SupportsInterfaceWithLookup
      * implement ERC165 itself
      */
      function initialize() initializer public {
      	_registerInterface(_InterfaceId_ERC165);
      }
      
      /**
      * @dev implement supportsInterface(bytes4) using a lookup table
      */
      function supportsInterface(bytes4 interfaceId)
      	external
      	view
      	returns (bool)
      {
      	return _supportedInterfaces[interfaceId];
      }
      
      /**
      * @dev private method for registering an interface
      */
      function _registerInterface(bytes4 interfaceId)
      	internal
      {
      	require(interfaceId != 0xffffffff);
      	_supportedInterfaces[interfaceId] = true;
      }
      }
      
      // import "./ERC721.sol";
      
      // import "./IERC721.sol";
      
      // import "../../introspection/IERC165.sol";
      
      /**
      * @title ERC721 Non-Fungible Token Standard basic interface
      * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
      */
      contract IERC721 is IERC165 {
      
      event Transfer(
      	address indexed from,
      	address indexed to,
      	uint256 indexed tokenId
      );
      event Approval(
      	address indexed owner,
      	address indexed approved,
      	uint256 indexed tokenId
      );
      event ApprovalForAll(
      	address indexed owner,
      	address indexed operator,
      	bool approved
      );
      
      function balanceOf(address owner) public view returns (uint256 balance);
      function ownerOf(uint256 tokenId) public view returns (address owner);
      
      function approve(address to, uint256 tokenId) public;
      function getApproved(uint256 tokenId)
      	public view returns (address operator);
      
      function setApprovalForAll(address operator, bool _approved) public;
      function isApprovedForAll(address owner, address operator)
      	public view returns (bool);
      
      function transferFrom(address from, address to, uint256 tokenId) public;
      function safeTransferFrom(address from, address to, uint256 tokenId)
      	public;
      
      function safeTransferFrom(
      	address from,
      	address to,
      	uint256 tokenId,
      	bytes data
      )
      	public;
      }
      // import "./IERC721Receiver.sol";
      
      /**
      * @title ERC721 token receiver interface
      * @dev Interface for any contract that wants to support safeTransfers
      * from ERC721 asset contracts.
      */
      contract IERC721Receiver {
      /**
      * @notice Handle the receipt of an NFT
      * @dev The ERC721 smart contract calls this function on the recipient
      * after a `safeTransfer`. This function MUST return the function selector,
      * otherwise the caller will revert the transaction. The selector to be
      * returned can be obtained as `this.onERC721Received.selector`. This
      * function MAY throw to revert and reject the transfer.
      * Note: the ERC721 contract address is always the message sender.
      * @param operator The address which called `safeTransferFrom` function
      * @param from The address which previously owned the token
      * @param tokenId The NFT identifier which is being transferred
      * @param data Additional data with no specified format
      * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
      */
      function onERC721Received(
      	address operator,
      	address from,
      	uint256 tokenId,
      	bytes data
      )
      	public
      	returns(bytes4);
      }
      
      
      // import "../../math/SafeMath.sol";
      
      /**
      * @title SafeMath
      * @dev Math operations with safety checks that revert on error
      */
      library SafeMath {
      
      /**
      * @dev Multiplies two numbers, reverts on overflow.
      */
      function mul(uint256 a, uint256 b) internal pure returns (uint256) {
      	// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
      	// benefit is lost if 'b' is also tested.
      	// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
      	if (a == 0) {
      	return 0;
      	}
      
      	uint256 c = a * b;
      	require(c / a == b);
      
      	return c;
      }
      
      /**
      * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
      */
      function div(uint256 a, uint256 b) internal pure returns (uint256) {
      	require(b > 0);// Solidity only automatically asserts when dividing by 0
      	uint256 c = a / b;
      	// assert(a == b * c + a % b);// There is no case in which this doesn't hold
      
      	return c;
      }
      
      /**
      * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
      */
      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
      	require(b <= a);
      	uint256 c = a - b;
      
      	return c;
      }
      
      /**
      * @dev Adds two numbers, reverts on overflow.
      */
      function add(uint256 a, uint256 b) internal pure returns (uint256) {
      	uint256 c = a + b;
      	require(c >= a);
      
      	return c;
      }
      
      /**
      * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
      * reverts when dividing by zero.
      */
      function mod(uint256 a, uint256 b) internal pure returns (uint256) {
      	require(b != 0);
      	return a % b;
      }
      }
      // import "../../utils/Address.sol";
      
      /**
      * Utility library of inline functions on addresses
      */
      library Address {
      
      /**
      * Returns whether the target address is a contract
      * @dev This function will return false if invoked during the constructor of a contract,
      * as the code is not actually created until after the constructor finishes.
      * @param account address of the account to check
      * @return whether the target address is a contract
      */
      function isContract(address account) internal view returns (bool) {
      	uint256 size;
      	// XXX Currently there is no better way to check if there is a contract in an address
      	// than to check the size of the code at that address.
      	// See https://ethereum.stackexchange.com/a/14016/36603
      	// for more details about how this works.
      	// TODO Check this again before the Serenity release, because all addresses will be
      	// contracts then.
      	// solium-disable-next-line security/no-inline-assembly
      	assembly { size := extcodesize(account) }
      	return size > 0;
      }
      
      }
      
      /**
      * @title ERC721 Non-Fungible Token Standard basic implementation
      * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
      */
      contract ERC721 is ERC165, IERC721 {
      
      using SafeMath for uint256;
      using Address for address;
      
      // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
      // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
      bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
      
      // Mapping from token ID to owner
      mapping (uint256 => address) private _tokenOwner;
      
      // Mapping from token ID to approved address
      mapping (uint256 => address) private _tokenApprovals;
      
      // Mapping from owner to number of owned token
      mapping (address => uint256) private _ownedTokensCount;
      
      // Mapping from owner to operator approvals
      mapping (address => mapping (address => bool)) private _operatorApprovals;
      
      bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd;
      /*
      * 0x80ac58cd ===
      *   bytes4(keccak256('balanceOf(address)')) ^
      *   bytes4(keccak256('ownerOf(uint256)')) ^
      *   bytes4(keccak256('approve(address,uint256)')) ^
      *   bytes4(keccak256('getApproved(uint256)')) ^
      *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^
      *   bytes4(keccak256('isApprovedForAll(address,address)')) ^
      *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^
      *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
      *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
      */
      
      function initialize() initializer public {
      	// register the supported interfaces to conform to ERC721 via ERC165
      	_registerInterface(_InterfaceId_ERC721);
      }
      
      /**
      * @dev Gets the balance of the specified address
      * @param owner address to query the balance of
      * @return uint256 representing the amount owned by the passed address
      */
      function balanceOf(address owner) public view returns (uint256) {
      	require(owner != address(0));
      	return _ownedTokensCount[owner];
      }
      
      /**
      * @dev Gets the owner of the specified token ID
      * @param tokenId uint256 ID of the token to query the owner of
      * @return owner address currently marked as the owner of the given token ID
      */
      function ownerOf(uint256 tokenId) public view returns (address) {
      	address owner = _tokenOwner[tokenId];
      	require(owner != address(0));
      	return owner;
      }
      
      /**
      * @dev Approves another address to transfer the given token ID
      * The zero address indicates there is no approved address.
      * There can only be one approved address per token at a given time.
      * Can only be called by the token owner or an approved operator.
      * @param to address to be approved for the given token ID
      * @param tokenId uint256 ID of the token to be approved
      */
      function approve(address to, uint256 tokenId) public {
      	address owner = ownerOf(tokenId);
      	require(to != owner);
      	require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
      
      	_tokenApprovals[tokenId] = to;
      	emit Approval(owner, to, tokenId);
      }
      
      /**
      * @dev Gets the approved address for a token ID, or zero if no address set
      * Reverts if the token ID does not exist.
      * @param tokenId uint256 ID of the token to query the approval of
      * @return address currently approved for the given token ID
      */
      function getApproved(uint256 tokenId) public view returns (address) {
      	require(_exists(tokenId));
      	return _tokenApprovals[tokenId];
      }
      
      /**
      * @dev Sets or unsets the approval of a given operator
      * An operator is allowed to transfer all tokens of the sender on their behalf
      * @param to operator address to set the approval
      * @param approved representing the status of the approval to be set
      */
      function setApprovalForAll(address to, bool approved) public {
      	require(to != msg.sender);
      	_operatorApprovals[msg.sender][to] = approved;
      	emit ApprovalForAll(msg.sender, to, approved);
      }
      
      /**
      * @dev Tells whether an operator is approved by a given owner
      * @param owner owner address which you want to query the approval of
      * @param operator operator address which you want to query the approval of
      * @return bool whether the given operator is approved by the given owner
      */
      function isApprovedForAll(
      	address owner,
      	address operator
      )
      	public
      	view
      	returns (bool)
      {
      	return _operatorApprovals[owner][operator];
      }
      
      /**
      * @dev Transfers the ownership of a given token ID to another address
      * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
      * Requires the msg sender to be the owner, approved, or operator
      * @param from current owner of the token
      * @param to address to receive the ownership of the given token ID
      * @param tokenId uint256 ID of the token to be transferred
      */
      function transferFrom(
      	address from,
      	address to,
      	uint256 tokenId
      )
      	public
      {
      	require(_isApprovedOrOwner(msg.sender, tokenId));
      	require(to != address(0));
      
      	_clearApproval(from, tokenId);
      	_removeTokenFrom(from, tokenId);
      	_addTokenTo(to, tokenId);
      
      	emit Transfer(from, to, tokenId);
      }
      
      /**
      * @dev Safely transfers the ownership of a given token ID to another address
      * If the target address is a contract, it must implement `onERC721Received`,
      * which is called upon a safe transfer, and return the magic value
      * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;otherwise,
      * the transfer is reverted.
      *
      * Requires the msg sender to be the owner, approved, or operator
      * @param from current owner of the token
      * @param to address to receive the ownership of the given token ID
      * @param tokenId uint256 ID of the token to be transferred
      */
      function safeTransferFrom(
      	address from,
      	address to,
      	uint256 tokenId
      )
      	public
      {
      	// solium-disable-next-line arg-overflow
      	safeTransferFrom(from, to, tokenId, "");
      }
      
      /**
      * @dev Safely transfers the ownership of a given token ID to another address
      * If the target address is a contract, it must implement `onERC721Received`,
      * which is called upon a safe transfer, and return the magic value
      * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;otherwise,
      * the transfer is reverted.
      * Requires the msg sender to be the owner, approved, or operator
      * @param from current owner of the token
      * @param to address to receive the ownership of the given token ID
      * @param tokenId uint256 ID of the token to be transferred
      * @param _data bytes data to send along with a safe transfer check
      */
      function safeTransferFrom(
      	address from,
      	address to,
      	uint256 tokenId,
      	bytes _data
      )
      	public
      {
      	transferFrom(from, to, tokenId);
      	// solium-disable-next-line arg-overflow
      	require(_checkAndCallSafeTransfer(from, to, tokenId, _data));
      }
      
      /**
      * @dev Returns whether the specified token exists
      * @param tokenId uint256 ID of the token to query the existence of
      * @return whether the token exists
      */
      function _exists(uint256 tokenId) internal view returns (bool) {
      	address owner = _tokenOwner[tokenId];
      	return owner != address(0);
      }
      
      /**
      * @dev Returns whether the given spender can transfer a given token ID
      * @param spender address of the spender to query
      * @param tokenId uint256 ID of the token to be transferred
      * @return bool whether the msg.sender is approved for the given token ID,
      *  is an operator of the owner, or is the owner of the token
      */
      function _isApprovedOrOwner(
      	address spender,
      	uint256 tokenId
      )
      	internal
      	view
      	returns (bool)
      {
      	address owner = ownerOf(tokenId);
      	// Disable solium check because of
      	// https://github.com/duaraghav8/Solium/issues/175
      	// solium-disable-next-line operator-whitespace
      	return (
      	spender == owner ||
      	getApproved(tokenId) == spender ||
      	isApprovedForAll(owner, spender)
      	);
      }
      
      /**
      * @dev Internal function to mint a new token
      * Reverts if the given token ID already exists
      * @param to The address that will own the minted token
      * @param tokenId uint256 ID of the token to be minted by the msg.sender
      */
      function _mint(address to, uint256 tokenId) internal {
      	require(to != address(0));
      	_addTokenTo(to, tokenId);
      	emit Transfer(address(0), to, tokenId);
      }
      
      /**
      * @dev Internal function to burn a specific token
      * Reverts if the token does not exist
      * @param tokenId uint256 ID of the token being burned by the msg.sender
      */
      function _burn(address owner, uint256 tokenId) internal {
      	_clearApproval(owner, tokenId);
      	_removeTokenFrom(owner, tokenId);
      	emit Transfer(owner, address(0), tokenId);
      }
      
      /**
      * @dev Internal function to clear current approval of a given token ID
      * Reverts if the given address is not indeed the owner of the token
      * @param owner owner of the token
      * @param tokenId uint256 ID of the token to be transferred
      */
      function _clearApproval(address owner, uint256 tokenId) internal {
      	require(ownerOf(tokenId) == owner);
      	if (_tokenApprovals[tokenId] != address(0)) {
      	_tokenApprovals[tokenId] = address(0);
      	}
      }
      
      /**
      * @dev Internal function to add a token ID to the list of a given address
      * @param to address representing the new owner of the given token ID
      * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
      */
      function _addTokenTo(address to, uint256 tokenId) internal {
      	require(_tokenOwner[tokenId] == address(0));
      	_tokenOwner[tokenId] = to;
      	_ownedTokensCount[to] = _ownedTokensCount[to].add(1);
      }
      
      /**
      * @dev Internal function to remove a token ID from the list of a given address
      * @param from address representing the previous owner of the given token ID
      * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
      */
      function _removeTokenFrom(address from, uint256 tokenId) internal {
      	require(ownerOf(tokenId) == from);
      	_ownedTokensCount[from] = _ownedTokensCount[from].sub(1);
      	_tokenOwner[tokenId] = address(0);
      }
      
      /**
      * @dev Internal function to invoke `onERC721Received` on a target address
      * The call is not executed if the target address is not a contract
      * @param from address representing the previous owner of the given token ID
      * @param to target address that will receive the tokens
      * @param tokenId uint256 ID of the token to be transferred
      * @param _data bytes optional data to send along with the call
      * @return whether the call correctly returned the expected magic value
      */
      function _checkAndCallSafeTransfer(
      	address from,
      	address to,
      	uint256 tokenId,
      	bytes _data
      )
      	internal
      	returns (bool)
      {
      	if (!to.isContract()) {
      	return true;
      	}
      	bytes4 retval = IERC721Receiver(to).onERC721Received(
      	msg.sender, from, tokenId, _data);
      	return (retval == _ERC721_RECEIVED);
      }
      }
      
      //import "./ERC721Enumerable.sol";
      
      // import "./IERC721Enumerable.sol";
      
      // import "./IERC721.sol";
      
      /**
      * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
      * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
      */
      contract IERC721Enumerable is IERC721 {
      function totalSupply() public view returns (uint256);
      function tokenOfOwnerByIndex(
      	address owner,
      	uint256 index
      )
      	public
      	view
      	returns (uint256 tokenId);
      
      function tokenByIndex(uint256 index) public view returns (uint256);
      }
      
      // import "./ERC721.sol";
      // import "../../introspection/ERC165.sol";
      
      contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable {
      // Mapping from owner to list of owned token IDs
      mapping(address => uint256[]) private _ownedTokens;
      
      // Mapping from token ID to index of the owner tokens list
      mapping(uint256 => uint256) private _ownedTokensIndex;
      
      // Array with all token ids, used for enumeration
      uint256[] private _allTokens;
      
      // Mapping from token id to position in the allTokens array
      mapping(uint256 => uint256) private _allTokensIndex;
      
      bytes4 private constant _InterfaceId_ERC721Enumerable = 0x780e9d63;
      /**
      * 0x780e9d63 ===
      *   bytes4(keccak256('totalSupply()')) ^
      *   bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
      *   bytes4(keccak256('tokenByIndex(uint256)'))
      */
      
      /**
      * @dev Constructor function
      */
      function initialize() initializer public {
      	// register the supported interface to conform to ERC721 via ERC165
      	_registerInterface(_InterfaceId_ERC721Enumerable);
      }
      
      /**
      * @dev Gets the token ID at a given index of the tokens list of the requested owner
      * @param owner address owning the tokens list to be accessed
      * @param index uint256 representing the index to be accessed of the requested tokens list
      * @return uint256 token ID at the given index of the tokens list owned by the requested address
      */
      function tokenOfOwnerByIndex(
      	address owner,
      	uint256 index
      )
      	public
      	view
      	returns (uint256)
      {
      	require(index < balanceOf(owner));
      	return _ownedTokens[owner][index];
      }
      
      /**
      * @dev Gets the total amount of tokens stored by the contract
      * @return uint256 representing the total amount of tokens
      */
      function totalSupply() public view returns (uint256) {
      	return _allTokens.length;
      }
      
      /**
      * @dev Gets the token ID at a given index of all the tokens in this contract
      * Reverts if the index is greater or equal to the total number of tokens
      * @param index uint256 representing the index to be accessed of the tokens list
      * @return uint256 token ID at the given index of the tokens list
      */
      function tokenByIndex(uint256 index) public view returns (uint256) {
      	require(index < totalSupply());
      	return _allTokens[index];
      }
      
      /**
      * @dev Internal function to add a token ID to the list of a given address
      * @param to address representing the new owner of the given token ID
      * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
      */
      function _addTokenTo(address to, uint256 tokenId) internal {
      	super._addTokenTo(to, tokenId);
      	uint256 length = _ownedTokens[to].length;
      	_ownedTokens[to].push(tokenId);
      	_ownedTokensIndex[tokenId] = length;
      }
      
      /**
      * @dev Internal function to remove a token ID from the list of a given address
      * @param from address representing the previous owner of the given token ID
      * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
      */
      function _removeTokenFrom(address from, uint256 tokenId) internal {
      	super._removeTokenFrom(from, tokenId);
      
      	// To prevent a gap in the array, we store the last token in the index of the token to delete, and
      	// then delete the last slot.
      	uint256 tokenIndex = _ownedTokensIndex[tokenId];
      	uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
      	uint256 lastToken = _ownedTokens[from][lastTokenIndex];
      
      	_ownedTokens[from][tokenIndex] = lastToken;
      	// This also deletes the contents at the last position of the array
      	_ownedTokens[from].length--;
      
      	// Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to
      	// be zero. Then we can make sure that we will remove tokenId from the ownedTokens list since we are first swapping
      	// the lastToken to the first position, and then dropping the element placed in the last position of the list
      
      	_ownedTokensIndex[tokenId] = 0;
      	_ownedTokensIndex[lastToken] = tokenIndex;
      }
      
      /**
      * @dev Internal function to mint a new token
      * Reverts if the given token ID already exists
      * @param to address the beneficiary that will own the minted token
      * @param tokenId uint256 ID of the token to be minted by the msg.sender
      */
      function _mint(address to, uint256 tokenId) internal {
      	super._mint(to, tokenId);
      
      	_allTokensIndex[tokenId] = _allTokens.length;
      	_allTokens.push(tokenId);
      }
      
      /**
      * @dev Internal function to burn a specific token
      * Reverts if the token does not exist
      * @param owner owner of the token to burn
      * @param tokenId uint256 ID of the token being burned by the msg.sender
      */
      function _burn(address owner, uint256 tokenId) internal {
      	super._burn(owner, tokenId);
      
      	// Reorg all tokens array
      	uint256 tokenIndex = _allTokensIndex[tokenId];
      	uint256 lastTokenIndex = _allTokens.length.sub(1);
      	uint256 lastToken = _allTokens[lastTokenIndex];
      
      	_allTokens[tokenIndex] = lastToken;
      	_allTokens[lastTokenIndex] = 0;
      
      	_allTokens.length--;
      	_allTokensIndex[tokenId] = 0;
      	_allTokensIndex[lastToken] = tokenIndex;
      }
      }
      
      // import "./ERC721Metadata.sol";
      
      // import "./IERC721Metadata.sol";
      
      // import "./IERC721.sol";
      
      
      /**
       * @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 is Initializable {
        address private _owner;
      
        event OwnershipRenounced(address indexed previousOwner);
        event OwnershipTransferred(
      	address indexed previousOwner,
      	address indexed newOwner
        );
      
        /**
         * @dev The Ownable constructor sets the original `owner` of the contract to the sender
         * account.
         */
      	function initialize(address addr) initializer public {
      		// can not be same as deployer!
      		_owner = addr;
      		
        }
      
        /**
         * @return the address of the owner.
         */
        function owner() public view returns(address) {
      	return _owner;
        }
      
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier contract_onlyOwner() {
      	require(isOwner());
      	_;
        }
      
        /**
         * @return true if `msg.sender` is the owner of the contract.
         */
        function isOwner() public view returns(bool) {
      	return msg.sender == _owner;
        }
      
        /**
         * @dev Allows the current owner to relinquish control of the contract.
         * @notice Renouncing to ownership will leave the contract without an owner.
         * It will not be possible to call the functions with the `onlyOwner`
         * modifier anymore.
         */
        function renounceOwnership() public contract_onlyOwner {
      	emit OwnershipRenounced(_owner);
      	_owner = address(0);
        }
      
        /**
         * @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) public contract_onlyOwner {
      	_transferOwnership(newOwner);
        }
      
        /**
         * @dev Transfers control of the contract to a newOwner.
         * @param newOwner The address to transfer ownership to.
         */
        function _transferOwnership(address newOwner) internal {
      	require(newOwner != address(0));
      	emit OwnershipTransferred(_owner, newOwner);
      	_owner = newOwner;
        }
      }
      
      
      /**
      * @title Helper to allow various addresses to mint Chibis
      * @dev Adds addresses to mapping that can be true/false queried
      */
      contract MintWallets is Ownable {
      	mapping (address => bool) internal _mintWallets;
      	
      	function initialize(address addr) initializer public {
      		_mintWallets[msg.sender] = true;
      		_mintWallets[addr] = true;
      	}
      	
      	/**
      	* @dev Add a wallet/contract to the mint function functionality
      	* @param _address The address/contract to allow minting 
      	*/
      	function setMintAddress(address _address, bool _active) public contract_onlyOwner {
      		_mintWallets[_address] = _active;
      	}
      
      	/**
      	* @dev Check if wallet is true/false
      	* @param _address The address/contract to check
      	*/
      	function checkMintAllowed(address _address) public view returns (bool) {
      		return _mintWallets[_address];
      	}
      	
      	/**
      	* @dev Throws if called by any account other than the owner.
      	*/
      	modifier mintAllowed(address _address) {
      		require(_mintWallets[_address]);
      		_;
      	}
      }
      
      
      
      /**
      * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
      * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
      */
      contract IERC721Metadata is IERC721 {
      function name() external view returns (string);
      function symbol() external view returns (string);
      function tokenURI(uint256 tokenId) public view returns (string);
      }
      // import "../../introspection/ERC165.sol";
      
      contract ERC721Metadata is ERC165, ERC721, IERC721Metadata, MintWallets {
      // Token name
      string internal _name;
      
      // Token symbol
      string internal _symbol;
      
      string infoUrlPrefix;
      
      
      bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f;
      /**
      * 0x5b5e139f ===
      *   bytes4(keccak256('name()')) ^
      *   bytes4(keccak256('symbol()')) ^
      *   bytes4(keccak256('tokenURI(uint256)'))
      */
      
      /**
      * @dev Constructor function
      */
      function initialize(string name, string symbol) initializer public {
      	_name = name;
      	_symbol = symbol;
      
      	// register the supported interfaces to conform to ERC721 via ERC165
      	_registerInterface(InterfaceId_ERC721Metadata);
      }
      
      /**
      * @dev Gets the token name
      * @return string representing the token name
      */
      function name() external view returns (string) {
      	return _name;
      }
      
      /**
      * @dev Gets the token symbol
      * @return string representing the token symbol
      */
      function symbol() external view returns (string) {
      	return _symbol;
      }
      
      /**
      * @dev Returns an URI for a given token ID
      * Throws if the token ID does not exist. May return an empty string.
      * @param tokenId uint256 ID of the token to query
      */
      function tokenURI(uint256 tokenId) public view returns (string) {
      	require(_exists(tokenId));
      	string memory uri = strConcat(infoUrlPrefix, uint2str(tokenId));
      	return uri;
      }
      
      
      /**
      * @dev Internal function to burn a specific token
      * Reverts if the token does not exist
      * @param owner owner of the token to burn
      * @param tokenId uint256 ID of the token being burned by the msg.sender
      */
      function _burn(address owner, uint256 tokenId) internal {
      	super._burn(owner, tokenId);
      }
      
      	// set info url for weapons
      	function setInfoUrl(string _url) public contract_onlyOwner returns(bool success) {
      		infoUrlPrefix = _url;
      		return true;
      	}
      	
      
      	/**
      	 * 
      	 * Helper stuff
      	 * 
      	 **/
      	 
      	function stringToBytes32(string memory source) internal pure returns (bytes32 result) {
      		bytes memory tempEmptyStringTest = bytes(source);
      		if (tempEmptyStringTest.length == 0) {
      			return 0x0;
      		}
      	
      		assembly {
      			result := mload(add(source, 32))
      		}
      	}
      	
      	function strConcat(string _a, string _b) internal pure returns (string) {
      		return strConcatDoIt(_a, _b, "", "", "");
      	}
      	
      	function strConcatDoIt(string _a, string _b, string _c, string _d, string _e) internal pure returns (string) {
      		bytes memory _ba = bytes(_a);
      		bytes memory _bb = bytes(_b);
      		bytes memory _bc = bytes(_c);
      		bytes memory _bd = bytes(_d);
      		bytes memory _be = bytes(_e);
      		string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length);
      		bytes memory babcde = bytes(abcde);
      		uint k = 0;
      		for (uint i = 0;i < _ba.length;i++) babcde[k++] = _ba[i];
      		for (i = 0;i < _bb.length;i++) babcde[k++] = _bb[i];
      		for (i = 0;i < _bc.length;i++) babcde[k++] = _bc[i];
      		for (i = 0;i < _bd.length;i++) babcde[k++] = _bd[i];
      		for (i = 0;i < _be.length;i++) babcde[k++] = _be[i];
      		return string(babcde);
      	}
      	
      	function uint2str(uint i) internal pure returns (string){
      		if (i == 0) return "0";
      		uint j = i;
      		uint len;
      		while (j != 0){
      			len++;
      			j /= 10;
      		}
      		bytes memory bstr = new bytes(len);
      		uint k = len - 1;
      		while (i != 0){
      			bstr[k--] = byte(48 + i % 10);
      			i /= 10;
      		}
      		return string(bstr);
      	}
      
      	function bytesToUint(bytes b) internal pure returns (uint256) {
      	  require(b.length == 32);
      
      	  bytes32 out;
      
      	  for (uint i = 0;i < 32;i++) {
      		out |= bytes32(b[i] & 0xFF) >> (i * 8);
      	  }
      
      	  return uint256(out);
      	}
      	
      	
      }
      
      /**
      * @title Full ERC721 Token
      * This implementation includes all the required and some optional functionality of the ERC721 standard
      * Moreover, it includes approve all functionality using operator terminology
      * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
      */
      contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata {
      	
      	string name;
      	string symbol;
      		
      	function initialize() initializer public {
      		name = 'weapons';
      		symbol = 'CBW';
      		ERC721Metadata.initialize(name, symbol);
      	}
      
      }
      
      
      interface ERC20InterfaceClassic {
      	function transfer(address to, uint tokens) external returns (bool success);
      }
      
      interface ERC20Interface {
      	function transferFrom(address from, address to, uint tokens) external returns (bool success);
      	function transfer(address to, uint tokens) external;
      	function balanceOf(address _owner) external view returns (uint256 _balance);
      }
      
      
      contract Referral is Ownable {
      	
      	uint refIdCounter;
      	uint refCutPerc;
      	
      	mapping (address => uint) refId;
      	mapping (uint => address) refIdAddress;
      	mapping (uint => uint) refCut;
      	mapping (uint => uint) refIdAvail;
      
      	event RefPaid(uint refId, address indexed refOwner, uint amount);
      	event RefCreated(uint refId, address indexed wallet);
      	
      	function initialize() initializer public {
      		refIdCounter = 400;
      		refCutPerc = 12;
      	}
      
      	// creates a new refid if address has none
          function createRefId() public {
              require(refId[msg.sender] == 0);
              
              refIdCounter++;
              refId[msg.sender] = refIdCounter;
              refIdAddress[refIdCounter] = msg.sender;
              refCut[refIdCounter] = refCutPerc;
      
      		emit RefCreated(refIdCounter, msg.sender);
          }
          
          function setRefCut(uint _refId, uint _cut) public contract_onlyOwner {
              refCut[_refId] = _cut;
          }
          
          // user can query his own ref data, not that of others
          function queryRefId() public view returns(uint _refId, uint _refCut, address _address) {
              uint _id = refId[msg.sender];
              return (_id, refCut[_id], refIdAddress[_id]);
          }
      	
      }
      
      
      contract WeaponGenesInterface {
      	function generateData(uint _tokenId) public view returns (uint, uint);
      	function generateRareMythicData(uint _tokenId) public view returns (uint);
      	function generateLegendaryData(uint _tokenId) public view returns (uint);
      }
      
      
      // new and old chibi contract
      contract ChibiInterface {
      	function queryChibiDNA(uint) public pure returns (
      		uint16[13]
      		) {}
      
      	function ownerOf(uint256) public pure returns (address) {}
      	
      	// legacy support old chibi contract
      	function queryChibi(uint) public pure returns (
      		string,
      		string,
      		uint16[13],
      		uint256,
      		uint256,
      		uint,
      		uint
      		) {}
      	
      }
      
      
      /**
       *  Weapons for Chibis
       *  
       */
      contract Weapons is ERC721Full, Referral {
      	
      	// couple events
      	event WeaponClaimed(address indexed from, uint chibiId, uint weaponTokenId, uint weaponRarity, uint weaponType);
      	event WeaponSaleBought(address indexed from, address indexed to, uint weaponTokenId, uint weaponPricePlayer, uint weaponPrice);
      	event WeaponBought(address indexed from, uint weaponTokenId, uint weaponRarity, uint weaponType);
      	event WeaponMintedToAddr(address indexed from, uint weaponTokenId, uint weaponRarity, uint weaponType, string weaponCode);
      	event WeaponForSale(address indexed from, uint weaponTokenId, uint weaponPrice);
      	event WeaponSaleCancelled(address indexed from, uint weaponTokenId);
      
      	uint uniqueCounter;
      
      	ChibiInterface chibiContract;
      
      	WeaponGenesInterface genesContract;
      
      	// default weapon price
      	uint _weaponPrice;
      	uint _rareWeaponPrice;
      	uint _mythicWeaponPrice;
      	uint _legendaryWeaponPrice;
      	
      	// sell weapon internally
      	mapping(uint256 => uint256) private _weaponSalePrice;
      	
      	// mapping for Chibi to claim weapon
      	mapping(uint256 => bool) private _weaponClaimed;
      	
      	// our comission
      	uint comission;
      	
      	// for players putting weapons up, to avoid super low prices from botters
      	uint minPrice;
      	
      	struct WeaponsData {
      		uint rarity;
      		uint weaponType;
      	}
      	
      	bool public gameState;
      	bool public gameStateClaim;
      	
      	mapping(uint256 => WeaponsData) private weapons;
      
      	uint presaleLockdown;
      	
      	function initialize() initializer public {
      
      		// 2019-02-28 00:00:00
      		presaleLockdown = 1551312000;
      
      		ERC721Full.initialize();
      		ERC165.initialize();
      		ERC721.initialize();
      		ERC721Enumerable.initialize();
      		Ownable.initialize(address(0x3e0f98ea1B916BB2373BAf21c2C8E6eE970e1126));
      		MintWallets.initialize(address(0x3e0f98ea1B916BB2373BAf21c2C8E6eE970e1126));
      		Referral.initialize();
      		
      		// min price people can put up weapons
      		minPrice = 100;
      		
      		// prices based on droprates
      		_weaponPrice = 20000000000000000; // 0.02 ETH ~3.50 USD (nov 18)
      		_rareWeaponPrice = 88000000000000000; // 0.088 ETH
      		_mythicWeaponPrice = 200000000000000000; // 0.2 ETH
      		_legendaryWeaponPrice = 3000000000000000000; // 3 ETH
      
      		uniqueCounter = 0;
      		infoUrlPrefix = "https://chibifighters.io/weaponapi/";
      
      		// set comission percentage inv
      		comission = 90;
      		
      		gameState = true;
      		gameStateClaim = true;
      		
      	}
      
      
          // returns min price for weapon sale to avoid cheap sales
          function queryMinPrice() public view returns (uint price) {
              return minPrice;
          }
      
          	
      	function queryDefaultSalePrice(uint rarity) public view returns (uint price) {
      		if (rarity == 0) {
      			return _weaponPrice;
      		}else
      		if (rarity == 1) {
      			return _rareWeaponPrice;
      		}else
      		if (rarity == 2) {
      			return _mythicWeaponPrice;
      		}else
      		if (rarity == 3) {
      			return _legendaryWeaponPrice;
      		}
      		return 0;
      	}
      
      	// returns min price for weapon sale to avoid cheap sales
      	function setMinPrice(uint _minPrice) public contract_onlyOwner returns (uint price) {
      		minPrice = _minPrice;
      		return minPrice;
      	}
      
      	// returns min price for weapon sale to avoid cheap sales
      	function setGameState(bool _paused) public contract_onlyOwner returns (bool paused) {
      		gameState = _paused;
      		return gameState;
      	}
      	
      	// returns min price for weapon sale to avoid cheap sales
      	function setGameStateClaim(bool _paused) public contract_onlyOwner returns (bool paused) {
      		gameStateClaim = _paused;
      		return gameState;
      	}
      	
      	function queryWeaponData(uint _tokenId) public view returns (uint tokenId, address owner, uint rarity, uint weaponType) {
      		return (
      			_tokenId,
      			ownerOf(_tokenId),
      			weapons[_tokenId].rarity,
      			weapons[_tokenId].weaponType
      			);
      	}
      
      	
      	// check if chibi already claimed weapon
      	function queryChibiClaimed(uint chibiId) public view returns (bool success) {
      		return _weaponClaimed[chibiId];
      	}
      	
      
      	function setCommission(uint percent) public contract_onlyOwner returns(bool success) {
      		comission = 100 - percent;
      		return true;
      	}
      	
      	
      	function getCommission() public view contract_onlyOwner returns(uint _comission) {
      		return 100 - comission;
      	}
      
      
      	function putWeaponForSale(uint tokenId, uint price) public notPaused returns (bool success) {
      		require (msg.sender == ownerOf(tokenId));
      		require (price >= minPrice);
      
      		_weaponSalePrice[tokenId] = price;
      		approve(this, tokenId);
      
      		emit WeaponForSale(msg.sender, tokenId, price);
      		return true;
      	}
      	
      	
      	function cancelWeaponSale(uint tokenId) public returns (bool success) {
      		require (msg.sender == ownerOf(tokenId));
      		_weaponSalePrice[tokenId] = 0;
      		
      		// remove approval from contract
      		_clearApproval(msg.sender, tokenId);
      
      		emit WeaponSaleCancelled(msg.sender, tokenId);
      		return true;
      	}
      	
      	
      	function buySaleWeapon(uint tokenId) public payable notPaused returns (bool success) {
      		require(msg.sender != ownerOf(tokenId));
      		require(_weaponSalePrice[tokenId] > 0);
      		require(msg.value == _weaponSalePrice[tokenId]);
      		require(_isApprovedOrOwner(this, tokenId));
      		
      		address _to = msg.sender;
      		require(_to != address(0));
      		
      		_weaponSalePrice[tokenId] = 0;
      		address _from = ownerOf(tokenId);
      		
      		uint finalPrice = msg.value / 100 * comission;
      		
      		// transfer weapon
      		_removeTokenFrom(_from, tokenId);
      		_addTokenTo(_to, tokenId);
      		_clearApproval(msg.sender, tokenId);
      	
      		emit Transfer(_from, _to, tokenId);
      
      		// transfer ether
      		_from.transfer(finalPrice);
      			
      		emit WeaponSaleBought(_from, _to, tokenId, finalPrice, msg.value);
      		return true;
      	}
      	
      
      	// price for default weapons
      	function setWeaponPrice(uint mode, uint _setWeaponPrice) public contract_onlyOwner returns(bool success, uint weaponPrice) {
      		if (mode == 0) {
      			_weaponPrice = _setWeaponPrice;
      		}else
      		if (mode == 1) {
      			_rareWeaponPrice = _setWeaponPrice;
      		}else
      		if (mode == 2) {
      			_mythicWeaponPrice = _setWeaponPrice;
      		}else
      		if (mode == 3) {
      			_legendaryWeaponPrice = _setWeaponPrice;
      		}
      		
      		return (true, _setWeaponPrice);
      	}
      	
      
      	// set chibi contract
      	function setChibiAddress(address _address) public contract_onlyOwner returns (bool success) {
      		chibiContract = ChibiInterface(_address);
      		return true;
      	}
      	
      	
      	// set genes contract
      	function setGenesAddress(address _address) public contract_onlyOwner returns (bool success) {
      		genesContract = WeaponGenesInterface(_address);
      		return true;
      	}
      	
      	
      	// get dna to claim weapons (only way to get founder weapons)
      	function getChibiWeaponDna(uint _chibiId) internal view returns (uint weapon, uint rarity) {
      		uint16[13] memory _dna = chibiContract.queryChibiDNA(_chibiId);
      		
      		return (_dna[7], _dna[8]);
      	}
      	
      
      	// buy a random weapon, can be anything from common to legendary
      	function buyWeapon(uint amount, uint _refId) public payable notPaused {
      		require(_weaponPrice.mul(amount) == msg.value);
      		// founder weapons can not be bought, and nothing that doesn't exist yet
      
      		for (uint i=0;i<amount;i++) {
      			uniqueCounter++;
      			require(!_exists(uniqueCounter));
      			
      			// mint also triggers transfer event
      			_mint(address(msg.sender), uniqueCounter);
      			
      			(uint _weaponRarity, uint _weaponType) = genesContract.generateData(uniqueCounter);
      			weapons[uniqueCounter].rarity = _weaponRarity;
      			weapons[uniqueCounter].weaponType = _weaponType;
      			
      			emit WeaponBought(msg.sender, uniqueCounter, _weaponRarity, _weaponType);
      		}
      		
      		if (refIdAddress[_refId] != address(0) && msg.sender != refIdAddress[_refId]) {
      		    uint amountRef = msg.value.mul(refCut[_refId]).div(100);
      		    refIdAddress[_refId].transfer(amountRef);
      		    emit RefPaid(_refId, refIdAddress[_refId], amountRef);
      		}
      	}
      	
      	
      	// buy a guaranteed rare weapon
      	function buyWeaponRare(uint amount, uint _refId) public payable notPaused {
      		require(_rareWeaponPrice.mul(amount) == msg.value);
      		require(now < presaleLockdown);
      
      		for (uint i=0;i<amount;i++) {
      			uniqueCounter++;
      			require(!_exists(uniqueCounter));
      			
      			// mint also triggers transfer event
      			_mint(address(msg.sender), uniqueCounter);
      			
      			uint _weaponType = genesContract.generateRareMythicData(uniqueCounter);
      			weapons[uniqueCounter].rarity = 1;
      			weapons[uniqueCounter].weaponType = _weaponType;
      
      			emit WeaponBought(msg.sender, uniqueCounter, 1, _weaponType);
      		}
      		
      		if (refIdAddress[_refId] != address(0) && msg.sender != refIdAddress[_refId]) {
      		    uint amountRef = msg.value.mul(refCut[_refId]).div(100);
      		    refIdAddress[_refId].transfer(amountRef);
      		    emit RefPaid(_refId, refIdAddress[_refId], amountRef);
      		}
      	}
      	
      	
      	// buy a guaranteed mythic weapon
      	function buyWeaponMythic(uint amount, uint _refId) public payable notPaused {
      		require(_mythicWeaponPrice.mul(amount) == msg.value);
      		require(now < presaleLockdown);
      
      		for (uint i=0;i<amount;i++) {
      			uniqueCounter++;
      			require(!_exists(uniqueCounter));
      			
      			// mint also triggers transfer event
      			_mint(address(msg.sender), uniqueCounter);
      			
      			uint _weaponType = genesContract.generateRareMythicData(uniqueCounter);
      			weapons[uniqueCounter].rarity = 2;
      			weapons[uniqueCounter].weaponType = _weaponType;
      
      			emit WeaponBought(msg.sender, uniqueCounter, 2, _weaponType);
      		}
      		
      		if (refIdAddress[_refId] != address(0) && msg.sender != refIdAddress[_refId]) {
      		    uint amountRef = msg.value.mul(refCut[_refId]).div(100);
      		    refIdAddress[_refId].transfer(amountRef);
      		    emit RefPaid(_refId, refIdAddress[_refId], amountRef);
      		}
      	}
      	
      	
      	// buy a guaranteed legendary weapon
      	function buyWeaponLegendary(uint amount, uint _refId) public payable notPaused {
      		require(_legendaryWeaponPrice.mul(amount) == msg.value);
      		require(now < presaleLockdown);
      
      		for (uint i=0;i<amount;i++) {
      			uniqueCounter++;
      			require(!_exists(uniqueCounter));
      			
      			// mint also triggers transfer event
      			_mint(address(msg.sender), uniqueCounter);
      			
      			uint _weaponType = genesContract.generateLegendaryData(uniqueCounter);
      			weapons[uniqueCounter].rarity = 3;
      			weapons[uniqueCounter].weaponType = _weaponType;
      
      			emit WeaponBought(msg.sender, uniqueCounter, 3, _weaponType);
      		}
      		
      		if (refIdAddress[_refId] != address(0) && msg.sender != refIdAddress[_refId]) {
      		    uint amountRef = msg.value.mul(refCut[_refId]).div(100);
      		    refIdAddress[_refId].transfer(amountRef);
      		    emit RefPaid(_refId, refIdAddress[_refId], amountRef);
      		}
      	}
      
      	// mint weapon as result of voucher purchase or what not
      	// code is used to identify weapon and apply required stats
      	function mintWeaponToAddr(uint _weaponRarity, uint _weaponType, address _receiver, string _code) public mintAllowed(msg.sender) {
      
              if (_weaponType < 10 || (_weaponType>=8000 && _weaponType<=8013)) revert();
              
      		uniqueCounter++;
      		require(!_exists(uniqueCounter));
      
      		// mint also triggers transfer event
      		_mint(address(_receiver), uniqueCounter);
      		
      		weapons[uniqueCounter].rarity = _weaponRarity;
      		weapons[uniqueCounter].weaponType = _weaponType;
      		
      		emit WeaponMintedToAddr(_receiver, uniqueCounter, _weaponRarity, _weaponType, _code);
      
      	}
      	
      	
      	// Chibis can claim their initial weapon
      	// that is also the only way to get a founder weapon
      	//
      	function claimWeapon(uint _chibiId) public claimNotPaused {
      		require(chibiContract.ownerOf(_chibiId) == msg.sender);
      		require(_weaponClaimed[_chibiId] == false);
      		
      		uniqueCounter++;
      		
      		// mark claimed
      		_weaponClaimed[_chibiId] = true;
      		
      		// get weapon dna of chibi
      		(uint _weaponType, uint _chibiRarity) = getChibiWeaponDna(_chibiId);
      		
      		_mint(address(msg.sender), uniqueCounter);
      		
      		weapons[uniqueCounter].weaponType = _weaponType;
      
      		if (_weaponType < 10 || _weaponType > 7999) {
      			weapons[uniqueCounter].rarity = 3;
      		} else {
      			// rarity comes from chibi when claimed, however legendary chibis still get just a mythic weapon since legendary weapons are either bought or made with a fragment
      			if (_chibiRarity == 3) weapons[uniqueCounter].rarity = 2;
      				else weapons[uniqueCounter].rarity = _chibiRarity;
      		}
      
      		emit WeaponClaimed(msg.sender, _chibiId, uniqueCounter, weapons[uniqueCounter].rarity, weapons[uniqueCounter].weaponType);
      		
      	}
      	
      	// old chibi contract
      	function claimWeaponOld(uint _chibiId) public notPaused {
      		require(chibiContract.ownerOf(_chibiId) == msg.sender);
      		require(_weaponClaimed[_chibiId] == false);
      		
      		uniqueCounter++;
      		
      		// mark claimed
      		_weaponClaimed[_chibiId] = true;
      		
      		// get weapon dna of chibi
      		uint16[13] memory _dna;
      		(
      		,
      		,
      		_dna,
      		,
      		,
      		,
      		
      		) = chibiContract.queryChibi(_chibiId);
      		
      		uint _weaponType = _dna[7];
      		uint _chibiRarity = _dna[8];
      
      		_mint(address(msg.sender), uniqueCounter);
      		
      		weapons[uniqueCounter].weaponType = _weaponType;
      
      		if (_weaponType < 10 || _weaponType > 7999) {
      			weapons[uniqueCounter].rarity = 3;
      		}else {
      			// rarity comes from chibi when claimed, however legendary chibis still get just a mythic weapon since legendary weapons are either bought or made with a fragment
      			if (_chibiRarity == 3) weapons[uniqueCounter].rarity = 2;
      				else weapons[uniqueCounter].rarity = _chibiRarity;
      		}
      
      		emit WeaponClaimed(msg.sender, _chibiId, uniqueCounter, weapons[uniqueCounter].rarity, weapons[uniqueCounter].weaponType);
      		
      	}
      
      
      	function queryForSale(uint _tokenId) public view returns (uint price, address owner) {
      		require(_isApprovedOrOwner(this, _tokenId));
      		
      		return (
      			_weaponSalePrice[_tokenId],
      			ownerOf(_tokenId)
      		);
      	}
      
      	
      	/**
      	* @dev Send Ether to owner
      	* @param _address Receiving address
      	* @param _amountWei Amount in WEI to send
      	**/
      	function weiToOwner(address _address, uint _amountWei) public contract_onlyOwner returns (bool success) {
      		require(_amountWei <= address(this).balance);
      		_address.transfer(_amountWei);
      		return true;
      	}
      	
      	function ERC20ToOwner(address _to, uint256 _amount, ERC20Interface _tokenContract) public contract_onlyOwner {
      		_tokenContract.transfer(_to, _amount);
      	}
      
      	function ERC20ClassicToOwner(address _to, uint256 _amount, ERC20InterfaceClassic _tokenContract) public contract_onlyOwner {
      		_tokenContract.transfer(_to, _amount);
      	}
      	
      	function queryERC20(ERC20Interface _tokenContract) public view contract_onlyOwner returns (uint) {
      		return _tokenContract.balanceOf(this);
      	}
      
      
      	modifier notPaused() {
      		require(gameState == false);
      		_;
      	}
      	
      	modifier claimNotPaused() {
      		require(gameStateClaim == false);
      		_;
      	}
      	
      }

      File 3 of 3: ChibiFighters
      pragma solidity ^0.4.21;
      
      // ----------------------------------------------------------------------------
      // Contract owner and transfer functions
      // just in case someone wants to get my bacon
      // ----------------------------------------------------------------------------
      contract ContractOwned {
          address public contract_owner;
          address public contract_newOwner;
      
          event OwnershipTransferred(address indexed _from, address indexed _to);
      
          constructor() public {
              contract_owner = msg.sender;
          }
      
          modifier contract_onlyOwner {
              require(msg.sender == contract_owner);
              _;
          }
      
          function transferOwnership(address _newOwner) public contract_onlyOwner {
              contract_newOwner = _newOwner;
          }
      
          function acceptOwnership() public {
              require(msg.sender == contract_newOwner);
              emit OwnershipTransferred(contract_owner, contract_newOwner);
              contract_owner = contract_newOwner;
              contract_newOwner = address(0);
          }
      }
      
      
      /**
      * @title SafeMath
      * @dev Math operations with safety checks that throw on error
      */
      library SafeMath {
      
          /**
          * @dev Multiplies two numbers, throws on overflow.
          */
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) {
                  return 0;
              }
              uint256 c = a * b;
              assert(c / a == b);
              return c;
          }
      
          /**
          * @dev Integer division of two numbers, truncating the quotient.
          */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              // assert(b > 0); // Solidity automatically throws when dividing by 0
              uint256 c = a / b;
              // assert(a == b * c + a % b); // There is no case in which this doesn't hold
              return c;
          }
      
          /**
          * @dev Substracts two numbers, returns 0 if it would go into minus range.
          */
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              if (b >= a) {
                  return 0;
              }
              return a - b;
          }
      
          /**
          * @dev Adds two numbers, throws on overflow.
          */
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              assert(c >= a);
              return c;
          }
      }
      
      /** 
      * ERC721 compatibility from
      * https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC721/ERC721Token.sol
      * plus our magic sauce
      */ 
      
      /**
      * @title Custom CustomEvents
      * @dev some custom events specific to this contract
      */
      contract CustomEvents {
          event ChibiCreated(uint tokenId, address indexed _owner, bool founder, string _name, uint16[13] dna, uint father, uint mother, uint gen, uint adult, string infoUrl);
          event ChibiForFusion(uint tokenId, uint price);
          event ChibiForFusionCancelled(uint tokenId);
          event WarriorCreated(uint tokenId, string battleRoar);
      }
      
      /**
      * @title ERC721 interface
      * @dev see https://github.com/ethereum/eips/issues/721
      */
      contract ERC721 {
          event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
          event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
          
          function balanceOf(address _owner) public view returns (uint256 _balance);
          function ownerOf(uint256 _tokenId) public view returns (address _owner);
          function transfer(address _to, uint256 _tokenId) public;
          function approve(address _to, uint256 _tokenId) public;
          function takeOwnership(uint256 _tokenId) public;
          function tokenMetadata(uint256 _tokenId) constant public returns (string infoUrl);
          function tokenURI(uint256 _tokenId) public view returns (string);
      }
      
      
      // interacting with gene contract
      contract GeneInterface {
          // creates genes when bought directly on this contract, they will always be superb
          // address, seed, founder, tokenId
          function createGenes(address, uint, bool, uint, uint) external view returns (
          uint16[13] genes
      );
       
      // transfusion chamber, no one really knows what that crazy thing does
      // except the scientists, but they giggle all day long
      // address, seed, tokenId
      function splitGenes(address, uint, uint) external view returns (
          uint16[13] genes
          );
          function exhaustAfterFusion(uint _gen, uint _counter, uint _exhaustionTime) public pure returns (uint);
          function exhaustAfterBattle(uint _gen, uint _exhaust) public pure returns (uint);
              
      }
      
      // interacting with fcf contract
      contract FcfInterface {
          function balanceOf(address) public pure returns (uint) {}
          function transferFrom(address, address, uint) public pure returns (bool) {}
      }
      
      // interacting with battle contract
      contract BattleInterface {
          function addWarrior(address, uint, uint8, string) pure public returns (bool) {}
          function isDead(uint) public pure returns (bool) {}
      }
       
      
      /**
       * @title ERC721Token
       * Generic implementation for the required functionality of the ERC721 standard
       */
      contract ChibiFighters is ERC721, ContractOwned, CustomEvents {
          using SafeMath for uint256;
      
          // Total amount of tokens
          uint256 private totalTokens;
      
          // Mapping from token ID to owner
          mapping (uint256 => address) private tokenOwner;
      
          // Mapping from token ID to approved address
          mapping (uint256 => address) private tokenApprovals;
      
          // Mapping from owner to list of owned token IDs
          mapping (address => uint256[]) private ownedTokens;
      
          // Mapping from token ID to index of the owner tokens list
          mapping(uint256 => uint256) private ownedTokensIndex;
      
          // interfaces for other contracts, so updates are possible
          GeneInterface geneContract;
          FcfInterface fcfContract;
          BattleInterface battleContract;
          address battleContractAddress;
      
          // default price for 1 Chibi
          uint public priceChibi;
          // minimum price for fusion chibis
          uint priceFusionChibi;
      
          // counter that keeps upping with each token
          uint uniqueCounter;
      
          // time to become adult
          uint adultTime;
      
          // recovery time after each fusion
          uint exhaustionTime;
          
          // our comission
          uint comission;
          
          // battleRemoveContractAddress to remove from array
          address battleRemoveContractAddress;
      
          struct Chibi {
              // address of current chibi owner
              address owner;
              // belongs to og
              bool founder;
              // name of the chibi, chibis need names
              string nameChibi;
              // the dna, specifies, bodyparts, etc.
              // array is easier to decode, but we are not reinventing the wheel here
              uint16[13] dna;
              // originates from tokenIds, gen0s will return 0
              // uint size only matters in structs
              uint256 father;
              uint256 mother;
              // generations, gen0 is created from the incubator, they are pure
              // but of course the funniest combos will come from the fusion chamber
              uint gen;
              // fusions, the beautiful fusion Chibis that came out of this one
              uint256[] fusions;
              // up for fusion?
              bool forFusion;
              // cost to fusion with this Chibi, can be set by player at will
              uint256 fusionPrice;
              // exhaustion after fusion
              uint256 exhausted;
              // block after which chibi is an adult 
              uint256 adult;
              // info url
              string infoUrl;
          }
      
          // the link to chibis website
          string _infoUrlPrefix;
      
          Chibi[] public chibies;
      
          string public constant name = "Chibi Fighters";
          string public constant symbol = "CBF";
      
          // pause function so fusion and minting can be paused for updates
          bool paused;
          bool fcfPaused;
          bool fusionPaused; // needed so founder can fuse while game is paused
      
          /**
          * @dev Run only once at contract creation
          */
          constructor() public {
              // a helping counter to keep chibis unique
              uniqueCounter = 0;
              // inital price in wei
              priceChibi = 100000000000000000;
              // default price to allow fusion
              priceFusionChibi = 10000000000000000;
              // time to become adult
              adultTime = 2 hours;
              //exhaustionTime = 3 hours;
              exhaustionTime = 1 hours;
              // start the contract paused
              paused = true;
              fcfPaused = true;
              fusionPaused = true;
              // set comission percentage 100-90 = 10%
              comission = 90; 
      
              _infoUrlPrefix = "https://chibigame.io/chibis.php?idj=";
          }
          
          /**
          * @dev Set Comission rate 100-x = %
          * @param _comission Rate inverted
          */
          function setComission(uint _comission) public contract_onlyOwner returns(bool success) {
              comission = _comission;
              return true;
          }
          
          /**
          * @dev Set minimum price for fusion Chibis in Wei
          */
          function setMinimumPriceFusion(uint _price) public contract_onlyOwner returns(bool success) {
              priceFusionChibi = _price;
              return true;
          }
          
          /**
          * @dev Set time until Chibi is considered adult
          * @param _adultTimeSecs Set time in seconds
          */
          function setAdultTime(uint _adultTimeSecs) public contract_onlyOwner returns(bool success) {
              adultTime = _adultTimeSecs;
              return true;
          }
      
          /**
          * @dev Fusion Chamber Cool down
          * @param _exhaustionTime Set time in seconds
          */
          function setExhaustionTime(uint _exhaustionTime) public contract_onlyOwner returns(bool success) {
              exhaustionTime = _exhaustionTime;
              return true;
          }
          
          /**
          * @dev Set game state paused for updates, pauses the entire creation
          * @param _setPaused Boolean sets the game paused or not
          */
          function setGameState(bool _setPaused) public contract_onlyOwner returns(bool _paused) {
              paused = _setPaused;
              fcfPaused = _setPaused;
              fusionPaused = _setPaused;
              return paused;
          }
          
          /**
          * @dev Set game state for fcf tokens only, so Founder can get Chibis pre launch
          * @param _setPaused Boolean sets the game paused or not
          */
          function setGameStateFCF(bool _setPaused) public contract_onlyOwner returns(bool _pausedFCF) {
              fcfPaused = _setPaused;
              return fcfPaused;
          }
          
          /**
          * @dev unpause Fusions so Founder can Fuse
          * @param _setPaused Boolean sets the game paused or not
          */
          function setGameStateFusion(bool _setPaused) public contract_onlyOwner returns(bool _pausedFusions) {
              fusionPaused = _setPaused;
              return fusionPaused;
          }
      
          /**
          * @dev Query game state. Paused (True) or not?
          */
          function getGameState() public constant returns(bool _paused) {
              return paused;
          }
      
          /**
          * @dev Set url prefix
          */
          function setInfoUrlPrefix(string prefix) external contract_onlyOwner returns (string infoUrlPrefix) {
              _infoUrlPrefix = prefix;
              return _infoUrlPrefix;
          }
          
          /**
          * @dev Set infoUrl of chibi
          */
          function changeInfoUrl(uint _tokenId, string _infoUrl) public returns (bool success) {
              if (ownerOf(_tokenId) != msg.sender && msg.sender != contract_owner) revert();
              chibies[_tokenId].infoUrl = _infoUrl;
              return true;
          }
      
          /**
          * @dev Connect to Founder contract so user can pay in FCF
          */
          function setFcfContractAddress(address _address) external contract_onlyOwner returns (bool success) {
              fcfContract = FcfInterface(_address);
              return true;
          }
      
          /**
          * @dev Connect to Battle contract
          */
          function setBattleContractAddress(address _address) external contract_onlyOwner returns (bool success) {
              battleContract = BattleInterface(_address);
              battleContractAddress = _address;
              return true;
          }
          
          /**
          * @dev Connect to Battle contract
          */
          function setBattleRemoveContractAddress(address _address) external contract_onlyOwner returns (bool success) {
              battleRemoveContractAddress = _address;
              return true;
          }
      
          /**
          * @dev Rename a Chibi
          * @param _tokenId ID of the Chibi
          * @param _name Name of the Chibi
          */
          function renameChibi(uint _tokenId, string _name) public returns (bool success){
              require(ownerOf(_tokenId) == msg.sender);
      
              chibies[_tokenId].nameChibi = _name;
              return true;
          }
      
          /**
           * @dev Has chibi necromancer trait?
           * @param _tokenId ID of the chibi
           */
          function isNecromancer(uint _tokenId) public view returns (bool) {
              for (uint i=10; i<13; i++) {
                  if (chibies[_tokenId].dna[i] == 1000) {
                      return true;
                  }
              }
              return false;
          }
      
          /**
          * @dev buy Chibis with Founders
          */
          function buyChibiWithFcf(string _name, string _battleRoar, uint8 _region, uint _seed) public returns (bool success) {
              // must own at least 1 FCF, only entire FCF can be swapped for Chibis
              require(fcfContract.balanceOf(msg.sender) >= 1 * 10 ** 18);
              require(fcfPaused == false);
              // prevent hack
              uint fcfBefore = fcfContract.balanceOf(address(this));
              // user must approved Founders contract to take tokens from account
              // oh my, this will need a tutorial video
              // always only take 1 Founder at a time
              if (fcfContract.transferFrom(msg.sender, this, 1 * 10 ** 18)) {
                  _mint(_name, _battleRoar, _region, _seed, true, 0);
              }
              // prevent hacking
              assert(fcfBefore == fcfContract.balanceOf(address(this)) - 1 * 10 ** 18);
              return true;
          }
      
          /**
          * @dev Put Chibi up for fusion, this will not destroy your Chibi. Only adults can fuse.
          * @param _tokenId Id of Chibi token that is for fusion
          * @param _price Price for the chibi in wei
          */
          function setChibiForFusion(uint _tokenId, uint _price) public returns (bool success) {
              require(ownerOf(_tokenId) == msg.sender);
              require(_price >= priceFusionChibi);
              require(chibies[_tokenId].adult <= now);
              require(chibies[_tokenId].exhausted <= now);
              require(chibies[_tokenId].forFusion == false);
              require(battleContract.isDead(_tokenId) == false);
      
              chibies[_tokenId].forFusion = true;
              chibies[_tokenId].fusionPrice = _price;
      
              emit ChibiForFusion(_tokenId, _price);
              return true;
          }
      
          function cancelChibiForFusion(uint _tokenId) public returns (bool success) {
              if (ownerOf(_tokenId) != msg.sender && msg.sender != address(battleRemoveContractAddress)) {
                  revert();
              }
              require(chibies[_tokenId].forFusion == true);
              
              chibies[_tokenId].forFusion = false;
              
              emit ChibiForFusionCancelled(_tokenId);
                  
          return false;
          }
          
      
       
          /**
          * @dev Connect to gene contract. That way we can update that contract and add more fighters.
          */
          function setGeneContractAddress(address _address) external contract_onlyOwner returns (bool success) {
              geneContract = GeneInterface(_address);
              return true;
          }
       
          /**
          * @dev Fusions cost too much so they are here
          * @return All the fusions (babies) of tokenId
          */
          function queryFusionData(uint _tokenId) public view returns (
              uint256[] fusions,
              bool forFusion,
              uint256 costFusion,
              uint256 adult,
              uint exhausted
              ) {
              return (
              chibies[_tokenId].fusions,
              chibies[_tokenId].forFusion,
              chibies[_tokenId].fusionPrice,
              chibies[_tokenId].adult,
              chibies[_tokenId].exhausted
              );
          }
          
          /**
          * @dev Minimal query for battle contract
          * @return If for fusion
          */
          function queryFusionData_ext(uint _tokenId) public view returns (
              bool forFusion,
              uint fusionPrice
              ) {
              return (
              chibies[_tokenId].forFusion,
              chibies[_tokenId].fusionPrice
              );
          }
       
          /**
          * @dev Triggers a Chibi event to get some data of token
          * @return various
          */
          function queryChibi(uint _tokenId) public view returns (
              string nameChibi,
              string infoUrl,
              uint16[13] dna,
              uint256 father,
              uint256 mother,
              uint gen,
              uint adult
              ) {
              return (
              chibies[_tokenId].nameChibi,
              chibies[_tokenId].infoUrl,
              chibies[_tokenId].dna,
              chibies[_tokenId].father,
              chibies[_tokenId].mother,
              chibies[_tokenId].gen,
              chibies[_tokenId].adult
              );
          }
      
          /**
          * @dev Triggers a Chibi event getting some additional data
          * @return various
          */
          function queryChibiAdd(uint _tokenId) public view returns (
              address owner,
              bool founder
              ) {
              return (
              chibies[_tokenId].owner,
              chibies[_tokenId].founder
              );
          }
          // exhaust after battle
          function exhaustBattle(uint _tokenId) internal view returns (uint) {
              uint _exhaust = 0;
              
              for (uint i=10; i<13; i++) {
                  if (chibies[_tokenId].dna[i] == 1) {
                      _exhaust += (exhaustionTime * 3);
                  }
                  if (chibies[_tokenId].dna[i] == 3) {
                      _exhaust += exhaustionTime.div(2);
                  }
              }
              
              _exhaust = geneContract.exhaustAfterBattle(chibies[_tokenId].gen, _exhaust);
      
              return _exhaust;
          }
          // exhaust after fusion
          function exhaustFusion(uint _tokenId) internal returns (uint) {
              uint _exhaust = 0;
              
              uint counter = chibies[_tokenId].dna[9];
              // set dna here, that way boni still apply but not infinite fusions possible
              // max value 9999
              if (chibies[_tokenId].dna[9] < 9999) chibies[_tokenId].dna[9]++;
              
              for (uint i=10; i<13; i++) {
                  if (chibies[_tokenId].dna[i] == 2) {
                      counter = counter.sub(1);
                  }
                  if (chibies[_tokenId].dna[i] == 4) {
                      counter++;
                  }
              }
      
              _exhaust = geneContract.exhaustAfterFusion(chibies[_tokenId].gen, counter, exhaustionTime);
              
              return _exhaust;
          }
          /** 
           * @dev Exhaust Chibis after battle
           */
          function exhaustChibis(uint _tokenId1, uint _tokenId2) public returns (bool success) {
              require(msg.sender == battleContractAddress);
              
              chibies[_tokenId1].exhausted = now.add(exhaustBattle(_tokenId1));
              chibies[_tokenId2].exhausted = now.add(exhaustBattle(_tokenId2)); 
              
              return true;
          }
          
          /**
           * @dev Split traits between father and mother and leave the random at the _tokenId2
           */
          function traits(uint16[13] memory genes, uint _seed, uint _fatherId, uint _motherId) internal view returns (uint16[13] memory) {
          
              uint _switch = uint136(keccak256(_seed, block.coinbase, block.timestamp)) % 5;
              
              if (_switch == 0) {
                  genes[10] = chibies[_fatherId].dna[10];
                  genes[11] = chibies[_motherId].dna[11];
              }
              if (_switch == 1) {
                  genes[10] = chibies[_motherId].dna[10];
                  genes[11] = chibies[_fatherId].dna[11];
              }
              if (_switch == 2) {
                  genes[10] = chibies[_fatherId].dna[10];
                  genes[11] = chibies[_fatherId].dna[11];
              }
              if (_switch == 3) {
                  genes[10] = chibies[_motherId].dna[10];
                  genes[11] = chibies[_motherId].dna[11];
              }
              
              return genes;
              
          }
          
          /**
          * @dev The fusion chamber combines both dnas and adds a generation.
          */
          function fusionChibis(uint _fatherId, uint _motherId, uint _seed, string _name, string _battleRoar, uint8 _region) payable public returns (bool success) {
              require(fusionPaused == false);
              require(ownerOf(_fatherId) == msg.sender);
              require(ownerOf(_motherId) != msg.sender);
              require(chibies[_fatherId].adult <= now);
              require(chibies[_fatherId].exhausted <= now);
              require(chibies[_motherId].adult <= now);
              require(chibies[_motherId].exhausted <= now);
              require(chibies[_motherId].forFusion == true);
              require(chibies[_motherId].fusionPrice == msg.value);
              // exhaust father and mother
              chibies[_motherId].forFusion = false;
              chibies[_motherId].exhausted = now.add(exhaustFusion(_motherId));
              chibies[_fatherId].exhausted = now.add(exhaustFusion(_fatherId));
              
              uint _gen = 0;
              if (chibies[_fatherId].gen >= chibies[_motherId].gen) {
                  _gen = chibies[_fatherId].gen.add(1);
              } else {
                  _gen = chibies[_motherId].gen.add(1);
              }
              // fusion chamber here we come
              uint16[13] memory dna = traits(geneContract.splitGenes(address(this), _seed, uniqueCounter+1), _seed, _fatherId, _motherId);
              
              // new Chibi is born!
              addToken(msg.sender, uniqueCounter);
      
              // father and mother get the chibi in their fusion list
              chibies[_fatherId].fusions.push(uniqueCounter);
              // only add if mother different than father, otherwise double entry
              if (_fatherId != _motherId) {
                  chibies[_motherId].fusions.push(uniqueCounter);
              }
              
              // baby Chibi won't have fusions
              uint[] memory _fusions;
              
              // baby Chibis can't be fused
              chibies.push(Chibi(
                  msg.sender,
                  false,
                  _name, 
                  dna,
                  _fatherId,
                  _motherId,
                  _gen,
                  _fusions,
                  false,
                  priceFusionChibi,
                  0,
                  now.add(adultTime.mul((_gen.mul(_gen)).add(1))),
                  strConcat(_infoUrlPrefix, uint2str(uniqueCounter))
              ));
              
              // fires chibi created event
              emit ChibiCreated(
                  uniqueCounter,
                  chibies[uniqueCounter].owner,
                  chibies[uniqueCounter].founder,
                  chibies[uniqueCounter].nameChibi,
                  chibies[uniqueCounter].dna, 
                  chibies[uniqueCounter].father, 
                  chibies[uniqueCounter].mother, 
                  chibies[uniqueCounter].gen,
                  chibies[uniqueCounter].adult,
                  chibies[uniqueCounter].infoUrl
              );
      
              // send transfer event
              emit Transfer(0x0, msg.sender, uniqueCounter);
              
              // create Warrior
              if (battleContract.addWarrior(address(this), uniqueCounter, _region, _battleRoar) == false) revert();
              
              uniqueCounter ++;
              // transfer money to seller minus our share, remain stays in contract
              uint256 amount = msg.value / 100 * comission;
              chibies[_motherId].owner.transfer(amount);
              return true;
       }
      
          /**
          * @dev Guarantees msg.sender is owner of the given token
          * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender
          */
          modifier onlyOwnerOf(uint256 _tokenId) {
              require(ownerOf(_tokenId) == msg.sender);
              _;
          }
       
          /**
          * @dev Gets the total amount of tokens stored by the contract
          * @return uint256 representing the total amount of tokens
          */
          function totalSupply() public view returns (uint256) {
              return totalTokens;
          }
       
          /**
          * @dev Gets the balance of the specified address
          * @param _owner address to query the balance of
          * @return uint256 representing the amount owned by the passed address
          */
          function balanceOf(address _owner) public view returns (uint256) {
              return ownedTokens[_owner].length;
          }
       
          /**
          * @dev Gets the list of tokens owned by a given address
          * @param _owner address to query the tokens of
          * @return uint256[] representing the list of tokens owned by the passed address
          */
          function tokensOf(address _owner) public view returns (uint256[]) {
              return ownedTokens[_owner];
          }
       
          /**
          * @dev Gets the owner of the specified token ID
          * @param _tokenId uint256 ID of the token to query the owner of
          * @return owner address currently marked as the owner of the given token ID
          */
          function ownerOf(uint256 _tokenId) public view returns (address) {
              address owner = tokenOwner[_tokenId];
              require(owner != address(0));
              return owner;
          }
       
          /**
          * @dev Gets the approved address to take ownership of a given token ID
          * @param _tokenId uint256 ID of the token to query the approval of
          * @return address currently approved to take ownership of the given token ID
          */
          function approvedFor(uint256 _tokenId) public view returns (address) {
              return tokenApprovals[_tokenId];
          }
       
          /**
          * @dev Transfers the ownership of a given token ID to another address
          * @param _to address to receive the ownership of the given token ID
          * @param _tokenId uint256 ID of the token to be transferred
          */
          function transfer(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
              clearApprovalAndTransfer(msg.sender, _to, _tokenId);
          }
       
          /**
          * @dev Approves another address to claim for the ownership of the given token ID
          * @param _to address to be approved for the given token ID
          * @param _tokenId uint256 ID of the token to be approved
          */
          function approve(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
              address owner = ownerOf(_tokenId);
              require(_to != owner);
              if (approvedFor(_tokenId) != 0 || _to != 0) {
                  tokenApprovals[_tokenId] = _to;
                  emit Approval(owner, _to, _tokenId);
              }
          }
       
          /**
          * @dev Claims the ownership of a given token ID
          * @param _tokenId uint256 ID of the token being claimed by the msg.sender
          */
          function takeOwnership(uint256 _tokenId) public {
              require(isApprovedFor(msg.sender, _tokenId));
              clearApprovalAndTransfer(ownerOf(_tokenId), msg.sender, _tokenId);
          }
          
          function mintSpecial(string _name, string _battleRoar, uint8 _region, uint _seed, uint _specialId) public contract_onlyOwner returns (bool success) {
              // name can be empty
              _mint(_name, _battleRoar, _region, _seed, false, _specialId);
              return true;
          }
          
          /**
          * @dev Mint token function
          * @param _name name of the Chibi
          */
          function _mint(string _name, string _battleRoar, uint8 _region, uint _seed, bool _founder, uint _specialId) internal {
              require(msg.sender != address(0));
              addToken(msg.sender, uniqueCounter);
          
              // creates a gen0 Chibi, no father, mother, gen0
              uint16[13] memory dna;
              
              if (_specialId > 0) {
                  dna  = geneContract.createGenes(address(this), _seed, _founder, uniqueCounter, _specialId);
              } else {
                  dna = geneContract.createGenes(address(this), _seed, _founder, uniqueCounter, 0);
              }
      
              uint[] memory _fusions;
      
              chibies.push(Chibi(
                  msg.sender,
                  _founder,
                  _name, 
                  dna,
                  0,
                  0,
                  0,
                  _fusions,
                  false,
                  priceFusionChibi,
                  0,
                  now.add(adultTime),
                  strConcat(_infoUrlPrefix, uint2str(uniqueCounter))
              ));
              
              // send transfer event
              emit Transfer(0x0, msg.sender, uniqueCounter);
              
              // create Warrior
              if (battleContract.addWarrior(address(this), uniqueCounter, _region, _battleRoar) == false) revert();
              
              // fires chibi created event
              emit ChibiCreated(
                  uniqueCounter,
                  chibies[uniqueCounter].owner,
                  chibies[uniqueCounter].founder,
                  chibies[uniqueCounter].nameChibi,
                  chibies[uniqueCounter].dna, 
                  chibies[uniqueCounter].father, 
                  chibies[uniqueCounter].mother, 
                  chibies[uniqueCounter].gen,
                  chibies[uniqueCounter].adult,
                  chibies[uniqueCounter].infoUrl
              );
              
              uniqueCounter ++;
          }
       
          /**
          * @dev buy gen0 chibis
          * @param _name name of the Chibi
          */
          function buyGEN0Chibi(string _name, string _battleRoar, uint8 _region, uint _seed) payable public returns (bool success) {
              require(paused == false);
              // cost at least 100 wei
              require(msg.value == priceChibi);
              // name can be empty
              _mint(_name, _battleRoar, _region, _seed, false, 0);
              return true;
          }
       
          /**
          * @dev set default sale price of Chibies
          * @param _priceChibi price of 1 Chibi in Wei
          */
          function setChibiGEN0Price(uint _priceChibi) public contract_onlyOwner returns (bool success) {
              priceChibi = _priceChibi;
              return true;
          }
       
          /**
          * @dev Tells whether the msg.sender is approved for the given token ID or not
          * This function is not private so it can be extended in further implementations like the operatable ERC721
          * @param _owner address of the owner to query the approval of
          * @param _tokenId uint256 ID of the token to query the approval of
          * @return bool whether the msg.sender is approved for the given token ID or not
          */
          function isApprovedFor(address _owner, uint256 _tokenId) internal view returns (bool) {
              return approvedFor(_tokenId) == _owner;
          }
       
          /**
          * @dev Internal function to clear current approval and transfer the ownership of a given token ID
          * @param _from address which you want to send tokens from
          * @param _to address which you want to transfer the token to
          * @param _tokenId uint256 ID of the token to be transferred
          */
          function clearApprovalAndTransfer(address _from, address _to, uint256 _tokenId) internal {
              require(_to != address(0));
              require(_to != ownerOf(_tokenId));
              require(ownerOf(_tokenId) == _from);
      
              clearApproval(_from, _tokenId);
              removeToken(_from, _tokenId);
              addToken(_to, _tokenId);
              
              // Chibbi code
              chibies[_tokenId].owner = _to;
              chibies[_tokenId].forFusion = false;
              
              emit Transfer(_from, _to, _tokenId);
          }
       
          /**
          * @dev Internal function to clear current approval of a given token ID
          * @param _tokenId uint256 ID of the token to be transferred
          */
          function clearApproval(address _owner, uint256 _tokenId) private {
              require(ownerOf(_tokenId) == _owner);
              tokenApprovals[_tokenId] = 0;
              emit Approval(_owner, 0, _tokenId);
          }
       
          /**
          * @dev Internal function to add a token ID to the list of a given address
          * @param _to address representing the new owner of the given token ID
          * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
          */
          function addToken(address _to, uint256 _tokenId) private {
              require(tokenOwner[_tokenId] == address(0));
              tokenOwner[_tokenId] = _to;
              uint256 length = balanceOf(_to);
              ownedTokens[_to].push(_tokenId);
              ownedTokensIndex[_tokenId] = length;
              totalTokens++;
          }
       
          /**
          * @dev Internal function to remove a token ID from the list of a given address
          * @param _from address representing the previous owner of the given token ID
          * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
          */
          function removeToken(address _from, uint256 _tokenId) private {
              require(ownerOf(_tokenId) == _from);
              
              uint256 tokenIndex = ownedTokensIndex[_tokenId];
              uint256 lastTokenIndex = balanceOf(_from).sub(1);
              uint256 lastToken = ownedTokens[_from][lastTokenIndex];
              
              tokenOwner[_tokenId] = 0;
              ownedTokens[_from][tokenIndex] = lastToken;
              ownedTokens[_from][lastTokenIndex] = 0;
              // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to
              // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping
              // the lastToken to the first position, and then dropping the element placed in the last position of the list
              
              ownedTokens[_from].length--;
              ownedTokensIndex[_tokenId] = 0;
              ownedTokensIndex[lastToken] = tokenIndex;
              totalTokens = totalTokens.sub(1);
          }
      
          /**
          * @dev Send Ether to owner
          * @param _address Receiving address
          * @param amount Amount in WEI to send
          **/
          function weiToOwner(address _address, uint amount) public contract_onlyOwner {
              require(amount <= address(this).balance);
              _address.transfer(amount);
          }
          
          /**
          * @dev Return the infoUrl of Chibi
          * @param _tokenId infoUrl of _tokenId
          **/
          function tokenMetadata(uint256 _tokenId) constant public returns (string infoUrl) {
              return chibies[_tokenId].infoUrl;
          }
          
          function tokenURI(uint256 _tokenId) public view returns (string) {
              return chibies[_tokenId].infoUrl;
          }
      
          //
          // some helpful functions
          // https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol
          //
          function uint2str(uint i) internal pure returns (string) {
              if (i == 0) return "0";
              uint j = i;
              uint len;
              while (j != 0){
                  len++;
                  j /= 10;
              }
              bytes memory bstr = new bytes(len);
              uint k = len - 1;
              while (i != 0){
                  bstr[k--] = byte(48 + i % 10);
                  i /= 10;
              }
              return string(bstr);
          }
      
          function strConcat(string _a, string _b) internal pure returns (string) {
              bytes memory _ba = bytes(_a);
              bytes memory _bb = bytes(_b);
      
              string memory ab = new string(_ba.length + _bb.length);
              bytes memory bab = bytes(ab);
              uint k = 0;
              for (uint i = 0; i < _ba.length; i++) bab[k++] = _ba[i];
              for (i = 0; i < _bb.length; i++) bab[k++] = _bb[i];
              return string(bab);
              }
          }