pragma solidity ^0.4.19;
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract ETH10K {
using SafeMath for uint256;
uint8 private constant MAX_COLS = 64;
uint8 private constant MAX_ROWS = 160;
uint8 private Reserved_upRow = 8;
uint8 private Reserved_downRow = 39;
uint8 private max_merge_size = 2;
event Bought (uint256 indexed _itemId, address indexed _owner, uint256 _price);
event Sold (uint256 indexed _itemId, address indexed _owner, uint256 _price);
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
address private owner;
mapping (address => bool) private admins;
bool private erc721Enabled = false;
bool private mergeEnabled = false;
uint256 private increaseLimit1 = 0.02 ether;
uint256 private increaseLimit2 = 0.5 ether;
uint256 private increaseLimit3 = 2.0 ether;
uint256 private increaseLimit4 = 5.0 ether;
uint256 private startingPrice = 0.001 ether;
uint256[] private listedItems;
mapping (uint256 => address) private ownerOfItem;
mapping (uint256 => uint256) private priceOfItem;
mapping (address => string) private usernameOfAddress;
function ETH10K () public {
owner = msg.sender;
admins[owner] = true;
}
/* Modifiers */
modifier onlyOwner() {
require(owner == msg.sender);
_;
}
modifier onlyAdmins() {
require(admins[msg.sender]);
_;
}
modifier onlyERC721() {
require(erc721Enabled);
_;
}
modifier onlyMergeEnable(){
require(mergeEnabled);
_;
}
/* Owner */
function setOwner (address _owner) onlyOwner() public {
owner = _owner;
}
function addAdmin (address _admin) onlyOwner() public {
admins[_admin] = true;
}
function removeAdmin (address _admin) onlyOwner() public {
delete admins[_admin];
}
// Unlocks ERC721 behaviour, allowing for trading on third party platforms.
function enableERC721 () onlyOwner() public {
erc721Enabled = true;
}
function enableMerge (bool status) onlyAdmins() public {
mergeEnabled = status;
}
function setReserved(uint8 _up,uint8 _down) onlyAdmins() public{
Reserved_upRow = _up;
Reserved_downRow = _down;
}
function setMaxMerge(uint8 num)onlyAdmins() external{
max_merge_size = num;
}
/* Withdraw */
/*
*/
function withdrawAll () onlyOwner() public {
require(this.balance > 0);
owner.transfer(this.balance);
}
function withdrawAmount (uint256 _amount) onlyOwner() public {
owner.transfer(_amount);
}
/* Buying */
function calculateNextPrice (uint256 _price) public view returns (uint256 _nextPrice) {
if (_price < increaseLimit1) {
return _price.mul(200).div(95);
} else if (_price < increaseLimit2) {
return _price.mul(135).div(96);
} else if (_price < increaseLimit3) {
return _price.mul(125).div(97);
} else if (_price < increaseLimit4) {
return _price.mul(117).div(97);
} else {
return _price.mul(115).div(98);
}
}
function calculateDevCut (uint256 _price) public view returns (uint256 _devCut) {
if (_price < increaseLimit1) {
return _price.mul(5).div(100); // 5%
} else if (_price < increaseLimit2) {
return _price.mul(4).div(100); // 4%
} else if (_price < increaseLimit3) {
return _price.mul(3).div(100); // 3%
} else if (_price < increaseLimit4) {
return _price.mul(3).div(100); // 3%
} else {
return _price.mul(2).div(100); // 2%
}
}
function requestMerge(uint256[] ids)onlyMergeEnable() external {
require(ids.length == 4);
require(ids[0]%(10**8)/(10**4)<max_merge_size);
require(ids[1]%(10**8)/(10**4)<max_merge_size);
require(ids[2]%(10**8)/(10**4)<max_merge_size);
require(ids[3]%(10**8)/(10**4)<max_merge_size);
require(ownerOfItem[ids[0]] == msg.sender);
require(ownerOfItem[ids[1]] == msg.sender);
require(ownerOfItem[ids[2]] == msg.sender);
require(ownerOfItem[ids[3]] == msg.sender);
require(ids[0]+ (10**12) == ids[1]);
require(ids[0]+ (10**8) == ids[2]);
require(ids[0]+ (10**8) + (10**12) == ids[3]);
uint256 newPrice = priceOfItem[ids[0]]+priceOfItem[ids[1]]+priceOfItem[ids[2]]+priceOfItem[ids[3]];
uint256 newId = ids[0] + ids[0]%(10**8);
listedItems.push(newId);
priceOfItem[newId] = newPrice;
ownerOfItem[newId] = msg.sender;
ownerOfItem[ids[0]] = address(0);
ownerOfItem[ids[1]] = address(0);
ownerOfItem[ids[2]] = address(0);
ownerOfItem[ids[3]] = address(0);
}
function checkIsOnSale(uint256 _ypos)public view returns(bool isOnSale){
if(_ypos<Reserved_upRow||_ypos>Reserved_downRow){
return false;
}else{
return true;
}
}
function generateId(uint256 _xpos,uint256 _ypos,uint256 _size)internal pure returns(uint256 _id){
uint256 temp= _xpos * (10**12) + _ypos * (10**8) + _size*(10**4);
return temp;
}
function parseId(uint256 _id)internal pure returns(uint256 _x,uint256 _y,uint256 _size){
uint256 xpos = _id / (10**12);
uint256 ypos = (_id-xpos*(10**12)) / (10**8);
uint256 size = _id % (10**5) / (10**4);
return (xpos,ypos,size);
}
function setUserName(string _name)payable public{
require(msg.value >= 0.01 ether);
usernameOfAddress[msg.sender] = _name;
uint256 excess = msg.value - 0.01 ether;
if (excess > 0) {
msg.sender.transfer(excess);
}
}
function getUserName()public view returns(string name){
return usernameOfAddress[msg.sender];
}
function getUserNameOf(address _user)public view returns(string name){
return usernameOfAddress[_user];
}
function addBlock(address _to, uint256 _xpos,uint256 _ypos,uint256 _size,uint256 _price) onlyAdmins() public {
require(checkIsOnSale(_ypos) == true);
require(_size == 1);
require(_xpos + _size <= MAX_COLS);
uint256 _itemId = generateId(_xpos,_ypos,_size);
require(priceOf(_itemId)==0);
require(ownerOf(_itemId)==address(0));
listedItems.push(_itemId);
priceOfItem[_itemId] = _price;
ownerOfItem[_itemId] = _to;
}
//Buy the block with somebody owned already
function buyOld (uint256 _index) payable public {
require(_index!=0);
require(msg.value >= priceOf(_index));
require(ownerOf(_index) != msg.sender);
require(ownerOf(_index) != address(0));
uint256 price = priceOf(_index);
address oldOwner = ownerOfItem[_index];
priceOfItem[_index] = calculateNextPrice(price);
uint256 excess = msg.value.sub(price);
address newOwner = msg.sender;
ownerOfItem[_index] = newOwner;
uint256 devCut = calculateDevCut(price);
oldOwner.transfer(price.sub(devCut));
if (excess > 0) {
newOwner.transfer(excess);
}
}
//Buy a new block without anybody owned
function buyNew (uint256 _xpos,uint256 _ypos,uint256 _size) payable public {
require(checkIsOnSale(_ypos) == true);
require(_size == 1);
require(_xpos + _size <= MAX_COLS);
uint256 _itemId = generateId(_xpos,_ypos,_size);
require(priceOf(_itemId)==0);
require(ownerOf(_itemId)==address(0));
uint256 price =startingPrice;
address oldOwner = owner;
listedItems.push(_itemId);
priceOfItem[_itemId] = calculateNextPrice(price);
uint256 excess = msg.value.sub(price);
address newOwner = msg.sender;
ownerOfItem[_itemId] = newOwner;
uint256 devCut = calculateDevCut(price);
oldOwner.transfer(price.sub(devCut));
if (excess > 0) {
newOwner.transfer(excess);
}
}
function MergeStatus() public view returns (bool _MergeOpen) {
return mergeEnabled;
}
/* ERC721 */
function implementsERC721() public view returns (bool _implements) {
return erc721Enabled;
}
function name() public pure returns (string _name) {
return "ETH10K.io";
}
function symbol() public pure returns (string _symbol) {
return "block";
}
function totalSupply() public view returns (uint256 _totalSupply) {
uint256 total = 0;
for(uint256 i=0; i<listedItems.length; i++){
if(ownerOf(listedItems[i])!=address(0)){
total++;
}
}
return total;
}
function balanceOf (address _owner) public view returns (uint256 _balance) {
uint256 counter = 0;
for (uint256 i = 0; i < listedItems.length; i++) {
if (ownerOf(listedItems[i]) == _owner) {
counter++;
}
}
return counter;
}
function ownerOf (uint256 _itemId) public view returns (address _owner) {
return ownerOfItem[_itemId];
}
function cellsOf (address _owner) public view returns (uint256[] _tokenIds) {
uint256[] memory items = new uint256[](balanceOf(_owner));
uint256 itemCounter = 0;
for (uint256 i = 0; i < listedItems.length; i++) {
if (ownerOf(listedItems[i]) == _owner) {
items[itemCounter] = listedItems[i];
itemCounter += 1;
}
}
return items;
}
function getAllCellIds () public view returns (uint256[] _tokenIds) {
uint256[] memory items = new uint256[](totalSupply());
uint256 itemCounter = 0;
for (uint256 i = 0; i < listedItems.length; i++) {
if (ownerOfItem[listedItems[i]] != address(0)) {
items[itemCounter] = listedItems[i];
itemCounter += 1;
}
}
return items;
}
/* Read */
function isAdmin (address _admin) public view returns (bool _isAdmin) {
return admins[_admin];
}
function startingPriceOf () public view returns (uint256 _startingPrice) {
return startingPrice;
}
function priceOf (uint256 _itemId) public view returns (uint256 _price) {
return priceOfItem[_itemId];
}
function nextPriceOf (uint256 _itemId) public view returns (uint256 _nextPrice) {
return calculateNextPrice(priceOf(_itemId));
}
function allOf (uint256 _itemId) external view returns (address _owner, uint256 _startingPrice, uint256 _price, uint256 _nextPrice, uint256 _xpos, uint256 _ypos, uint256 _size) {
uint256 xpos;
uint256 ypos;
uint256 size;
(xpos,ypos,size) = parseId(_itemId);
return (ownerOfItem[_itemId],startingPriceOf(),priceOf(_itemId),nextPriceOf(_itemId),xpos,ypos,size);
}
function getAllCellInfo()external view returns(uint256[] _tokenIds,uint256[] _prices, address[] _owners){
uint256[] memory items = new uint256[](totalSupply());
uint256[] memory prices = new uint256[](totalSupply());
address[] memory owners = new address[](totalSupply());
uint256 itemCounter = 0;
for (uint256 i = 0; i < listedItems.length; i++) {
if (ownerOf(listedItems[i]) !=address(0)) {
items[itemCounter] = listedItems[i];
prices[itemCounter] = priceOf(listedItems[i]);
owners[itemCounter] = ownerOf(listedItems[i]);
itemCounter += 1;
}
}
return (items,prices,owners);
}
function getAllCellInfoFrom_To(uint256 _from, uint256 _to)external view returns(uint256[] _tokenIds,uint256[] _prices, address[] _owners){
uint256 totalsize = totalSupply();
require(_from <= _to);
require(_to < totalsize);
uint256 size = _to-_from +1;
uint256[] memory items = new uint256[](size);
uint256[] memory prices = new uint256[](size);
address[] memory owners = new address[](size);
uint256 itemCounter = 0;
for (uint256 i = _from; i < listedItems.length; i++) {
if (ownerOf(listedItems[i]) !=address(0)) {
items[itemCounter] = listedItems[i];
prices[itemCounter] = priceOf(listedItems[i]);
owners[itemCounter] = ownerOf(listedItems[i]);
itemCounter += 1;
if(itemCounter > _to){
break;
}
}
}
return (items,prices,owners);
}
function getMaxMerge()external view returns(uint256 _maxMergeSize){
return max_merge_size;
}
function showBalance () onlyAdmins() public view returns (uint256 _ProfitBalance) {
return this.balance;
}
}
{
"compilationTarget": {
"ETH10K.sol": "ETH10K"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[{"name":"_from","type":"uint256"},{"name":"_to","type":"uint256"}],"name":"getAllCellInfoFrom_To","outputs":[{"name":"_tokenIds","type":"uint256[]"},{"name":"_prices","type":"uint256[]"},{"name":"_owners","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMaxMerge","outputs":[{"name":"_maxMergeSize","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"withdrawAmount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"_name","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_index","type":"uint256"}],"name":"buyOld","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"implementsERC721","outputs":[{"name":"_implements","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getUserName","outputs":[{"name":"name","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_admin","type":"address"}],"name":"removeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"_totalSupply","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"status","type":"bool"}],"name":"enableMerge","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_admin","type":"address"}],"name":"isAdmin","outputs":[{"name":"_isAdmin","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"setUserName","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_itemId","type":"uint256"}],"name":"allOf","outputs":[{"name":"_owner","type":"address"},{"name":"_startingPrice","type":"uint256"},{"name":"_price","type":"uint256"},{"name":"_nextPrice","type":"uint256"},{"name":"_xpos","type":"uint256"},{"name":"_ypos","type":"uint256"},{"name":"_size","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAllCellInfo","outputs":[{"name":"_tokenIds","type":"uint256[]"},{"name":"_prices","type":"uint256[]"},{"name":"_owners","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_itemId","type":"uint256"}],"name":"nextPriceOf","outputs":[{"name":"_nextPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_xpos","type":"uint256"},{"name":"_ypos","type":"uint256"},{"name":"_size","type":"uint256"}],"name":"buyNew","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_itemId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"_owner","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_price","type":"uint256"}],"name":"calculateDevCut","outputs":[{"name":"_devCut","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"cellsOf","outputs":[{"name":"_tokenIds","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_admin","type":"address"}],"name":"addAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"_balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"enableERC721","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_up","type":"uint8"},{"name":"_down","type":"uint8"}],"name":"setReserved","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"showBalance","outputs":[{"name":"_ProfitBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"_symbol","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getAllCellIds","outputs":[{"name":"_tokenIds","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"ids","type":"uint256[]"}],"name":"requestMerge","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MergeStatus","outputs":[{"name":"_MergeOpen","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_itemId","type":"uint256"}],"name":"priceOf","outputs":[{"name":"_price","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_ypos","type":"uint256"}],"name":"checkIsOnSale","outputs":[{"name":"isOnSale","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"startingPriceOf","outputs":[{"name":"_startingPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_price","type":"uint256"}],"name":"calculateNextPrice","outputs":[{"name":"_nextPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_user","type":"address"}],"name":"getUserNameOf","outputs":[{"name":"name","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_xpos","type":"uint256"},{"name":"_ypos","type":"uint256"},{"name":"_size","type":"uint256"},{"name":"_price","type":"uint256"}],"name":"addBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"num","type":"uint8"}],"name":"setMaxMerge","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_itemId","type":"uint256"},{"indexed":true,"name":"_owner","type":"address"},{"indexed":false,"name":"_price","type":"uint256"}],"name":"Bought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_itemId","type":"uint256"},{"indexed":true,"name":"_owner","type":"address"},{"indexed":false,"name":"_price","type":"uint256"}],"name":"Sold","type":"event"},{"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"}]