Contract Overview
Balance: 0.113060718276223924 Ether
Transactions: 34 txns
 Latest 25 transactions from a total of 34 transactions

TxHash Age From To Value [TxFee]
0x84201c2f0215554b6f791e74ea2c48bb147fae56634f734dbebe3902ca68230f20 days 14 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.00016547
0x467b8b9a896561e22584d6cd9a8dd88f20b7ea941a612194ada97f2b272e262921 days 15 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000359846
0xa46da001ee7e2b0819c13cd0ca1c28de9d9df6baac4311d8f593fd4c72f4bd8c21 days 15 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000358272
0xd36ed0678cb2bbd2b6bd4f7d0667cdb9ea2448ec5e155773fc4007c18ed5cde521 days 15 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000247808
0xdd89e2959275c8953a40bb90df05986c2518e3ffc8c6856aa0d00ac4e60a265021 days 16 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.00233333325 Ether0.00033256
0xc0412737c5dd33f45fb2f9ac7d0a7801cdf021f267ec4082e02ea6945d04aa9834 days 10 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.033470504545572 Ether0.000266098
0xb492508b624bd309727bac0c353c445b2157ae98558f05344ea0c067219f4a7634 days 10 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000023185
0x6923165e1deb43c35ec133011b877814e67349c864c3a346c5f8afe82c2d961135 days 4 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000248216
0x53878fc48c03176d0944895050437f10a5963ce08e9c6a0c5540a17691a486f135 days 4 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000033287
0x71fdc5e23bd1d5b34354845e90b17945308ce344ca784008e4e31987c48ffa8935 days 4 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.008671418832655 Ether0.000210322
0xd3bc14b1f77a1304ce26bbb748544953c941973cd4d3d9e8ac41a4cdf08d834f35 days 23 hrs ago0x66253d14cf139c260d8c98ba8f56064ebab7bdde  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.001777777666666 Ether0.000279208
0xc3022e4b13bff168376124aef622152970455430ed060175c99e3f34e2f4ac5735 days 23 hrs ago0x66253d14cf139c260d8c98ba8f56064ebab7bdde  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.001999999833333 Ether0.000255931
0x70e34a2e36814b1226ae0d97599d672e6a9a8e016c63d1cba42d8fb566ecd60336 days 7 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000033351
0xbc3e6463f4b4bc50b4c26283f05631e96f3a581436d58183a25e9325281a361e36 days 7 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.004156281057808 Ether0.000287229
0xe6521b8667d344a51e8f64cf5f7a9359aa5bde7fc5b26a7f40e062a012054b2236 days 10 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.010826697635429 Ether0.000333705
0x911fe9538e108f00ac5a4c31e4d0db3532898d798b67e149e4848ebbff28e15c36 days 17 hrs ago0x520dffed1dc6e3e871d944bb473c3d483f5f3fb9  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.02165016447169 Ether0.000319339
0xb911846ed930558d5b2b5b1a64845a9e3dcb02a16f94af8aebd522d9ce05252236 days 19 hrs ago0x520dffed1dc6e3e871d944bb473c3d483f5f3fb9  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000227591
0x0910b8cabea3be4a17b83047f28ea49e45481acfca17524b5b0f18a0f82883b336 days 19 hrs ago0xcaaae655d431bddb3f2f20bd31bc629928131582  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.026569649525596 Ether0.000337493
0x2cf5fa77fb9d88a2be900556ee436e0b83962567d35829c45bbcda3e06c8ef1136 days 19 hrs ago0x520dffed1dc6e3e871d944bb473c3d483f5f3fb9  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000390618
0x1fd34ad1eb0f7c3387e949c2c52698ee0d21a2ebb44536ff2970fdf69519fa8736 days 19 hrs ago0x520dffed1dc6e3e871d944bb473c3d483f5f3fb9  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000245996
0xd158a52a870f31923e5d55ea593f0f8b25137bb8e9e73a04c57f1bfea4f2fd4c36 days 19 hrs ago0x520dffed1dc6e3e871d944bb473c3d483f5f3fb9  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000033287
0xfa270673d6f3ed10122d5fbf35cf6b2a8f49b9543d1ecd0d0197cd53ba51dcdc36 days 19 hrs ago0x520dffed1dc6e3e871d944bb473c3d483f5f3fb9  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000033287
0xca7ff912d2191519d74b83176cceef51f17fa67193192d0b714675d0e4b71c4536 days 19 hrs ago0x520dffed1dc6e3e871d944bb473c3d483f5f3fb9  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000033671
0xc0550eda310c62b9dddf000b02f7b54293fc3e7eb17a6701bc42344c6ab5e3e636 days 19 hrs ago0x520dffed1dc6e3e871d944bb473c3d483f5f3fb9  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690 Ether0.000033351
0xa981aaedb43a7bc997c6fc4113628f72c9af09769c2a3a387916662cea4a22a236 days 19 hrs ago0x520dffed1dc6e3e871d944bb473c3d483f5f3fb9  IN   0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690.005406397594637 Ether0.000242016
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
 Latest 25 Internal Txns, Click here To View More View All
ParentTxHash Block Age From To Value
0x84201c2f0215554b6f791e74ea2c48bb147fae56634f734dbebe3902ca68230f493156720 days 14 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0x84201c2f0215554b6f791e74ea2c48bb147fae56634f734dbebe3902ca68230f493156720 days 14 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0x84201c2f0215554b6f791e74ea2c48bb147fae56634f734dbebe3902ca68230f493156720 days 14 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0x467b8b9a896561e22584d6cd9a8dd88f20b7ea941a612194ada97f2b272e2629492474021 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0x467b8b9a896561e22584d6cd9a8dd88f20b7ea941a612194ada97f2b272e2629492474021 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0x467b8b9a896561e22584d6cd9a8dd88f20b7ea941a612194ada97f2b272e2629492474021 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0x467b8b9a896561e22584d6cd9a8dd88f20b7ea941a612194ada97f2b272e2629492474021 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x31f2e532799041fea9c72cd3f5160b45c68a8a5e0.00002135273890151 Ether
0x467b8b9a896561e22584d6cd9a8dd88f20b7ea941a612194ada97f2b272e2629492474021 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0x467b8b9a896561e22584d6cd9a8dd88f20b7ea941a612194ada97f2b272e2629492474021 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0x467b8b9a896561e22584d6cd9a8dd88f20b7ea941a612194ada97f2b272e2629492474021 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xa46da001ee7e2b0819c13cd0ca1c28de9d9df6baac4311d8f593fd4c72f4bd8c492473721 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x31f2e532799041fea9c72cd3f5160b45c68a8a5e0.002049858834827284 Ether
0xa46da001ee7e2b0819c13cd0ca1c28de9d9df6baac4311d8f593fd4c72f4bd8c492473721 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xa46da001ee7e2b0819c13cd0ca1c28de9d9df6baac4311d8f593fd4c72f4bd8c492473721 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xa46da001ee7e2b0819c13cd0ca1c28de9d9df6baac4311d8f593fd4c72f4bd8c492473721 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xd36ed0678cb2bbd2b6bd4f7d0667cdb9ea2448ec5e155773fc4007c18ed5cde5492472721 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xd36ed0678cb2bbd2b6bd4f7d0667cdb9ea2448ec5e155773fc4007c18ed5cde5492472721 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xd36ed0678cb2bbd2b6bd4f7d0667cdb9ea2448ec5e155773fc4007c18ed5cde5492472721 days 15 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xdd89e2959275c8953a40bb90df05986c2518e3ffc8c6856aa0d00ac4e60a2650492465221 days 16 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xdd89e2959275c8953a40bb90df05986c2518e3ffc8c6856aa0d00ac4e60a2650492465221 days 16 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xdd89e2959275c8953a40bb90df05986c2518e3ffc8c6856aa0d00ac4e60a2650492465221 days 16 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xc0412737c5dd33f45fb2f9ac7d0a7801cdf021f267ec4082e02ea6945d04aa98484752834 days 10 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xc0412737c5dd33f45fb2f9ac7d0a7801cdf021f267ec4082e02ea6945d04aa98484752834 days 10 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xc0412737c5dd33f45fb2f9ac7d0a7801cdf021f267ec4082e02ea6945d04aa98484752834 days 10 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
0xb492508b624bd309727bac0c353c445b2157ae98558f05344ea0c067219f4a76484752734 days 10 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x2621ea417659ad69bae66af05ebe5788e533e5e70.007313627813436616 Ether
0x6923165e1deb43c35ec133011b877814e67349c864c3a346c5f8afe82c2d9611484325235 days 4 hrs ago0x038cecf8e1fecfdb33d5f17bf21834cbe41ec5690x6d40039fa13d6abf95d29dd809caba70b63862540 Ether
[ Download CSV Export  ] 
Contract Source Code Verified (Exact Match)
Contract Name: UpcityGame
Compiler Version: v0.5.2+commit.1df8f40c
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity ^0.5;

/**
 * @title SafeMath
 * @dev Math operations with safety checks that revert on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, reverts on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (a == 0) {
      return 0;
    }

    uint256 c = a * b;
    require(c / a == b);

    return c;
  }

  /**
  * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b > 0); // Solidity only automatically asserts when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  /**
  * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b <= a);
    uint256 c = a - b;

    return c;
  }

  /**
  * @dev Adds two numbers, reverts on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a);

    return c;
  }

  /**
  * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
  * reverts when dividing by zero.
  */
  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0);
    return a % b;
  }
}

/// @title Definition for a resource token used by upcity.
/// @author Lawrence Forman ([email protected])
interface IResourceToken {

	function transfer(address to, uint256 amt) external returns (bool);
	function mint(address to, uint256 amt) external;
	function burn(address from, uint256 amt) external;
	function totalSupply() external view returns (uint256);
	function balanceOf(address who) external view returns (uint256);
	function isAuthority(address addr) external view returns (bool);
	function decimals() external view returns (uint8);
}

/// @title Definition for a resource token used by upcity.
/// @author Lawrence Forman ([email protected])
interface IMarket {

	function getPrice(address resource) external view returns (uint256);
	function mint(address resource, address to, uint256 amount) external;
	function burn(address resource, address from, uint256 amount) external;
}

/// @title Base contract defining common error codes.
/// @author Lawrence Forman ([email protected])
contract Errors {

	string internal constant ERROR_MAX_HEIGHT = "MAX_HEIGHT";
	string internal constant ERROR_NOT_ALLOWED = "NOT_ALLOWED";
	string internal constant ERROR_ALREADY = "ALREADY";
	string internal constant ERROR_INSUFFICIENT = "INSUFFICIENT";
	string internal constant ERROR_RESTRICTED = "RESTRICTED";
	string internal constant ERROR_UNINITIALIZED = "UNINITIALIZED";
	string internal constant ERROR_TIME_TRAVEL = "TIME_TRAVEL";
	string internal constant ERROR_INVALID = "INVALID";
	string internal constant ERROR_NOT_FOUND = "NOT_FOUND";
	string internal constant ERROR_GAS = "GAS";
	string internal constant ERROR_TRANSFER_FAILED = "TRANSFER_FAILED";
}

/// @title Base for contracts that require a separate
/// initialization step beyond the constructor.
/// @author Lawrence Forman ([email protected])
/// @dev Deriving contracts should call super._init() in their initialization step
/// to initialize the contract.
contract Uninitialized is Errors {

	/// @dev Whether the contract is fully initialized.
	bool private _isInitialized;

	/// @dev Only callable when contract is initialized.
	modifier onlyInitialized() {
		require(_isInitialized, ERROR_UNINITIALIZED);
		_;
	}

	/// @dev Only callable when contract is uninitialized.
	modifier onlyUninitialized() {
		require(!_isInitialized, ERROR_UNINITIALIZED);
		_;
	}

	/// @dev initialize the contract.
	function _init() internal onlyUninitialized {
		_isInitialized = true;
	}

}

/// @title Base class for contracts that want to restrict access to privileged
/// functions to either the contract creator or a group of addresses.
/// @author Lawrence Forman ([email protected])
/// @dev Derived contracts should set isAuthority to true for each address
/// with privileged access to functions protected by the onlyAuthority modifier.
contract Restricted is Errors {

	/// @dev Creator of this contract.
	address internal _creator;
	/// @dev Addresses that can call onlyAuthority functions.
	mapping(address=>bool) public isAuthority;

	/// @dev Set the contract creator to the sender.
	constructor() public {
		_creator = msg.sender;
	}

	/// @dev Only callable by contract creator.
	modifier onlyCreator() {
		require(msg.sender == _creator, ERROR_RESTRICTED);
		_;
	}

	/// @dev Restrict calls to only from an authority
	modifier onlyAuthority() {
		require(isAuthority[msg.sender], ERROR_RESTRICTED);
		_;
	}
}

/// @title Base for contracts that don't want to hold ether.
/// @author Lawrence Forman ([email protected])
/// @dev Reverts in the fallback function.
contract Nonpayable is Errors {

	/// @dev Revert in the fallback function to prevent accidental
	/// transfer of funds to this contract.
	function() external payable {
		revert(ERROR_INVALID);
	}
}

/// @title Constants, types, and helpers for UpCityGame
/// @author Lawrence Forman ([email protected])
contract UpcityBase {

	// Tile data.
	struct Tile {
		// Deterministic ID of the tile. Will be 0x0 if tile does not exist.
		bytes10 id;
		// Right-aligned, packed representation of blocks,
		// where 0x..FF is empty.
		bytes16 blocks;
		// The height of the tower on the tile (length of blocks).
		uint8 height;
		// NUM_NEIGHBORS + the height of each neighbor's tower.
		uint8 neighborCloutsTotal;
		// How many times the tile has been bought. Always >= 1.
		uint32 timesBought;
		// When the tile was last collected.
		uint64 lastTouchTime;
		// The x coordinate of the tile.
		int32 x;
		// The y coordinate of the tile.
		int32 y;
		// The name of the tile.
		bytes16 name;
		// The "base" price of a tile, NOT including neighborhood bonus,
		// resource costs, and seasonal bonus. This goes up every time a
		// tile is bought.
		uint256 basePrice;
		// The aggregated shared resources from neighbor tiles after
		// they do a collect().
		uint256[NUM_RESOURCES] sharedResources;
		// The aggregated shared ether from neighbor tiles. after they
		// do a collect().
		uint256 sharedFunds;
		// The aggregate scores for each resource on this tile.
		uint64[NUM_RESOURCES] scores;
		// The current owner of the tile.
		address owner;
	}

	// Global metrics, for a specific resource;
	struct BlockStats {
		// The total number of blocks of this resource, across all tiles.
		uint64 count;
		// The global production daily limit for this resource, expressed in PPM.
		// Note that this is a "soft" limit, as tiles in season produce bonus
		// resources defined by SEASON_YIELD_BONUS.
		uint64 production;
		// The total "score" of blocks of this resource, across all tiles.
		// Score for a block depends on its height.
		uint128 score;
	}

	// solhint-disable
	// Zero address (0x0).
	address internal constant ZERO_ADDRESS = address(0x0);
	// 100%, or 1.0, in parts per million.
	uint64 internal constant PPM_ONE = uint64(1000000);
	// The number of wei in one token (10**18).
	uint256 internal constant ONE_TOKEN = 1000000000000000000;
	// The number of seconds in one day.
	uint64 internal constant ONE_DAY = 86400;
	// The number of resource types.
	uint8 internal constant NUM_RESOURCES = 3;
	// The number of neighbors for each tile.
	uint8 internal constant NUM_NEIGHBORS = 6;
	// The maximum number of blocks that can be built on a tile.
	uint8 internal constant MAX_HEIGHT = 16;
	// Packed representation of an empty tower.
	bytes16 internal constant EMPTY_BLOCKS = 0xffffffffffffffffffffffffffffffff;
	// The ratio of collected resources to share with neighbors, in ppm.
	uint64 internal constant TAX_RATE = 166667;
	// The minimum tile price.
	uint256 internal constant MINIMUM_TILE_PRICE = 1000000000000000;
	// How much to increase the base tile price every time it's bought, in ppm.
	uint64 internal constant PURCHASE_MARKUP = 1333333;
	// Scaling factor for global production limits.
	uint64 internal constant PRODUCTION_ALPHA = 1500000;
	// The number of seasons.
	uint64 internal constant NUM_SEASONS = 8;
	// The length of each season, in seconds.
	uint64 internal constant SEASON_DURATION = 1314900;
	// The start of the season calendar, in unix time.
	uint64 internal constant CALENDAR_START = 1546318800;
	// Multiplier for the total price of a tile when it is in season, in ppm.
	uint64 internal constant SEASON_PRICE_BONUS = 1500000;
	// Multiplier for to resources generated when a tile is in season, in ppm.
	uint64 internal constant SEASON_YIELD_BONUS = 1250000;
	// The building cost multiplier for any block at a certain height, in ppm.
	uint64[MAX_HEIGHT] internal BLOCK_HEIGHT_PREMIUM = [
		uint64(1000000),
		uint64(1096825),
		uint64(1203025),
		uint64(1319508),
		uint64(1447269),
		uint64(1587401),
		uint64(1741101),
		uint64(1909683),
		uint64(2094588),
		uint64(2297397),
		uint64(2519842),
		uint64(2763826),
		uint64(3031433),
		uint64(3324952),
		uint64(3646890),
		uint64(4000000)
	];
	// The yield multiplier for any block at a certain height, in ppm.
	uint64[MAX_HEIGHT] internal BLOCK_HEIGHT_BONUS = [
		uint64(1000000),
		uint64(1047294),
		uint64(1096825),
		uint64(1148698),
		uint64(1203025),
		uint64(1259921),
		uint64(1319508),
		uint64(1381913),
		uint64(1447269),
		uint64(1515717),
		uint64(1587401),
		uint64(1662476),
		uint64(1741101),
		uint64(1823445),
		uint64(1909683),
		uint64(2000000)
	];
	// The linear rate at which each block's costs increase with the total
	// blocks built, in ppm.
	uint64[NUM_RESOURCES] internal RESOURCE_ALPHAS =
		[50000, 330000, 660000];
	// Recipes for each block type, as whole tokens.
	uint256[NUM_RESOURCES][NUM_RESOURCES] internal RECIPES = [
		[3, 1, 1],
		[1, 3, 1],
		[1, 1, 3]
	];
	// solhint-enable

	/// @dev Given an amount, subtract taxes from it.
	function _toTaxed(uint256 amount) internal pure returns (uint256) {
		return amount - (amount * TAX_RATE) / PPM_ONE;
	}

	/// @dev Given an amount, get the taxed quantity.
	function _toTaxes(uint256 amount) internal pure returns (uint256) {
		return (amount * TAX_RATE) / PPM_ONE;
	}

	/// @dev Given a tile coordinate, return the tile id.
	function _toTileId(int32 x, int32 y) internal pure returns (bytes10) {
		return bytes10(0x13370000000000000000) |
			bytes10(uint80(((uint64(y) & uint32(-1)) << (8*4)) |
				(uint64(x) & uint32(-1))));
	}

	/// @dev Check if a block ID number is valid.
	function _isValidBlock(uint8 _block) internal pure returns (bool) {
		return _block <= 2;
	}

	/// @dev Check if a tower height is valid.
	function _isValidHeight(uint8 height) internal pure returns (bool) {
		return height <= MAX_HEIGHT;
	}

	/// @dev Insert packed representation of a tower `b` into `a`.
	/// @param a Packed represenation of the current tower.
	/// @param b Packed represenation of blocks to append.
	/// @param idx The index in `a` to insert the new blocks.
	/// @param count The length of `b`.
	function _assignBlocks(bytes16 a, bytes16 b, uint8 idx, uint8 count)
			internal pure returns (bytes16) {

		uint128 mask = ((uint128(1) << (count*8)) - 1) << (idx*8);
		uint128 v = uint128(b) << (idx*8);
		return bytes16((uint128(a) & ~mask) | (v & mask));
	}

	/// @dev Get the current season.
	function _getSeason() private view returns (uint128) {
		return ((uint64(block.timestamp) - CALENDAR_START) / SEASON_DURATION) % NUM_SEASONS;
	}

	/// @dev Check if a tile is in season (has a bonus in effect).
	/// @param tile The tile to check.
	/// @return true if tile is in season.
	function _isTileInSeason(Tile storage tile) internal view returns (bool) {
		bytes32 hash = keccak256(abi.encodePacked(address(this), tile.id));
		return uint256(hash) % NUM_SEASONS == _getSeason();
	}

	/// @dev Estimate the sqrt of an integer n, returned in ppm, using small
	/// steps of the Babylonian method.
	/// @param n The integer whose sqrt is to the found, NOT in ppm.
	/// @param hint A number close to the sqrt, in ppm.
	/// @return sqrt(n) in ppm
	function _estIntegerSqrt(uint64 n, uint64 hint)
			internal pure returns (uint64) {

		if (n == 0)
			return 0;
		if (n == 1)
			return PPM_ONE;
		uint256 _n = uint256(n) * PPM_ONE;
		uint256 _n2 = _n * PPM_ONE;
		uint256 r = hint == 0 ? ((uint256(n)+1) * PPM_ONE) / 2 : hint;
		r = (r + _n2 / r) / 2;
		r = (r + _n2 / r) / 2;
		return uint64(r);
	}

}

/// @title Game contract for upcity.app
contract UpcityGame is
		UpcityBase,
		Uninitialized,
		Nonpayable,
		Restricted {
	using SafeMath for uint256;

	/// @dev Payments to individual players when someone buys their tile.
	/// Can be pulled vial collectCredits().
	mapping(address=>uint256) public credits;
	/// @dev Fees collected.
	/// These are funds that have been shared to unowned tiles as well as
	/// funds paid to buy unowned tiles.
	/// An authority may call collectFees() to withdraw these fees.
	uint256 public fees = 0;
	/// @dev List of all tile IDs that are owned.
	/// This gets appended to every time someone does a buy() on an empty
	/// tile.
	bytes10[] public tilesBought;
	// Global block stats for each resource.
	BlockStats[NUM_RESOURCES] private _blockStats;
	// Tokens for each resource.
	IResourceToken[NUM_RESOURCES] private _tokens;
	// The market for all resources.
	IMarket private _market;
	// Tiles by ID.
	mapping(bytes10=>Tile) private _tiles;

	/// @dev Raised whenever a tile is bought.
	event Bought(bytes10 indexed id, address indexed from, address indexed to, uint256 price);
	/// @dev Raised whenever a tile's resources/funds are collected.
	event Collected(bytes10 indexed id, address indexed owner);
	/// @dev Raised whenever credited funds (ether) are collected.
	event CreditsCollected(address indexed from, address indexed to, uint256 amount);
	/// @dev Raised whenever a block is built on a tile.
	event Built(bytes10 indexed id, address indexed owner, bytes16 blocks);
	/// @dev Raised whenever a tile is renamed.
	event Renamed(bytes10 indexed id, bytes16 name);
	/// @dev Raised whenever a player is credited some funds to be collected via
	/// collectCredits().
	event Credited(address indexed to, uint256 amount);
	/// @dev Raised whenever amn authority claims fees through collectFees().
	event FeesCollected(address indexed to, uint256 amount);

	/// @dev Doesn't really do anything.
	/// init() needs to be called by the creator before this contract
	/// can be interacted with. All transactional functions will revert if
	/// init() has not been called first.
	constructor() public { /* NOOP */ }

	/// @dev Initialize this contract.
	/// All transactional functions will revert if this has not been called
	/// first by the the contract creator. This cannot be called twice.
	/// @param tokens Each resource's UpcityResourceToken addresses.
	/// @param market The UpcityMarket address.
	/// @param authorities Array of addresses allowed to call collectFees().
	/// @param genesisPlayer The owner of the genesis tile, at <0,0>.
	function init(
			address[NUM_RESOURCES] calldata tokens,
			address market,
			address genesisPlayer,
			address[] calldata authorities)
			external onlyCreator onlyUninitialized {

		require(tokens.length == NUM_RESOURCES, ERROR_INVALID);
		for (uint256 i = 0; i < authorities.length; i++)
			isAuthority[authorities[i]] = true;
		for (uint256 i = 0; i < NUM_RESOURCES; i++)
			_tokens[i] = IResourceToken(tokens[i]);
		_market = IMarket(market);

		// Create the genesis tile and its neighbors.
		Tile storage tile = _createTileAt(0, 0);
		tile.owner = genesisPlayer;
		tile.timesBought = 1;
		tilesBought.push(tile.id);
		_createNeighbors(tile.x, tile.y);
		_init();
	}

	/// @dev Get global stats for every resource type.
	/// @return A tuple of:
	/// array of the total number of blocks for each resource,
	/// array of the total scores for each resource, in ppm.
	/// array of the daily production limit for each resource, in tokens, in ppm.
	function getBlockStats()
			external view returns (
				uint64[NUM_RESOURCES] memory counts,
				uint64[NUM_RESOURCES] memory productions,
				uint128[NUM_RESOURCES] memory scores) {

		counts[0] = _blockStats[0].count;
		scores[0] = _blockStats[0].score;
		productions[0] = _blockStats[0].production;
		counts[1] = _blockStats[1].count;
		scores[1] = _blockStats[1].score;
		productions[1] = _blockStats[1].production;
		counts[2] = _blockStats[2].count;
		scores[2] = _blockStats[2].score;
		productions[2] = _blockStats[2].production;
	}

	/// @dev Get a slice of the tilesBought array.
	/// @param start The start index.
	/// @param count The maximum number of elements to return.
	/// @return A slice of the tilesBought array. If the length of the
	/// returned array is less than `count`, you've hit the end.
	function getTilesBoughtSlice(uint32 start, uint32 count)
			external view returns (bytes10[] memory) {

		if (tilesBought.length == 0)
			return new bytes10[](0);
		uint32 _start = ((start) <= (uint32(tilesBought.length)-1) ? (start) : (uint32(tilesBought.length)-1));
		uint32 _count = ((count) <= (uint32(tilesBought.length)-_start) ? (count) : (uint32(tilesBought.length)-_start));
		bytes10[] memory slice = new bytes10[](_count);
		for (uint32 i = 0; i < _count; i++)
			slice[i] = tilesBought[_start + i];
		return slice;
	}

	/// @dev Gets the resource and ether balance of a player.
	/// Note that this does not include credits (see 'credits' field).
	/// @param player The player's address.
	/// @return A tuple of:
	/// ether balance,
	/// array of balance for each resource.
	function getPlayerBalance(address player)
			external view returns (
				uint256 funds,
				uint256[NUM_RESOURCES] memory resources) {

		funds = player.balance;
		resources[0] = _tokens[0].balanceOf(player);
		resources[1] = _tokens[1].balanceOf(player);
		resources[2] = _tokens[2].balanceOf(player);
	}

	/// @dev Get detailed information about a tile.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	/// @return A tuple of details.
	function describeTile(int32 x, int32 y) external view
			returns (
				/// @dev The id of the tile. This will be 0x0 if the tile does not
				/// exist.
				bytes10 id,
				/// @dev The name of the tile. Zero-terminated UTF-8 string.
				bytes16 name,
				/// @dev The number of times the tile was bought.
				uint32 timesBought,
				/// @dev The current owner of the tile (0x0 if unowned).
				address owner,
				// Right-aligned, packed representation of blocks,
				// where 0x..FF is empty.
				bytes16 blocks,
				/// @dev The current price of the tile.
				uint256 price,
				/// @dev The number of shared resource available to collect()
				/// (untaxed).
				uint256[NUM_RESOURCES] memory sharedResources,
				/// @dev The amount ether available to collect()
				/// (including tax).
				uint256 funds,
				/// @dev The aggregated yield scores for each resource for this
				/// tile.
				uint64[NUM_RESOURCES] memory scores,
				/// @dev Whether or not this tile is in season.
				/// Tiles in season yield more resources and have higher prices.
				bool inSeason,
				/// @dev The last time the tile was touched (collected),
				// in unix time.
				uint64 lastTouchTime) {

		Tile storage tile = _getTileAt(x, y);
		id = tile.id;
		timesBought = tile.timesBought;
		name = tile.name;
		owner = tile.owner;
		blocks = tile.blocks;
		if (id != 0x0) {
			price = _getTilePrice(tile);
			sharedResources = tile.sharedResources;
			funds = _toTaxed(tile.sharedFunds);
			scores = tile.scores;
			inSeason = _isTileInSeason(tile);
			lastTouchTime = tile.lastTouchTime;
		}
		else {
			// Tile does not exist.
			assert(owner == address(0x0));
			name = 0x0;
			price = 0;
			sharedResources = [uint256(0), uint256(0), uint256(0)];
			funds = 0;
			scores = [uint64(0), uint64(0), uint64(0)];
			inSeason = false;
			lastTouchTime = 0;
		}
	}

	/// @dev Buy a tile.
	/// Ether equivalent to the price of the tile must be attached to this call.
	/// Any excess ether (overpayment) will be transfered back to the caller.
	/// The caller will be the new owner.
	/// This will first do a collect(), so the previous owner will be paid
	/// any resources/ether held by the tile. The buyer does not inherit
	/// existing funds/resources. Only the tile and its tower.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	function buy(int32 x, int32 y) external payable onlyInitialized {
		collect(x, y);
		Tile storage tile = _getExistingTileAt(x, y);
		require(tile.owner != msg.sender, ERROR_ALREADY);
		uint256 price = _getTilePrice(tile);
		require(msg.value >= price, ERROR_INSUFFICIENT);
		address oldOwner = tile.owner;
		tile.owner = msg.sender;
		tile.timesBought += 1;
		// Base price increases every time a tile is bought.
		tile.basePrice = (tile.basePrice * PURCHASE_MARKUP) / PPM_ONE;
		// Create the neighboring tiles.
		_createNeighbors(tile.x, tile.y);
		// Share with neighbors.
		_share(tile, price, [uint256(0), uint256(0), uint256(0)]);
		// If this tile was previously unowned, append it to the tilesBought
		// list.
		if (oldOwner == ZERO_ADDRESS)
			tilesBought.push(tile.id);
		// Pay previous owner.
		_creditTo(oldOwner, _toTaxed(price));
		// Refund any overpayment.
		if (msg.value > price)
			_transferTo(msg.sender, msg.value - price);
		emit Bought(tile.id, oldOwner, tile.owner, price);
	}

	/// @dev Build, by appending, blocks on a tile.
	/// This will first do a collect().
	/// Empty blocks, or building beyond MAX_HEIGHT will revert.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	/// @param blocks Right-aligned, packed representation of blocks to append.
	function buildBlocks(int32 x, int32 y, bytes16 blocks)
			external onlyInitialized {

		collect(x, y);
		Tile storage tile = _getExistingTileAt(x, y);
		// Must be owned by caller.
		require(tile.owner == msg.sender, ERROR_NOT_ALLOWED);
		// Get the costs and count of the new blocks.
		(uint256[NUM_RESOURCES] memory cost, uint8 count) =
			_getBuildCostAndCount(tile, blocks);
		// Empty blocks aren't allowed.
		require(count > 0, ERROR_INVALID);
		// Building beyond the maximum height is not allowed.
		require(_isValidHeight(tile.height + count), ERROR_MAX_HEIGHT);
		_incrementTileScores(tile, blocks, count);
		_incrementNeighborCloutTotals(tile, count);
		_incrementBlockStats(blocks, count);
		tile.blocks = _assignBlocks(tile.blocks, blocks, tile.height, count);
		tile.height += count;
		// Burn the costs.
		_burn(msg.sender, cost);
		emit Built(tile.id, tile.owner, tile.blocks);
	}

	/// @dev Rename a tile.
	/// Only the owner of the tile may call this.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	/// @param name Name to give the tile (UTF-8, zero-terminated).
	function rename(int32 x, int32 y, bytes16 name) external onlyInitialized {
		Tile storage tile = _getExistingTileAt(x, y);
		// Must be owned by caller.
		require(tile.owner == msg.sender, ERROR_NOT_ALLOWED);
		tile.name = name;
		emit Renamed(tile.id, name);
	}

	/// @dev Transfer fees (ether) collected to an address.
	/// May only be called by an authority set in init().
	/// @param to Recipient.
	function collectFees(address to) external onlyInitialized onlyAuthority {
		assert(fees <= address(this).balance);
		if (fees > 0) {
			uint256 amount = fees;
			fees = 0;
			_transferTo(to, amount);
			emit FeesCollected(to, amount);
		}
	}

	/// @dev Collect funds (ether) credited to the caller.
	/// Credits come from someone buying an owned tile, or when someone
	/// other than the owner of a tile (holding ether) calls collect().
	/// @param to Recipient.
	function collectCredits(address to) external {
		uint256 amount = credits[msg.sender];
		if (amount > 0) {
			credits[msg.sender] = 0;
			_transferTo(to, amount);
			emit CreditsCollected(msg.sender, to, amount);
		}
	}

	/// @dev Collect the resources from a tile.
	/// The caller need not be the owner of the tile.
	/// Calling this on unowned tiles is a no-op since unowned tiles cannot hold
	/// resources/funds.
	/// If the tile is holding resources, they will be immediately minted to
	/// the owner of the tile, with a portion (1/TAX_RATE) shared to its neighbors.
	/// If the tile has funds (ether), they will be credited to the tile owner
	/// (who can later redeem them via collectCredits()), and a portion
	/// (1/TAX_RATE) will be shared to its neighbors.
	/// If the caller is the owner, funds/ether will be directly transfered to the
	/// owner, rather than merely credited (push rather than pull).
	/// The exact proportion of resources and funds each neighbor receives will
	/// depend on its tower height relative to the tile's other immediate
	/// neighbors.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	function collect(int32 x, int32 y) public onlyInitialized {
		Tile storage tile = _getExistingTileAt(x, y);
		// If tile is unowned, it cannot yield or hold anything.
		if (tile.owner == ZERO_ADDRESS)
			return;

		uint256[NUM_RESOURCES] memory produced = _getTileYield(tile, uint64(block.timestamp));
		uint256 funds = tile.sharedFunds;

		tile.lastTouchTime = uint64(block.timestamp);
		tile.sharedResources = [uint256(0), uint256(0), uint256(0)];
		tile.sharedFunds = 0;

		// Share to neighbors.
		_share(tile, funds, produced);
		_claim(tile, funds, produced);
		emit Collected(tile.id, tile.owner);
	}

	/// @dev Get the build cost (in resources) to build a sequence of blocks on
	/// a tile.
	/// This will revert if the number of blocks would exceed the height limit
	/// or the tile does not exist.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	/// @param blocks Right-aligned, packed representation of blocks to append.
	function getBuildCost(int32 x, int32 y, bytes16 blocks)
			public view returns (uint256[NUM_RESOURCES] memory cost) {

		Tile storage tile = _getExistingTileAt(x, y);
		(cost,) = _getBuildCostAndCount(tile, blocks);
	}

	/// @dev Get the build cost (in resources) to build a sequence of blocks on
	/// a tile and the count of those blocks.
	/// @param tile The tile info structure.
	/// @param blocks Right-aligned, packed representation of blocks to append.
	/// @return A tuple of:
	/// The cost per-resource,
	/// The count of the blocks passed.
	function _getBuildCostAndCount(Tile storage tile, bytes16 blocks)
			private view returns (uint256[NUM_RESOURCES] memory, uint8) {

		assert(tile.id != 0x0);
		uint256[NUM_RESOURCES] memory cost = [uint256(0), uint256(0), uint256(0)];
		// The global block totals. We will increment this for each block to get
		// the accurate/integrated cost.
		uint64[NUM_RESOURCES] memory blockTotals =
			[_blockStats[0].count, _blockStats[1].count, _blockStats[2].count];
		uint8 count = 0;
		for (; count < MAX_HEIGHT; count++) {
			uint8 b = uint8(uint128(blocks));
			blocks = blocks >> 8;
			if (!_isValidBlock(b))
				break;
			require(_isValidHeight(tile.height + count + 1), ERROR_MAX_HEIGHT);
			uint256[NUM_RESOURCES] memory bc = _getBlockCost(
				b, blockTotals[b], tile.height + count);
			cost[0] = cost[0].add(bc[0]);
			cost[1] = cost[1].add(bc[1]);
			cost[2] = cost[2].add(bc[2]);
			blockTotals[b] += 1;
		}
		return (cost, count);
	}

	/// @dev Update a tile's resource scores given new blocks to append.
	/// @param tile The tile.
	/// @param blocks the blocks to append.
	function _incrementTileScores(Tile storage tile, bytes16 blocks, uint8 count)
			private {

		for (uint8 h = 0; h < count; h++) {
			// Pop each block off the tower.
			uint8 b = uint8(uint128(blocks));
			blocks = blocks >> 8;
			tile.scores[b] += BLOCK_HEIGHT_BONUS[tile.height + h];
		}
	}

	/// @dev Update the clout totals for each neighbor of a given tile.
	/// @param center The center tile.
	/// @param amount The extra clout (height) the center tile gained .
	function _incrementNeighborCloutTotals(Tile storage center, uint8 amount)
			private {

		for (uint8 i = 0; i < NUM_NEIGHBORS; i++) {
			(int32 ox, int32 oy) = (((int32(i)%3)-1), (1-int32(i)/2));
			Tile storage neighbor = _getTileAt(center.x + ox, center.y + oy);
			neighbor.neighborCloutsTotal += amount;
		}
	}

	/// @dev Get the amount resources held by a tile at a time (in the future).
	/// This will include shared resources from neighboring tiles.
	/// The resources held by a tile is an aggregate of the production rate
	/// of the blocks on it (multiplied by a seasonal bonus if the tile is in
	/// season) plus resources shared from neighboring tiles.
	/// @param tile The tile info structure.
	/// @param when The time when to evaluate the yield.
	/// @return The amount of each resource produced.
	function _getTileYield(Tile storage tile, uint64 when)
			private view returns (uint256[NUM_RESOURCES] memory produced) {

		assert(tile.id != 0x0);
		require(when >= tile.lastTouchTime, ERROR_TIME_TRAVEL);
		uint64 seasonBonus = _isTileInSeason(tile) ? SEASON_YIELD_BONUS : PPM_ONE;
		uint64 dt = when - tile.lastTouchTime;
		// Geneerate resources on top of what's been shared to this tile.
		produced = tile.sharedResources;
		for (uint8 b = 0; b < NUM_RESOURCES; b++) {
			uint256 amt = ONE_TOKEN * _blockStats[b].production;
			amt *= dt;
			amt *= tile.scores[b];
			amt *= seasonBonus;
			amt /= ((_blockStats[b].score) >= (PPM_ONE) ? (_blockStats[b].score) : (PPM_ONE)) * 86400000000000000;
			produced[b] += amt;
		}
	}

	/// @dev Get the resource costs to build a block at a height.
	/// @param _block The block ID number.
	/// @param globalTotal The total number of the same block type in existence.
	/// @param height The height of the block in the tower.
	/// @return The amount of each resource it would take to build this block.
	function _getBlockCost(uint8 _block, uint64 globalTotal, uint8 height)
			private view returns (uint256[NUM_RESOURCES] memory) {

		assert(_isValidBlock(_block) && _isValidHeight(height));
		uint256 c = ((globalTotal) >= (1) ? (globalTotal) : (1));
		uint256 a = RESOURCE_ALPHAS[_block];
		uint256 s = BLOCK_HEIGHT_PREMIUM[height] * ((c*a) >= (PPM_ONE) ? (c*a) : (PPM_ONE));
		uint256[NUM_RESOURCES] memory cost = [uint256(0), uint256(0), uint256(0)];
		cost[0] = (ONE_TOKEN * RECIPES[_block][0] * s) / 1000000000000;
		cost[1] = (ONE_TOKEN * RECIPES[_block][1] * s) / 1000000000000;
		cost[2] = (ONE_TOKEN * RECIPES[_block][2] * s) / 1000000000000;
		return cost;
	}

	/// @dev Create a tile at a position.
	/// This will initalize the id, price, blocks, and neighbor clouts.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	/// @return The created Tile (storage) instance.
	function _createTileAt(int32 x, int32 y) private returns (Tile storage) {
		bytes10 id = _toTileId(x, y);
		Tile storage tile = _tiles[id];
		if (tile.id == 0x0) {
			tile.id = id;
			tile.x = x;
			tile.y = y;
			tile.blocks = EMPTY_BLOCKS;
			tile.basePrice = MINIMUM_TILE_PRICE;
			// No need to iterate over neighbors to get accurate clouts since we know
			// tiles are only created when an unowned edge tile is bought, so its
			// only existing neighbor should be empty.
			tile.neighborCloutsTotal = NUM_NEIGHBORS;
		}
		return tile;
	}

	/// @dev Create neighbors for a tile at a position.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	function _createNeighbors(int32 x, int32 y) private {
		for (uint8 i = 0; i < NUM_NEIGHBORS; i++) {
			(int32 ox, int32 oy) = (((int32(i)%3)-1), (1-int32(i)/2));
			_createTileAt(x + ox, y + oy);
		}
	}

	/// @dev Get the Tile storage object at a position.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	/// @return The tile storage object at that position.
	function _getTileAt(int32 x, int32 y)
			private view returns (Tile storage) {

		return _tiles[_toTileId(x, y)];
	}

	/// @dev Get the Tile storage object at a position.
	/// Reverts if it does not exist.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	/// @return The tile storage object at that position.
	function _getExistingTileAt(int32 x, int32 y)
			private view returns (Tile storage) {

		bytes10 id = _toTileId(x, y);
		Tile storage tile = _tiles[id];
		require(tile.id == id, ERROR_NOT_FOUND);
		return tile;
	}

	/// @dev Increment the global block stats for all blocks passed.
	/// This will adjust the total counts, production rates, and total scores.
	/// @param blocks Right-aligned, packed representation of blocks to append.
	/// @param count The number of blocks packed in 'blocks'.
	function _incrementBlockStats(bytes16 blocks, uint8 count) private {
		for (uint8 h = 0; h < count; h++) {
			// Pop each block off the tower.
			uint8 b = uint8(uint128(blocks));
			blocks = blocks >> 8;
			BlockStats storage bs = _blockStats[b];
			bs.score += BLOCK_HEIGHT_BONUS[h];
			bs.count += 1;
			// Incrementally compute the production limit.
			uint64 production = (PPM_ONE * bs.production) / PRODUCTION_ALPHA;
			production = _estIntegerSqrt(bs.count, production);
			production = (production * PRODUCTION_ALPHA) / PPM_ONE;
			bs.production = production;
		}
	}

	/// @dev Share funds and resources from a tile to its immediate neighbors.
	/// The total amount distributed to all neighbors is defined by the TAX_RATE.
	/// The amount each neighbor actually receives depends on its relative
	/// 'clout', which is the height of its tower against all combined heights
	/// of all the towers of the tile's neighbors, so the tallest tower will
	/// receive the largest share.
	/// If a neighbor is unowned, its share of resources are discarded, but the
	/// funds are added to the 'fees' collected by this contract.
	/// @param tile The tile object sharing its funds/resources.
	/// @param funds The (untaxed) funds to share.
	/// @param resources The (untaxed) resources to share.
	function _share(
			Tile storage tile,
			uint256 funds,
			uint256[NUM_RESOURCES] memory resources)
			private {

		// Compute how much each neighbor is entitled to.
		uint256 sharedFunds = _toTaxes(funds);
		uint256[NUM_RESOURCES] memory sharedResources =
			[_toTaxes(resources[0]), _toTaxes(resources[1]), _toTaxes(resources[2])];
		// Share with neighbors.
		for (uint8 i = 0; i < NUM_NEIGHBORS; i++) {
			(int32 ox, int32 oy) = (((int32(i)%3)-1), (1-int32(i)/2));
			Tile storage neighbor = _getExistingTileAt(tile.x + ox, tile.y + oy);
			// Normalization factor so that taller towers receive more.
			uint64 clout = ((neighbor.height + 1) * PPM_ONE)
				/ tile.neighborCloutsTotal;
			// If the tile is owned, share resources and funds.
			if (neighbor.owner != ZERO_ADDRESS) {
				neighbor.sharedResources[0] =
					neighbor.sharedResources[0].add(
						(clout * sharedResources[0]) / PPM_ONE);
				neighbor.sharedResources[1] =
					neighbor.sharedResources[1].add(
						(clout * sharedResources[1]) / PPM_ONE);
				neighbor.sharedResources[2] =
					neighbor.sharedResources[2].add(
						(clout * sharedResources[2]) / PPM_ONE);
				neighbor.sharedFunds = neighbor.sharedFunds.add(
					clout * sharedFunds / PPM_ONE);
			} else {
				// If the tile is unowned, keep the funds as fees.
				fees = fees.add(
					(clout * sharedFunds) / PPM_ONE);
			}
		}
	}

	/// @dev Claims funds and resources from a tile to its owner.
	/// The amount minted/transfered/credited will be minus the tax.
	/// Resources are immediately minted to the tile owner.
	/// Funds (ether) are credited (pull pattern) to the tile owner unless
	/// the caller is also the tile owner, in which case it will be transfered
	/// immediately.
	/// @param tile The tile object.
	/// @param funds The funds (ether) held by the tile.
	/// @param resources The resources held by the tile.
	function _claim(
			Tile storage tile,
			uint256 funds,
			uint256[NUM_RESOURCES] memory resources)
			private {

		require(tile.owner != ZERO_ADDRESS, ERROR_INVALID);
		_mintTo(tile.owner, 0, _toTaxed(resources[0]));
		_mintTo(tile.owner, 1, _toTaxed(resources[1]));
		_mintTo(tile.owner, 2, _toTaxed(resources[2]));
		// If caller is not the owner, only credit funds.
		if (tile.owner != msg.sender)
			_creditTo(tile.owner, _toTaxed(funds));
		else // Otherwise try to transfer the funds synchronously.
			_transferTo(tile.owner, _toTaxed(funds));
	}

	/// @dev Get the full price for a tile.
	/// This is the isolated tile price plus seasonal bonuses,
	/// and neighborhood bonus.
	/// @param tile The tile object.
	/// @return The ether price, in wei.
	function _getTilePrice(Tile storage tile) private view
			returns (uint256 price) {

		uint256[NUM_RESOURCES] memory marketPrices = _getMarketPrices();
		price = _getIsolatedTilePrice(tile, marketPrices);
		/// Get the aggregate of neighbor prices.
		uint256 neighborPrices = 0;
		for (uint8 i = 0; i < NUM_NEIGHBORS; i++) {
			(int32 ox, int32 oy) = (((int32(i)%3)-1), (1-int32(i)/2));
			Tile storage neighbor = _getTileAt(tile.x + ox, tile.y + oy);
			if (neighbor.id != 0x0)
				neighborPrices = neighborPrices.add(
					_getIsolatedTilePrice(neighbor, marketPrices));
		}
		// Add the average of the neighbor prices.
		price = price.add(neighborPrices / NUM_NEIGHBORS);
		// If the tile is in season, it has a price bonus.
		if (_isTileInSeason(tile))
			price = price.mul(SEASON_PRICE_BONUS) / PPM_ONE;
	}

	/// @dev Get the isolated price for a tile.
	/// This is a sum of the base price for a tile (which increases
	/// with every purchase of the tile) and the materials costs of each block
	/// built on the tile at current market prices.
	function _getIsolatedTilePrice(
			Tile storage tile,
			uint256[NUM_RESOURCES] memory marketPrices)
			private view returns (uint256) {

		uint256 price = tile.basePrice;
		bytes16 blocks = tile.blocks;
		for (uint8 h = 0; h < tile.height; h++) {
			// Pop each block off the tower.
			uint8 b = uint8(uint128(blocks));
			blocks = blocks >> 8;
			uint256[NUM_RESOURCES] memory bc =
				_getBlockCost(b, _blockStats[b].count, h);
			price = price.add(marketPrices[0].mul(bc[0]) / ONE_TOKEN);
			price = price.add(marketPrices[1].mul(bc[1]) / ONE_TOKEN);
			price = price.add(marketPrices[2].mul(bc[2]) / ONE_TOKEN);
		}
		return price;
	}

	/// @dev Do a direct transfer of ether to someone.
	/// This is like address.transfer() but with some key differences:
	/// The transfer will forward all remaining gas to the recipient and
	/// will revert with an ERROR_TRANSFER_FAILED on failure.
	/// Transfers to the zero address (0x0), will simply add to the fees
	/// collected.
	/// @param to Recipient address.
	/// @param amount Amount of ether (in wei) to transfer.
	function _transferTo(address to, uint256 amount) private {
		if (amount > 0) {
			if (to == ZERO_ADDRESS) {
				fees = fees.add(amount);
				return;
			}
			// Use fallback function and forward all remaining gas.
			//solhint-disable-next-line
			(bool success,) = to.call.value(amount)("");
			require(success, ERROR_TRANSFER_FAILED);
		}
	}

	/// @dev Credit someone some ether to be pulled via collectCredits() later.
	/// Transfers to the zero address (0x0), will simply add to the fees
	/// collected.
	/// @param to Recipient address.
	/// @param amount Amount of ether (in wei) to transfer.
	function _creditTo(address to, uint256 amount) private {
		if (amount > 0) {
			// Payments to zero address are just fees collected.
			if (to == ZERO_ADDRESS) {
				fees = fees.add(amount);
				return;
			}
			// Just credit the player. She can collect it later through
			// collectCredits().
			credits[to] = credits[to].add(amount);
			emit Credited(to, amount);
		}
	}

	/// @dev Mint some resource tokens to someone.
	/// @param recipient The recipient.
	/// @param resource The resource ID number.
	/// @param amount The amount of tokens to mint (in wei).
	function _mintTo(
			address recipient, uint8 resource, uint256 amount) private {

		if (amount > 0)
			_market.mint(address(_tokens[resource]), recipient, amount);
	}

	/// @dev Burn some resource tokens from someone.
	/// @param spender The owner of the tokens.
	/// @param resources Amount of each resource to burn.
	function _burn(
			address spender,
			uint256[NUM_RESOURCES] memory resources) private {

		assert(spender != ZERO_ADDRESS);
		if (resources[0] > 0)
			_market.burn(address(_tokens[0]), spender, resources[0]);
		if (resources[1] > 0)
			_market.burn(address(_tokens[1]), spender, resources[1]);
		if (resources[2] > 0)
			_market.burn(address(_tokens[2]), spender, resources[2]);
	}

	/// @dev Get the current market price of each resource token.
	/// @return The ether market price of each token, in wei.
	function _getMarketPrices() private view
			returns (uint256[NUM_RESOURCES] memory prices) {

		prices[0] = _market.getPrice(address(_tokens[0]));
		prices[1] = _market.getPrice(address(_tokens[1]));
		prices[2] = _market.getPrice(address(_tokens[2]));
	}

}

    Contract ABI  
[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tilesBought","outputs":[{"name":"","type":"bytes10"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"int32"},{"name":"y","type":"int32"}],"name":"describeTile","outputs":[{"name":"id","type":"bytes10"},{"name":"name","type":"bytes16"},{"name":"timesBought","type":"uint32"},{"name":"owner","type":"address"},{"name":"blocks","type":"bytes16"},{"name":"price","type":"uint256"},{"name":"sharedResources","type":"uint256[3]"},{"name":"funds","type":"uint256"},{"name":"scores","type":"uint64[3]"},{"name":"inSeason","type":"bool"},{"name":"lastTouchTime","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isAuthority","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"}],"name":"collectCredits","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"int32"},{"name":"y","type":"int32"}],"name":"collect","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"blocks","type":"bytes16"}],"name":"getBuildCost","outputs":[{"name":"cost","type":"uint256[3]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"int32"},{"name":"y","type":"int32"}],"name":"buy","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getBlockStats","outputs":[{"name":"counts","type":"uint64[3]"},{"name":"productions","type":"uint64[3]"},{"name":"scores","type":"uint128[3]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"name","type":"bytes16"}],"name":"rename","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fees","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"}],"name":"collectFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"tokens","type":"address[3]"},{"name":"market","type":"address"},{"name":"genesisPlayer","type":"address"},{"name":"authorities","type":"address[]"}],"name":"init","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"blocks","type":"bytes16"}],"name":"buildBlocks","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"start","type":"uint32"},{"name":"count","type":"uint32"}],"name":"getTilesBoughtSlice","outputs":[{"name":"","type":"bytes10[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"player","type":"address"}],"name":"getPlayerBalance","outputs":[{"name":"funds","type":"uint256"},{"name":"resources","type":"uint256[3]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"credits","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes10"},{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"price","type":"uint256"}],"name":"Bought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes10"},{"indexed":true,"name":"owner","type":"address"}],"name":"Collected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"CreditsCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes10"},{"indexed":true,"name":"owner","type":"address"},{"indexed":false,"name":"blocks","type":"bytes16"}],"name":"Built","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes10"},{"indexed":false,"name":"name","type":"bytes16"}],"name":"Renamed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Credited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"FeesCollected","type":"event"}]

  Contract Creation Code Switch To Opcodes View
610280604052620f424060809081526210bc7960a05262125b5160c0526214225460e0526216156561010052621838c961012052621a912d61014052621d23b361016052621ff5fc6101805262230e356101a052622673226101c052622a2c326101e052622e4189610200526232bc18610220526237a5aa61024052623d090061026052620000939060009060106200021b565b506040805161020081018252620f42408152620ffafe60208201526210bc79918101919091526211871a606082015262125b5160808201526213399160a08201526214225460c08201526215161960e082015262161565610100820152621720c5610120820152621838c961014082015262195e0c610160820152621a912d610180820152621bd2d56101a0820152621d23b36101c0820152621e84806101e0820152620001469060049060106200021b565b506040805160608101825261c3508152620509106020820152620a1220918101919091526200017a906008906003620002c7565b506040805160c0810182526003606082810182815260016080850181905260a08501819052908452845180830186528181526020818101859052818701839052808601919091528551928301865281835282015280840182905292820192909252620001ea916009919062000326565b506000601555348015620001fd57600080fd5b506012805461010060a860020a03191633610100021790556200043d565b600483019183908215620002b55791602002820160005b838211156200027e57835183826101000a8154816001604060020a0302191690836001604060020a03160217905550926020019260080160208160070104928301926001030262000232565b8015620002b35782816101000a8154906001604060020a0302191690556008016020816007010492830192600103026200027e565b505b50620002c392915062000374565b5090565b600183019183908215620002b55791602002820160005b838211156200027e57835183826101000a8154816001604060020a03021916908362ffffff1602179055509260200192600801602081600701049283019260010302620002de565b60098301918390821562000366579160200282015b82811115620003665782516200035590839060036200039f565b50916020019190600301906200033b565b50620002c3929150620003e3565b6200039c91905b80821115620002c357805467ffffffffffffffff191681556001016200037b565b90565b8260038101928215620003d5579160200282015b82811115620003d5578251829060ff16905591602001919060010190620003b3565b50620002c39291506200040b565b6200039c91905b80821115620002c357600062000401828262000428565b50600301620003ea565b6200039c91905b80821115620002c3576000815560010162000412565b50600081556001016000815560010160009055565b613837806200044d6000396000f3fe6080604052600436106100f75760003560e060020a90048063734b9a861161008e578063cecaf3951161005d578063cecaf39514610639578063d73af1ae14610681578063e2734c9314610709578063fe5ff4681461075e576100f7565b8063734b9a86146104fe5780639af1d35a14610546578063a480ca791461056d578063cbb30f23146105a0576100f7565b80635c36a0bb116100ca5780635c36a0bb146103785780635e1bd33e146103af5780636373bb351461042f57806371e1272614610459576100f7565b80631622553a1461019e57806318e2d679146101e55780632330f247146102fc57806358bcdb5e14610343575b604080518082018252600781526000805160206137cc8339815191526020808301918252925160e560020a62461bcd0281526004810193845282516024820152825192939283926044909201919080838360005b8381101561016357818101518382015260200161014b565b50505050905090810190601f1680156101905780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b3480156101aa57600080fd5b506101c8600480360360208110156101c157600080fd5b5035610791565b60408051600160b060020a03199092168252519081900360200190f35b3480156101f157600080fd5b5061021c6004803603604081101561020857600080fd5b508035600390810b9160200135900b6107c9565b60408051600160b060020a03198d1681526001608060020a0319808d16602083015263ffffffff8c1692820192909252600160a060020a038a16606080830191909152918916608082015260a081018890529060c0820190879080838360005b8381101561029457818101518382015260200161027c565b5050505090500185815260200184600360200280838360005b838110156102c55781810151838201526020016102ad565b505050509415159190940190815267ffffffffffffffff9092166020830152506040805191829003019a5098505050505050505050f35b34801561030857600080fd5b5061032f6004803603602081101561031f57600080fd5b5035600160a060020a031661098d565b604080519115158252519081900360200190f35b34801561034f57600080fd5b506103766004803603602081101561036657600080fd5b5035600160a060020a03166109a2565b005b34801561038457600080fd5b506103766004803603604081101561039b57600080fd5b508035600390810b9160200135900b610a19565b3480156103bb57600080fd5b506103f7600480360360608110156103d257600080fd5b508035600390810b91602081013590910b90604001356001608060020a031916610b98565b6040518082606080838360005b8381101561041c578181015183820152602001610404565b5050505090500191505060405180910390f35b6103766004803603604081101561044557600080fd5b508035600390810b9160200135900b610bc2565b34801561046557600080fd5b5061046e610f63565b6040518084606080838360005b8381101561049357818101518382015260200161047b565b5050505090500183600360200280838360005b838110156104be5781810151838201526020016104a6565b5050505090500182600360200280838360005b838110156104e95781810151838201526020016104d1565b50505050905001935050505060405180910390f35b34801561050a57600080fd5b506103766004803603606081101561052157600080fd5b508035600390810b91602081013590910b90604001356001608060020a031916611005565b34801561055257600080fd5b5061055b6111a0565b60408051918252519081900360200190f35b34801561057957600080fd5b506103766004803603602081101561059057600080fd5b5035600160a060020a03166111a6565b3480156105ac57600080fd5b50610376600480360360c08110156105c357600080fd5b600160a060020a03606083013581169160808401359091169083018360c0810160a08201356401000000008111156105fa57600080fd5b82018360208201111561060c57600080fd5b8035906020019184602083028401116401000000008311171561062e57600080fd5b50909250905061132d565b34801561064557600080fd5b506103766004803603606081101561065c57600080fd5b508035600390810b91602081013590910b90604001356001608060020a03191661165b565b34801561068d57600080fd5b506106b9600480360360408110156106a457600080fd5b5063ffffffff813581169160200135166119f9565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106f55781810151838201526020016106dd565b505050509050019250505060405180910390f35b34801561071557600080fd5b5061073c6004803603602081101561072c57600080fd5b5035600160a060020a0316611b3c565b60405182815260208101826060808383600081810151838201526020016106dd565b34801561076a57600080fd5b5061055b6004803603602081101561078157600080fd5b5035600160a060020a0316611d14565b601680548290811061079f57fe5b9060005260206000209060039182820401919006600a02915054906101000a900460b060020a0281565b6000806000806000806107da613754565b60006107e4613754565b60008060006107f38e8e611d26565b80546001820154600883015460b060020a83029f50608060020a9182900482029e5063ffffffff60e060020a8404169d50600160a060020a03169b506a01000000000000000000009091040298509050600160b060020a03198c16156109245761085c81611d57565b60408051606081019182905291985060038381019182845b815481526020019060010190808311610874575050505050955061089b8160060154611e67565b6040805160608101918290529196506007830190600390826000855b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff16815260200190600801906020826007010492830192600103820291508084116108b75790505050505050935061090b81611e77565b600182015490935067ffffffffffffffff16915061097c565b600160a060020a0389161561093557fe5b604080516060818101835260008083526020808401829052838501829052845192830185528183528201819052928101839052919c508c9850965087955093508492508291505b509295989b509295989b9093969950565b60136020526000908152604090205460ff1681565b3360009081526014602052604081205490811115610a1557336000908152601460205260408120556109d48282611eed565b604080518281529051600160a060020a0384169133917f75bc698f04990cbcb7684cd06df09b9891d98b560d93b5cd33256e7c42f688c19181900360200190a35b5050565b60125460408051808201909152600d81526000805160206137ec83398151915260208201529060ff161515610a935760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b506000610aa08383612002565b6008810154909150600160a060020a03161515610abd5750610a15565b610ac5613754565b610acf82426120ca565b600683015460018401805467ffffffffffffffff19164267ffffffffffffffff16179055604080516060810182526000808252602082018190529181019190915291925090610b249060038086019190613773565b5060006006840155610b37838284612337565b610b42838284612545565b60088301548354604051600160a060020a039092169160b060020a909102600160b060020a031916907fdb3f5ac435ff0ad621ed00e6414d1ffa42e13ded49d340a558d3808cdec943fc90600090a35050505050565b610ba0613754565b6000610bac8585612002565b9050610bb88184612686565b5095945050505050565b60125460408051808201909152600d81526000805160206137ec83398151915260208201529060ff161515610c3c5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b50610c478282610a19565b6000610c538383612002565b600881015460408051808201909152600781527f414c5245414459000000000000000000000000000000000000000000000000006020820152919250600160a060020a0316331415610cea5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b506000610cf682611d57565b60408051808201909152600c81527f494e53554646494349454e540000000000000000000000000000000000000000602082015290915034821115610d805760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b5060088201805473ffffffffffffffffffffffffffffffffffffffff1981163317909155825463ffffffff60e060020a8083048216600101909116027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091161783556002830154600160a060020a0390911690620f42409062145855020460028401556001830154610e3290680100000000000000008104600390810b916c010000000000000000000000009004900b6128a6565b610e5b838360606040519081016040528060008152602001600081526020016000815250612337565b600160a060020a0381161515610ed95782546016805460018101825560009190915260038082047fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428901805460b060020a94850294909404600a92909306919091026101000a91820269ffffffffffffffffffff909202199092161790555b610eeb81610ee684611e67565b6128ea565b81341115610eff57610eff33833403611eed565b60088301548354604080518581529051600160a060020a0393841693851692600160b060020a031960b060020a90910216917fed66c913a4f5408d4dd860adb1025167bd6cc51316bdd8efb513820a9e3b6805919081900360200190a45050505050565b610f6b613754565b610f73613754565b610f7b613754565b60175467ffffffffffffffff80821685526fffffffffffffffffffffffffffffffff608060020a808404821685526801000000000000000093849004831686526018548084166020808a0191909152828204841687820152908590048416908701526019548084166040808a01919091529181049092168186015292900416908301529192909190565b60125460408051808201909152600d81526000805160206137ec83398151915260208201529060ff16151561107f5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b50600061108c8484612002565b600881015460408051808201909152600b81527f4e4f545f414c4c4f5745440000000000000000000000000000000000000000006020820152919250600160a060020a031633146111225760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b506001810180546fffffffffffffffffffffffffffffffff16608060020a808504021790558054604080516001608060020a031985168152905160b060020a909202600160b060020a031916917f0bf33e996815f37e226cce32a451cd67b9823a37f027a67a024237498a867679916020908290030190a250505050565b60155481565b60125460408051808201909152600d81526000805160206137ec83398151915260208201529060ff1615156112205760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b5033600090815260136020908152604091829020548251808401909352600a83527f52455354524943544544000000000000000000000000000000000000000000009183019190915260ff1615156112bd5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b50601554303110156112cb57fe5b6000601554111561132a576015805460009091556112e98282611eed565b604080518281529051600160a060020a038416917f9dc46f23cfb5ddcad0ae7ea2be38d47fec07bb9382ec7e564efc69e036dd66ce919081900360200190a2505b50565b60125460408051808201909152600a81527f52455354524943544544000000000000000000000000000000000000000000006020820152906101009004600160a060020a031633146113c45760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b5060125460408051808201909152600d81526000805160206137ec83398151915260208201529060ff161561143e5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b5060408051808201909152600781526000805160206137cc83398151915260208201525060005b818110156114b85760016013600085858581811061147f57fe5b60209081029290920135600160a060020a0316835250810191909152604001600020805460ff1916911515919091179055600101611465565b5060005b6003811015611522578581600381106114d157fe5b6020020135600160a060020a0316601a826003811015156114ee57fe5b01805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790556001016114bc565b50601d805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03861617905560006115578180612995565b60088101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038716179055805460e060020a7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091161780825560168054600181810183556000929092527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b5124289600380830491909101805469ffffffffffffffffffff93839006600a026101000a938402191660b060020a958602959095049290920293909317905582015491925061164b91680100000000000000008104820b916c01000000000000000000000000909104900b6128a6565b611653612ada565b505050505050565b60125460408051808201909152600d81526000805160206137ec83398151915260208201529060ff1615156116d55760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b506116e08383610a19565b60006116ec8484612002565b600881015460408051808201909152600b81527f4e4f545f414c4c4f5745440000000000000000000000000000000000000000006020820152919250600160a060020a031633146117825760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b5061178b613754565b60006117978385612686565b60408051808201909152600781526000805160206137cc83398151915260208201529193509150600060ff8316116118145760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b50825461182c9060d060020a900460ff168201612b63565b60408051808201909152600a81527f4d41585f4845494748540000000000000000000000000000000000000000000060208201529015156118b25760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b506118be838583612b70565b6118c88382612c2c565b6118d28482612ceb565b82546118ff906a01000000000000000000008104608060020a0290869060d060020a900460ff1684612e10565b835460ff60d060020a608060020a9093046a01000000000000000000000279ffffffffffffffffffffffffffffffff000000000000000000001990921691909117828104821684019091169091027aff00000000000000000000000000000000000000000000000000001990911617835561197a3383612e64565b60088301548354604080516a01000000000000000000008304608060020a026001608060020a03191681529051600160a060020a039093169260b060020a909202600160b060020a031916917f956a8614019d48b7d2ee9a31e1c7fd4c61dca239d8a6cfacf1ea5065135f9a4a916020908290030190a3505050505050565b6016546060901515611a1a5750604080516000815260208101909152611b36565b600060016016805490500363ffffffff168463ffffffff161115611a445760165460001901611a46565b835b90506000816016805490500363ffffffff168463ffffffff161115611a7057601654829003611a72565b835b905060608163ffffffff16604051908082528060200260200182016040528015611aa6578160200160208202803883390190505b50905060005b8263ffffffff168163ffffffff161015611b30576016805463ffffffff86840116908110611ad657fe5b9060005260206000209060039182820401919006600a029054906101000a900460b060020a02828263ffffffff16815181101515611b1057fe5b600160b060020a0319909216602092830290910190910152600101611aac565b50925050505b92915050565b6000611b46613754565b601a54604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a0386811660048301819052925192319550909216916370a08231916024808301926020929190829003018186803b158015611bb157600080fd5b505afa158015611bc5573d6000803e3d6000fd5b505050506040513d6020811015611bdb57600080fd5b50518152601b54604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152915191909216916370a08231916024808301926020929190829003018186803b158015611c4557600080fd5b505afa158015611c59573d6000803e3d6000fd5b505050506040513d6020811015611c6f57600080fd5b5051602080830191909152601c54604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152915191909216926370a082319260248082019391829003018186803b158015611cdc57600080fd5b505afa158015611cf0573d6000803e3d6000fd5b505050506040513d6020811015611d0657600080fd5b505160408201529092909150565b60146020526000908152604090205481565b6000601e6000611d368585613057565b600160b060020a031916815260208101919091526040016000209392505050565b6000611d61613754565b611d696130a9565b9050611d75838261327f565b91506000805b600660ff82161015611e1e57600185810154600019600360ff8516810b81810783810195600290920590910393600093611ddc93680100000000000000008304810b90930101916c01000000000000000000000000909104900b8401611d26565b805490915060b060020a02600160b060020a03191615611e1357611e10611e03828861327f565b869063ffffffff61339a16565b94505b505050600101611d7b565b50611e2c836006830461339a565b9250611e3784611e77565b15611e6057620f4240611e53846216e36063ffffffff6133b316565b811515611e5c57fe5b0492505b5050919050565b620f424062028b0b820204900390565b805460408051306c010000000000000000000000000260208083019190915260b060020a909302600160b060020a03191660348201528151808203601e018152603e9091019091528051910120600090611ecf6133de565b6fffffffffffffffffffffffffffffffff1660088206149392505050565b6000811115610a1557600160a060020a0382161515611f2157601554611f19908263ffffffff61339a16565b601555610a15565b604051600090600160a060020a0384169083908381818185875af1925050503d8060008114611f6c576040519150601f19603f3d011682016040523d82523d6000602084013e611f71565b606091505b505060408051808201909152600f81527f5452414e534645525f4641494c454400000000000000000000000000000000006020820152909150811515611ffc5760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b50505050565b60008061200f8484613057565b600160b060020a03198082166000818152601e602090815260409182902080548351808501909452600984527f4e4f545f464f554e44000000000000000000000000000000000000000000000092840192909252949550909260b060020a90910216146120c15760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b50949350505050565b6120d2613754565b825460b060020a02600160b060020a03191615156120ec57fe5b600183015460408051808201909152600b81527f54494d455f54524156454c00000000000000000000000000000000000000000060208201529067ffffffffffffffff90811690841610156121865760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b50600061219284611e77565b61219f57620f42406121a4565b621312d05b600185015460408051606081019182905292935067ffffffffffffffff9091168503919060038088019182845b8154815260200190600101908083116121d15750939650600093505050505b600360ff8216101561232e576000601760ff83166003811061220e57fe5b015467ffffffffffffffff848116680100000000000000009092041602670de0b6b3a76400000290506007870160ff83166003811061224957fe5b600481049091015467ffffffffffffffff86811660086003948516026101000a90920416929092029190910290620f42409060179060ff851690811061228b57fe5b0154608060020a90046fffffffffffffffffffffffffffffffff1610156122b557620f42406122e1565b601760ff8316600381106122c557fe5b0154608060020a90046fffffffffffffffffffffffffffffffff165b670132f4579c980000026fffffffffffffffffffffffffffffffff168181151561230757fe5b049050808560ff84166003811061231a57fe5b6020020180519091019052506001016121f0565b50505092915050565b60006123428361341d565b905061234c613754565b6040805160608101909152806123698560005b602002015161341d565b815260200161237985600161235f565b815260200161238985600261235f565b9052905060005b600660ff8216101561165357600186810154600019600360ff8516810b818107838101956002909205909103936000936123f193680100000000000000008304810b90930101916c01000000000000000000000000909104900b8401612002565b8954815491925060009160ff7b0100000000000000000000000000000000000000000000000000000090920482169167ffffffffffffffff600160d060020a90930482169290920116620f4240021681151561244957fe5b60088401549190049150600160a060020a03161561251357855161248e90620f42409067ffffffffffffffff841602046003840160005b01549063ffffffff61339a16565b600383015560208601516124b990620f42409067ffffffffffffffff84160204600384016001612480565b600483015560408601516124e490620f42409067ffffffffffffffff84160204600384016002612480565b6005830155600682015461250990620f424067ffffffffffffffff84168a020461339a565b6006830155612535565b60155461253190620f424067ffffffffffffffff84168a020461339a565b6015555b5050600190920191506123909050565b600883015460408051808201909152600781526000805160206137cc833981519152602082015290600160a060020a031615156125c75760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b5060088301546125f190600160a060020a031660006125ec84825b6020020151611e67565b61342d565b600883015461260f90600160a060020a031660016125ec84826125e2565b600883015461262d90600160a060020a031660026125ec84826125e2565b6008830154600160a060020a0316331461266157600883015461265c90600160a060020a0316610ee684611e67565b612681565b600883015461268190600160a060020a031661267c84611e67565b611eed565b505050565b61268e613754565b825460009060b060020a02600160b060020a03191615156126ab57fe5b6126b3613754565b6060604051908101604052806000815260200160008152602001600081525090506126dc613754565b506040805160608101825260175467ffffffffffffffff908116825260185481166020830152601954169181019190915260005b601060ff82161015612899576101006001608060020a031987160495608060020a900461273c816134c9565b15156127485750612899565b87546127629060d060020a900460ff168301600101612b63565b60408051808201909152600a81527f4d41585f4845494748540000000000000000000000000000000000000000000060208201529015156127e85760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b506127f1613754565b61281c828560ff82166003811061280457fe5b60200201518b5460d060020a900460ff1686016134d6565b805190915061283a908660005b60200201519063ffffffff61339a16565b8552602081015161284d90866001612829565b6020860152604081015161286390866002612829565b604086015260018460ff84166003811061287957fe5b6020020180519190910167ffffffffffffffff1690525050600101612710565b9196919550909350505050565b60005b600660ff8216101561268157600019600360ff8316810b908107828101926002909205600103916128df91870101858301612995565b5050506001016128a9565b6000811115610a1557600160a060020a038216151561291657601554611f19908263ffffffff61339a16565b600160a060020a03821660009081526014602052604090205461293f908263ffffffff61339a16565b600160a060020a038316600081815260146020908152604091829020939093558051848152905191927f9c9e0cdb1670e88302408e5b941dc636f63a3293204694bb68910fcf3d9305f392918290030190a25050565b6000806129a28484613057565b600160b060020a03198082166000908152601e6020526040902080549293509160b060020a02161515612ad25780546001820180546bffffffff0000000000000000191668010000000000000000600389810b63ffffffff90811692909202929092176fffffffff00000000000000000000000019166c010000000000000000000000009289900b919091169190910217905566038d7ea4c68000600283015579ffffffffffffffffffffffffffffffff0000000000000000000069ffffffffffffffffffff1990911660b060020a84041779ffffffffffffffffffffffffffffffff000000000000000000001916177bff00000000000000000000000000000000000000000000000000000019167b060000000000000000000000000000000000000000000000000000001781555b949350505050565b60125460408051808201909152600d81526000805160206137ec83398151915260208201529060ff1615612b535760405160e560020a62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561016357818101518382015260200161014b565b506012805460ff19166001179055565b601060ff82161115919050565b60005b8160ff168160ff161015611ffc5783546101006001608060020a031985160493608060020a90049060049060ff60d060020a909104811684011660108110612bb757fe5b600491828204019190066008029054906101000a900467ffffffffffffffff16856007018260ff16600381101515612beb57fe5b60048104909101805467ffffffffffffffff60086003909416939093026101000a808204841690940183168402929093021990921617905550600101612b73565b60005b600660ff8216101561268157600183810154600019600360ff8516810b81810783810195600290920590910393600093612c9093680100000000000000008304810b90930101916c01000000000000000000000000909104900b8401611d26565b805460ff7b0100000000000000000000000000000000000000000000000000000080830482168901909116027bff00000000000000000000000000000000000000000000000000000019909116179055505050600101612c2f565b60005b8160ff168160ff161015612681576101006001608060020a031984160492608060020a90046000601760ff831660038110612d2557fe5b019050600460ff841660108110612d3857fe5b6004810491909101548254608060020a8082046fffffffffffffffffffffffffffffffff90811667ffffffffffffffff60086003909716969096026101000a909404851693909301831602911617808216600101821667ffffffffffffffff1991909116178083556216e360620f424068010000000000000000830484160283160491612dc691168261368d565b8254620f424067ffffffffffffffff6216e36090930283160490911668010000000000000000026fffffffffffffffff000000000000000019909116179091555050600101612cee565b608060020a80850460ff60088086028216600290810a600019928702909316900a016fffffffffffffffffffffffffffffffff90811682028019939093168488049091169091029091161702949350505050565b600160a060020a0382161515612e7657fe5b805160001015612f1457601d54601a548251604080517ff6b911bc000000000000000000000000000000000000000000000000000000008152600160a060020a0393841660048201528684166024820152604481019290925251919092169163f6b911bc91606480830192600092919082900301818387803b158015612efb57600080fd5b505af1158015612f0f573d6000803e3d6000fd5b505050505b602081015160001015612fb857601d54601b546020830151604080517ff6b911bc000000000000000000000000000000000000000000000000000000008152600160a060020a0393841660048201528684166024820152604481019290925251919092169163f6b911bc91606480830192600092919082900301818387803b158015612f9f57600080fd5b505af1158015612fb3573d6000803e3d6000fd5b505050505b604081015160001015610a1557601d54601c5460408084015181517ff6b911bc000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152868416602482015260448101919091529051919092169163f6b911bc91606480830192600092919082900301818387803b15801561304357600080fd5b505af1158015611653573d6000803e3d6000fd5b67ffffffffffffffff600392830b63ffffffff9081169290930b9290921664010000000002171660b060020a027f13370000000000000000000000000000000000000000000000000000000000001790565b6130b1613754565b601d54601a54604080517f41976e09000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152905191909216916341976e09916024808301926020929190829003018186803b15801561311a57600080fd5b505afa15801561312e573d6000803e3d6000fd5b505050506040513d602081101561314457600080fd5b50518152601d54601b54604080517f41976e09000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152905191909216916341976e09916024808301926020929190829003018186803b1580156131b157600080fd5b505afa1580156131c5573d6000803e3d6000fd5b505050506040513d60208110156131db57600080fd5b5051602080830191909152601d54601c54604080517f41976e09000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152905191909216926341976e099260248082019391829003018186803b15801561324b57600080fd5b505afa15801561325f573d6000803e3d6000fd5b505050506040513d602081101561327557600080fd5b5051604082015290565b60028201548254600091906a01000000000000000000009004608060020a02825b855460ff60d060020a90910481169082161015613390576101006001608060020a031983160491608060020a90046132d6613754565b6132fc82601760ff8216600381106132ea57fe5b015467ffffffffffffffff16856134d6565b9050613342670de0b6b3a764000061332a83600060200201518a60005b60200201519063ffffffff6133b316565b81151561333357fe5b8791900463ffffffff61339a16565b9450613363670de0b6b3a764000061332a83600160200201518a6001613319565b9450613384670de0b6b3a764000061332a83600260200201518a6002613319565b945050506001016132a0565b5090949350505050565b6000828201838110156133ac57600080fd5b9392505050565b60008215156133c457506000611b36565b8282028284828115156133d357fe5b04146133ac57600080fd5b6000600862141054635c2af3cf19420167ffffffffffffffff160467ffffffffffffffff1681151561340c57fe5b0667ffffffffffffffff1690505b90565b620f424062028b0b919091020490565b600081111561268157601d54600160a060020a031663c6c3bbe6601a60ff85166003811061345757fe5b01546040805160e060020a63ffffffff8516028152600160a060020a03928316600482015291871660248301526044820185905251606480830192600092919082900301818387803b1580156134ac57600080fd5b505af11580156134c0573d6000803e3d6000fd5b50505050505050565b600260ff82161115919050565b6134de613754565b6134e7846134c9565b80156134f757506134f782612b63565b15156134ff57fe5b600060018467ffffffffffffffff16101561351b57600161351d565b835b67ffffffffffffffff1690506000600860ff87166003811061353b57fe5b60048104919091015460039091166008026101000a900467ffffffffffffffff1690506000620f4240838302101561357657620f424061357a565b8183025b600060ff87166010811061358a57fe5b600491828204019190066008029054906101000a900467ffffffffffffffff1667ffffffffffffffff160290506135bf613754565b50604080516060810182526000808252602082018190529181019190915264e8d4a5100082600960ff8b16600381106135f457fe5b600302015402670de0b6b3a76400000281151561360d57fe5b04815264e8d4a5100082600960ff8b166003811061362757fe5b6003020160010154670de0b6b3a7640000020281151561364357fe5b04602082015264e8d4a5100082600960ff8b166003811061366057fe5b6003020160020154670de0b6b3a7640000020281151561367c57fe5b046040820152979650505050505050565b600067ffffffffffffffff831615156136a857506000611b36565b8267ffffffffffffffff16600114156136c55750620f4240611b36565b620f424067ffffffffffffffff8481169182029164e8d4a5100002906000908516156136fb578467ffffffffffffffff16613712565b6002600167ffffffffffffffff881601620f424002045b90506002818381151561372157fe5b04820181151561372d57fe5b0490506002818381151561373d57fe5b04820181151561374957fe5b049695505050505050565b6060604051908101604052806003906020820280388339509192915050565b82600381019282156137a1579160200282015b828111156137a1578251825591602001919060010190613786565b506137ad9291506137b1565b5090565b61341a91905b808211156137ad57600081556001016137b756fe494e56414c494400000000000000000000000000000000000000000000000000554e494e495449414c495a454400000000000000000000000000000000000000a165627a7a7230582095d81de47e957184ea7264b90d3ad0a007e4160da6ca632ab38a09e2e5ad81d20029

   Swarm Source:
bzzr://95d81de47e957184ea7264b90d3ad0a007e4160da6ca632ab38a09e2e5ad81d2

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward