pragma solidity ^0.4.19;
/**
* https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/ownership/Ownable.sol
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
* license: MIT
*/
contract OwnableSimple {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function OwnableSimple() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
// based on axiomzen, MIT license
contract RandomApi {
uint64 _seed = 0;
function random(uint64 maxExclusive) public returns (uint64 randomNumber) {
// the blockhash of the current block (and future block) is 0 because it doesn't exist
_seed = uint64(keccak256(keccak256(block.blockhash(block.number - 1), _seed), block.timestamp));
return _seed % maxExclusive;
}
function random256() public returns (uint256 randomNumber) {
uint256 rand = uint256(keccak256(keccak256(block.blockhash(block.number - 1), _seed), block.timestamp));
_seed = uint64(rand);
return rand;
}
}
// @title ERC-165: Standard interface detection
// https://github.com/ethereum/EIPs/issues/165
contract ERC165 {
function supportsInterface(bytes4 _interfaceID) external view returns (bool);
}
// @title ERC-721: Non-Fungible Tokens
// @author Dieter Shirley (https://github.com/dete)
// @dev https://github.com/ethereum/eips/issues/721
contract ERC721 is ERC165 {
// Required methods
function totalSupply() public view returns (uint256 total);
function balanceOf(address _owner) public view returns (uint256 count);
function ownerOf(uint256 _tokenId) external view returns (address owner);
function approve(address _to, uint256 _tokenId) external;
function transfer(address _to, uint256 _tokenId) external;
function transferFrom(address _from, address _to, uint256 _tokenId) external;
// described in old version of the standard
// use the more flexible transferFrom
function takeOwnership(uint256 _tokenId) external;
// Events
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
// Optional
// function name() public view returns (string);
// function symbol() public view returns (string);
function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds);
function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl);
// Optional, described in old version of the standard
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256 tokenId);
function tokenMetadata(uint256 _tokenId) external view returns (string infoUrl);
}
// Based on strings library by Nick Johnson <arachnid@notdot.net>
// Apache license
// https://github.com/Arachnid/solidity-stringutils
library strings {
struct slice {
uint _len;
uint _ptr;
}
function memcpy(uint dest, uint src, uint len) private pure {
// Copy word-length chunks while possible
for(; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
// Copy remaining bytes
uint mask = 256 ** (32 - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
function toSlice(string self) internal pure returns (slice) {
uint ptr;
assembly {
ptr := add(self, 0x20)
}
return slice(bytes(self).length, ptr);
}
function toString(slice self) internal pure returns (string) {
var ret = new string(self._len);
uint retptr;
assembly { retptr := add(ret, 32) }
memcpy(retptr, self._ptr, self._len);
return ret;
}
function len(slice self) internal pure returns (uint l) {
// Starting at ptr-31 means the LSB will be the byte we care about
var ptr = self._ptr - 31;
var end = ptr + self._len;
for (l = 0; ptr < end; l++) {
uint8 b;
assembly { b := and(mload(ptr), 0xFF) }
if (b < 0x80) {
ptr += 1;
} else if(b < 0xE0) {
ptr += 2;
} else if(b < 0xF0) {
ptr += 3;
} else if(b < 0xF8) {
ptr += 4;
} else if(b < 0xFC) {
ptr += 5;
} else {
ptr += 6;
}
}
}
function len(bytes32 self) internal pure returns (uint) {
uint ret;
if (self == 0)
return 0;
if (self & 0xffffffffffffffffffffffffffffffff == 0) {
ret += 16;
self = bytes32(uint(self) / 0x100000000000000000000000000000000);
}
if (self & 0xffffffffffffffff == 0) {
ret += 8;
self = bytes32(uint(self) / 0x10000000000000000);
}
if (self & 0xffffffff == 0) {
ret += 4;
self = bytes32(uint(self) / 0x100000000);
}
if (self & 0xffff == 0) {
ret += 2;
self = bytes32(uint(self) / 0x10000);
}
if (self & 0xff == 0) {
ret += 1;
}
return 32 - ret;
}
function toSliceB32(bytes32 self) internal pure returns (slice ret) {
assembly {
let ptr := mload(0x40)
mstore(0x40, add(ptr, 0x20))
mstore(ptr, self)
mstore(add(ret, 0x20), ptr)
}
ret._len = len(self);
}
function concat(slice self, slice other) internal pure returns (string) {
var ret = new string(self._len + other._len);
uint retptr;
assembly { retptr := add(ret, 32) }
memcpy(retptr, self._ptr, self._len);
memcpy(retptr + self._len, other._ptr, other._len);
return ret;
}
}
/**
* https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/lifecycle/Pausable.sol
* @title Pausable
* @dev Base contract which allows children to implement an emergency stop mechanism.
*/
contract PausableSimple is OwnableSimple {
event Pause();
event Unpause();
bool public paused = true;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!paused);
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(paused);
_;
}
/**
* @dev called by the owner to pause, triggers stopped state
*/
function pause() onlyOwner whenNotPaused public {
paused = true;
Pause();
}
/**
* @dev called by the owner to unpause, returns to normal state
*/
function unpause() onlyOwner whenPaused public {
paused = false;
Unpause();
}
}
// heavily modified from https://github.com/dob/auctionhouse/blob/master/contracts/AuctionHouse.sol
// license: MIT
// original author: Doug Petkanics (petkanics@gmail.com) https://github.com/dob
contract PresaleMarket is PausableSimple {
struct Auction {
address seller;
uint256 price; // In wei, can be 0
}
ERC721 public artworkContract;
mapping (uint256 => Auction) artworkIdToAuction;
// 0 means everything goes to the seller
// 1000 means 1%
// 2500 means 2.5%
// 4000 means 4%
// 50000 means 50%
// 100000 means everything goes to us
uint256 public distributionCut = 2500;
bool public constant isPresaleMarket = true;
event AuctionCreated(uint256 _artworkId, uint256 _price);
event AuctionConcluded(uint256 _artworkId, uint256 _price, address _buyer);
event AuctionCancelled(uint256 _artworkId);
// mapping(address => uint256[]) public auctionsRunByUser;
// No need to have a dedicated variable
// Can be found by
// iterate all artwork ids owned by this auction contract
// get the auction object from artworkIdToAuction
// get the seller property
// return artwork id
// however it would be a lot better if our second layer keeps track of it
function auctionsRunByUser(address _address) external view returns(uint256[]) {
uint256 allArtworkCount = artworkContract.balanceOf(this);
uint256 artworkCount = 0;
uint256[] memory allArtworkIds = new uint256[](allArtworkCount);
for(uint256 i = 0; i < allArtworkCount; i++) {
uint256 artworkId = artworkContract.tokenOfOwnerByIndex(this, i);
Auction storage auction = artworkIdToAuction[artworkId];
if(auction.seller == _address) {
allArtworkIds[artworkCount++] = artworkId;
}
}
uint256[] memory result = new uint256[](artworkCount);
for(i = 0; i < artworkCount; i++) {
result[i] = allArtworkIds[i];
}
return result;
}
// constructor. rename this if you rename the contract
function PresaleMarket(address _artworkContract) public {
artworkContract = ERC721(_artworkContract);
}
function bid(uint256 _artworkId) external payable whenNotPaused {
require(_isAuctionExist(_artworkId));
Auction storage auction = artworkIdToAuction[_artworkId];
require(auction.seller != msg.sender);
uint256 price = auction.price;
require(msg.value == price);
address seller = auction.seller;
delete artworkIdToAuction[_artworkId];
if(price > 0) {
uint256 myCut = price * distributionCut / 100000;
uint256 sellerCut = price - myCut;
seller.transfer(sellerCut);
}
AuctionConcluded(_artworkId, price, msg.sender);
artworkContract.transfer(msg.sender, _artworkId);
}
function getAuction(uint256 _artworkId) external view returns(address seller, uint256 price) {
require(_isAuctionExist(_artworkId));
Auction storage auction = artworkIdToAuction[_artworkId];
return (auction.seller, auction.price);
}
function createAuction(uint256 _artworkId, uint256 _price, address _originalOwner) external whenNotPaused {
require(msg.sender == address(artworkContract));
// Will check to see if the seller owns the asset at the contract
_takeOwnership(_originalOwner, _artworkId);
Auction memory auction;
auction.seller = _originalOwner;
auction.price = _price;
_createAuction(_artworkId, auction);
}
function _createAuction(uint256 _artworkId, Auction _auction) internal {
artworkIdToAuction[_artworkId] = _auction;
AuctionCreated(_artworkId, _auction.price);
}
function cancelAuction(uint256 _artworkId) external {
require(_isAuctionExist(_artworkId));
Auction storage auction = artworkIdToAuction[_artworkId];
address seller = auction.seller;
require(msg.sender == seller);
_cancelAuction(_artworkId, seller);
}
function _cancelAuction(uint256 _artworkId, address _owner) internal {
delete artworkIdToAuction[_artworkId];
artworkContract.transfer(_owner, _artworkId);
AuctionCancelled(_artworkId);
}
function withdraw() public onlyOwner {
msg.sender.transfer(this.balance);
}
// only if there is a bug discovered and we need to migrate to a new market contract
function cancelAuctionEmergency(uint256 _artworkId) external whenPaused onlyOwner {
require(_isAuctionExist(_artworkId));
Auction storage auction = artworkIdToAuction[_artworkId];
_cancelAuction(_artworkId, auction.seller);
}
// simple methods
function _isAuctionExist(uint256 _artworkId) internal view returns(bool) {
return artworkIdToAuction[_artworkId].seller != address(0);
}
function _owns(address _address, uint256 _artworkId) internal view returns(bool) {
return artworkContract.ownerOf(_artworkId) == _address;
}
function _takeOwnership(address _originalOwner, uint256 _artworkId) internal {
artworkContract.transferFrom(_originalOwner, this, _artworkId);
}
}
contract Presale is OwnableSimple, RandomApi, ERC721 {
using strings for *;
// There are 4 batches available for presale.
// A batch is a set of artworks and
// we plan to release batches monthly.
uint256 public batchCount;
mapping(uint256 => uint256) public prices;
mapping(uint256 => uint256) public supplies;
mapping(uint256 => uint256) public sold;
// Before each batch is released on the main contract,
// we will disable transfers (including trading)
// on this contract.
// This is to prevent someone selling an artwork
// on the presale contract when we are migrating
// the artworks to the main contract.
mapping(uint256 => bool) public isTransferDisabled;
uint256[] public dnas;
mapping(address => uint256) public ownerToTokenCount;
mapping (uint256 => address) public artworkIdToOwner;
mapping (uint256 => address) public artworkIdToTransferApproved;
PresaleMarket public presaleMarket;
bytes4 constant ERC165Signature_ERC165 = bytes4(keccak256('supportsInterface(bytes4)'));
// Latest version of ERC721 perhaps
bytes4 constant ERC165Signature_ERC721A =
bytes4(keccak256('totalSupply()')) ^
bytes4(keccak256('balanceOf(address)')) ^
bytes4(keccak256('ownerOf(uint256)')) ^
bytes4(keccak256('approve(address,uint256)')) ^
bytes4(keccak256('transfer(address,uint256)')) ^
bytes4(keccak256('transferFrom(address,address,uint256)')) ^
bytes4(keccak256('name()')) ^
bytes4(keccak256('symbol()')) ^
bytes4(keccak256('tokensOfOwner(address)')) ^
bytes4(keccak256('tokenMetadata(uint256,string)'));
// as described in https://github.com/ethereum/eips/issues/721
// as of January 23, 2018
bytes4 constant ERC165Signature_ERC721B =
bytes4(keccak256('name()')) ^
bytes4(keccak256('symbol()')) ^
bytes4(keccak256('totalSupply()')) ^
bytes4(keccak256('balanceOf(address)')) ^
bytes4(keccak256('ownerOf(uint256)')) ^
bytes4(keccak256('approve(address,uint256)')) ^
bytes4(keccak256('takeOwnership(uint256)')) ^
bytes4(keccak256('transfer(address,uint256)')) ^
bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
bytes4(keccak256('tokenMetadata(uint256)'));
function Presale() public {
// Artworks are released in batches, which we plan to release
// every month if possible. New batches might contain new characters,
// or old characters in new poses. Later batches will definitely be
// more rare.
// By buying at presale, you have a chance to buy the
// artwork at potentially 50% of the public release initial sales price.
// Note that because the public release uses a sliding price system,
// once an artwork is in the marketplace, the price will get lower until
// someone buys it.
// Example: You bought a batch 1 artwork at presale for 0.05 eth.
// When the game launches, the first batch 1 artworks are generated
// on the marketplace with the initial price of 0.1 eth. You sell yours
// on the marketplace for 0.08 eth which is lower than the public release
// initial sales price. If someone buys your artwork, you will get profit.
// Note that we do not guarantee any profit whatsoever. The price of an
// item we sell will get cheaper until someone buys it. So other people might wait
// for the public release artworks to get cheaper and buy it instead of
// buying yours.
// Distribution of presale artworks:
// When the game is released, all batch 1 presale artworks
// will be immediately available for trading.
// When other batches are released, first we will generate 10 artworks
// on the marketplace. After that we will distribute the presale
// artworks with the rate of around 10 every minute.
// Note that because of mining uncertainties we cannot guarantee any
// specific timings.
// public release initial sales price >= 0.1 ether
_addPresale(0.05 ether, 450);
// public release initial sales price >= 0.24 ether
_addPresale(0.12 ether, 325);
// public release initial sales price >= 0.7 ether
_addPresale(0.35 ether, 150);
// public release initial sales price >= 2.0 ether
_addPresale(1.0 ether, 75);
}
function buy(uint256 _batch) public payable {
require(_batch < batchCount);
require(msg.value == prices[_batch]); // we don't want to deal with refunds
require(sold[_batch] < supplies[_batch]);
sold[_batch]++;
uint256 dna = _generateRandomDna(_batch);
uint256 artworkId = dnas.push(dna) - 1;
ownerToTokenCount[msg.sender]++;
artworkIdToOwner[artworkId] = msg.sender;
Transfer(0, msg.sender, artworkId);
}
function getArtworkInfo(uint256 _id) external view returns (
uint256 dna, address owner) {
require(_id < totalSupply());
dna = dnas[_id];
owner = artworkIdToOwner[_id];
}
function withdraw() public onlyOwner {
msg.sender.transfer(this.balance);
}
function getBatchInfo(uint256 _batch) external view returns(uint256 price, uint256 supply, uint256 soldAmount) {
require(_batch < batchCount);
return (prices[_batch], supplies[_batch], sold[_batch]);
}
function setTransferDisabled(uint256 _batch, bool _isDisabled) external onlyOwner {
require(_batch < batchCount);
isTransferDisabled[_batch] = _isDisabled;
}
function setPresaleMarketAddress(address _address) public onlyOwner {
PresaleMarket presaleMarketTest = PresaleMarket(_address);
require(presaleMarketTest.isPresaleMarket());
presaleMarket = presaleMarketTest;
}
function sell(uint256 _artworkId, uint256 _price) external {
require(_isOwnerOf(msg.sender, _artworkId));
require(_canTransferBatch(_artworkId));
_approveTransfer(_artworkId, presaleMarket);
presaleMarket.createAuction(_artworkId, _price, msg.sender);
}
// Helper methods
function _addPresale(uint256 _price, uint256 _supply) private {
prices[batchCount] = _price;
supplies[batchCount] = _supply;
batchCount++;
}
function _generateRandomDna(uint256 _batch) private returns(uint256 dna) {
uint256 rand = random256() % (10 ** 76);
// set batch digits
rand = rand / 100000000 * 100000000 + _batch;
return rand;
}
function _isOwnerOf(address _address, uint256 _tokenId) private view returns (bool) {
return artworkIdToOwner[_tokenId] == _address;
}
function _approveTransfer(uint256 _tokenId, address _address) internal {
artworkIdToTransferApproved[_tokenId] = _address;
}
function _transfer(address _from, address _to, uint256 _tokenId) internal {
artworkIdToOwner[_tokenId] = _to;
ownerToTokenCount[_to]++;
ownerToTokenCount[_from]--;
delete artworkIdToTransferApproved[_tokenId];
Transfer(_from, _to, _tokenId);
}
function _approvedForTransfer(address _address, uint256 _tokenId) internal view returns (bool) {
return artworkIdToTransferApproved[_tokenId] == _address;
}
function _transferFrom(address _from, address _to, uint256 _tokenId) internal {
require(_isOwnerOf(_from, _tokenId));
require(_approvedForTransfer(msg.sender, _tokenId));
// prevent accidental transfer
require(_to != address(0));
require(_to != address(this));
// perform the transfer and emit Transfer event
_transfer(_from, _to, _tokenId);
}
function _canTransferBatch(uint256 _tokenId) internal view returns(bool) {
uint256 batch = dnas[_tokenId] % 10;
return !isTransferDisabled[batch];
}
function _tokenMetadata(uint256 _tokenId, string _preferredTransport) internal view returns (string infoUrl) {
_preferredTransport; // we don't use this parameter
require(_tokenId < totalSupply());
strings.slice memory tokenIdSlice = _uintToBytes(_tokenId).toSliceB32();
return "/http/etherwaifu.com/presale/artwork/".toSlice().concat(tokenIdSlice);
}
// Author: pipermerriam
// MIT license
// https://github.com/pipermerriam/ethereum-string-utils
function _uintToBytes(uint256 v) internal pure returns(bytes32 ret) {
if (v == 0) {
ret = '0';
}
else {
while (v > 0) {
ret = bytes32(uint256(ret) / (2 ** 8));
ret |= bytes32(((v % 10) + 48) * 2 ** (8 * 31));
v /= 10;
}
}
return ret;
}
// Required methods of ERC721
function totalSupply() public view returns (uint256) {
return dnas.length;
}
function balanceOf(address _owner) public view returns (uint256) {
return ownerToTokenCount[_owner];
}
function ownerOf(uint256 _tokenId) external view returns (address) {
address theOwner = artworkIdToOwner[_tokenId];
require(theOwner != address(0));
return theOwner;
}
function approve(address _to, uint256 _tokenId) external {
require(_canTransferBatch(_tokenId));
require(_isOwnerOf(msg.sender, _tokenId));
// MUST throw if _tokenID does not represent an NFT
// but if it is not NFT, owner is address(0)
// which means it is impossible because msg.sender is a nonzero address
require(msg.sender != _to);
address prevApprovedAddress = artworkIdToTransferApproved[_tokenId];
_approveTransfer(_tokenId, _to);
// Don't send Approval event if it is just
// reaffirming that there is no one approved
if(!(prevApprovedAddress == address(0) && _to == address(0))) {
Approval(msg.sender, _to, _tokenId);
}
}
function transfer(address _to, uint256 _tokenId) external {
require(_canTransferBatch(_tokenId));
require(_isOwnerOf(msg.sender, _tokenId));
// prevent accidental transfers
require(_to != address(0));
require(_to != address(this));
require(_to != address(presaleMarket));
// perform the transfer and emit Transfer event
_transfer(msg.sender, _to, _tokenId);
}
function transferFrom(address _from, address _to, uint256 _tokenId) external {
require(_canTransferBatch(_tokenId));
_transferFrom(_from, _to, _tokenId);
}
function takeOwnership(uint256 _tokenId) external {
require(_canTransferBatch(_tokenId));
address owner = artworkIdToOwner[_tokenId];
_transferFrom(owner, msg.sender, _tokenId);
}
// Optional methods of ERC721
function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds) {
uint256 count = balanceOf(_owner);
uint256[] memory res = new uint256[](count);
uint256 allArtworkCount = totalSupply();
uint256 i = 0;
for(uint256 artworkId = 1; artworkId <= allArtworkCount && i < count; artworkId++) {
if(artworkIdToOwner[artworkId] == _owner) {
res[i++] = artworkId;
}
}
return res;
}
function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) {
return _tokenMetadata(_tokenId, _preferredTransport);
}
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256 tokenId) {
require(_index < balanceOf(_owner));
// not strictly needed because if the state is consistent then
// a match will be found
uint256 allArtworkCount = totalSupply();
uint256 i = 0;
for(uint256 artworkId = 0; artworkId < allArtworkCount; artworkId++) {
if(artworkIdToOwner[artworkId] == _owner) {
if(i == _index) {
return artworkId;
} else {
i++;
}
}
}
assert(false); // should never reach here
}
function tokenMetadata(uint256 _tokenId) external view returns (string infoUrl) {
return _tokenMetadata(_tokenId, "http");
}
// ERC-165 Standard interface detection (required)
function supportsInterface(bytes4 _interfaceID) external view returns (bool)
{
return _interfaceID == ERC165Signature_ERC165 ||
_interfaceID == ERC165Signature_ERC721A ||
_interfaceID == ERC165Signature_ERC721B;
}
}
{
"compilationTarget": {
"Presale.sol": "Presale"
},
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[{"name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_preferredTransport","type":"string"}],"name":"tokenMetadata","outputs":[{"name":"infoUrl","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"batchCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_batch","type":"uint256"}],"name":"getBatchInfo","outputs":[{"name":"price","type":"uint256"},{"name":"supply","type":"uint256"},{"name":"soldAmount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"maxExclusive","type":"uint64"}],"name":"random","outputs":[{"name":"randomNumber","type":"uint64"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"presaleMarket","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_batch","type":"uint256"},{"name":"_isDisabled","type":"bool"}],"name":"setTransferDisabled","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"supplies","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"artworkIdToOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"name":"tokenId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"dnas","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"ownerToTokenCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"tokenMetadata","outputs":[{"name":"infoUrl","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"name":"tokenIds","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"isTransferDisabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"random256","outputs":[{"name":"randomNumber","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"sold","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"takeOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"prices","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_artworkId","type":"uint256"},{"name":"_price","type":"uint256"}],"name":"sell","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_batch","type":"uint256"}],"name":"buy","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"getArtworkInfo","outputs":[{"name":"dna","type":"uint256"},{"name":"owner","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"artworkIdToTransferApproved","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"setPresaleMarketAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_approved","type":"address"},{"indexed":false,"name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]