pragma solidity ^0.5.12;
/**
* @title SafeMath
* @dev Unsigned math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two unsigned integers, 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 unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 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 unsigned integers, 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 unsigned integers, 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 unsigned integers 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;
}
}
/**
* 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.
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
}
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids
*
* Include with `using Counter for Counter.Counter;`
* Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the SafeMath
* overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
* directly accessed.
*/
library Counters {
using SafeMath for uint256;
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function set(Counter storage counter, uint256 value) internal returns (uint256) {
counter._value = value;
}
function increment(Counter storage counter) internal {
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}
/**
* @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 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
*/
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
public returns (bytes4);
}
/**
* @title CryptoTitties Implementation of ERC721
* @dev ERC721, ERC721Meta plus custom market implementation.
*/
contract CryptoTitties {
using SafeMath for uint;
using Address for address;
using Counters for Counters.Counter;
// ----------------------------------------------------------------------------
// Contract ownership
// ----------------------------------------------------------------------------
// - variables
address public _ownershipOwner;
address public _ownershipNewOwner;
// - events
event OwnershipTransferred(address indexed _from, address indexed _to);
// - modifiers
modifier onlyOwner {
require(msg.sender == _ownershipOwner, "Only contract owner is allowed.");
_;
}
// - functions
/**
* @notice Initialize contract ownership transfer
* @dev This function can be called only by current contract owner,
* to initialize ownership transfer to other address.
* @param newOwner The address of desired new owner
*/
function ownershipTransfer(address newOwner) public onlyOwner {
_ownershipNewOwner = newOwner;
}
/**
* @notice Finish contract ownership transfer
* @dev This function can be called only by new contract owner,
* to accept ownership transfer.
*/
function ownershipAccept() public {
require(msg.sender == _ownershipNewOwner, "Only new contract owner is allowed to accept.");
emit OwnershipTransferred(_ownershipOwner, _ownershipNewOwner);
_ownershipOwner = _ownershipNewOwner;
_ownershipNewOwner = address(0);
}
// ----------------------------------------------------------------------------
// ERC165
// ----------------------------------------------------------------------------
// - variables
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
mapping(bytes4 => bool) private _supportedInterfaces;
// - functions
function _registerInterface(bytes4 interfaceId) internal {
require(interfaceId != 0xffffffff);
_supportedInterfaces[interfaceId] = true;
}
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
return _supportedInterfaces[interfaceId];
}
// ----------------------------------------------------------------------------
// ERC721
// based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol
// ----------------------------------------------------------------------------
// - variables
// 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 => Counters.Counter) private _ownedTokensCount;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;
/*
* bytes4(keccak256('balanceOf(address)')) == 0x70a08231
* bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
* bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
* bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
* bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
* bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
* bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
*
* => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
* 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
*/
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
// - events
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);
// - functions
/**
* @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].current();
}
/**
* @dev Gets the owner of the specified token ID.
* @param tokenId uint256 ID of the token to query the owner of
* @return address currently marked as the owner of the given token ID
*/
function ownerOf(uint256 tokenId) public view returns (address) {
require(_exists(tokenId), "Token does not exists.");
return _ownerOf(tokenId);
}
/**
* @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(!_marketOfferExists(tokenId), "Token is offered on market can't be transfered.");
require(!_marketAuctionExists(tokenId), "Token is in auction can't be transfered.");
_transferFrom(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 {IERC721Receiver-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 {
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 {IERC721Receiver-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 _msgSender() 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 memory _data) public {
transferFrom(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data));
}
// ----------------------------------------------------------------------------
// ERC721 Meta
// based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721Metadata.sol
// ----------------------------------------------------------------------------
// - variables
// Token name
string private _name;
// Token symbol
string private _symbol;
// Base uri to generate tokenURI
string private _baseTokenURI;
//hash to prove token images not changes in time
string private _imagesJsonHash;
/*
* bytes4(keccak256('name()')) == 0x06fdde03
* bytes4(keccak256('symbol()')) == 0x95d89b41
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
*
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
*/
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
// - functions
/**
* @dev Gets the token name.
* @return string representing the token name
*/
function name() external view returns (string memory) {
return _name;
}
/**
* @dev Gets the token symbol.
* @return string representing the token symbol
*/
function symbol() external view returns (string memory) {
return _symbol;
}
/**
* @dev Returns an URI for a given token ID.
* Throws if the token ID does not exist.
* @param tokenId uint256 ID of the token to query
*/
function tokenURI(uint256 tokenId) external view returns (string memory) {
require(_exists(tokenId));
return string(abi.encodePacked(_baseTokenURI, uint2str(tokenId)));
}
/**
* @dev Returns saved hash.
* Throws if the token ID does not exist.
*/
function imagesJsonHash() external view returns (string memory){
return _imagesJsonHash;
}
// ----------------------------------------------------------------------------
// ERC721 Meta Total suply
// added totalSuply functionality
// ----------------------------------------------------------------------------
// - vars
//total suply
uint256 private _totalSupply;
// - functions
/**
* @dev Returns totalSupply.
*/
function totalSupply() public view returns (uint256 _supply) {
return _totalSupply;
}
// ----------------------------------------------------------------------------
// Build In Market
// ----------------------------------------------------------------------------
// - types
/**
* @title MarketOffer
* @dev Stores information about token market offer.
*/
struct MarketOffer {
bool isOffer;
address owner;
uint256 price;
}
/**
* @title MarketAuction
* @dev Stores information about token market auction.
*/
struct MarketAuction {
bool isAuction;
address highestBidder;
uint256 highestBid;
uint256 initPrice;
uint endTime;
}
// - variables
// Mapping from token ID to MarketOffer
mapping (uint256 => MarketOffer) private _marketOffers;
// Mapping from token ID to MarketAuction
mapping (uint256 => MarketAuction) private _marketAuctions;
// Mapping from address to marketBalance (ETH)
mapping (address => uint256) private _marketBalances;
//Mapping from token ID to First owner of token
mapping (uint256 => address) private _tokenFirstOwner;
//Address allowed to place tokens owned by contract to auction
address private _auctionsAddress;
//Address allowed to gift (transfer) tokens owned by contract
address private _giftsAddress;
// - events
event MarketOfferCreated(address indexed _from, uint256 _tokenId, uint256 _price);
event MarketOfferRemoved(address indexed _from, uint256 _tokenId);
event MarketOfferSold(address indexed _owner, address indexed _buyer, uint256 _tokenId, uint256 _price);
event MarketAuctionCreated(uint256 _tokenId, uint256 _initPrice, uint256 _starttime, uint256 _endtime);
event MarketAuctionBid(uint256 _tokenId, uint256 _bid, address _bidder, address _old_bidder);
event MarketAuctionClaimed(uint256 _tokenId, uint256 _bid, address _bidder);
// - functions
/**
* @dev Sets new _auctionsAddress allowed to place tokens owned by
* contract to auction.
* Requires the msg.sender to be the contract owner
* @param auctionsAddress new _auctionsAddress
*/
function setAuctionAddress(address auctionsAddress) public onlyOwner {
_auctionsAddress = auctionsAddress;
}
/**
* @dev Sets new _giftsAddress allowed to place tokens owned by
* contract to auction.
* Requires the msg.sender to be the contract owner
* @param giftsAddress new _giftsAddress
*/
function setGiftsAddress(address giftsAddress) public onlyOwner {
_giftsAddress = giftsAddress;
}
/**
* @dev Gets token market price, returns 0 for tokens not on market.
* Requires token existence
* @param _tokenId uint256 ID of the token
*/
function marketOfferGetTokenPrice(uint256 _tokenId) public view returns (uint256 _price) {
require(_exists(_tokenId), "Token does not exists.");
return _marketOfferGetTokenPrice(_tokenId);
}
/**
* @dev Gets token market price, returns 0 for tokens not on market.
* Internal implementation. For tokens owned by address(0), gets token
* not from price _marketOffers[_tokenId], but from function
* _countBasePrice(_tokenId)
* @param _tokenId uint256 ID of the token
*/
function _marketOfferGetTokenPrice(uint256 _tokenId) private view returns (uint256 _price) {
if(_tokenOwner[_tokenId]==address(0)){
return _countBasePrice(_tokenId);
}
return _marketOffers[_tokenId].price;
}
/**
* @dev Returns whatever token is offered on market or not.
* Requires token existence
* @param _tokenId uint256 ID of the token
*/
function marketOfferExists(uint256 _tokenId) public view returns (bool) {
require(_exists(_tokenId), "Token does not exists.");
return _marketOfferExists(_tokenId);
}
/**
* @dev Returns whatever token is offered on market or not.
* Internal implementation. For tokens owned by address(0), gets token
* not from price _marketOffers[_tokenId], but from function
* _baseIsOnMarket(_tokenId)
* @param _tokenId uint256 ID of the token
*/
function _marketOfferExists(uint256 _tokenId) private view returns (bool) {
if(_tokenOwner[_tokenId]==address(0)){
return _baseIsOnMarket(_tokenId);
}
return _marketOffers[_tokenId].isOffer;
}
/**
* @dev Places token on internal market.
* Requires token existence. Requires token not offered and not in auction.
* Requires owner of token == msg.sender
* @param _tokenId uint256 ID of the token
* @param _price uint256 token price
*/
function marketOfferCreate(uint256 _tokenId, uint256 _price) public {
require(_exists(_tokenId), "Token does not exists.");
require(!_marketOfferExists(_tokenId), "Token is allready offered.");
require(!_marketAuctionExists(_tokenId), "Token is allready in auction.");
address _owner = _ownerOf(_tokenId);
require(_owner==msg.sender, "Sender is not authorized.");
_marketOffers[_tokenId].isOffer = true;
_marketOffers[_tokenId].owner = _owner;
_marketOffers[_tokenId].price = _price;
if(_tokenOwner[_tokenId]==address(0)){
_tokenOwner[_tokenId] = _owner;
}
emit MarketOfferCreated(_owner, _tokenId, _price);
}
/**
* @dev Removes token from internal market.
* Requires token existence. Requires token is offered .
* Requires owner of token == msg.sender
* @param _tokenId uint256 ID of the token
*/
function marketOfferRemove(uint256 _tokenId) public {
require(_exists(_tokenId), "Token does not exists.");
address _owner = _ownerOf(_tokenId);
require(_owner==msg.sender, "Sender is not authorized.");
require(_marketOfferExists(_tokenId), "Token is not offered.");
_marketOffers[_tokenId].isOffer = false;
_marketOffers[_tokenId].owner = address(0);
_marketOffers[_tokenId].price = 0;
if(_tokenOwner[_tokenId]==address(0)){
_tokenOwner[_tokenId] = _owner;
}
//marketOffers[_tokenId] = MarketOffer(false, address(0),0);
emit MarketOfferRemoved(_owner, _tokenId);
}
/**
* @dev Buy token from internal market.
* Requires token existence. Requires token is offered.
* Requires owner of msg.value >= token price.
* @param _tokenId uint256 ID of the token
*/
function marketOfferBuy(uint256 _tokenId) public payable {
require(_exists(_tokenId), "Token does not exists.");
require(_marketOfferExists(_tokenId), "Token is not offered.");
uint256 _price = _marketOfferGetTokenPrice(_tokenId);
uint256 _finalprice = _price;
uint256 _payed = msg.value;
address _buyer = msg.sender;
address _owner = _ownerOf(_tokenId);
uint256 fee_price = 0;
uint256 charger_fee = 0;
uint256 charity_fee = 0;
uint256 charity_price = 0;
require(_price<=_payed, "Payed price is lower than market price.");
//return balance to buyer if send more than price
if(_payed>_price){
_marketBalances[_buyer] = _marketBalances[_buyer].add(_payed.sub(_price));
}
if((_tokenOwner[_tokenId]==address(0)) || (_tokenOwner[_tokenId]==_ownershipOwner)){
// Primary market
if(_isCharityToken(_tokenId)){
//charity token
//full price payed to _charityOwnerAddress
charity_price = _price;
//charity sets as first owner
_tokenFirstOwner[_tokenId] = _charityOwnerAddress;
}else{
//contract token
//10% to charity
charity_fee = _price.div(10);
//90% to charger
charger_fee = _price.sub(charity_fee);
}
}else{
//Secondary market
//calculate 1 %
fee_price = _price.div(100);
//1% to charity - final price subtracted by 1%
charity_fee = fee_price;
_finalprice = _finalprice.sub(fee_price);
//1% to first owner
if(_tokenFirstOwner[_tokenId]!=address(0)){
//added 1% to first owner
_marketBalances[_tokenFirstOwner[_tokenId]] = _marketBalances[_tokenFirstOwner[_tokenId]].add(fee_price);
//final price subtracted by 1%
_finalprice = _finalprice.sub(fee_price);
}
//1% to charger - final price subtracted by 1%
charger_fee = fee_price;
_finalprice = _finalprice.sub(fee_price);
//add final price to market balances of seller 97 or 98%
_marketBalances[_owner] = _marketBalances[_owner].add(_finalprice);
}
//remove from market
_marketOffers[_tokenId].isOffer = false;
_marketOffers[_tokenId].owner = address(0);
_marketOffers[_tokenId].price = 0;
//actual token transfer
_transferFrom(_owner, _buyer, _tokenId);
//eth transfers to _chargerAddress, _charityAddress, and _charityOwnerAddress
_charityAddBalance(charity_fee);
_chargerAddBalance(charger_fee);
_charityOwnerAddBalance(charity_price);
//emit market sold event
emit MarketOfferSold(_owner, _buyer, _tokenId, _price);
}
/**
* @dev Places token on internal auction.
* Requires token existence.
* Requires token not offered and not in auction.
* Requires owner of token == msg.sender or if contract token _auctionsAddress == msg.sender.
* Requires _initPrice > 0.
* @param _tokenId uint256 ID of the token
* @param _initPrice uint256 initial (minimal bid) price
* @param _duration uint256 auction duration in secconds
*/
function marketAuctionCreate(uint256 _tokenId, uint256 _initPrice, uint _duration) public {
require(_exists(_tokenId), "Token does not exists.");
require(!_marketOfferExists(_tokenId), "Token is allready offered.");
require(!_marketAuctionExists(_tokenId), "Token is allready in auction.");
address _owner = _ownerOf(_tokenId);
//requre msg.sender to be owner
if(_owner!=msg.sender){
//OR require owner == _ownershipOwner
require(_owner==_ownershipOwner, "Sender is not authorized.");
//AND msg.sender == _auctionsAddress
require(_auctionsAddress==msg.sender, "Sender is not authorized.");
}
require(_initPrice>0, "Auction Init price has to be bigger than 0.");
//set auction parameters
_marketAuctions[_tokenId].isAuction = true;
_marketAuctions[_tokenId].highestBidder = address(0);
_marketAuctions[_tokenId].highestBid = 0;
_marketAuctions[_tokenId].initPrice = _initPrice;
_marketAuctions[_tokenId].endTime = block.timestamp+_duration;
//emits MarketAuctionCreated
emit MarketAuctionCreated(_tokenId, _initPrice, block.timestamp, block.timestamp+_duration);
}
/**
* @dev Bids on token in internal auction.
* Requires token existence.
* Requires token in auction.
* Requires bid >= _initPrice.
* Requires bid > highestBid.
* @param _tokenId uint256 ID of the token
*/
function marketAuctionBid(uint256 _tokenId) public payable {
require(_exists(_tokenId), "Token does not exists.");
require(_marketAuctionExists(_tokenId), "Token is not in auction.");
require(_marketAuctions[_tokenId].highestBid < msg.value, "Bid has to be bigger than the current highest bid.");
require(_marketAuctions[_tokenId].initPrice <= msg.value, "Bid has to be at least initPrice value.");
address oldBidder = _marketAuctions[_tokenId].highestBidder;
address bidder = msg.sender;
uint256 bidValue = msg.value;
//return old bidder bid his to market balances
if(oldBidder!=address(0)){
_marketBalances[oldBidder] += _marketAuctions[_tokenId].highestBid;
}
//set new highest bid
_marketAuctions[_tokenId].highestBidder = bidder;
_marketAuctions[_tokenId].highestBid = bidValue;
//emits MarketAuctionBid
emit MarketAuctionBid(_tokenId, bidValue, bidder, oldBidder);
}
/**
* @dev Resolved internal auction. Auction can not be resolved automatically after
* duration expires. Transfer token to auction winner (if someone bids) and
* remove token from auction.
* Requires token existence.
* Requires _marketAuctions[_tokenId].isAuction.
* Requires _marketAuctions[_tokenId].endTime < block.timestamp - duration expired.
* @param _tokenId uint256 ID of the token
*/
function marketAuctionClaim(uint256 _tokenId) public {
require(_exists(_tokenId), "Token does not exists.");
require(_marketAuctions[_tokenId].isAuction, "Token is not in auction.");
require(_marketAuctions[_tokenId].endTime < block.timestamp, "Auction not finished yet.");
uint256 fee_price = 0;
uint256 charger_fee = 0;
uint256 charity_fee = 0;
uint256 charity_price = 0;
uint256 _price = _marketAuctions[_tokenId].highestBid;
uint256 _finalprice = _price;
address _buyer = _marketAuctions[_tokenId].highestBidder;
address _owner = _ownerOf(_tokenId);
// if winner exist (if someone bids)
if(_buyer != address(0)){
if(_tokenOwner[_tokenId]==address(0)){
// Primary market
if(_isCharityToken(_tokenId)){
//charity token
//full price payed to _charityOwnerAddress
charity_price = _price;
//charity sets as first owner
_tokenFirstOwner[_tokenId] = _charityOwnerAddress;
}else{
//contract token
//10% to charity
charity_fee = _price.div(10);
//90% to charger
charger_fee = _price.sub(charity_fee);
}
}else{
//Secondary market
//calculate 1 %
fee_price = _price.div(100);
//1% to charity - final price subtracted by 1%
charity_fee = fee_price;
_finalprice = _finalprice.sub(fee_price);
//1% to first owner
if(_tokenFirstOwner[_tokenId]!=address(0)){
//added 1% to first owner
_marketBalances[_tokenFirstOwner[_tokenId]] = _marketBalances[_tokenFirstOwner[_tokenId]].add(fee_price);
//final price subtracted by 1%
_finalprice = _finalprice.sub(fee_price);
}
//1% to charger - final price subtracted by 1%
charger_fee = fee_price;
_finalprice = _finalprice.sub(fee_price);
//add final price to market balances of seller 97 or 98%
_marketBalances[_owner] = _marketBalances[_owner].add(_finalprice);
}
//actual transfer to winner
_transferFrom(_owner, _buyer, _tokenId);
//emit MarketAuctionClaimed
emit MarketAuctionClaimed(_tokenId, _price, _buyer);
}else{
//emit MarketAuctionClaimed - when no bidder/winner
emit MarketAuctionClaimed(_tokenId, 0, address(0));
}
//remove auction
_marketAuctions[_tokenId].isAuction = false;
_marketAuctions[_tokenId].highestBidder = address(0);
_marketAuctions[_tokenId].highestBid = 0;
//eth transfers to _chargerAddress, _charityAddress, and _charityOwnerAddress
_charityAddBalance(charity_fee);
_chargerAddBalance(charger_fee);
_charityOwnerAddBalance(charity_price);
}
/**
* @dev Gets current highest bid, returns 0 for tokens not in auction.
* Requires token existence
* @param _tokenId uint256 ID of the token
*/
function marketAuctionGetTokenPrice(uint256 _tokenId) public view returns (uint256 _price) {
require(_exists(_tokenId), "Token does not exists.");
return _marketAuctions[_tokenId].highestBid;
}
/**
* @dev Gets address of current highest bidder, returns addres(0) for tokens not in auction.
* Requires token existence
* @param _tokenId uint256 ID of the token
*/
function marketAuctionGetHighestBidder(uint256 _tokenId) public view returns (address _bidder) {
require(_exists(_tokenId), "Token does not exists.");
return _marketAuctions[_tokenId].highestBidder;
}
/**
* @dev Returns whatever token is in auction or not.
* @param _tokenId uint256 ID of the token
*/
function marketAuctionExists(uint256 _tokenId) public view returns(bool _exists){
return _marketAuctionExists(_tokenId);
}
/**
* @dev Returns whatever token is in auction or not.
* Internal implementation. Check if endTime not expired.
* @param _tokenId uint256 ID of the token
*/
function _marketAuctionExists(uint256 _tokenId) private view returns(bool _exists){
if(_marketAuctions[_tokenId].endTime < block.timestamp){
return false;
}
return _marketAuctions[_tokenId].isAuction;
}
/**
* @dev Transfers market balance of msg.sender.
* Requires _marketBalances[msg.sender]>0
*/
function marketWithdrawBalance() public {
uint amount = _marketBalances[msg.sender];
require(amount>0, "Sender has no market balance to withdraw.");
_marketBalances[msg.sender] = 0;
msg.sender.transfer(amount);
}
/**
* @dev Get ammount of _owner.
* @param _owner address Requested address;
*/
function marketGetBalance(address _owner) public view returns(uint256 _balance){
return _marketBalances[_owner];
}
/**
* @dev Send/transfer token.
* Requires token exist.
* Requires token is not offered or in auction.
* Requires token is owned by _ownershipOwner
* Requires msq.sender==_giftsAddress
* @param _tokenId uint256 ID of the token to send
* @param _to address to send token
*/
function marketSendGift(uint256 _tokenId, address _to) public {
require(_exists(_tokenId), "Token does not exists.");
require(!_marketOfferExists(_tokenId), "Token is offered.");
require(!_marketAuctionExists(_tokenId), "Token is in auction.");
require(_ownerOf(_tokenId)==_ownershipOwner, "Sender is not authorized.");
require(_giftsAddress==msg.sender, "Sender is not authorized.");
_transferFrom(_ownerOf(_tokenId), _to, _tokenId);
}
// --------------------------
// Safe transfers functions (transefer to kown adresses)
// -------------------------
address payable private _chargeAddress;
address payable private _charityAddress;
address payable private _charityOwnerAddress;
/**
* @dev Transfers eth to _charityAddress
* @param _balance uint256 Ammount to transfer
*/
function _charityAddBalance(uint256 _balance) internal {
if(_balance>0){
_charityAddress.transfer(_balance);
}
}
/**
* @dev Transfers eth to _charityOwnerAddress
* @param _balance uint256 Ammount to transfer
*/
function _charityOwnerAddBalance(uint256 _balance) internal {
if(_balance>0){
_charityOwnerAddress.transfer(_balance);
}
}
/**
* @dev Transfers eth to _chargeAddress
* @param _balance uint256 Ammount to transfer
*/
function _chargerAddBalance(uint256 _balance) internal {
if(_balance>0){
_chargeAddress.transfer(_balance);
}
}
// --------------------------
// Internal functions
// -------------------------
/**
* @dev Internal function return owner of token _tokenOwner[_tokenId].
* if _tokenOwner[_tokenId] == address(0), owner is _charityOwnerAddress
* OR _ownershipOwner (based on _isCharityToken(_tokenId))
* @param _tokenId uint256 ID of the token
*/
function _ownerOf(uint256 _tokenId) internal view returns (address _owner) {
if(_tokenOwner[_tokenId]==address(0)){
//token has no owner - owner is _charityOwnerAddress OR _ownershipOwner;
if(_isCharityToken(_tokenId)){
//owner is _charityOwnerAddress
return _charityOwnerAddress;
}
//owner is _ownershipOwner
return _ownershipOwner;
}
//owner is _tokenOwner[_tokenId]
return _tokenOwner[_tokenId];
}
/**
* @dev Returns whatever token is charity token or not
* @param _tokenId uint256 ID of the token
*/
function _isCharityToken(uint256 _tokenId) internal pure returns (bool _isCharity) {
if(_tokenId>720 && _tokenId<=1320){
return true;
}
return false;
}
/**
* @dev Returns whether the specified token exists.
* @param _tokenId uint256 ID of the token to query the existence of
* @return bool whether the token exists
*/
function _exists(uint256 _tokenId) internal view returns(bool _tokenExistence) {
//all tokens lower then supply exists
return (_tokenId <= _totalSupply);
}
/**
* @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);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Internal function to transfer ownership of a given token ID to another address.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
* @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) internal {
require(_ownerOf(tokenId) == from);
require(to != address(0));
_clearApproval(tokenId);
_ownedTokensCount[from].decrement();
_ownedTokensCount[to].increment();
if(_tokenFirstOwner[tokenId]==address(0)){
_tokenFirstOwner[tokenId] = to;
}
_tokenOwner[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* This function is deprecated.
* @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 bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
internal returns (bool)
{
if (!to.isContract()) {
return true;
}
bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data);
return (retval == _ERC721_RECEIVED);
}
/**
* @dev Private function to clear current approval of a given token ID.
* @param tokenId uint256 ID of the token to be transferred
*/
function _clearApproval(uint256 tokenId) private {
if (_tokenApprovals[tokenId] != address(0)) {
_tokenApprovals[tokenId] = address(0);
}
}
/**
* @dev Converts uint256 number to string
* @param i uint256
*/
function uint2str(uint256 i) internal pure returns (string memory){
uint256 _tmpN = i;
if (_tmpN == 0) {
return "0";
}
uint256 j = _tmpN;
uint256 length = 0;
while (j != 0){
length++;
j /= 10;
}
bytes memory bstr = new bytes(length);
uint256 k = length - 1;
while (_tmpN != 0) {
bstr[k--] = byte(uint8(48 + _tmpN % 10));
_tmpN /= 10;
}
return string(bstr);
}
/**
* @dev Returns market price of token based on its id.
* Only used if tokenOwner == address(0)
* @param _tokenId uint256 id of token
* @return uint256 marketPrice
*/
function _countBasePrice(uint256 _tokenId) internal pure returns (uint256 _price) {
if(_tokenId<=720){
//reserved for gifts and auctions
return 0;
}
if(_tokenId>720 && _tokenId<=1320){
//charity owned on market
return 100 * (uint256(10) ** 15);
}
if(_tokenId>1320 && _tokenId<=8020){
// price 5
return 34 * (uint256(10) ** 15);
}
if(_tokenId>=8021 && _tokenId<10920){
// price 6
return 40 * (uint256(10) ** 15);
}
if(_tokenId>=10920 && _tokenId<17720){
// price 7
return 47 * (uint256(10) ** 15);
}
if(_tokenId>=17720 && _tokenId<22920){
// price 8
return 54* (uint256(10) ** 15);
}
if(_tokenId>=22920 && _tokenId<29470){
// price 10
return 67 * (uint256(10) ** 15);
}
if(_tokenId>=29470 && _tokenId<30320){
// price 11
return 74 * (uint256(10) ** 15);
}
if(_tokenId>=30320 && _tokenId<32470){
// price 12
return 80 * (uint256(10) ** 15);
}
if(_tokenId>=32470 && _tokenId<35120){
// price 13
return 87 * (uint256(10) ** 15);
}
if(_tokenId>=35120 && _tokenId<35520){
// price 14
return 94 * (uint256(10) ** 15);
}
if(_tokenId>=35520 && _tokenId<42370){
// price 15
return 100 * (uint256(10) ** 15);
}
if(_tokenId>=42370 && _tokenId<46370){
// price 18
return 120 * (uint256(10) ** 15);
}
if(_tokenId>=46370 && _tokenId<55920){
// price 20
return 134 * (uint256(10) ** 15);
}
if(_tokenId>=55920 && _tokenId<59820){
// price 22
return 147 * (uint256(10) ** 15);
}
if(_tokenId>=59820 && _tokenId<63120){
// price 25
return 167 * (uint256(10) ** 15);
}
if(_tokenId>=63120 && _tokenId<78870){
// price 30
return 200 * (uint256(10) ** 15);
}
if(_tokenId>=78870 && _tokenId<79010){
// price 35
return 234 * (uint256(10) ** 15);
}
if(_tokenId>=79010 && _tokenId<84505){
// price 40
return 267 * (uint256(10) ** 15);
}
if(_tokenId>=84505 && _tokenId<84645){
// price 45
return 300 * (uint256(10) ** 15);
}
if(_tokenId>=84645 && _tokenId<85100){
// price 50
return 334 * (uint256(10) ** 15);
}
if(_tokenId>=85100 && _tokenId<85165){
// price 60
return 400 * (uint256(10) ** 15);
}
if(_tokenId>=85165 && _tokenId<85175){
// price 65
return 434 * (uint256(10) ** 15);
}
if(_tokenId>=85175 && _tokenId<85205){
// price 70
return 467 * (uint256(10) ** 15);
}
if(_tokenId>=85205 && _tokenId<85235){
// price 80
return 534 * (uint256(10) ** 15);
}
if(_tokenId>=85235 && _tokenId<85319){
// price 90
return 600 * (uint256(10) ** 15);
}
if(_tokenId>=85319 && _tokenId<85427){
// price 100
return 667 * (uint256(10) ** 15);
}
if(_tokenId>=85427 && _tokenId<85441){
// price 110
return 734 * (uint256(10) ** 15);
}
if(_tokenId>=85441 && _tokenId<85457){
// price 120
return 800 * (uint256(10) ** 15);
}
if(_tokenId>=85457 && _tokenId<85464){
// price 130
return 867 * (uint256(10) ** 15);
}
if(_tokenId>=85464 && _tokenId<85465){
// price 140
return 934 * (uint256(10) ** 15);
}
if(_tokenId>=85465 && _tokenId<85502){
// price 150
return 1000 * (uint256(10) ** 15);
}
if(_tokenId>=85502 && _tokenId<85506){
// price 160
return 1067 * (uint256(10) ** 15);
}
if(_tokenId==85506){
// price 170
return 1134 * (uint256(10) ** 15);
}
if(_tokenId==85507){
// price 180
return 1200 * (uint256(10) ** 15);
}
if(_tokenId>=85508 && _tokenId<85516){
// price 200
return 1334 * (uint256(10) ** 15);
}
if(_tokenId>=85516 && _tokenId<85518){
// price 230
return 1534 * (uint256(10) ** 15);
}
if(_tokenId>=85518 && _tokenId<85571){
// price 250
return 1667 * (uint256(10) ** 15);
}
if(_tokenId>=85571 && _tokenId<85587){
// price 300
return 2000 * (uint256(10) ** 15);
}
if(_tokenId>=85587 && _tokenId<85594){
// price 350
return 2334 * (uint256(10) ** 15);
}
if(_tokenId>=85594 && _tokenId<85597){
// price 400
return 2667 * (uint256(10) ** 15);
}
if(_tokenId>=85597 && _tokenId<85687){
// price 500
return 3334 * (uint256(10) ** 15);
}
if(_tokenId==85687){
// price 550
return 3667 * (uint256(10) ** 15);
}
if(_tokenId>=85688 && _tokenId<85692){
// price 600
return 4000 * (uint256(10) ** 15);
}
if(_tokenId==85692){
// price 680
return 4534 * (uint256(10) ** 15);
}
if(_tokenId>=85693 && _tokenId<85698){
// price 700
return 4667 * (uint256(10) ** 15);
}
if(_tokenId>=85698 && _tokenId<85700){
// price 750
return 5000 * (uint256(10) ** 15);
}
if(_tokenId==85700){
// price 800
return 5334 * (uint256(10) ** 15);
}
if(_tokenId==85701){
// price 900
return 6000 * (uint256(10) ** 15);
}
if(_tokenId>=85702 && _tokenId<85776){
// price 1000
return 6667 * (uint256(10) ** 15);
}
if(_tokenId==85776){
// price 1100
return 7334 * (uint256(10) ** 15);
}
if(_tokenId>=85777 && _tokenId<85788){
// price 1500
return 10000 * (uint256(10) ** 15);
}
if(_tokenId>=85788 && _tokenId<85795){
// price 2000
return 13334 * (uint256(10) ** 15);
}
if(_tokenId>=85795 && _tokenId<85798){
// price 2500
return 16667 * (uint256(10) ** 15);
}
if(_tokenId>=85798 && _tokenId<85803){
// price 3000
return 20000 * (uint256(10) ** 15);
}
if(_tokenId>=85803 && _tokenId<85806){
// price 5000
return 33334 * (uint256(10) ** 15);
}
if(_tokenId>=85806 && _tokenId<85807){
// price 10000
return 66667 * (uint256(10) ** 15);
}
if(_tokenId==85807){
// price 50000
return 333334 * (uint256(10) ** 15);
}
}
/**
* @dev Returns whatever token is offerd on market.
* Only used if tokenOwner == address(0)
* @param _tokenId uint256 id of token
*/
function _baseIsOnMarket(uint256 _tokenId) internal pure returns (bool _isOnMarket) {
if(_tokenId<=720){
//reserved for gits and auctions
return false;
}
if(_tokenId>720 && _tokenId<=1320){
//charity owned on market
return true;
}
if(_tokenId>1320){
//other on market
return true;
}
}
/**
* @dev Constructor
*/
constructor () public {
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC165);
_registerInterface(_INTERFACE_ID_ERC721);
//set metadata values
_name = "Crypto Tittiez";
_symbol = "CTT";
// register the supported interfaces to conform to ERC721 ERC721_METADATA
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
//set metadata values
_baseTokenURI = "https://cryptotittiez.com/api/tokeninfo/";
_totalSupply = 85807;
//after tokens creation (allmost) all tokens pretends are owned by _ownershipOwner. Look at function _ownerOf
_ownedTokensCount[msg.sender].set(85207);
//sets known addresse
_chargeAddress = address(0x03559A5AFC7F55F3d71619523d45889a6b0905c0);
_charityAddress = address(0x40497Be989B8d6fb532a6A2f0Dbf759F5d644e76);
_charityOwnerAddress = address(0x949577b216ee2D44d70d6DB210422275694cbA27);
_auctionsAddress = address(0x6800B4f9A80a1fbA4674a5716A5554f3869b57Bf);
_giftsAddress = address(0x3990e05DA96EFfF38b0aC9ddD495F41BB82Bf9a9);
//after tokens creation 600 tokens pretends are owned by _charityOwnerAddress. Look at function _ownerOf
_ownedTokensCount[_charityOwnerAddress].set(600);
//sets json hash to prove images not change
_imagesJsonHash = "2485dabaebe62276c976e55b290438799f2b60cdb845c50053e2c2be43fa6fce";
//set contract owner
_ownershipOwner = msg.sender;
}
}
{
"compilationTarget": {
"CryptoTitties.sol": "CryptoTitties"
},
"evmVersion": "petersburg",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_bid","type":"uint256"},{"indexed":false,"internalType":"address","name":"_bidder","type":"address"},{"indexed":false,"internalType":"address","name":"_old_bidder","type":"address"}],"name":"MarketAuctionBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_bid","type":"uint256"},{"indexed":false,"internalType":"address","name":"_bidder","type":"address"}],"name":"MarketAuctionClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_initPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_starttime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_endtime","type":"uint256"}],"name":"MarketAuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"}],"name":"MarketOfferCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MarketOfferRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"}],"name":"MarketOfferSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"_ownershipNewOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_ownershipOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"imagesJsonHash","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"marketAuctionBid","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"marketAuctionClaim","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_initPrice","type":"uint256"},{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"marketAuctionCreate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"marketAuctionExists","outputs":[{"internalType":"bool","name":"_exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"marketAuctionGetHighestBidder","outputs":[{"internalType":"address","name":"_bidder","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"marketAuctionGetTokenPrice","outputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"marketGetBalance","outputs":[{"internalType":"uint256","name":"_balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"marketOfferBuy","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"marketOfferCreate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"marketOfferExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"marketOfferGetTokenPrice","outputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"marketOfferRemove","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"marketSendGift","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"marketWithdrawBalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"ownershipAccept","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"ownershipTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"auctionsAddress","type":"address"}],"name":"setAuctionAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"giftsAddress","type":"address"}],"name":"setGiftsAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"_supply","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]