ETH Price: $1,813.13 (-3.20%)

Transaction Decoder

Block:
5632551 at May-18-2018 02:28:57 AM +UTC
Transaction Fee:
0.001064097 ETH $1.93
Gas Used:
118,233 Gas / 9 Gwei

Emitted Events:

108 Marketplace.AuctionCreated( id=755C53BFB4983F4871E33F1D6807C7333101A49FAF0A4F0AFB141B77C34C8813, assetId=2722258935367507707706996859454145691716, seller=[Sender] 0xe010b3bcbb3d077a82985194800227914393360a, priceInWei=860000000000000000000000, expiresAt=1679097600000 )

Account State Difference:

  Address   Before After State Difference Code
(Spark Pool)
3,318.825343684709294139 Eth3,318.826407781709294139 Eth0.001064097
0xB3BCa6F5...A8A1b98f8
0xe010B3bc...14393360a
0.08674251115 Eth
Nonce: 318
0.08567841415 Eth
Nonce: 319
0.001064097

Execution Trace

Marketplace.createOrder( assetId=2722258935367507707706996859454145691716, priceInWei=860000000000000000000000, expiresAt=1679097600000 )
  • LANDProxy.6352211e( )
    • LANDRegistry.ownerOf( assetId=2722258935367507707706996859454145691716 ) => ( 0xe010B3bcbB3D077A82985194800227914393360a )
    • LANDProxy.2972b0f0( )
      • LANDRegistry.isAuthorized( operator=0xB3BCa6F5052c7e24726b44da7403b56A8A1b98f8, assetId=2722258935367507707706996859454145691716 ) => ( True )
        File 1 of 3: Marketplace
        pragma solidity 0.4.21;
        
        // File: zeppelin-solidity/contracts/ownership/Ownable.sol
        
        /**
         * @title Ownable
         * @dev The Ownable contract has an owner address, and provides basic authorization control
         * functions, this simplifies the implementation of "user permissions".
         */
        contract Ownable {
          address public owner;
        
        
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
        
        
          /**
           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
           * account.
           */
          function Ownable() public {
            owner = msg.sender;
          }
        
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
            require(msg.sender == owner);
            _;
          }
        
          /**
           * @dev Allows the current owner to transfer control of the contract to a newOwner.
           * @param newOwner The address to transfer ownership to.
           */
          function transferOwnership(address newOwner) public onlyOwner {
            require(newOwner != address(0));
            OwnershipTransferred(owner, newOwner);
            owner = newOwner;
          }
        
        }
        
        // File: zeppelin-solidity/contracts/lifecycle/Destructible.sol
        
        /**
         * @title Destructible
         * @dev Base contract that can be destroyed by owner. All funds in contract will be sent to the owner.
         */
        contract Destructible is Ownable {
        
          function Destructible() public payable { }
        
          /**
           * @dev Transfers the current balance to the owner and terminates the contract.
           */
          function destroy() onlyOwner public {
            selfdestruct(owner);
          }
        
          function destroyAndSend(address _recipient) onlyOwner public {
            selfdestruct(_recipient);
          }
        }
        
        // File: zeppelin-solidity/contracts/lifecycle/Pausable.sol
        
        /**
         * @title Pausable
         * @dev Base contract which allows children to implement an emergency stop mechanism.
         */
        contract Pausable is Ownable {
          event Pause();
          event Unpause();
        
          bool public paused = false;
        
        
          /**
           * @dev Modifier to make a function callable only when the contract is not paused.
           */
          modifier whenNotPaused() {
            require(!paused);
            _;
          }
        
          /**
           * @dev Modifier to make a function callable only when the contract is paused.
           */
          modifier whenPaused() {
            require(paused);
            _;
          }
        
          /**
           * @dev called by the owner to pause, triggers stopped state
           */
          function pause() onlyOwner whenNotPaused public {
            paused = true;
            Pause();
          }
        
          /**
           * @dev called by the owner to unpause, returns to normal state
           */
          function unpause() onlyOwner whenPaused public {
            paused = false;
            Unpause();
          }
        }
        
        // File: zeppelin-solidity/contracts/math/SafeMath.sol
        
        /**
         * @title SafeMath
         * @dev Math operations with safety checks that throw on error
         */
        library SafeMath {
        
          /**
          * @dev Multiplies two numbers, throws on overflow.
          */
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            if (a == 0) {
              return 0;
            }
            uint256 c = a * b;
            assert(c / a == b);
            return c;
          }
        
          /**
          * @dev Integer division of two numbers, truncating the quotient.
          */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
            // assert(b > 0); // Solidity automatically throws when dividing by 0
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
            return c;
          }
        
          /**
          * @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
          */
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            assert(b <= a);
            return a - b;
          }
        
          /**
          * @dev Adds two numbers, throws on overflow.
          */
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            assert(c >= a);
            return c;
          }
        }
        
        // File: contracts/marketplace/Marketplace.sol
        
        /**
         * @title Interface for contracts conforming to ERC-20
         */
        contract ERC20Interface {
            function transferFrom(address from, address to, uint tokens) public returns (bool success);
        }
        
        /**
         * @title Interface for contracts conforming to ERC-721
         */
        contract ERC721Interface {
            function ownerOf(uint256 assetId) public view returns (address);
            function safeTransferFrom(address from, address to, uint256 assetId) public;
            function isAuthorized(address operator, uint256 assetId) public view returns (bool);
        }
        
        contract Marketplace is Ownable, Pausable, Destructible {
            using SafeMath for uint256;
        
            ERC20Interface public acceptedToken;
            ERC721Interface public nonFungibleRegistry;
        
            struct Auction {
                // Auction ID
                bytes32 id;
                // Owner of the NFT
                address seller;
                // Price (in wei) for the published item
                uint256 price;
                // Time when this sale ends
                uint256 expiresAt;
            }
        
            mapping (uint256 => Auction) public auctionByAssetId;
        
            uint256 public ownerCutPercentage;
            uint256 public publicationFeeInWei;
        
            /* EVENTS */
            event AuctionCreated(
                bytes32 id,
                uint256 indexed assetId,
                address indexed seller, 
                uint256 priceInWei, 
                uint256 expiresAt
            );
            event AuctionSuccessful(
                bytes32 id,
                uint256 indexed assetId, 
                address indexed seller, 
                uint256 totalPrice, 
                address indexed winner
            );
            event AuctionCancelled(
                bytes32 id,
                uint256 indexed assetId, 
                address indexed seller
            );
        
            event ChangedPublicationFee(uint256 publicationFee);
            event ChangedOwnerCut(uint256 ownerCut);
        
        
            /**
             * @dev Constructor for this contract.
             * @param _acceptedToken - Address of the ERC20 accepted for this marketplace
             * @param _nonFungibleRegistry - Address of the ERC721 registry contract.
             */
            function Marketplace(address _acceptedToken, address _nonFungibleRegistry) public {
                acceptedToken = ERC20Interface(_acceptedToken);
                nonFungibleRegistry = ERC721Interface(_nonFungibleRegistry);
            }
        
            /**
             * @dev Sets the publication fee that's charged to users to publish items
             * @param publicationFee - Fee amount in wei this contract charges to publish an item
             */
            function setPublicationFee(uint256 publicationFee) onlyOwner public {
                publicationFeeInWei = publicationFee;
        
                ChangedPublicationFee(publicationFeeInWei);
            }
        
            /**
             * @dev Sets the share cut for the owner of the contract that's
             *  charged to the seller on a successful sale.
             * @param ownerCut - Share amount, from 0 to 100
             */
            function setOwnerCut(uint8 ownerCut) onlyOwner public {
                require(ownerCut < 100);
        
                ownerCutPercentage = ownerCut;
        
                ChangedOwnerCut(ownerCutPercentage);
            }
        
            /**
             * @dev Cancel an already published order
             * @param assetId - ID of the published NFT
             * @param priceInWei - Price in Wei for the supported coin.
             * @param expiresAt - Duration of the auction (in hours)
             */
            function createOrder(uint256 assetId, uint256 priceInWei, uint256 expiresAt) public whenNotPaused {
                address assetOwner = nonFungibleRegistry.ownerOf(assetId);
                require(msg.sender == assetOwner);
                require(nonFungibleRegistry.isAuthorized(address(this), assetId));
                require(priceInWei > 0);
                require(expiresAt > now.add(1 minutes));
        
                bytes32 auctionId = keccak256(
                    block.timestamp, 
                    assetOwner,
                    assetId, 
                    priceInWei
                );
        
                auctionByAssetId[assetId] = Auction({
                    id: auctionId,
                    seller: assetOwner,
                    price: priceInWei,
                    expiresAt: expiresAt
                });
        
                // Check if there's a publication fee and
                // transfer the amount to marketplace owner.
                if (publicationFeeInWei > 0) {
                    require(acceptedToken.transferFrom(
                        msg.sender,
                        owner,
                        publicationFeeInWei
                    ));
                }
        
                AuctionCreated(
                    auctionId,
                    assetId, 
                    assetOwner,
                    priceInWei, 
                    expiresAt
                );
            }
        
            /**
             * @dev Cancel an already published order
             *  can only be canceled by seller or the contract owner.
             * @param assetId - ID of the published NFT
             */
            function cancelOrder(uint256 assetId) public whenNotPaused {
                require(auctionByAssetId[assetId].seller == msg.sender || msg.sender == owner);
        
                bytes32 auctionId = auctionByAssetId[assetId].id;
                address auctionSeller = auctionByAssetId[assetId].seller;
                delete auctionByAssetId[assetId];
        
                AuctionCancelled(auctionId, assetId, auctionSeller);
            }
        
            /**
             * @dev Executes the sale for a published NTF
             * @param assetId - ID of the published NFT
             */
            function executeOrder(uint256 assetId, uint256 price) public whenNotPaused {
                address seller = auctionByAssetId[assetId].seller;
        
                require(seller != address(0));
                require(seller != msg.sender);
                require(auctionByAssetId[assetId].price == price);
                require(now < auctionByAssetId[assetId].expiresAt);
        
                require(seller == nonFungibleRegistry.ownerOf(assetId));
        
                uint saleShareAmount = 0;
        
                if (ownerCutPercentage > 0) {
        
                    // Calculate sale share
                    saleShareAmount = price.mul(ownerCutPercentage).div(100);
        
                    // Transfer share amount for marketplace Owner.
                    acceptedToken.transferFrom(
                        msg.sender,
                        owner,
                        saleShareAmount
                    );
                }
        
                // Transfer sale amount to seller
                acceptedToken.transferFrom(
                    msg.sender,
                    seller,
                    price.sub(saleShareAmount)
                );
        
                // Transfer asset owner
                nonFungibleRegistry.safeTransferFrom(
                    seller,
                    msg.sender,
                    assetId
                );
        
        
                bytes32 auctionId = auctionByAssetId[assetId].id;
                delete auctionByAssetId[assetId];
        
                AuctionSuccessful(auctionId, assetId, seller, price, msg.sender);
            }
         }

        File 2 of 3: LANDProxy
        pragma solidity ^0.4.18;
        
        // File: contracts/land/LANDStorage.sol
        
        contract LANDStorage {
        
          mapping (address => uint) latestPing;
        
          uint256 constant clearLow = 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000;
          uint256 constant clearHigh = 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;
          uint256 constant factor = 0x100000000000000000000000000000000;
        
          mapping (address => bool) authorizedDeploy;
        
        }
        
        // File: contracts/upgradable/OwnableStorage.sol
        
        contract OwnableStorage {
        
          address public owner;
        
          function OwnableStorage() internal {
            owner = msg.sender;
          }
        
        }
        
        // File: contracts/upgradable/ProxyStorage.sol
        
        contract ProxyStorage {
        
          /**
           * Current contract to which we are proxing
           */
          address public currentContract;
          address public proxyOwner;
        }
        
        // File: erc821/contracts/AssetRegistryStorage.sol
        
        contract AssetRegistryStorage {
        
          string internal _name;
          string internal _symbol;
          string internal _description;
        
          /**
           * Stores the total count of assets managed by this registry
           */
          uint256 internal _count;
        
          /**
           * Stores an array of assets owned by a given account
           */
          mapping(address => uint256[]) internal _assetsOf;
        
          /**
           * Stores the current holder of an asset
           */
          mapping(uint256 => address) internal _holderOf;
        
          /**
           * Stores the index of an asset in the `_assetsOf` array of its holder
           */
          mapping(uint256 => uint256) internal _indexOfAsset;
        
          /**
           * Stores the data associated with an asset
           */
          mapping(uint256 => string) internal _assetData;
        
          /**
           * For a given account, for a given opperator, store whether that operator is
           * allowed to transfer and modify assets on behalf of them.
           */
          mapping(address => mapping(address => bool)) internal _operators;
        
          /**
           * Simple reentrancy lock
           */
          bool internal _reentrancy;
        }
        
        // File: contracts/Storage.sol
        
        contract Storage is ProxyStorage, OwnableStorage, AssetRegistryStorage, LANDStorage {
        }
        
        // File: contracts/upgradable/DelegateProxy.sol
        
        contract DelegateProxy {
          /**
           * @dev Performs a delegatecall and returns whatever the delegatecall returned (entire context execution will return!)
           * @param _dst Destination address to perform the delegatecall
           * @param _calldata Calldata for the delegatecall
           */
          function delegatedFwd(address _dst, bytes _calldata) internal {
            require(isContract(_dst));
            assembly {
              let result := delegatecall(sub(gas, 10000), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0)
              let size := returndatasize
        
              let ptr := mload(0x40)
              returndatacopy(ptr, 0, size)
        
              // revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas.
              // if the call returned error data, forward it
              switch result case 0 { revert(ptr, size) }
              default { return(ptr, size) }
            }
          }
        
          function isContract(address _target) constant internal returns (bool) {
            uint256 size;
            assembly { size := extcodesize(_target) }
            return size > 0;
          }
        }
        
        // File: contracts/upgradable/IApplication.sol
        
        contract IApplication {
          function initialize(bytes data) public;
        }
        
        // File: contracts/upgradable/Ownable.sol
        
        contract Ownable is Storage {
        
          event OwnerUpdate(address _prevOwner, address _newOwner);
        
          function bytesToAddress (bytes b) pure public returns (address) {
            uint result = 0;
            for (uint i = b.length-1; i+1 > 0; i--) {
              uint c = uint(b[i]);
              uint to_inc = c * ( 16 ** ((b.length - i-1) * 2));
              result += to_inc;
            }
            return address(result);
          }
        
          modifier onlyOwner {
            assert(msg.sender == owner);
            _;
          }
        
          function initialize(bytes data) public {
            owner = bytesToAddress(data);
          }
        
          function transferOwnership(address _newOwner) public onlyOwner {
            require(_newOwner != owner);
            owner = _newOwner;
          }
        }
        
        // File: contracts/upgradable/Proxy.sol
        
        contract Proxy is Storage, DelegateProxy {
        
          event Upgrade(address indexed newContract, bytes initializedWith);
          event OwnerUpdate(address _prevOwner, address _newOwner);
        
          function Proxy() public {
            proxyOwner = msg.sender;
          }
        
          modifier onlyProxyOwner() {
            require(msg.sender == proxyOwner);
            _;
          }
        
          function transferOwnership(address _newOwner) public onlyProxyOwner {
            require(_newOwner != proxyOwner);
        
            OwnerUpdate(proxyOwner, _newOwner);
            proxyOwner = _newOwner;
          }
        
          function upgrade(IApplication newContract, bytes data) public onlyProxyOwner {
            currentContract = newContract;
            IApplication(this).initialize(data);
        
            Upgrade(newContract, data);
          }
        
          function () payable public {
            require(currentContract != 0); // if app code hasn't been set yet, don't call
            delegatedFwd(currentContract, msg.data);
          }
        }
        
        // File: contracts/upgradable/LANDProxy.sol
        
        contract LANDProxy is Storage, Proxy {
        }

        File 3 of 3: LANDRegistry
        pragma solidity ^0.4.23;
        
        // File: contracts/land/LANDStorage.sol
        
        contract LANDStorage {
        
          mapping (address => uint) public latestPing;
        
          uint256 constant clearLow = 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000;
          uint256 constant clearHigh = 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;
          uint256 constant factor = 0x100000000000000000000000000000000;
        
          mapping (address => bool) public authorizedDeploy;
        
          mapping (uint256 => address) public updateOperator;
        }
        
        // File: contracts/upgradable/OwnableStorage.sol
        
        contract OwnableStorage {
        
          address public owner;
        
          function OwnableStorage() internal {
            owner = msg.sender;
          }
        
        }
        
        // File: contracts/upgradable/ProxyStorage.sol
        
        contract ProxyStorage {
        
          /**
           * Current contract to which we are proxing
           */
          address public currentContract;
          address public proxyOwner;
        }
        
        // File: erc821/contracts/AssetRegistryStorage.sol
        
        contract AssetRegistryStorage {
        
          string internal _name;
          string internal _symbol;
          string internal _description;
        
          /**
           * Stores the total count of assets managed by this registry
           */
          uint256 internal _count;
        
          /**
           * Stores an array of assets owned by a given account
           */
          mapping(address => uint256[]) internal _assetsOf;
        
          /**
           * Stores the current holder of an asset
           */
          mapping(uint256 => address) internal _holderOf;
        
          /**
           * Stores the index of an asset in the `_assetsOf` array of its holder
           */
          mapping(uint256 => uint256) internal _indexOfAsset;
        
          /**
           * Stores the data associated with an asset
           */
          mapping(uint256 => string) internal _assetData;
        
          /**
           * For a given account, for a given operator, store whether that operator is
           * allowed to transfer and modify assets on behalf of them.
           */
          mapping(address => mapping(address => bool)) internal _operators;
        
          /**
           * Approval array
           */
          mapping(uint256 => address) internal _approval;
        }
        
        // File: contracts/Storage.sol
        
        contract Storage is ProxyStorage, OwnableStorage, AssetRegistryStorage, LANDStorage {
        }
        
        // File: contracts/upgradable/IApplication.sol
        
        contract IApplication {
          function initialize(bytes data) public;
        }
        
        // File: contracts/upgradable/Ownable.sol
        
        contract Ownable is Storage {
        
          event OwnerUpdate(address _prevOwner, address _newOwner);
        
          function bytesToAddress (bytes b) pure public returns (address) {
            uint result = 0;
            for (uint i = b.length-1; i+1 > 0; i--) {
              uint c = uint(b[i]);
              uint to_inc = c * ( 16 ** ((b.length - i-1) * 2));
              result += to_inc;
            }
            return address(result);
          }
        
          modifier onlyOwner {
            assert(msg.sender == owner);
            _;
          }
        
          function transferOwnership(address _newOwner) public onlyOwner {
            require(_newOwner != owner);
            owner = _newOwner;
          }
        }
        
        // File: contracts/land/ILANDRegistry.sol
        
        interface ILANDRegistry {
        
          // LAND can be assigned by the owner
          function assignNewParcel(int x, int y, address beneficiary) external;
          function assignMultipleParcels(int[] x, int[] y, address beneficiary) external;
        
          // After one year, land can be claimed from an inactive public key
          function ping() external;
        
          // LAND-centric getters
          function encodeTokenId(int x, int y) pure external returns (uint256);
          function decodeTokenId(uint value) pure external returns (int, int);
          function exists(int x, int y) view external returns (bool);
          function ownerOfLand(int x, int y) view external returns (address);
          function ownerOfLandMany(int[] x, int[] y) view external returns (address[]);
          function landOf(address owner) view external returns (int[], int[]);
          function landData(int x, int y) view external returns (string);
        
          // Transfer LAND
          function transferLand(int x, int y, address to) external;
          function transferManyLand(int[] x, int[] y, address to) external;
        
          // Update LAND
          function updateLandData(int x, int y, string data) external;
          function updateManyLandData(int[] x, int[] y, string data) external;
        
          // Events
        
          event Update(  
            uint256 indexed assetId, 
            address indexed holder,  
            address indexed operator,  
            string data  
          );
        }
        
        // File: erc821/contracts/ERC165.sol
        
        interface ERC165 {
          function supportsInterface(bytes4 interfaceID) external view returns (bool);
        }
        
        // File: contracts/land/IMetadataHolder.sol
        
        contract IMetadataHolder is ERC165 {
          function getMetadata(uint256 /* assetId */) external view returns (string);
        }
        
        // File: erc821/contracts/IERC721Base.sol
        
        interface IERC721Base {
          function totalSupply() external view returns (uint256);
        
          // function exists(uint256 assetId) external view returns (bool);
          function ownerOf(uint256 assetId) external view returns (address);
        
          function balanceOf(address holder) external view returns (uint256);
        
          function safeTransferFrom(address from, address to, uint256 assetId) external;
          function safeTransferFrom(address from, address to, uint256 assetId, bytes userData) external;
        
          function transferFrom(address from, address to, uint256 assetId) external;
        
          function approve(address operator, uint256 assetId) external;
          function setApprovalForAll(address operator, bool authorized) external;
        
          function getApprovedAddress(uint256 assetId) external view returns (address);
          function isApprovedForAll(address operator, address assetOwner) external view returns (bool);
        
          function isAuthorized(address operator, uint256 assetId) external view returns (bool);
        
          event Transfer(
            address indexed from,
            address indexed to,
            uint256 indexed assetId,
            address operator,
            bytes userData
          );
          event ApprovalForAll(
            address indexed operator,
            address indexed holder,
            bool authorized
          );
          event Approval(
            address indexed owner,
            address indexed operator,
            uint256 indexed assetId
          );
        }
        
        // File: erc821/contracts/IERC721Receiver.sol
        
        interface IERC721Receiver {
          function onERC721Received(
            address _oldOwner,
            uint256 _tokenId,
            bytes   _userData
          ) external returns (bytes4);
        }
        
        // File: zeppelin-solidity/contracts/math/SafeMath.sol
        
        /**
         * @title SafeMath
         * @dev Math operations with safety checks that throw on error
         */
        library SafeMath {
        
          /**
          * @dev Multiplies two numbers, throws on overflow.
          */
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            if (a == 0) {
              return 0;
            }
            uint256 c = a * b;
            assert(c / a == b);
            return c;
          }
        
          /**
          * @dev Integer division of two numbers, truncating the quotient.
          */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
            // assert(b > 0); // Solidity automatically throws when dividing by 0
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
            return c;
          }
        
          /**
          * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
          */
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            assert(b <= a);
            return a - b;
          }
        
          /**
          * @dev Adds two numbers, throws on overflow.
          */
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            assert(c >= a);
            return c;
          }
        }
        
        // File: erc821/contracts/ERC721Base.sol
        
        contract ERC721Base is AssetRegistryStorage, IERC721Base, ERC165 {
          using SafeMath for uint256;
        
          //
          // Global Getters
          //
        
          /**
           * @dev Gets the total amount of assets stored by the contract
           * @return uint256 representing the total amount of assets
           */
          function totalSupply() external view returns (uint256) {
            return _totalSupply();
          }
          function _totalSupply() internal view returns (uint256) {
            return _count;
          }
        
          //
          // Asset-centric getter functions
          //
        
          /**
           * @dev Queries what address owns an asset. This method does not throw.
           * In order to check if the asset exists, use the `exists` function or check if the
           * return value of this call is `0`.
           * @return uint256 the assetId
           */
          function ownerOf(uint256 assetId) external view returns (address) {
            return _ownerOf(assetId);
          }
          function _ownerOf(uint256 assetId) internal view returns (address) {
            return _holderOf[assetId];
          }
        
          //
          // Holder-centric getter functions
          //
          /**
           * @dev Gets the balance of the specified address
           * @param owner address to query the balance of
           * @return uint256 representing the amount owned by the passed address
           */
          function balanceOf(address owner) external view returns (uint256) {
            return _balanceOf(owner);
          }
          function _balanceOf(address owner) internal view returns (uint256) {
            return _assetsOf[owner].length;
          }
        
          //
          // Authorization getters
          //
        
          /**
           * @dev Query whether an address has been authorized to move any assets on behalf of someone else
           * @param operator the address that might be authorized
           * @param assetHolder the address that provided the authorization
           * @return bool true if the operator has been authorized to move any assets
           */
          function isApprovedForAll(address operator, address assetHolder)
            external view returns (bool)
          {
            return _isApprovedForAll(operator, assetHolder);
          }
          function _isApprovedForAll(address operator, address assetHolder)
            internal view returns (bool)
          {
            return _operators[assetHolder][operator];
          }
        
          /**
           * @dev Query what address has been particularly authorized to move an asset
           * @param assetId the asset to be queried for
           * @return bool true if the asset has been approved by the holder
           */
          function getApprovedAddress(uint256 assetId) external view returns (address) {
            return _getApprovedAddress(assetId);
          }
          function _getApprovedAddress(uint256 assetId) internal view returns (address) {
            return _approval[assetId];
          }
        
          /**
           * @dev Query if an operator can move an asset.
           * @param operator the address that might be authorized
           * @param assetId the asset that has been `approved` for transfer
           * @return bool true if the asset has been approved by the holder
           */
          function isAuthorized(address operator, uint256 assetId) external view returns (bool) {
            return _isAuthorized(operator, assetId);
          }
          function _isAuthorized(address operator, uint256 assetId) internal view returns (bool)
          {
            require(operator != 0);
            address owner = _ownerOf(assetId);
            if (operator == owner) {
              return true;
            }
            return _isApprovedForAll(operator, owner) || _getApprovedAddress(assetId) == operator;
          }
        
          //
          // Authorization
          //
        
          /**
           * @dev Authorize a third party operator to manage (send) msg.sender's asset
           * @param operator address to be approved
           * @param authorized bool set to true to authorize, false to withdraw authorization
           */
          function setApprovalForAll(address operator, bool authorized) external {
            return _setApprovalForAll(operator, authorized);
          }
          function _setApprovalForAll(address operator, bool authorized) internal {
            if (authorized) {
              require(!_isApprovedForAll(operator, msg.sender));
              _addAuthorization(operator, msg.sender);
            } else {
              require(_isApprovedForAll(operator, msg.sender));
              _clearAuthorization(operator, msg.sender);
            }
            emit ApprovalForAll(operator, msg.sender, authorized);
          }
        
          /**
           * @dev Authorize a third party operator to manage one particular asset
           * @param operator address to be approved
           * @param assetId asset to approve
           */
          function approve(address operator, uint256 assetId) external {
            address holder = _ownerOf(assetId);
            require(operator != holder);
            if (_getApprovedAddress(assetId) != operator) {
              _approval[assetId] = operator;
              emit Approval(holder, operator, assetId);
            }
          }
        
          function _addAuthorization(address operator, address holder) private {
            _operators[holder][operator] = true;
          }
        
          function _clearAuthorization(address operator, address holder) private {
            _operators[holder][operator] = false;
          }
        
          //
          // Internal Operations
          //
        
          function _addAssetTo(address to, uint256 assetId) internal {
            _holderOf[assetId] = to;
        
            uint256 length = _balanceOf(to);
        
            _assetsOf[to].push(assetId);
        
            _indexOfAsset[assetId] = length;
        
            _count = _count.add(1);
          }
        
          function _removeAssetFrom(address from, uint256 assetId) internal {
            uint256 assetIndex = _indexOfAsset[assetId];
            uint256 lastAssetIndex = _balanceOf(from).sub(1);
            uint256 lastAssetId = _assetsOf[from][lastAssetIndex];
        
            _holderOf[assetId] = 0;
        
            // Insert the last asset into the position previously occupied by the asset to be removed
            _assetsOf[from][assetIndex] = lastAssetId;
        
            // Resize the array
            _assetsOf[from][lastAssetIndex] = 0;
            _assetsOf[from].length--;
        
            // Remove the array if no more assets are owned to prevent pollution
            if (_assetsOf[from].length == 0) {
              delete _assetsOf[from];
            }
        
            // Update the index of positions for the asset
            _indexOfAsset[assetId] = 0;
            _indexOfAsset[lastAssetId] = assetIndex;
        
            _count = _count.sub(1);
          }
        
          function _clearApproval(address holder, uint256 assetId) internal {
            if (_ownerOf(assetId) == holder && _approval[assetId] != 0) {
              _approval[assetId] = 0;
              emit Approval(holder, 0, assetId);
            }
          }
        
          //
          // Supply-altering functions
          //
        
          function _generate(uint256 assetId, address beneficiary) internal {
            require(_holderOf[assetId] == 0);
        
            _addAssetTo(beneficiary, assetId);
        
            emit Transfer(0, beneficiary, assetId, msg.sender, '');
          }
        
          function _destroy(uint256 assetId) internal {
            address holder = _holderOf[assetId];
            require(holder != 0);
        
            _removeAssetFrom(holder, assetId);
        
            emit Transfer(holder, 0, assetId, msg.sender, '');
          }
        
          //
          // Transaction related operations
          //
        
          modifier onlyHolder(uint256 assetId) {
            require(_ownerOf(assetId) == msg.sender);
            _;
          }
        
          modifier onlyAuthorized(uint256 assetId) {
            require(_isAuthorized(msg.sender, assetId));
            _;
          }
        
          modifier isCurrentOwner(address from, uint256 assetId) {
            require(_ownerOf(assetId) == from);
            _;
          }
        
          modifier isDestinataryDefined(address destinatary) {
            require(destinatary != 0);
            _;
          }
        
          modifier destinataryIsNotHolder(uint256 assetId, address to) {
            require(_ownerOf(assetId) != to);
            _;
          }
        
          /**
           * @dev Alias of `safeTransferFrom(from, to, assetId, '')`
           *
           * @param from address that currently owns an asset
           * @param to address to receive the ownership of the asset
           * @param assetId uint256 ID of the asset to be transferred
           */
          function safeTransferFrom(address from, address to, uint256 assetId) external {
            return _doTransferFrom(from, to, assetId, '', msg.sender, true);
          }
        
          /**
           * @dev Securely transfers the ownership of a given asset from one address to
           * another address, calling the method `onNFTReceived` on the target address if
           * there's code associated with it
           *
           * @param from address that currently owns an asset
           * @param to address to receive the ownership of the asset
           * @param assetId uint256 ID of the asset to be transferred
           * @param userData bytes arbitrary user information to attach to this transfer
           */
          function safeTransferFrom(address from, address to, uint256 assetId, bytes userData) external {
            return _doTransferFrom(from, to, assetId, userData, msg.sender, true);
          }
        
          /**
           * @dev Transfers the ownership of a given asset from one address to another address
           * Warning! This function does not attempt to verify that the target address can send
           * tokens.
           *
           * @param from address sending the asset
           * @param to address to receive the ownership of the asset
           * @param assetId uint256 ID of the asset to be transferred
           */
          function transferFrom(address from, address to, uint256 assetId) external {
            return _doTransferFrom(from, to, assetId, '', msg.sender, false);
          }
        
          function _doTransferFrom(
            address from,
            address to,
            uint256 assetId,
            bytes userData,
            address operator,
            bool doCheck
          )
            onlyAuthorized(assetId)
            internal
          {
            _moveToken(from, to, assetId, userData, operator, doCheck);
          }
        
          function _moveToken(
            address from,
            address to,
            uint256 assetId,
            bytes userData,
            address operator,
            bool doCheck
          )
            isDestinataryDefined(to)
            destinataryIsNotHolder(assetId, to)
            isCurrentOwner(from, assetId)
            internal
          {
            address holder = _holderOf[assetId];
            _removeAssetFrom(holder, assetId);
            _clearApproval(holder, assetId);
            _addAssetTo(to, assetId);
        
            if (doCheck && _isContract(to)) {
              // Equals to bytes4(keccak256("onERC721Received(address,uint256,bytes)"))
              bytes4 ERC721_RECEIVED = bytes4(0xf0b9e5ba);
              require(
                IERC721Receiver(to).onERC721Received(
                  holder, assetId, userData
                ) == ERC721_RECEIVED
              );
            }
        
            emit Transfer(holder, to, assetId, operator, userData);
          }
        
          /**
           * Internal function that moves an asset from one holder to another
           */
        
          /**
           * @dev Returns `true` if the contract implements `interfaceID` and `interfaceID` is not 0xffffffff, `false` otherwise
           * @param  _interfaceID The interface identifier, as specified in ERC-165
           */
          function supportsInterface(bytes4 _interfaceID) external view returns (bool) {
        
            if (_interfaceID == 0xffffffff) {
              return false;
            }
            return _interfaceID == 0x01ffc9a7 || _interfaceID == 0x80ac58cd;
          }
        
          //
          // Utilities
          //
        
          function _isContract(address addr) internal view returns (bool) {
            uint size;
            assembly { size := extcodesize(addr) }
            return size > 0;
          }
        }
        
        // File: erc821/contracts/IERC721Enumerable.sol
        
        contract IERC721Enumerable {
        
          /**
           * @notice Enumerate active tokens
           * @dev Throws if `index` >= `totalSupply()`, otherwise SHALL NOT throw.
           * @param index A counter less than `totalSupply()`
           * @return The identifier for the `index`th asset, (sort order not
           *  specified)
           */
          // TODO (eordano): Not implemented
          // function tokenByIndex(uint256 index) public view returns (uint256 _assetId);
        
          /**
           * @notice Count of owners which own at least one asset
           *  Must not throw.
           * @return A count of the number of owners which own asset
           */
          // TODO (eordano): Not implemented
          // function countOfOwners() public view returns (uint256 _count);
        
          /**
           * @notice Enumerate owners
           * @dev Throws if `index` >= `countOfOwners()`, otherwise must not throw.
           * @param index A counter less than `countOfOwners()`
           * @return The address of the `index`th owner (sort order not specified)
           */
          // TODO (eordano): Not implemented
          // function ownerByIndex(uint256 index) public view returns (address owner);
        
          /**
           * @notice Get all tokens of a given address
           * @dev This is not intended to be used on-chain
           * @param owner address of the owner to query
           * @return a list of all assetIds of a user
           */
          function tokensOf(address owner) external view returns (uint256[]);
        
          /**
           * @notice Enumerate tokens assigned to an owner
           * @dev Throws if `index` >= `balanceOf(owner)` or if
           *  `owner` is the zero address, representing invalid assets.
           *  Otherwise this must not throw.
           * @param owner An address where we are interested in assets owned by them
           * @param index A counter less than `balanceOf(owner)`
           * @return The identifier for the `index`th asset assigned to `owner`,
           *   (sort order not specified)
           */
          function tokenOfOwnerByIndex(
            address owner, uint256 index
          ) external view returns (uint256 tokenId);
        }
        
        // File: erc821/contracts/ERC721Enumerable.sol
        
        contract ERC721Enumerable is AssetRegistryStorage, IERC721Enumerable {
        
          /**
           * @notice Get all tokens of a given address
           * @dev This is not intended to be used on-chain
           * @param owner address of the owner to query
           * @return a list of all assetIds of a user
           */
          function tokensOf(address owner) external view returns (uint256[]) {
            return _assetsOf[owner];
          }
        
          /**
           * @notice Enumerate tokens assigned to an owner
           * @dev Throws if `index` >= `balanceOf(owner)` or if
           *  `owner` is the zero address, representing invalid assets.
           *  Otherwise this must not throw.
           * @param owner An address where we are interested in assets owned by them
           * @param index A counter less than `balanceOf(owner)`
           * @return The identifier for the `index`th asset assigned to `owner`,
           *   (sort order not specified)
           */
          function tokenOfOwnerByIndex(
            address owner, uint256 index
          )
            external
            view
            returns (uint256 assetId)
          {
            require(index < _assetsOf[owner].length);
            require(index < (1<<127));
            return _assetsOf[owner][index];
          }
        
        }
        
        // File: erc821/contracts/IERC721Metadata.sol
        
        contract IERC721Metadata {
        
          /**
           * @notice A descriptive name for a collection of NFTs in this contract
           */
          function name() external view returns (string);
        
          /**
           * @notice An abbreviated name for NFTs in this contract
           */
          function symbol() external view returns (string);
        
          /**
           * @notice A description of what this DAR is used for
           */
          function description() external view returns (string);
        
          /**
           * Stores arbitrary info about a token
           */
          function tokenMetadata(uint256 assetId) external view returns (string);
        }
        
        // File: erc821/contracts/ERC721Metadata.sol
        
        contract ERC721Metadata is AssetRegistryStorage, IERC721Metadata {
          function name() external view returns (string) {
            return _name;
          }
          function symbol() external view returns (string) {
            return _symbol;
          }
          function description() external view returns (string) {
            return _description;
          }
          function tokenMetadata(uint256 assetId) external view returns (string) {
            return _assetData[assetId];
          }
          function _update(uint256 assetId, string data) internal {
            _assetData[assetId] = data;
          }
        }
        
        // File: erc821/contracts/FullAssetRegistry.sol
        
        contract FullAssetRegistry is ERC721Base, ERC721Enumerable, ERC721Metadata {
          constructor() public {
          }
        
          /**
           * @dev Method to check if an asset identified by the given id exists under this DAR.
           * @return uint256 the assetId
           */
          function exists(uint256 assetId) external view returns (bool) {
            return _exists(assetId);
          }
          function _exists(uint256 assetId) internal view returns (bool) {
            return _holderOf[assetId] != 0;
          }
        
          function decimals() external pure returns (uint256) {
            return 0;
          }
        }
        
        // File: contracts/land/LANDRegistry.sol
        
        contract LANDRegistry is Storage,
          Ownable, FullAssetRegistry,
          ILANDRegistry
        {
        
          bytes4 public GET_METADATA = bytes4(keccak256("getMetadata(uint256)"));
        
          function initialize(bytes) external {
            _name = "Decentraland LAND";
            _symbol = "LAND";
            _description = "Contract that stores the Decentraland LAND registry";
          }
        
          modifier onlyProxyOwner() {
            require(msg.sender == proxyOwner, "this function can only be called by the proxy owner");
            _;
          }
        
          //
          // LAND Create and destroy
          //
        
          modifier onlyOwnerOf(uint256 assetId) {
            require(msg.sender == _ownerOf(assetId), "this function can only be called by the owner of the asset");
            _;
          }
        
          modifier onlyUpdateAuthorized(uint256 tokenId) {
            require(msg.sender == _ownerOf(tokenId) || _isUpdateAuthorized(msg.sender, tokenId), "msg.sender is not authorized to update");
            _;
          }
        
          function isUpdateAuthorized(address operator, uint256 assetId) external view returns (bool) {
            return _isUpdateAuthorized(operator, assetId);
          }
          function _isUpdateAuthorized(address operator, uint256 assetId) internal view returns (bool) {
            return operator == _ownerOf(assetId) || updateOperator[assetId] == operator;
          }
        
          function authorizeDeploy(address beneficiary) external onlyProxyOwner {
            authorizedDeploy[beneficiary] = true;
          }
          function forbidDeploy(address beneficiary) external onlyProxyOwner {
            authorizedDeploy[beneficiary] = false;
          }
        
          function assignNewParcel(int x, int y, address beneficiary) external onlyProxyOwner {
            _generate(_encodeTokenId(x, y), beneficiary);
          }
        
          function assignMultipleParcels(int[] x, int[] y, address beneficiary) external onlyProxyOwner {
            for (uint i = 0; i < x.length; i++) {
              _generate(_encodeTokenId(x[i], y[i]), beneficiary);
            }
          }
        
          //
          // Inactive keys after 1 year lose ownership
          //
        
          function ping() external {
            latestPing[msg.sender] = now;
          }
        
          function setLatestToNow(address user) external {
            require(msg.sender == proxyOwner || _isApprovedForAll(msg.sender, user));
            latestPing[user] = now;
          }
        
          //
          // LAND Getters
          //
        
          function encodeTokenId(int x, int y) pure external returns (uint) {
            return _encodeTokenId(x, y);
          }
          function _encodeTokenId(int x, int y) pure internal returns (uint result) {
            require(-1000000 < x && x < 1000000 && -1000000 < y && y < 1000000);
            return _unsafeEncodeTokenId(x, y);
          }
          function _unsafeEncodeTokenId(int x, int y) pure internal returns (uint) {
            return ((uint(x) * factor) & clearLow) | (uint(y) & clearHigh);
          }
        
          function decodeTokenId(uint value) pure external returns (int, int) {
            return _decodeTokenId(value);
          }
          function _unsafeDecodeTokenId(uint value) pure internal returns (int x, int y) {
            x = expandNegative128BitCast((value & clearLow) >> 128);
            y = expandNegative128BitCast(value & clearHigh);
          }
          function _decodeTokenId(uint value) pure internal returns (int x, int y) {
            (x, y) = _unsafeDecodeTokenId(value);
            require(-1000000 < x && x < 1000000 && -1000000 < y && y < 1000000);
          }
        
          function expandNegative128BitCast(uint value) pure internal returns (int) {
            if (value & (1<<127) != 0) {
              return int(value | clearLow);
            }
            return int(value);
          }
        
          function exists(int x, int y) view external returns (bool) {
            return _exists(x, y);
          }
          function _exists(int x, int y) view internal returns (bool) {
            return _exists(_encodeTokenId(x, y));
          }
        
          function ownerOfLand(int x, int y) view external returns (address) {
            return _ownerOfLand(x, y);
          }
          function _ownerOfLand(int x, int y) view internal returns (address) {
            return _ownerOf(_encodeTokenId(x, y));
          }
        
          function ownerOfLandMany(int[] x, int[] y) view external returns (address[]) {
            require(x.length > 0);
            require(x.length == y.length);
        
            address[] memory addrs = new address[](x.length);
            for (uint i = 0; i < x.length; i++) {
              addrs[i] = _ownerOfLand(x[i], y[i]);
            }
        
            return addrs;
          }
        
          function landOf(address owner) external view returns (int[], int[]) {
            uint256 len = _assetsOf[owner].length;
            int[] memory x = new int[](len);
            int[] memory y = new int[](len);
        
            int assetX;
            int assetY;
            for (uint i = 0; i < len; i++) {
              (assetX, assetY) = _decodeTokenId(_assetsOf[owner][i]);
              x[i] = assetX;
              y[i] = assetY;
            }
        
            return (x, y);
          }
        
          function tokenMetadata(uint256 assetId) external view returns (string) {
            return _tokenMetadata(assetId);
          }
        
          function _tokenMetadata(uint256 assetId) internal view returns (string) {
            address _owner = _ownerOf(assetId);
            if (_isContract(_owner)) {
              if (ERC165(_owner).supportsInterface(GET_METADATA)) {
                return IMetadataHolder(_owner).getMetadata(assetId);
              }
            }
            return _assetData[assetId];
          }
        
          function landData(int x, int y) external view returns (string) {
            return _tokenMetadata(_encodeTokenId(x, y));
          }
        
          //
          // LAND Transfer
          //
        
          function transferLand(int x, int y, address to) external {
            uint256 tokenId = _encodeTokenId(x, y);
            _doTransferFrom(_ownerOf(tokenId), to, tokenId, '', msg.sender, true);
          }
        
          function transferManyLand(int[] x, int[] y, address to) external {
            require(x.length > 0);
            require(x.length == y.length);
        
            for (uint i = 0; i < x.length; i++) {
              uint256 tokenId = _encodeTokenId(x[i], y[i]);
              _doTransferFrom(_ownerOf(tokenId), to, tokenId, '', msg.sender, true);
            }
          }
        
          function setUpdateOperator(uint256 assetId, address operator) external onlyOwnerOf(assetId) {
            updateOperator[assetId] = operator;
          }
        
          //
          // LAND Update
          //
        
          function updateLandData(int x, int y, string data) external onlyUpdateAuthorized (_encodeTokenId(x, y)) {
            return _updateLandData(x, y, data);
          }
          function _updateLandData(int x, int y, string data) internal onlyUpdateAuthorized (_encodeTokenId(x, y)) {
            uint256 assetId = _encodeTokenId(x, y);
            _update(assetId, data);
        
            emit Update(assetId, _holderOf[assetId], msg.sender, data);
          }
        
          function updateManyLandData(int[] x, int[] y, string data) external {
            require(x.length > 0);
            require(x.length == y.length);
            for (uint i = 0; i < x.length; i++) {
              _updateLandData(x[i], y[i], data);
            }
          }
        
          function _doTransferFrom(
            address from,
            address to,
            uint256 assetId,
            bytes userData,
            address operator,
            bool doCheck
          ) internal {
            updateOperator[assetId] = address(0);
            super._doTransferFrom(from, to, assetId, userData, operator, doCheck);
          }
        
          function _isContract(address addr) internal view returns (bool) {
            uint size;
            assembly { size := extcodesize(addr) }
            return size > 0;
          }
        }