Contract Overview
Balance: 0.459895833333333327 Ether
Transactions: 13 txns
 Latest 13 txns

TxHash Age From To Value [TxFee]
0xc09c924ea30e86e4d1ed80501ea30943b4df775bca9f9c7ae0872d5801e025b440 days 3 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.057291666666666 Ether0.000168842
0xc4bc2b7f924bad43ff97ead622b83e194aa59cbd1cd4fa996fe9fe4f3a8a6bfa40 days 3 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.038541666666666 Ether0.00032654
0x80c6318761ac5d178eae5b2f0ff1e6b6dc7d07a2bb37adc0d8f8d84546a5232040 days 4 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.038541666666666 Ether0.00032654
0xb35c565ae7e7f98f8b97ae3ef4d5105a5535af03661960a4eef836bd584c78ee40 days 4 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.038541666666666 Ether0.00032654
0x4f3d79f1195c5e7fd06f9ab96dde4c7604dfbd3329418ddda104b3586d5fde6240 days 4 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.057812499999999 Ether0.000326719
0xa0eac0b36122280676c559951796f839f40ff96fbb091f789168f78cd01cab2d40 days 4 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.038541666666666 Ether0.00032654
0xd4e338d6a9be6d6e4761713a24e72036168ef467444acf244b275c808f7bf07a40 days 4 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.038541666666666 Ether0.00032654
0x00eae77886ef72e9472714373486532b9d96552d5e0e2b66815ad0b4b837b93840 days 4 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.0375 Ether0.00031154
0xe615163705f6bb6a2024626e1bc28a0b445b9255044d1bc1ec2be6210530174140 days 4 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.038541666666666 Ether0.000326476
0xb16cec10b923cb7c47913b3171f6e71e78f7a19e80151c240a2933968d78d55c40 days 4 hrs ago0x2621ea417659ad69bae66af05ebe5788e533e5e7  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.038541666666666 Ether0.000326476
0xcb0ebd89243286efe0c8ac6017093a0f0d8c3d9811b67f98ef431e53c931809340 days 4 hrs ago0x31f2e532799041fea9c72cd3f5160b45c68a8a5e  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430.0375 Ether0.000341476
0xda969c15dd9464c65752bed1772d152c1b6b7e6f68ad65fc9b100a63ff2d9b7c40 days 6 hrs ago0x506a11d2763b61300425bbb54c9f2490cc238707  IN   0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430 Ether0.00592862
0x29f55fa020f56a971c36e9109863c1f481f02c008e60fe3776cf2b329fd157d740 days 6 hrs ago0x506a11d2763b61300425bbb54c9f2490cc238707  IN    Contract Creation0 Ether0.03948636
[ 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
0xc09c924ea30e86e4d1ed80501ea30943b4df775bca9f9c7ae0872d5801e025b4481992740 days 3 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xc09c924ea30e86e4d1ed80501ea30943b4df775bca9f9c7ae0872d5801e025b4481992740 days 3 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xc09c924ea30e86e4d1ed80501ea30943b4df775bca9f9c7ae0872d5801e025b4481992740 days 3 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xc4bc2b7f924bad43ff97ead622b83e194aa59cbd1cd4fa996fe9fe4f3a8a6bfa481963740 days 3 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xc4bc2b7f924bad43ff97ead622b83e194aa59cbd1cd4fa996fe9fe4f3a8a6bfa481963740 days 3 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xc4bc2b7f924bad43ff97ead622b83e194aa59cbd1cd4fa996fe9fe4f3a8a6bfa481963740 days 3 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0x80c6318761ac5d178eae5b2f0ff1e6b6dc7d07a2bb37adc0d8f8d84546a52320481932640 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0x80c6318761ac5d178eae5b2f0ff1e6b6dc7d07a2bb37adc0d8f8d84546a52320481932640 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0x80c6318761ac5d178eae5b2f0ff1e6b6dc7d07a2bb37adc0d8f8d84546a52320481932640 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xb35c565ae7e7f98f8b97ae3ef4d5105a5535af03661960a4eef836bd584c78ee481928740 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xb35c565ae7e7f98f8b97ae3ef4d5105a5535af03661960a4eef836bd584c78ee481928740 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xb35c565ae7e7f98f8b97ae3ef4d5105a5535af03661960a4eef836bd584c78ee481928740 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0x4f3d79f1195c5e7fd06f9ab96dde4c7604dfbd3329418ddda104b3586d5fde62481926040 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0x4f3d79f1195c5e7fd06f9ab96dde4c7604dfbd3329418ddda104b3586d5fde62481926040 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0x4f3d79f1195c5e7fd06f9ab96dde4c7604dfbd3329418ddda104b3586d5fde62481926040 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xa0eac0b36122280676c559951796f839f40ff96fbb091f789168f78cd01cab2d481920540 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xa0eac0b36122280676c559951796f839f40ff96fbb091f789168f78cd01cab2d481920540 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xa0eac0b36122280676c559951796f839f40ff96fbb091f789168f78cd01cab2d481920540 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xd4e338d6a9be6d6e4761713a24e72036168ef467444acf244b275c808f7bf07a481905540 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xd4e338d6a9be6d6e4761713a24e72036168ef467444acf244b275c808f7bf07a481905540 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xd4e338d6a9be6d6e4761713a24e72036168ef467444acf244b275c808f7bf07a481905540 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0x00eae77886ef72e9472714373486532b9d96552d5e0e2b66815ad0b4b837b938481899140 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0x00eae77886ef72e9472714373486532b9d96552d5e0e2b66815ad0b4b837b938481899140 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0x00eae77886ef72e9472714373486532b9d96552d5e0e2b66815ad0b4b837b938481899140 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 Ether
0xe615163705f6bb6a2024626e1bc28a0b445b9255044d1bc1ec2be62105301741481896740 days 4 hrs ago0x4d8ea3a1c677c4405757853c96ffb1c24ebd5b430x836c03ee97f5e140c6b0b2a7721ae86cb968995c0 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);
}

/// @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.
		bytes16 id;
		// Right-aligned, packed representation of blocks,
		// where 0x..FF is empty.
		bytes16 blocks;
		// 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 height of the tower on the tile (length of blocks).
		uint8 height;
		// NUM_NEIGHBORS + the height of each neighbor's tower.
		uint8 neighborCloutsTotal;
		// The name of the tile.
		bytes12 name;
		// The current owner of the tile.
		address owner;
		// 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;
	}

	// 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);
	// Number of decimals for all resource tokens and ether (18).
	uint8 internal constant DECIMALS = 18;
	// 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.
	uint256 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 = 25000000000000000;
	// How much to increase the base tile price every time it's bought, in ppm.
	uint64 internal constant PURCHASE_MARKUP = 1250000;
	// 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, 250000, 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 view returns (bytes16) {
		return bytes16(keccak256(abi.encodePacked(x, y, address(this))));
	}

	/// @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) {
		return uint128(tile.id) % 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;
	// 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(bytes16=>Tile) private _tiles;

	/// @dev Raised whenever a tile is bought.
	event Bought(bytes16 indexed id, address indexed from, address indexed to, uint256 price);
	/// @dev Raised whenever a tile's resources/funds are collected.
	event Collected(bytes16 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(bytes16 indexed id, address indexed owner, bytes16 blocks);
	/// @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;
		_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 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.
				bytes16 id,
				/// @dev The name of the tile. Zero-terminated UTF-8 string.
				bytes12 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 each resource available to collect()
				/// (including tax).
				uint256[NUM_RESOURCES] memory resources,
				/// @dev The amount ether available to collect()
				/// (including tax).
				uint256 funds,
				/// @dev Whether or not this tile is in season.
				/// Tiles in season yield more resources and have higher prices.
				bool inSeason) {

		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);
			resources = _getTileYield(tile);
			inSeason = _isTileInSeason(tile);
			funds = _toTaxed(tile.sharedFunds);
		}
		else {
			assert(owner == address(0x0));
			name = 0x0;
			price = 0;
			resources = [uint256(0), uint256(0), uint256(0)];
			inSeason = false;
			funds = 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)]);
		// 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);
		// Burn the costs.
		_burn(msg.sender, cost);
		tile.blocks = _assignBlocks(tile.blocks, blocks, tile.height, count);
		tile.height += count;
		// Increase clout total for each neighbor.
		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);
			neighbor.neighborCloutsTotal += count;
		}
		_incrementBlockStats(blocks, count);
		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, bytes12 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;
	}

	/// @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);
		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);
	/// @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.
		_claim(tile, funds, produced);
		emit Collected(tile.id, tile.owner);
	}

	/// @dev Convert a tile position to its ID.
	/// The ID is deterministic, and depends on the instance of this contract.
	/// @param x The x position of the tile.
	/// @param y The y position of the tile.
	/// @return A bytes16 unique ID of the tile.
	function toTileId(int32 x, int32 y) public view returns (bytes16) {
		return _toTileId(x, y);
	}

	/// @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 Get the amount resources held by a tile at the current time.
	/// 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.
	/// @return The amount of each resource produced.
	function _getTileYield(Tile storage tile)
			private view returns (uint256[NUM_RESOURCES] memory produced) {

		assert(tile.id != 0x0);
		require(uint64(block.timestamp) >= tile.lastTouchTime, ERROR_TIME_TRAVEL);
		uint64 seasonBonus = _isTileInSeason(tile) ? SEASON_YIELD_BONUS : PPM_ONE;
		uint64 dt = uint64(block.timestamp) - tile.lastTouchTime;
		// Geneerate resources on top of what's been shared to this tile.
		produced = tile.sharedResources;
		bytes16 blocks = tile.blocks;
		for (uint8 height = 0; height < tile.height; height++) {
			// Pop each block off the tower.
			uint8 b = uint8(uint128(blocks));
			blocks = blocks >> 8;
			uint256 amt = ONE_TOKEN * _blockStats[b].production;
			amt *= dt;
			amt *= BLOCK_HEIGHT_BONUS[height];
			amt *= seasonBonus;
			amt /= (_blockStats[b].score) * 86400000000000000000000;
			produced[b] = produced[b].add(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) {
		bytes16 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;
			// 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;
			tile.basePrice = MINIMUM_TILE_PRICE;
		}
		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) {

		bytes16 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(sharedFunds);
			} 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)
			_tokens[resource].mint(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)
			_tokens[0].burn(spender, resources[0]);
		if (resources[1] > 0)
			_tokens[1].burn(spender, resources[1]);
		if (resources[2] > 0)
			_tokens[2].burn(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":"x","type":"int32"},{"name":"y","type":"int32"}],"name":"describeTile","outputs":[{"name":"id","type":"bytes16"},{"name":"name","type":"bytes12"},{"name":"timesBought","type":"uint32"},{"name":"owner","type":"address"},{"name":"blocks","type":"bytes16"},{"name":"price","type":"uint256"},{"name":"resources","type":"uint256[3]"},{"name":"funds","type":"uint256"},{"name":"inSeason","type":"bool"}],"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":true,"inputs":[{"name":"x","type":"int32"},{"name":"y","type":"int32"}],"name":"toTileId","outputs":[{"name":"","type":"bytes16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"name","type":"bytes12"}],"name":"rename","outputs":[],"payable":false,"stateMutability":"nonpayable","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":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":"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":"bytes16"},{"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":"bytes16"},{"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":"bytes16"},{"indexed":true,"name":"owner","type":"address"},{"indexed":false,"name":"blocks","type":"bytes16"}],"name":"Built","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
610280604052620f424060809081526210bc7960a05262125b5160c0526214225460e0526216156561010052621838c961012052621a912d61014052621d23b361016052621ff5fc6101805262230e356101a052622673226101c052622a2c326101e052622e4189610200526232bc18610220526237a5aa61024052623d090061026052620000939060009060106200021b565b506040805161020081018252620f42408152620ffafe60208201526210bc79918101919091526211871a606082015262125b5160808201526213399160a08201526214225460c08201526215161960e082015262161565610100820152621720c5610120820152621838c961014082015262195e0c610160820152621a912d610180820152621bd2d56101a0820152621d23b36101c0820152621e84806101e0820152620001469060049060106200021b565b506040805160608101825261c35081526203d0906020820152620a1220918101919091526200017a906008906003620002c7565b506040805160c0810182526003606082810182815260016080850181905260a08501819052908452845180830186528181526020818101859052818701839052808601919091528551928301865281835282015280840182905292820192909252620001ea916009919062000326565b506000601555348015620001fd57600080fd5b506012805461010060a860020a03191633610100021790556200043d565b600483019183908215620002b55791602002820160005b838211156200027e57835183826101000a8154816001604060020a0302191690836001604060020a03160217905550926020019260080160208160070104928301926001030262000232565b8015620002b35782816101000a8154906001604060020a0302191690556008016020816007010492830192600103026200027e565b505b50620002c392915062000374565b5090565b600183019183908215620002b55791602002820160005b838211156200027e57835183826101000a8154816001604060020a03021916908362ffffff1602179055509260200192600801602081600701049283019260010302620002de565b60098301918390821562000366579160200282015b82811115620003665782516200035590839060036200039f565b50916020019190600301906200033b565b50620002c3929150620003e3565b6200039c91905b80821115620002c357805467ffffffffffffffff191681556001016200037b565b90565b8260038101928215620003d5579160200282015b82811115620003d5578251829060ff16905591602001919060010190620003b3565b50620002c39291506200040b565b6200039c91905b80821115620002c357600062000401828262000428565b50600301620003ea565b6200039c91905b80821115620002c3576000815560010162000412565b50600081556001016000815560010160009055565b6132c5806200044d6000396000f3fe608060405260043610610105576000357c0100000000000000000000000000000000000000000000000000000000900480636373bb35116100a7578063cbb30f2311610076578063cbb30f2314610595578063cecaf3951461062e578063e2734c9314610676578063fe5ff468146106e857610105565b80636373bb351461046c57806371e12726146104965780639af1d35a1461053b578063a480ca791461056257610105565b80634eab9277116100e35780634eab92771461032b57806358bcdb5e146103825780635c36a0bb146103b55780635e1bd33e146103ec57610105565b806318e2d679146101ac5780632330f2471461029057806332ca966e146102d7575b6040805180820182526007815260008051602061325a8339815191526020808301918252925160e560020a62461bcd0281526004810193845282516024820152825192939283926044909201919080838360005b83811015610171578181015183820152602001610159565b50505050905090810190601f16801561019e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b3480156101b857600080fd5b506101e3600480360360408110156101cf57600080fd5b508035600390810b9160200135900b61071b565b604080516001608060020a0319808c16825273ffffffffffffffffffffffffffffffffffffffff198b16602083015263ffffffff8a1692820192909252600160a060020a038816606080830191909152918716608082015260a081018690529060c0820190859080838360005b83811015610268578181015183820152602001610250565b5050505091909101938452505015156020820152604080519182900301975095505050505050f35b34801561029c57600080fd5b506102c3600480360360208110156102b357600080fd5b5035600160a060020a031661080e565b604080519115158252519081900360200190f35b3480156102e357600080fd5b5061030e600480360360408110156102fa57600080fd5b508035600390810b9160200135900b610823565b604080516001608060020a03199092168252519081900360200190f35b34801561033757600080fd5b506103806004803603606081101561034e57600080fd5b508035600390810b91602081013590910b906040013573ffffffffffffffffffffffffffffffffffffffff1916610838565b005b34801561038e57600080fd5b50610380600480360360208110156103a557600080fd5b5035600160a060020a0316610983565b3480156103c157600080fd5b50610380600480360360408110156103d857600080fd5b508035600390810b9160200135900b6109fa565b3480156103f857600080fd5b506104346004803603606081101561040f57600080fd5b508035600390810b91602081013590910b90604001356001608060020a031916610b90565b6040518082606080838360005b83811015610459578181015183820152602001610441565b5050505090500191505060405180910390f35b6103806004803603604081101561048257600080fd5b508035600390810b9160200135900b610bba565b3480156104a257600080fd5b506104ab610ec6565b6040518084606080838360005b838110156104d05781810151838201526020016104b8565b5050505090500183600360200280838360005b838110156104fb5781810151838201526020016104e3565b5050505090500182600360200280838360005b8381101561052657818101518382015260200161050e565b50505050905001935050505060405180910390f35b34801561054757600080fd5b50610550610f68565b60408051918252519081900360200190f35b34801561056e57600080fd5b506103806004803603602081101561058557600080fd5b5035600160a060020a0316610f6e565b3480156105a157600080fd5b50610380600480360360c08110156105b857600080fd5b600160a060020a03606083013581169160808401359091169083018360c0810160a08201356401000000008111156105ef57600080fd5b82018360208201111561060157600080fd5b8035906020019184602083028401116401000000008311171561062357600080fd5b5090925090506110f5565b34801561063a57600080fd5b506103806004803603606081101561065157600080fd5b508035600390810b91602081013590910b90604001356001608060020a03191661138e565b34801561068257600080fd5b506106a96004803603602081101561069957600080fd5b5035600160a060020a03166117a6565b6040518281526020810182606080838360005b838110156106d45781810151838201526020016106bc565b505050509050019250505060405180910390f35b3480156106f457600080fd5b506105506004803603602081101561070b57600080fd5b5035600160a060020a031661197e565b60008060008060008061072c6131e2565b600080600061073b8c8c611990565b805460018201546002830154608060020a8084029e5060a060020a82029d5063ffffffff9092169b50606060020a9004600160a060020a031699509081900402965090506001608060020a03198a16156107c457610798816119c1565b94506107a381611ac3565b93506107ae81611d44565b91506107bd8160070154611d8d565b9250610800565b600160a060020a038716156107d557fe5b6040805160608101825260008082526020820181905291810182905290995089955093508492508291505b509295985092959850929598565b60136020526000908152604090205460ff1681565b600061082f8383611d9d565b90505b92915050565b60125460408051808201909152600d815260008051602061327a83398151915260208201529060ff1615156108b25760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b5060006108bf8484611e04565b600281015460408051808201909152600b81527f4e4f545f414c4c4f5745440000000000000000000000000000000000000000006020820152919250606060020a9004600160a060020a0316331461095c5760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b5060020180546bffffffffffffffffffffffff191660a060020a9092049190911790555050565b33600090815260146020526040812054908111156109f657336000908152601460205260408120556109b58282611ecc565b604080518281529051600160a060020a0384169133917f75bc698f04990cbcb7684cd06df09b9891d98b560d93b5cd33256e7c42f688c19181900360200190a35b5050565b60125460408051808201909152600d815260008051602061327a83398151915260208201529060ff161515610a745760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b506000610a818383611e04565b6002810154909150606060020a9004600160a060020a03161515610aa557506109f6565b610aad6131e2565b610ab682611ac3565b60078301546001840180546bffffffffffffffff0000000019166401000000004267ffffffffffffffff1602179055604080516060810182526000808252602082018190529181019190915291925090610b169060048501906003613201565b5060006007840155610b29838284611fe1565b610b348382846121d3565b60028301548354604051606060020a909204600160a060020a031691608060020a9091026001608060020a031916907f351710d38fce23d9ad96076c9d0b3eac6035bbc8926d81e30d9d5a0f1bc80da590600090a35050505050565b610b986131e2565b6000610ba48585611e04565b9050610bb08184612346565b5095945050505050565b60125460408051808201909152600d815260008051602061327a83398151915260208201529060ff161515610c345760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b50610c3f82826109fa565b6000610c4b8383611e04565b600281015460408051808201909152600781527f414c5245414459000000000000000000000000000000000000000000000000006020820152919250606060020a9004600160a060020a0316331415610ce95760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b506000610cf5826119c1565b60408051808201909152600c81527f494e53554646494349454e540000000000000000000000000000000000000000602082015290915034821115610d7f5760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b506002820180546bffffffffffffffffffffffff8116606060020a338102919091179092556001808501805463ffffffff19811663ffffffff918216909301169190911790556003840154919004600160a060020a031690620f424090621312d002046003808501919091556001840154610e0c91606060020a8204810b91608060020a9004900b612561565b610e35838360606040519081016040528060008152602001600081526020016000815250611fe1565b610e4781610e4284611d8d565b6125a5565b81341115610e5b57610e5b33833403611ecc565b60028301548354604080518581529051600160a060020a03606060020a9094048416938516926001608060020a0319608060020a90910216917fcbe1a7ca5fd2af80ad56cc827c558cbf539e7bffb83fe5d7b87a45197965dbb0919081900360200190a45050505050565b610ece6131e2565b610ed66131e2565b610ede6131e2565b60165467ffffffffffffffff80821685526fffffffffffffffffffffffffffffffff608060020a808404821685526801000000000000000093849004831686526017548084166020808a0191909152828204841687820152908590048416908701526018548084166040808a01919091529181049092168186015292900416908301529192909190565b60155481565b60125460408051808201909152600d815260008051602061327a83398151915260208201529060ff161515610fe85760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b5033600090815260136020908152604091829020548251808401909352600a83527f52455354524943544544000000000000000000000000000000000000000000009183019190915260ff1615156110855760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b506015543031101561109357fe5b600060155411156110f2576015805460009091556110b18282611ecc565b604080518281529051600160a060020a038416917f9dc46f23cfb5ddcad0ae7ea2be38d47fec07bb9382ec7e564efc69e036dd66ce919081900360200190a2505b50565b60125460408051808201909152600a81527f52455354524943544544000000000000000000000000000000000000000000006020820152906101009004600160a060020a0316331461118c5760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b5060125460408051808201909152600d815260008051602061327a83398151915260208201529060ff16156112065760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b50604080518082019091526007815260008051602061325a83398151915260208201525060005b818110156112805760016013600085858581811061124757fe5b60209081029290920135600160a060020a0316835250810191909152604001600020805460ff191691151591909117905560010161122d565b5060005b60038110156112ea5785816003811061129957fe5b6020020135600160a060020a03166019826003811015156112b657fe5b01805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055600101611284565b50601c805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038616179055600061131f8180612650565b6002810180546bffffffffffffffffffffffff16606060020a600160a060020a0388168102919091179091556001808301805463ffffffff19169091179081905591925061137e91908104600390810b91608060020a9004900b612561565b61138661275c565b505050505050565b60125460408051808201909152600d815260008051602061327a83398151915260208201529060ff1615156114085760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b5061141383836109fa565b600061141f8484611e04565b600281015460408051808201909152600b81527f4e4f545f414c4c4f5745440000000000000000000000000000000000000000006020820152919250606060020a9004600160a060020a031633146114bc5760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b506114c56131e2565b60006114d18385612346565b604080518082019091526007815260008051602061325a83398151915260208201529193509150600060ff83161161154e5760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b5060018301546115699060a060020a900460ff1682016127e5565b60408051808201909152600a81527f4d41585f4845494748540000000000000000000000000000000000000000000060208201529015156115ef5760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b506115fa33836127f2565b8254600184015461162291608060020a908190040290869060a060020a900460ff16846129c5565b83546fffffffffffffffffffffffffffffffff16608060020a9182900490910217835560018301805474ff000000000000000000000000000000000000000019811660a060020a9182900460ff90811685011690910217905560005b600660ff8216101561172857600184810154600019600360ff8516810b818107838101956002909205909103936000936116d193606060020a8304810b9093010191608060020a909104900b8401611990565b6001908101805460ff750100000000000000000000000000000000000000000080830482168a019091160275ff0000000000000000000000000000000000000000001990911617905593909301925061167e915050565b506117338482612a19565b6002830154835460408051608060020a80840481026001608060020a031990811683529251600160a060020a03606060020a9096049590951694930291909116917f105da5dce44c2a8878d76bfa865c68b564f7fa7f2d01da1df30430a49f3cad569181900360200190a3505050505050565b60006117b06131e2565b601954604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a0386811660048301819052925192319550909216916370a08231916024808301926020929190829003018186803b15801561181b57600080fd5b505afa15801561182f573d6000803e3d6000fd5b505050506040513d602081101561184557600080fd5b50518152601a54604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156118af57600080fd5b505afa1580156118c3573d6000803e3d6000fd5b505050506040513d60208110156118d957600080fd5b5051602080830191909152601b54604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152915191909216926370a082319260248082019391829003018186803b15801561194657600080fd5b505afa15801561195a573d6000803e3d6000fd5b505050506040513d602081101561197057600080fd5b505160408201529092909150565b60146020526000908152604090205481565b6000601d60006119a08585611d9d565b6001608060020a031916815260208101919091526040016000209392505050565b60006119cb6131e2565b6119d3612b3e565b90506119df8382612d14565b91506000805b600660ff82161015611a7a57600185810154600019600360ff8516810b81810783810195600290920590910393600093611a3893606060020a8304810b9093010191608060020a909104900b8401611990565b8054909150608060020a026001608060020a03191615611a6f57611a6c611a5f8288612d14565b869063ffffffff612e2816565b94505b5050506001016119e5565b50611a888360068304612e28565b9250611a9384611d44565b15611abc57620f4240611aaf846216e36063ffffffff612e3a16565b811515611ab857fe5b0492505b5050919050565b611acb6131e2565b8154608060020a026001608060020a0319161515611ae557fe5b600182015460408051808201909152600b81527f54494d455f54524156454c00000000000000000000000000000000000000000060208201529067ffffffffffffffff6401000000009091048116429091161015611b885760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b506000611b9483611d44565b611ba157620f4240611ba6565b621312d05b600184015460408051606081019182905292935064010000000090910467ffffffffffffffff1642039190600486019060039082845b815481526020019060010190808311611bdc57505087549396505050608060020a91829004909102905060005b600186015460ff60a060020a90910481169082161015611d3b576101006001608060020a031983160491608060020a90046000601660ff831660038110611c4c57fe5b015467ffffffffffffffff868116680100000000000000009092041602670de0b6b3a7640000029050600460ff841660108110611c8557fe5b600481049091015467ffffffffffffffff88811660086003948516026101000a9092041692909202919091029060169060ff8416908110611cc257fe5b015469124bc0ddd92e560000006fffffffffffffffffffffffffffffffff608060020a9092048216021681811515611cf657fe5b049050611d1d818860ff851660038110611d0c57fe5b60200201519063ffffffff612e2816565b8760ff841660038110611d2c57fe5b60200201525050600101611c09565b50505050919050565b6000611d4e612e65565b82546fffffffffffffffffffffffffffffffff91821691600891608060020a9081020416066fffffffffffffffffffffffffffffffff16149050919050565b620f424062028b0b820204900390565b604080517c0100000000000000000000000000000000000000000000000000000000600394850b850b810260208084019190915293850b90940b9093026024840152606060020a300260288401528051601c818503018152603c9093019052815191012090565b600080611e118484611d9d565b6001608060020a03198082166000818152601d602090815260409182902080548351808501909452600984527f4e4f545f464f554e440000000000000000000000000000000000000000000000928401929092529495509092608060020a9091021614611ec35760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b50949350505050565b60008111156109f657600160a060020a0382161515611f0057601554611ef8908263ffffffff612e2816565b6015556109f6565b604051600090600160a060020a0384169083908381818185875af1925050503d8060008114611f4b576040519150601f19603f3d011682016040523d82523d6000602084013e611f50565b606091505b505060408051808201909152600f81527f5452414e534645525f4641494c454400000000000000000000000000000000006020820152909150811515611fdb5760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b50505050565b6000611fec83612ea4565b9050611ff66131e2565b6040805160608101909152806120138560005b6020020151612ea4565b8152602001612023856001612009565b8152602001612033856002612009565b9052905060005b600660ff8216101561138657600186810154600019600360ff8516810b8181078381019560029092059091039360009361208d93606060020a8304810b9093010191608060020a909104900b8401611e04565b60018a81015482820154929350600092750100000000000000000000000000000000000000000090910460ff90811692620f424060a060020a909304821601160267ffffffffffffffff168115156120e157fe5b60028401549190049150606060020a9004600160a060020a0316156121a157855161212d90620f42409067ffffffffffffffff841602046004840160005b01549063ffffffff612e2816565b6004830155602086015161215890620f42409067ffffffffffffffff8416020460048401600161211f565b6005830155604086015161218390620f42409067ffffffffffffffff8416020460048401600261211f565b600683015560078201546121979088612e28565b60078301556121c3565b6015546121bf90620f424067ffffffffffffffff84168a0204612e28565b6015555b50506001909201915061203a9050565b6002830154604080518082019091526007815260008051602061325a833981519152602082015290606060020a9004600160a060020a0316151561225c5760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b50600283015461228d90606060020a9004600160a060020a0316600061228884825b6020020151611d8d565b612eb4565b60028301546122b290606060020a9004600160a060020a03166001612288848261227e565b6002838101546122d891606060020a909104600160a060020a031690612288848261227e565b6002830154606060020a9004600160a060020a0316331461231a57600283015461231590606060020a9004600160a060020a0316610e4284611d8d565b612341565b600283015461234190606060020a9004600160a060020a031661233c84611d8d565b611ecc565b505050565b61234e6131e2565b8254600090608060020a026001608060020a031916151561236b57fe5b6123736131e2565b60606040519081016040528060008152602001600081526020016000815250905061239c6131e2565b506040805160608101825260165467ffffffffffffffff908116825260175481166020830152601854169181019190915260005b601060ff82161015612554576101006001608060020a031987160495608060020a90046123fc81612f57565b15156124085750612554565b612427828960010160149054906101000a900460ff16016001016127e5565b60408051808201909152600a81527f4d41585f4845494748540000000000000000000000000000000000000000000060208201529015156124ad5760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b506124b66131e2565b6124e4828560ff8216600381106124c957fe5b602002015160018c015460a060020a900460ff168601612f64565b80519091506124f590866000611d0c565b8552602081015161250890866001611d0c565b6020860152604081015161251e90866002611d0c565b604086015260018460ff84166003811061253457fe5b6020020180519190910167ffffffffffffffff16905250506001016123d0565b9196919550909350505050565b60005b600660ff8216101561234157600019600360ff8316810b9081078281019260029092056001039161259a91870101858301612650565b505050600101612564565b60008111156109f657600160a060020a03821615156125d157601554611ef8908263ffffffff612e2816565b600160a060020a0382166000908152601460205260409020546125fa908263ffffffff612e2816565b600160a060020a038316600081815260146020908152604091829020939093558051848152905191927f9c9e0cdb1670e88302408e5b941dc636f63a3293204694bb68910fcf3d9305f392918290030190a25050565b60008061265d8484611d9d565b6001608060020a03198082166000908152601d60205260409020805492935091608060020a02161515612754578054600182018054608060020a8086046001608060020a0319948516176fffffffffffffffffffffffffffffffff169093178455750600000000000000000000000000000000000000000075ff00000000000000000000000000000000000000000019600389810b63ffffffff90811690960273ffffffff00000000000000000000000000000000198c830b909716606060020a026fffffffff00000000000000000000000019909516949094179590951692909217919091161790556658d15e17628000908201555b949350505050565b60125460408051808201909152600d815260008051602061327a83398151915260208201529060ff16156127d55760405160e560020a62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610171578181015183820152602001610159565b506012805460ff19166001179055565b601060ff82161115919050565b600160a060020a038216151561280457fe5b805160001015612898576019548151604080517f9dc29fac000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152602482019390935290519190921691639dc29fac91604480830192600092919082900301818387803b15801561287f57600080fd5b505af1158015612893573d6000803e3d6000fd5b505050505b60208101516000101561293257601a546020820151604080517f9dc29fac000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152602482019390935290519190921691639dc29fac91604480830192600092919082900301818387803b15801561291957600080fd5b505af115801561292d573d6000803e3d6000fd5b505050505b6040810151600010156109f657601b5460408083015181517f9dc29fac000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015260248201929092529151921691639dc29fac9160448082019260009290919082900301818387803b1580156129b157600080fd5b505af1158015611386573d6000803e3d6000fd5b608060020a80850460ff60088086028216600290810a600019928702909316900a016fffffffffffffffffffffffffffffffff90811682028019939093168488049091169091029091161702949350505050565b60005b8160ff168160ff161015612341576101006001608060020a031984160492608060020a90046000601660ff831660038110612a5357fe5b019050600460ff841660108110612a6657fe5b6004810491909101548254608060020a8082046fffffffffffffffffffffffffffffffff90811667ffffffffffffffff60086003909716969096026101000a909404851693909301831602911617808216600101821667ffffffffffffffff1991909116178083556216e360620f424068010000000000000000830484160283160491612af491168261311b565b8254620f424067ffffffffffffffff6216e36090930283160490911668010000000000000000026fffffffffffffffff000000000000000019909116179091555050600101612a1c565b612b466131e2565b601c54601954604080517f41976e09000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152905191909216916341976e09916024808301926020929190829003018186803b158015612baf57600080fd5b505afa158015612bc3573d6000803e3d6000fd5b505050506040513d6020811015612bd957600080fd5b50518152601c54601a54604080517f41976e09000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152905191909216916341976e09916024808301926020929190829003018186803b158015612c4657600080fd5b505afa158015612c5a573d6000803e3d6000fd5b505050506040513d6020811015612c7057600080fd5b5051602080830191909152601c54601b54604080517f41976e09000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152905191909216926341976e099260248082019391829003018186803b158015612ce057600080fd5b505afa158015612cf4573d6000803e3d6000fd5b505050506040513d6020811015612d0a57600080fd5b5051604082015290565b6003820154825460009190608060020a9081900402825b600186015460ff60a060020a90910481169082161015612e1e576101006001608060020a031983160491608060020a9004612d646131e2565b612d8a82601660ff821660038110612d7857fe5b015467ffffffffffffffff1685612f64565b9050612dd0670de0b6b3a7640000612db883600060200201518a60005b60200201519063ffffffff612e3a16565b811515612dc157fe5b8791900463ffffffff612e2816565b9450612df1670de0b6b3a7640000612db883600160200201518a6001612da7565b9450612e12670de0b6b3a7640000612db883600260200201518a6002612da7565b94505050600101612d2b565b5090949350505050565b60008282018381101561082f57600080fd5b6000821515612e4b57506000610832565b828202828482811515612e5a57fe5b041461082f57600080fd5b6000600862141054635c2af3cf19420167ffffffffffffffff160467ffffffffffffffff16811515612e9357fe5b0667ffffffffffffffff1690505b90565b620f424062028b0b919091020490565b600081111561234157601960ff831660038110612ecd57fe5b0154604080517f40c10f19000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015612f3a57600080fd5b505af1158015612f4e573d6000803e3d6000fd5b50505050505050565b600260ff82161115919050565b612f6c6131e2565b612f7584612f57565b8015612f855750612f85826127e5565b1515612f8d57fe5b600060018467ffffffffffffffff161015612fa9576001612fab565b835b67ffffffffffffffff1690506000600860ff871660038110612fc957fe5b60048104919091015460039091166008026101000a900467ffffffffffffffff1690506000620f4240838302101561300457620f4240613008565b8183025b600060ff87166010811061301857fe5b600491828204019190066008029054906101000a900467ffffffffffffffff1667ffffffffffffffff1602905061304d6131e2565b50604080516060810182526000808252602082018190529181019190915264e8d4a5100082600960ff8b166003811061308257fe5b600302015402670de0b6b3a76400000281151561309b57fe5b04815264e8d4a5100082600960ff8b16600381106130b557fe5b6003020160010154670de0b6b3a764000002028115156130d157fe5b04602082015264e8d4a5100082600960ff8b16600381106130ee57fe5b6003020160020154670de0b6b3a7640000020281151561310a57fe5b046040820152979650505050505050565b600067ffffffffffffffff8316151561313657506000610832565b8267ffffffffffffffff16600114156131535750620f4240610832565b620f424067ffffffffffffffff8481169182029164e8d4a510000290600090851615613189578467ffffffffffffffff166131a0565b6002600167ffffffffffffffff881601620f424002045b9050600281838115156131af57fe5b0482018115156131bb57fe5b049050600281838115156131cb57fe5b0482018115156131d757fe5b049695505050505050565b6060604051908101604052806003906020820280388339509192915050565b826003810192821561322f579160200282015b8281111561322f578251825591602001919060010190613214565b5061323b92915061323f565b5090565b612ea191905b8082111561323b576000815560010161324556fe494e56414c494400000000000000000000000000000000000000000000000000554e494e495449414c495a454400000000000000000000000000000000000000a165627a7a72305820589dc667cf069e0c1178d75e7565747b7c8aac8d9c9110ab3142a060ab8349da0029

   Swarm Source:
bzzr://589dc667cf069e0c1178d75e7565747b7c8aac8d9c9110ab3142a060ab8349da

 

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