pragma solidity 0.4.19;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint a, uint b) internal pure returns (uint) {
if (a == 0) {
return 0;
}
uint c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint a, uint b) internal pure returns (uint) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint 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, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint a, uint b) internal pure returns (uint) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() 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;
}
}
/**
* @title Heritable
* @dev The Heritable contract provides ownership transfer capabilities, in the
* case that the current owner stops "heartbeating". Only the heir can pronounce the
* owner's death.
*/
contract Heritable is Ownable {
address public heir;
// Time window the owner has to notify they are alive.
uint public heartbeatTimeout;
// Timestamp of the owner's death, as pronounced by the heir.
uint public timeOfDeath;
event HeirChanged(address indexed owner, address indexed newHeir);
event OwnerHeartbeated(address indexed owner);
event OwnerProclaimedDead(address indexed owner, address indexed heir, uint timeOfDeath);
event HeirOwnershipClaimed(address indexed previousOwner, address indexed newOwner);
/**
* @dev Throw an exception if called by any account other than the heir's.
*/
modifier onlyHeir() {
require(msg.sender == heir);
_;
}
/**
* @notice Create a new Heritable Contract with heir address 0x0.
* @param _heartbeatTimeout time available for the owner to notify they are alive,
* before the heir can take ownership.
*/
function Heritable(uint _heartbeatTimeout) public {
setHeartbeatTimeout(_heartbeatTimeout);
}
function setHeir(address newHeir) public onlyOwner {
require(newHeir != owner);
heartbeat();
HeirChanged(owner, newHeir);
heir = newHeir;
}
/**
* @dev set heir = 0x0
*/
function removeHeir() public onlyOwner {
heartbeat();
heir = 0;
}
/**
* @dev Heir can pronounce the owners death. To claim the ownership, they will
* have to wait for `heartbeatTimeout` seconds.
*/
function proclaimDeath() public onlyHeir {
require(owner != heir); // added
require(ownerLives());
OwnerProclaimedDead(owner, heir, timeOfDeath);
timeOfDeath = now;
}
/**
* @dev Owner can send a heartbeat if they were mistakenly pronounced dead.
*/
function heartbeat() public onlyOwner {
OwnerHeartbeated(owner);
timeOfDeath = 0;
}
/**
* @dev Allows heir to transfer ownership only if heartbeat has timed out.
*/
function claimHeirOwnership() public onlyHeir {
require(!ownerLives());
require(now >= timeOfDeath + heartbeatTimeout);
OwnershipTransferred(owner, heir);
HeirOwnershipClaimed(owner, heir);
owner = heir;
timeOfDeath = 0;
}
function setHeartbeatTimeout(uint newHeartbeatTimeout) internal onlyOwner {
require(ownerLives());
heartbeatTimeout = newHeartbeatTimeout;
}
function ownerLives() internal view returns (bool) {
return timeOfDeath == 0;
}
}
/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens
/// @author Dieter Shirley <dete@axiomzen.co> (https://github.com/dete)
contract ERC721 {
// Required methods
function approve(address _to, uint _tokenId) public;
function balanceOf(address _owner) public view returns (uint balance);
function implementsERC721() public pure returns (bool);
function ownerOf(uint _tokenId) public view returns (address addr);
function takeOwnership(uint _tokenId) public;
function totalSupply() public view returns (uint total);
function transferFrom(address _from, address _to, uint _tokenId) public;
function transfer(address _to, uint _tokenId) public;
event Transfer(address indexed from, address indexed to, uint tokenId);
event Approval(address indexed owner, address indexed approved, uint tokenId);
// Optional
// function name() public view returns (string name);
// function symbol() public view returns (string symbol);
// function tokenOfOwnerByIndex(address _owner, uint _index) external view returns (uint tokenId);
// function tokenMetadata(uint _tokenId) public view returns (string infoUrl);
}
contract BitArtToken is Heritable, ERC721 {
string public constant NAME = "BitGallery";
string public constant SYMBOL = "BitArt";
struct Art {
bytes32 data;
}
Art[] internal arts;
mapping (uint => address) public tokenOwner;
mapping (address => uint) public ownedTokenCount;
mapping (uint => address) public tokenApprovals;
event Transfer(address from, address to, uint tokenId);
event Approval(address owner, address approved, uint tokenId);
// 30 days to change owner
function BitArtToken() Heritable(2592000) public {}
function tokensOf(address _owner) external view returns(uint[]) {
uint tokenCount = balanceOf(_owner);
if (tokenCount == 0) {
return new uint[](0);
} else {
uint[] memory result = new uint[](tokenCount);
uint totaltokens = totalSupply();
uint index = 0;
for (uint tokenId = 0; tokenId < totaltokens; tokenId++) {
if (tokenOwner[tokenId] == _owner) {
result[index] = tokenId;
index++;
}
}
return result;
}
}
function approve(address _to, uint _tokenId) public {
require(_owns(msg.sender, _tokenId));
tokenApprovals[_tokenId] = _to;
Approval(msg.sender, _to, _tokenId);
}
function balanceOf(address _owner) public view returns (uint balance) {
return ownedTokenCount[_owner];
}
function getArts() public view returns (bytes32[]) {
uint count = totalSupply();
bytes32[] memory result = new bytes32[](count);
for (uint i = 0; i < count; i++) {
result[i] = arts[i].data;
}
return result;
}
function implementsERC721() public pure returns (bool) {
return true;
}
function name() public pure returns (string) {
return NAME;
}
function ownerOf(uint _tokenId) public view returns (address owner) {
owner = tokenOwner[_tokenId];
require(_addressNotNull(owner));
}
function symbol() public pure returns (string) {
return SYMBOL;
}
function takeOwnership(uint _tokenId) public {
address newOwner = msg.sender;
require(_addressNotNull(newOwner));
require(_approved(newOwner, _tokenId));
address oldOwner = tokenOwner[_tokenId];
_transfer(oldOwner, newOwner, _tokenId);
}
function totalSupply() public view returns (uint total) {
return arts.length;
}
function transfer(address _to, uint _tokenId) public {
require(_owns(msg.sender, _tokenId));
require(_addressNotNull(_to));
_transfer(msg.sender, _to, _tokenId);
}
function transferFrom(address _from, address _to, uint _tokenId) public {
require(_owns(_from, _tokenId));
require(_approved(_to, _tokenId));
require(_addressNotNull(_to));
_transfer(_from, _to, _tokenId);
}
function _mint(address _to, uint256 _tokenId) internal {
require(_to != address(0));
require(tokenOwner[_tokenId] == address(0));
_transfer(0x0, _to, _tokenId);
}
function _transfer(address _from, address _to, uint _tokenId) internal {
require(_from != _to);
ownedTokenCount[_to]++;
tokenOwner[_tokenId] = _to;
if (_addressNotNull(_from)) {
ownedTokenCount[_from]--;
delete tokenApprovals[_tokenId];
}
Transfer(_from, _to, _tokenId);
}
function _addressNotNull(address _address) private pure returns (bool) {
return _address != address(0);
}
function _approved(address _to, uint _tokenId) private view returns (bool) {
return tokenApprovals[_tokenId] == _to;
}
function _owns(address _claimant, uint _tokenId) private view returns (bool) {
return _claimant == tokenOwner[_tokenId];
}
}
contract BitAuction is BitArtToken {
using SafeMath for uint;
struct Auction {
uint basePrice;
uint64 time1;
uint64 time2;
uint8 pct1;
uint8 pct2;
uint8 discount;
}
uint internal _auctionStartsAfter;
uint internal _auctionDuration;
uint internal _auctionFee;
mapping (uint => Auction) public tokenAuction;
event AuctionRulesChanged(uint startsAfter, uint duration, uint fee);
event NewAuction(uint tokenId, uint discount);
event NewSaleDiscount(uint tokenId, uint discount);
function BitAuction() public { }
function setSaleDiscount(uint _tokenId, uint _discount) external {
require(ownerOf(_tokenId) == msg.sender);
require(_discount <= 90);
require(_discount >= 10);
Auction storage auction = tokenAuction[_tokenId];
require(auction.basePrice > 0);
require(auction.time2 <= now);
auction.discount = uint8(_discount);
NewSaleDiscount(_tokenId, _discount);
}
function canPurchase(uint _tokenId) public view returns (bool) {
Auction storage auction = tokenAuction[_tokenId];
require(auction.time1 > 0);
return (now >= auction.time1 && priceOf(_tokenId) > 0);
}
function getPrices(uint[] _ids) public view returns (uint[]) {
uint count = _ids.length;
bool isEmpty = count == 0;
if (isEmpty) {
count = totalSupply();
}
uint[] memory result = new uint[](count);
for (uint i = 0; i < count; i++) {
uint tokenId = isEmpty ? i : _ids[i];
result[i] = priceOf(tokenId);
}
return result;
}
function priceOf(uint _tokenId) public view returns (uint) {
Auction storage auction = tokenAuction[_tokenId];
return _currentPrice(auction);
}
function setAuctionDurationRules(uint _timeAfter, uint _duration, uint _fee) public onlyOwner {
require(_timeAfter >= 0 seconds);
require(_timeAfter <= 7 days);
require(_duration >= 24 hours);
require(_duration <= 30 days);
require(_fee >= 1);
require(_fee <= 5);
_auctionStartsAfter = _timeAfter;
_auctionDuration = _duration;
_auctionFee = _fee;
AuctionRulesChanged(_timeAfter, _duration, _fee);
}
function _createCustomAuction(uint _tokenId, uint _basePrice, uint _time1, uint _time2, uint _pct1, uint _pct2) private {
require(_time1 >= now);
require(_time2 >= _time1);
require(_pct1 > 0);
require(_pct2 > 0);
Auction memory auction = Auction({
basePrice: _basePrice,
time1: uint64(_time1),
time2: uint64(_time2),
pct1: uint8(_pct1),
pct2: uint8(_pct2),
discount: 0
});
tokenAuction[_tokenId] = auction;
}
function _createNewTokenAuction(uint _tokenId, uint _basePrice) internal {
_createCustomAuction(_tokenId, _basePrice, now, now + _auctionStartsAfter + _auctionDuration, 100, 10);
}
function _createStandartAuction(uint _tokenId, uint _basePrice) internal {
uint start = now + _auctionStartsAfter;
_createCustomAuction(_tokenId, _basePrice, start, start + _auctionDuration, 200, 110);
}
function _currentPrice(Auction _auction) internal view returns (uint) {
if (_auction.discount > 0) {
return uint((_auction.basePrice * (100 - _auction.discount)) / 100);
}
uint _startingPrice = uint((_auction.basePrice * _auction.pct1) / 100);
if (_auction.time1 > now) {
return _startingPrice;
}
uint _secondsPassed = uint(now - _auction.time1);
uint _duration = uint(_auction.time2 - _auction.time1);
uint _endingPrice = uint((_auction.basePrice * _auction.pct2) / 100);
if (_secondsPassed >= _duration) {
return _endingPrice;
} else {
int totalPriceChange = int(_endingPrice) - int(_startingPrice);
int currentPriceChange = totalPriceChange * int(_secondsPassed) / int(_duration);
int currentPrice = int(_startingPrice) + currentPriceChange;
return uint(currentPrice);
}
}
function _computePrice(uint _secondsPassed, uint _duration, uint _startingPrice, uint _endingPrice) private pure returns (uint) {
if (_secondsPassed >= _duration) {
return _endingPrice;
} else {
int totalPriceChange = int(_endingPrice) - int(_startingPrice);
int currentPriceChange = totalPriceChange * int(_secondsPassed) / int(_duration);
int currentPrice = int(_startingPrice) + currentPriceChange;
return uint(currentPrice);
}
}
}
contract BitGallery is BitAuction {
using SafeMath for uint;
string public infoMessage;
event TokenSold(uint tokenId, uint price, address from, address to);
event NewToken(uint tokenId, string metadata);
function BitGallery() public {
setAuctionDurationRules(24 hours, 6 days, 3);
setMessage("Our web site is www.bitgallery.co");
}
function() public payable {}
function addArt(string _keyData, uint _basePrice) public onlyOwner {
return addArtTo(address(this), _keyData, _basePrice);
}
function addArtTo(address _owner, string _keyData, uint _basePrice) public onlyOwner {
require(_basePrice >= 1 finney);
Art memory _art = Art({
data: keccak256(_keyData)
});
uint tokenId = arts.push(_art) - 1;
NewToken(tokenId, _keyData);
_mint(_owner, tokenId);
_createNewTokenAuction(tokenId, _basePrice);
}
function artExists(string _keydata) public view returns (bool) {
for (uint i = 0; i < totalSupply(); i++) {
if (arts[i].data == keccak256(_keydata)) {
return true;
}
}
return false;
}
function fullDataOf(uint _tokenId) public view returns (
uint basePrice,
uint64 time1,
uint64 time2,
uint8 pct1,
uint8 pct2,
uint8 discount,
uint currentPrice,
bool _canPurchase,
address owner
) {
Auction storage auction = tokenAuction[_tokenId];
basePrice = auction.basePrice;
time1 = auction.time1;
time2 = auction.time2;
pct1 = auction.pct1;
pct2 = auction.pct2;
discount = auction.discount;
currentPrice = priceOf(_tokenId);
_canPurchase = canPurchase(_tokenId);
owner = ownerOf(_tokenId);
}
function payout(address _to) public onlyOwner {
require(_to != address(this));
if (_to == address(0)) {
_to = msg.sender;
}
_to.transfer(this.balance);
}
function purchase(uint _tokenId) public payable {
Auction storage auction = tokenAuction[_tokenId];
require(now >= auction.time1);
uint price = _currentPrice(auction);
require(msg.value >= price);
uint payment = uint((price * (100 - _auctionFee)) / 100);
uint purchaseExcess = msg.value - price;
_createStandartAuction(_tokenId, price);
address from = ownerOf(_tokenId);
address to = msg.sender;
_transfer(from, to, _tokenId);
if (from != address(this)) {
from.transfer(payment);
}
TokenSold(_tokenId, price, from, to);
msg.sender.transfer(purchaseExcess);
}
function setMessage(string _message) public onlyOwner {
infoMessage = _message;
}
}
{
"compilationTarget": {
"BitGallery.sol": "BitGallery"
},
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","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":"_ids","type":"uint256[]"}],"name":"getPrices","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"}],"name":"payout","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"implementsERC721","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"total","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"claimHeirOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tokenOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"ownedTokenCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","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":false,"inputs":[{"name":"newHeir","type":"address"}],"name":"setHeir","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"proclaimDeath","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_keyData","type":"string"},{"name":"_basePrice","type":"uint256"}],"name":"addArt","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_message","type":"string"}],"name":"setMessage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_discount","type":"uint256"}],"name":"setSaleDiscount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"heartbeat","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"tokensOf","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"fullDataOf","outputs":[{"name":"basePrice","type":"uint256"},{"name":"time1","type":"uint64"},{"name":"time2","type":"uint64"},{"name":"pct1","type":"uint8"},{"name":"pct2","type":"uint8"},{"name":"discount","type":"uint8"},{"name":"currentPrice","type":"uint256"},{"name":"_canPurchase","type":"bool"},{"name":"owner","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getArts","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"owner","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"heartbeatTimeout","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"canPurchase","outputs":[{"name":"","type":"bool"}],"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":"heir","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"infoMessage","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"NAME","outputs":[{"name":"","type":"string"}],"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":true,"inputs":[{"name":"_keydata","type":"string"}],"name":"artExists","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tokenApprovals","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"takeOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"timeOfDeath","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"priceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_timeAfter","type":"uint256"},{"name":"_duration","type":"uint256"},{"name":"_fee","type":"uint256"}],"name":"setAuctionDurationRules","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"removeHeir","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tokenAuction","outputs":[{"name":"basePrice","type":"uint256"},{"name":"time1","type":"uint64"},{"name":"time2","type":"uint64"},{"name":"pct1","type":"uint8"},{"name":"pct2","type":"uint8"},{"name":"discount","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"purchase","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_keyData","type":"string"},{"name":"_basePrice","type":"uint256"}],"name":"addArtTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"SYMBOL","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"tokenId","type":"uint256"},{"indexed":false,"name":"price","type":"uint256"},{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"to","type":"address"}],"name":"TokenSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"tokenId","type":"uint256"},{"indexed":false,"name":"metadata","type":"string"}],"name":"NewToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"startsAfter","type":"uint256"},{"indexed":false,"name":"duration","type":"uint256"},{"indexed":false,"name":"fee","type":"uint256"}],"name":"AuctionRulesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"tokenId","type":"uint256"},{"indexed":false,"name":"discount","type":"uint256"}],"name":"NewAuction","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"tokenId","type":"uint256"},{"indexed":false,"name":"discount","type":"uint256"}],"name":"NewSaleDiscount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"approved","type":"address"},{"indexed":false,"name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"newHeir","type":"address"}],"name":"HeirChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"OwnerHeartbeated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"heir","type":"address"},{"indexed":false,"name":"timeOfDeath","type":"uint256"}],"name":"OwnerProclaimedDead","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"HeirOwnershipClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]