ETH Price: $2,416.26 (-1.36%)

Transaction Decoder

Block:
21295965 at Nov-29-2024 09:15:47 PM +UTC
Transaction Fee:
0.001085931944605611 ETH $2.62
Gas Used:
83,513 Gas / 13.003148547 Gwei

Emitted Events:

204 AdminUpgradeabilityProxy.0x84c66c3f7ba4b390e20e8e8233e2a516f3ce34a72749e4f12bd010dfba238039( 0x84c66c3f7ba4b390e20e8e8233e2a516f3ce34a72749e4f12bd010dfba238039, 0x000000000000000000000000000000000000000000000000000000000000169a, 0x00000000000000000000000013fddbd26818b837c0f7df428084ebeaf1ecd3fa, 55f20d7eb5d126f48632632748b2b1f430a901de68c9a167c06d268ac3a68c1e, 000000000000000000000000959e104e1a4db6317fa58f8295f586e1a978c297, 00000000000000000000000000000000000000000000021e19e0c9bab2400000, 000000000000000000000000000000000000000000000000000000006850e840 )

Account State Difference:

  Address   Before After State Difference Code
0x13FDdBD2...aF1ecD3FA
0.036164566131885286 Eth
Nonce: 770
0.035078634187279675 Eth
Nonce: 771
0.001085931944605611
(Titan Builder)
11.421359608295026913 Eth11.421460042544587863 Eth0.00010043424956095
0x8e5660b4...49c8Cd539
(Decentraland: Marketplace Proxy)

Execution Trace

AdminUpgradeabilityProxy.6f652e1a( )
  • Marketplace.createOrder( nftAddress=0x959e104E1a4dB6317fA58F8295F586e1A978c297, assetId=5786, priceInWei=10000000000000000000000, expiresAt=1750132800 )
    • AdminUpgradeabilityProxy.01ffc9a7( )
    • AdminUpgradeabilityProxy.6352211e( )
      • EstateRegistry.ownerOf( _tokenId=5786 ) => ( 0x13FDdBD26818b837C0F7df428084ebeaF1ecD3FA )
      • AdminUpgradeabilityProxy.081812fc( )
        • EstateRegistry.getApproved( _tokenId=5786 ) => ( 0x0000000000000000000000000000000000000000 )
        • AdminUpgradeabilityProxy.e985e9c5( )
          • EstateRegistry.isApprovedForAll( _owner=0x13FDdBD26818b837C0F7df428084ebeaF1ecD3FA, _operator=0x8e5660b4Ab70168b5a6fEeA0e0315cb49c8Cd539 ) => ( True )
            File 1 of 4: AdminUpgradeabilityProxy
            pragma solidity ^0.4.24;
            
            // File: node_modules/zos-lib/contracts/upgradeability/Proxy.sol
            
            /**
             * @title Proxy
             * @dev Implements delegation of calls to other contracts, with proper
             * forwarding of return values and bubbling of failures.
             * It defines a fallback function that delegates all calls to the address
             * returned by the abstract _implementation() internal function.
             */
            contract Proxy {
              /**
               * @dev Fallback function.
               * Implemented entirely in `_fallback`.
               */
              function () payable external {
                _fallback();
              }
            
              /**
               * @return The Address of the implementation.
               */
              function _implementation() internal view returns (address);
            
              /**
               * @dev Delegates execution to an implementation contract.
               * This is a low level function that doesn't return to its internal call site.
               * It will return to the external caller whatever the implementation returns.
               * @param implementation Address to delegate.
               */
              function _delegate(address implementation) internal {
                assembly {
                  // Copy msg.data. We take full control of memory in this inline assembly
                  // block because it will not return to Solidity code. We overwrite the
                  // Solidity scratch pad at memory position 0.
                  calldatacopy(0, 0, calldatasize)
            
                  // Call the implementation.
                  // out and outsize are 0 because we don't know the size yet.
                  let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
            
                  // Copy the returned data.
                  returndatacopy(0, 0, returndatasize)
            
                  switch result
                  // delegatecall returns 0 on error.
                  case 0 { revert(0, returndatasize) }
                  default { return(0, returndatasize) }
                }
              }
            
              /**
               * @dev Function that is run as the first thing in the fallback function.
               * Can be redefined in derived contracts to add functionality.
               * Redefinitions must call super._willFallback().
               */
              function _willFallback() internal {
              }
            
              /**
               * @dev fallback implementation.
               * Extracted to enable manual triggering.
               */
              function _fallback() internal {
                _willFallback();
                _delegate(_implementation());
              }
            }
            
            // File: openzeppelin-solidity/contracts/AddressUtils.sol
            
            /**
             * Utility library of inline functions on addresses
             */
            library AddressUtils {
            
              /**
               * Returns whether the target address is a contract
               * @dev This function will return false if invoked during the constructor of a contract,
               * as the code is not actually created until after the constructor finishes.
               * @param _addr address to check
               * @return whether the target address is a contract
               */
              function isContract(address _addr) internal view returns (bool) {
                uint256 size;
                // XXX Currently there is no better way to check if there is a contract in an address
                // than to check the size of the code at that address.
                // See https://ethereum.stackexchange.com/a/14016/36603
                // for more details about how this works.
                // TODO Check this again before the Serenity release, because all addresses will be
                // contracts then.
                // solium-disable-next-line security/no-inline-assembly
                assembly { size := extcodesize(_addr) }
                return size > 0;
              }
            
            }
            
            // File: node_modules/zos-lib/contracts/upgradeability/UpgradeabilityProxy.sol
            
            /**
             * @title UpgradeabilityProxy
             * @dev This contract implements a proxy that allows to change the
             * implementation address to which it will delegate.
             * Such a change is called an implementation upgrade.
             */
            contract UpgradeabilityProxy is Proxy {
              /**
               * @dev Emitted when the implementation is upgraded.
               * @param implementation Address of the new implementation.
               */
              event Upgraded(address implementation);
            
              /**
               * @dev Storage slot with the address of the current implementation.
               * This is the keccak-256 hash of "org.zeppelinos.proxy.implementation", and is
               * validated in the constructor.
               */
              bytes32 private constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;
            
              /**
               * @dev Contract constructor.
               * @param _implementation Address of the initial implementation.
               */
              constructor(address _implementation) public {
                assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation"));
            
                _setImplementation(_implementation);
              }
            
              /**
               * @dev Returns the current implementation.
               * @return Address of the current implementation
               */
              function _implementation() internal view returns (address impl) {
                bytes32 slot = IMPLEMENTATION_SLOT;
                assembly {
                  impl := sload(slot)
                }
              }
            
              /**
               * @dev Upgrades the proxy to a new implementation.
               * @param newImplementation Address of the new implementation.
               */
              function _upgradeTo(address newImplementation) internal {
                _setImplementation(newImplementation);
                emit Upgraded(newImplementation);
              }
            
              /**
               * @dev Sets the implementation address of the proxy.
               * @param newImplementation Address of the new implementation.
               */
              function _setImplementation(address newImplementation) private {
                require(AddressUtils.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
            
                bytes32 slot = IMPLEMENTATION_SLOT;
            
                assembly {
                  sstore(slot, newImplementation)
                }
              }
            }
            
            // File: node_modules/zos-lib/contracts/upgradeability/AdminUpgradeabilityProxy.sol
            
            /**
             * @title AdminUpgradeabilityProxy
             * @dev This contract combines an upgradeability proxy with an authorization
             * mechanism for administrative tasks.
             * All external functions in this contract must be guarded by the
             * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity
             * feature proposal that would enable this to be done automatically.
             */
            contract AdminUpgradeabilityProxy is UpgradeabilityProxy {
              /**
               * @dev Emitted when the administration has been transferred.
               * @param previousAdmin Address of the previous admin.
               * @param newAdmin Address of the new admin.
               */
              event AdminChanged(address previousAdmin, address newAdmin);
            
              /**
               * @dev Storage slot with the admin of the contract.
               * This is the keccak-256 hash of "org.zeppelinos.proxy.admin", and is
               * validated in the constructor.
               */
              bytes32 private constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b;
            
              /**
               * @dev Modifier to check whether the `msg.sender` is the admin.
               * If it is, it will run the function. Otherwise, it will delegate the call
               * to the implementation.
               */
              modifier ifAdmin() {
                if (msg.sender == _admin()) {
                  _;
                } else {
                  _fallback();
                }
              }
            
              /**
               * Contract constructor.
               * It sets the `msg.sender` as the proxy administrator.
               * @param _implementation address of the initial implementation.
               */
              constructor(address _implementation) UpgradeabilityProxy(_implementation) public {
                assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin"));
            
                _setAdmin(msg.sender);
              }
            
              /**
               * @return The address of the proxy admin.
               */
              function admin() external view ifAdmin returns (address) {
                return _admin();
              }
            
              /**
               * @return The address of the implementation.
               */
              function implementation() external view ifAdmin returns (address) {
                return _implementation();
              }
            
              /**
               * @dev Changes the admin of the proxy.
               * Only the current admin can call this function.
               * @param newAdmin Address to transfer proxy administration to.
               */
              function changeAdmin(address newAdmin) external ifAdmin {
                require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
                emit AdminChanged(_admin(), newAdmin);
                _setAdmin(newAdmin);
              }
            
              /**
               * @dev Upgrade the backing implementation of the proxy.
               * Only the admin can call this function.
               * @param newImplementation Address of the new implementation.
               */
              function upgradeTo(address newImplementation) external ifAdmin {
                _upgradeTo(newImplementation);
              }
            
              /**
               * @dev Upgrade the backing implementation of the proxy and call a function
               * on the new implementation.
               * This is useful to initialize the proxied contract.
               * @param newImplementation Address of the new implementation.
               * @param data Data to send as msg.data in the low level call.
               * It should include the signature and the parameters of the function to be
               * called, as described in
               * https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding.
               */
              function upgradeToAndCall(address newImplementation, bytes data) payable external ifAdmin {
                _upgradeTo(newImplementation);
                require(address(this).call.value(msg.value)(data));
              }
            
              /**
               * @return The admin slot.
               */
              function _admin() internal view returns (address adm) {
                bytes32 slot = ADMIN_SLOT;
                assembly {
                  adm := sload(slot)
                }
              }
            
              /**
               * @dev Sets the address of the proxy admin.
               * @param newAdmin Address of the new proxy admin.
               */
              function _setAdmin(address newAdmin) internal {
                bytes32 slot = ADMIN_SLOT;
            
                assembly {
                  sstore(slot, newAdmin)
                }
              }
            
              /**
               * @dev Only fall back when the sender is not the admin.
               */
              function _willFallback() internal {
                require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
                super._willFallback();
              }
            }

            File 2 of 4: Marketplace
            pragma solidity ^0.4.24;
            
            // File: zos-lib/contracts/migrations/Migratable.sol
            
            /**
             * @title Migratable
             * Helper contract to support intialization and migration schemes between
             * different implementations of a contract in the context of upgradeability.
             * To use it, replace the constructor with a function that has the
             * `isInitializer` modifier starting with `"0"` as `migrationId`.
             * When you want to apply some migration code during an upgrade, increase
             * the `migrationId`. Or, if the migration code must be applied only after
             * another migration has been already applied, use the `isMigration` modifier.
             * This helper supports multiple inheritance.
             * WARNING: It is the developer's responsibility to ensure that migrations are
             * applied in a correct order, or that they are run at all.
             * See `Initializable` for a simpler version.
             */
            contract Migratable {
              /**
               * @dev Emitted when the contract applies a migration.
               * @param contractName Name of the Contract.
               * @param migrationId Identifier of the migration applied.
               */
              event Migrated(string contractName, string migrationId);
            
              /**
               * @dev Mapping of the already applied migrations.
               * (contractName => (migrationId => bool))
               */
              mapping (string => mapping (string => bool)) internal migrated;
            
              /**
               * @dev Internal migration id used to specify that a contract has already been initialized.
               */
              string constant private INITIALIZED_ID = "initialized";
            
            
              /**
               * @dev Modifier to use in the initialization function of a contract.
               * @param contractName Name of the contract.
               * @param migrationId Identifier of the migration.
               */
              modifier isInitializer(string contractName, string migrationId) {
                validateMigrationIsPending(contractName, INITIALIZED_ID);
                validateMigrationIsPending(contractName, migrationId);
                _;
                emit Migrated(contractName, migrationId);
                migrated[contractName][migrationId] = true;
                migrated[contractName][INITIALIZED_ID] = true;
              }
            
              /**
               * @dev Modifier to use in the migration of a contract.
               * @param contractName Name of the contract.
               * @param requiredMigrationId Identifier of the previous migration, required
               * to apply new one.
               * @param newMigrationId Identifier of the new migration to be applied.
               */
              modifier isMigration(string contractName, string requiredMigrationId, string newMigrationId) {
                require(isMigrated(contractName, requiredMigrationId), "Prerequisite migration ID has not been run yet");
                validateMigrationIsPending(contractName, newMigrationId);
                _;
                emit Migrated(contractName, newMigrationId);
                migrated[contractName][newMigrationId] = true;
              }
            
              /**
               * @dev Returns true if the contract migration was applied.
               * @param contractName Name of the contract.
               * @param migrationId Identifier of the migration.
               * @return true if the contract migration was applied, false otherwise.
               */
              function isMigrated(string contractName, string migrationId) public view returns(bool) {
                return migrated[contractName][migrationId];
              }
            
              /**
               * @dev Initializer that marks the contract as initialized.
               * It is important to run this if you had deployed a previous version of a Migratable contract.
               * For more information see https://github.com/zeppelinos/zos-lib/issues/158.
               */
              function initialize() isInitializer("Migratable", "1.2.1") public {
              }
            
              /**
               * @dev Reverts if the requested migration was already executed.
               * @param contractName Name of the contract.
               * @param migrationId Identifier of the migration.
               */
              function validateMigrationIsPending(string contractName, string migrationId) private view {
                require(!isMigrated(contractName, migrationId), "Requested target migration ID has already been run");
              }
            }
            
            // File: openzeppelin-zos/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 is Migratable {
              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 initialize(address _sender) public isInitializer("Ownable", "1.9.0") {
                owner = _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));
                emit OwnershipTransferred(owner, newOwner);
                owner = newOwner;
              }
            
            }
            
            // File: openzeppelin-zos/contracts/lifecycle/Pausable.sol
            
            /**
             * @title Pausable
             * @dev Base contract which allows children to implement an emergency stop mechanism.
             */
            contract Pausable is Migratable, Ownable {
              event Pause();
              event Unpause();
            
              bool public paused = false;
            
            
              function initialize(address _sender) isInitializer("Pausable", "1.9.0")  public {
                Ownable.initialize(_sender);
              }
            
              /**
               * @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;
                emit Pause();
              }
            
              /**
               * @dev called by the owner to unpause, returns to normal state
               */
              function unpause() onlyOwner whenPaused public {
                paused = false;
                emit Unpause();
              }
            }
            
            // File: openzeppelin-zos/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 c) {
                if (a == 0) {
                  return 0;
                }
                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 a / b;
              }
            
              /**
              * @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 c) {
                c = a + b;
                assert(c >= a);
                return c;
              }
            }
            
            // File: openzeppelin-zos/contracts/AddressUtils.sol
            
            /**
             * Utility library of inline functions on addresses
             */
            library AddressUtils {
            
              /**
               * Returns whether the target address is a contract
               * @dev This function will return false if invoked during the constructor of a contract,
               *  as the code is not actually created until after the constructor finishes.
               * @param addr address to check
               * @return whether the target address is a contract
               */
              function isContract(address addr) internal view returns (bool) {
                uint256 size;
                // XXX Currently there is no better way to check if there is a contract in an address
                // than to check the size of the code at that address.
                // See https://ethereum.stackexchange.com/a/14016/36603
                // for more details about how this works.
                // TODO Check this again before the Serenity release, because all addresses will be
                // contracts then.
                assembly { size := extcodesize(addr) }  // solium-disable-line security/no-inline-assembly
                return size > 0;
              }
            
            }
            
            // File: contracts/marketplace/MarketplaceStorage.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 _tokenId) public view returns (address _owner);
              function approve(address _to, uint256 _tokenId) public;
              function getApproved(uint256 _tokenId) public view returns (address);
              function isApprovedForAll(address _owner, address _operator) public view returns (bool);
              function safeTransferFrom(address _from, address _to, uint256 _tokenId) public;
              function supportsInterface(bytes4) public view returns (bool);
            }
            
            
            contract ERC721Verifiable is ERC721Interface {
              function verifyFingerprint(uint256, bytes) public view returns (bool);
            }
            
            
            contract MarketplaceStorage {
              ERC20Interface public acceptedToken;
            
              struct Order {
                // Order ID
                bytes32 id;
                // Owner of the NFT
                address seller;
                // NFT registry address
                address nftAddress;
                // Price (in wei) for the published item
                uint256 price;
                // Time when this sale ends
                uint256 expiresAt;
              }
            
              // From ERC721 registry assetId to Order (to avoid asset collision)
              mapping (address => mapping(uint256 => Order)) public orderByAssetId;
            
              uint256 public ownerCutPerMillion;
              uint256 public publicationFeeInWei;
            
              address public legacyNFTAddress;
            
              bytes4 public constant InterfaceId_ValidateFingerprint = bytes4(
                keccak256("verifyFingerprint(uint256,bytes)")
              );
            
              bytes4 public constant ERC721_Interface = bytes4(0x80ac58cd);
            
              // EVENTS
              event OrderCreated(
                bytes32 id,
                uint256 indexed assetId,
                address indexed seller,
                address nftAddress,
                uint256 priceInWei,
                uint256 expiresAt
              );
              event OrderSuccessful(
                bytes32 id,
                uint256 indexed assetId,
                address indexed seller,
                address nftAddress,
                uint256 totalPrice,
                address indexed buyer
              );
              event OrderCancelled(
                bytes32 id,
                uint256 indexed assetId,
                address indexed seller,
                address nftAddress
              );
            
              event ChangedPublicationFee(uint256 publicationFee);
              event ChangedOwnerCutPerMillion(uint256 ownerCutPerMillion);
              event ChangeLegacyNFTAddress(address indexed legacyNFTAddress);
            
              // [LEGACY] Auction 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
              );
            }
            
            // File: contracts/marketplace/Marketplace.sol
            
            contract Marketplace is Migratable, Ownable, Pausable, MarketplaceStorage {
              using SafeMath for uint256;
              using AddressUtils for address;
            
              /**
                * @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) external onlyOwner {
                publicationFeeInWei = _publicationFee;
                emit ChangedPublicationFee(publicationFeeInWei);
              }
            
              /**
                * @dev Sets the share cut for the owner of the contract that's
                *  charged to the seller on a successful sale
                * @param _ownerCutPerMillion - Share amount, from 0 to 999,999
                */
              function setOwnerCutPerMillion(uint256 _ownerCutPerMillion) external onlyOwner {
                require(_ownerCutPerMillion < 1000000, "The owner cut should be between 0 and 999,999");
            
                ownerCutPerMillion = _ownerCutPerMillion;
                emit ChangedOwnerCutPerMillion(ownerCutPerMillion);
              }
            
              /**
                * @dev Sets the legacy NFT address to be used
                * @param _legacyNFTAddress - Address of the NFT address used for legacy methods that don't have nftAddress as parameter
                */
              function setLegacyNFTAddress(address _legacyNFTAddress) external onlyOwner {
                _requireERC721(_legacyNFTAddress);
            
                legacyNFTAddress = _legacyNFTAddress;
                emit ChangeLegacyNFTAddress(legacyNFTAddress);
              }
            
              /**
                * @dev Initialize this contract. Acts as a constructor
                * @param _acceptedToken - Address of the ERC20 accepted for this marketplace
                * @param _legacyNFTAddress - Address of the NFT address used for legacy methods that don't have nftAddress as parameter
                */
              function initialize(
                address _acceptedToken,
                address _legacyNFTAddress,
                address _owner
              )
                public
                isInitializer("Marketplace", "0.0.1")
              {
            
                // msg.sender is the App contract not the real owner. Calls ownable behind the scenes...sigh
                require(_owner != address(0), "Invalid owner");
                Pausable.initialize(_owner);
            
                require(_acceptedToken.isContract(), "The accepted token address must be a deployed contract");
                acceptedToken = ERC20Interface(_acceptedToken);
            
                _requireERC721(_legacyNFTAddress);
                legacyNFTAddress = _legacyNFTAddress;
              }
            
              /**
                * @dev Creates a new order
                * @param nftAddress - Non fungible registry address
                * @param assetId - ID of the published NFT
                * @param priceInWei - Price in Wei for the supported coin
                * @param expiresAt - Duration of the order (in hours)
                */
              function createOrder(
                address nftAddress,
                uint256 assetId,
                uint256 priceInWei,
                uint256 expiresAt
              )
                public
                whenNotPaused
              {
                _createOrder(
                  nftAddress,
                  assetId,
                  priceInWei,
                  expiresAt
                );
              }
            
              /**
                * @dev [LEGACY] Creates a new order
                * @param assetId - ID of the published NFT
                * @param priceInWei - Price in Wei for the supported coin
                * @param expiresAt - Duration of the order (in hours)
                */
              function createOrder(
                uint256 assetId,
                uint256 priceInWei,
                uint256 expiresAt
              )
                public
                whenNotPaused
              {
                _createOrder(
                  legacyNFTAddress,
                  assetId,
                  priceInWei,
                  expiresAt
                );
            
                Order memory order = orderByAssetId[legacyNFTAddress][assetId];
                emit AuctionCreated(
                  order.id,
                  assetId,
                  order.seller,
                  order.price,
                  order.expiresAt
                );
              }
            
              /**
                * @dev Cancel an already published order
                *  can only be canceled by seller or the contract owner
                * @param nftAddress - Address of the NFT registry
                * @param assetId - ID of the published NFT
                */
              function cancelOrder(address nftAddress, uint256 assetId) public whenNotPaused {
                _cancelOrder(nftAddress, assetId);
              }
            
              /**
                * @dev [LEGACY] 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 {
                Order memory order = _cancelOrder(legacyNFTAddress, assetId);
            
                emit AuctionCancelled(
                  order.id,
                  assetId,
                  order.seller
                );
              }
            
              /**
                * @dev Executes the sale for a published NFT and checks for the asset fingerprint
                * @param nftAddress - Address of the NFT registry
                * @param assetId - ID of the published NFT
                * @param price - Order price
                * @param fingerprint - Verification info for the asset
                */
              function safeExecuteOrder(
                address nftAddress,
                uint256 assetId,
                uint256 price,
                bytes fingerprint
              )
               public
               whenNotPaused
              {
                _executeOrder(
                  nftAddress,
                  assetId,
                  price,
                  fingerprint
                );
              }
            
              /**
                * @dev Executes the sale for a published NFT
                * @param nftAddress - Address of the NFT registry
                * @param assetId - ID of the published NFT
                * @param price - Order price
                */
              function executeOrder(
                address nftAddress,
                uint256 assetId,
                uint256 price
              )
               public
               whenNotPaused
              {
                _executeOrder(
                  nftAddress,
                  assetId,
                  price,
                  ""
                );
              }
            
              /**
                * @dev [LEGACY] Executes the sale for a published NFT
                * @param assetId - ID of the published NFT
                * @param price - Order price
                */
              function executeOrder(
                uint256 assetId,
                uint256 price
              )
               public
               whenNotPaused
              {
                Order memory order = _executeOrder(
                  legacyNFTAddress,
                  assetId,
                  price,
                  ""
                );
            
                emit AuctionSuccessful(
                  order.id,
                  assetId,
                  order.seller,
                  price,
                  msg.sender
                );
              }
            
              /**
                * @dev [LEGACY] Gets an order using the legacy NFT address.
                * @dev It's equivalent to orderByAssetId[legacyNFTAddress][assetId] but returns same structure as the old Auction
                * @param assetId - ID of the published NFT
                */
              function auctionByAssetId(
                uint256 assetId
              )
                public
                view
                returns
                (bytes32, address, uint256, uint256)
              {
                Order memory order = orderByAssetId[legacyNFTAddress][assetId];
                return (order.id, order.seller, order.price, order.expiresAt);
              }
            
              /**
                * @dev Creates a new order
                * @param nftAddress - Non fungible registry address
                * @param assetId - ID of the published NFT
                * @param priceInWei - Price in Wei for the supported coin
                * @param expiresAt - Duration of the order (in hours)
                */
              function _createOrder(
                address nftAddress,
                uint256 assetId,
                uint256 priceInWei,
                uint256 expiresAt
              )
                internal
              {
                _requireERC721(nftAddress);
            
                ERC721Interface nftRegistry = ERC721Interface(nftAddress);
                address assetOwner = nftRegistry.ownerOf(assetId);
            
                require(msg.sender == assetOwner, "Only the owner can create orders");
                require(
                  nftRegistry.getApproved(assetId) == address(this) || nftRegistry.isApprovedForAll(assetOwner, address(this)),
                  "The contract is not authorized to manage the asset"
                );
                require(priceInWei > 0, "Price should be bigger than 0");
                require(expiresAt > block.timestamp.add(1 minutes), "Publication should be more than 1 minute in the future");
            
                bytes32 orderId = keccak256(
                  abi.encodePacked(
                    block.timestamp,
                    assetOwner,
                    assetId,
                    nftAddress,
                    priceInWei
                  )
                );
            
                orderByAssetId[nftAddress][assetId] = Order({
                  id: orderId,
                  seller: assetOwner,
                  nftAddress: nftAddress,
                  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),
                    "Transfering the publication fee to the Marketplace owner failed"
                  );
                }
            
                emit OrderCreated(
                  orderId,
                  assetId,
                  assetOwner,
                  nftAddress,
                  priceInWei,
                  expiresAt
                );
              }
            
              /**
                * @dev Cancel an already published order
                *  can only be canceled by seller or the contract owner
                * @param nftAddress - Address of the NFT registry
                * @param assetId - ID of the published NFT
                */
              function _cancelOrder(address nftAddress, uint256 assetId) internal returns (Order) {
                Order memory order = orderByAssetId[nftAddress][assetId];
            
                require(order.id != 0, "Asset not published");
                require(order.seller == msg.sender || msg.sender == owner, "Unauthorized user");
            
                bytes32 orderId = order.id;
                address orderSeller = order.seller;
                address orderNftAddress = order.nftAddress;
                delete orderByAssetId[nftAddress][assetId];
            
                emit OrderCancelled(
                  orderId,
                  assetId,
                  orderSeller,
                  orderNftAddress
                );
            
                return order;
              }
            
              /**
                * @dev Executes the sale for a published NFT
                * @param nftAddress - Address of the NFT registry
                * @param assetId - ID of the published NFT
                * @param price - Order price
                * @param fingerprint - Verification info for the asset
                */
              function _executeOrder(
                address nftAddress,
                uint256 assetId,
                uint256 price,
                bytes fingerprint
              )
               internal returns (Order)
              {
                _requireERC721(nftAddress);
            
                ERC721Verifiable nftRegistry = ERC721Verifiable(nftAddress);
            
                if (nftRegistry.supportsInterface(InterfaceId_ValidateFingerprint)) {
                  require(
                    nftRegistry.verifyFingerprint(assetId, fingerprint),
                    "The asset fingerprint is not valid"
                  );
                }
                Order memory order = orderByAssetId[nftAddress][assetId];
            
                require(order.id != 0, "Asset not published");
            
                address seller = order.seller;
            
                require(seller != address(0), "Invalid address");
                require(seller != msg.sender, "Unauthorized user");
                require(order.price == price, "The price is not correct");
                require(block.timestamp < order.expiresAt, "The order expired");
                require(seller == nftRegistry.ownerOf(assetId), "The seller is no longer the owner");
            
                uint saleShareAmount = 0;
            
                bytes32 orderId = order.id;
                delete orderByAssetId[nftAddress][assetId];
            
                if (ownerCutPerMillion > 0) {
                  // Calculate sale share
                  saleShareAmount = price.mul(ownerCutPerMillion).div(1000000);
            
                  // Transfer share amount for marketplace Owner
                  require(
                    acceptedToken.transferFrom(msg.sender, owner, saleShareAmount),
                    "Transfering the cut to the Marketplace owner failed"
                  );
                }
            
                // Transfer sale amount to seller
                require(
                  acceptedToken.transferFrom(msg.sender, seller, price.sub(saleShareAmount)),
                  "Transfering the sale amount to the seller failed"
                );
            
                // Transfer asset owner
                nftRegistry.safeTransferFrom(
                  seller,
                  msg.sender,
                  assetId
                );
            
                emit OrderSuccessful(
                  orderId,
                  assetId,
                  seller,
                  nftAddress,
                  price,
                  msg.sender
                );
            
                return order;
              }
            
              function _requireERC721(address nftAddress) internal view {
                require(nftAddress.isContract(), "The NFT Address should be a contract");
            
                ERC721Interface nftRegistry = ERC721Interface(nftAddress);
                require(
                  nftRegistry.supportsInterface(ERC721_Interface),
                  "The NFT contract has an invalid ERC721 implementation"
                );
              }
            }

            File 3 of 4: AdminUpgradeabilityProxy
            pragma solidity ^0.4.24;
            
            // File: node_modules/zos-lib/contracts/upgradeability/Proxy.sol
            
            /**
             * @title Proxy
             * @dev Implements delegation of calls to other contracts, with proper
             * forwarding of return values and bubbling of failures.
             * It defines a fallback function that delegates all calls to the address
             * returned by the abstract _implementation() internal function.
             */
            contract Proxy {
              /**
               * @dev Fallback function.
               * Implemented entirely in `_fallback`.
               */
              function () payable external {
                _fallback();
              }
            
              /**
               * @return The Address of the implementation.
               */
              function _implementation() internal view returns (address);
            
              /**
               * @dev Delegates execution to an implementation contract.
               * This is a low level function that doesn't return to its internal call site.
               * It will return to the external caller whatever the implementation returns.
               * @param implementation Address to delegate.
               */
              function _delegate(address implementation) internal {
                assembly {
                  // Copy msg.data. We take full control of memory in this inline assembly
                  // block because it will not return to Solidity code. We overwrite the
                  // Solidity scratch pad at memory position 0.
                  calldatacopy(0, 0, calldatasize)
            
                  // Call the implementation.
                  // out and outsize are 0 because we don't know the size yet.
                  let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
            
                  // Copy the returned data.
                  returndatacopy(0, 0, returndatasize)
            
                  switch result
                  // delegatecall returns 0 on error.
                  case 0 { revert(0, returndatasize) }
                  default { return(0, returndatasize) }
                }
              }
            
              /**
               * @dev Function that is run as the first thing in the fallback function.
               * Can be redefined in derived contracts to add functionality.
               * Redefinitions must call super._willFallback().
               */
              function _willFallback() internal {
              }
            
              /**
               * @dev fallback implementation.
               * Extracted to enable manual triggering.
               */
              function _fallback() internal {
                _willFallback();
                _delegate(_implementation());
              }
            }
            
            // File: openzeppelin-solidity/contracts/AddressUtils.sol
            
            /**
             * Utility library of inline functions on addresses
             */
            library AddressUtils {
            
              /**
               * Returns whether the target address is a contract
               * @dev This function will return false if invoked during the constructor of a contract,
               * as the code is not actually created until after the constructor finishes.
               * @param _addr address to check
               * @return whether the target address is a contract
               */
              function isContract(address _addr) internal view returns (bool) {
                uint256 size;
                // XXX Currently there is no better way to check if there is a contract in an address
                // than to check the size of the code at that address.
                // See https://ethereum.stackexchange.com/a/14016/36603
                // for more details about how this works.
                // TODO Check this again before the Serenity release, because all addresses will be
                // contracts then.
                // solium-disable-next-line security/no-inline-assembly
                assembly { size := extcodesize(_addr) }
                return size > 0;
              }
            
            }
            
            // File: node_modules/zos-lib/contracts/upgradeability/UpgradeabilityProxy.sol
            
            /**
             * @title UpgradeabilityProxy
             * @dev This contract implements a proxy that allows to change the
             * implementation address to which it will delegate.
             * Such a change is called an implementation upgrade.
             */
            contract UpgradeabilityProxy is Proxy {
              /**
               * @dev Emitted when the implementation is upgraded.
               * @param implementation Address of the new implementation.
               */
              event Upgraded(address implementation);
            
              /**
               * @dev Storage slot with the address of the current implementation.
               * This is the keccak-256 hash of "org.zeppelinos.proxy.implementation", and is
               * validated in the constructor.
               */
              bytes32 private constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;
            
              /**
               * @dev Contract constructor.
               * @param _implementation Address of the initial implementation.
               */
              constructor(address _implementation) public {
                assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation"));
            
                _setImplementation(_implementation);
              }
            
              /**
               * @dev Returns the current implementation.
               * @return Address of the current implementation
               */
              function _implementation() internal view returns (address impl) {
                bytes32 slot = IMPLEMENTATION_SLOT;
                assembly {
                  impl := sload(slot)
                }
              }
            
              /**
               * @dev Upgrades the proxy to a new implementation.
               * @param newImplementation Address of the new implementation.
               */
              function _upgradeTo(address newImplementation) internal {
                _setImplementation(newImplementation);
                emit Upgraded(newImplementation);
              }
            
              /**
               * @dev Sets the implementation address of the proxy.
               * @param newImplementation Address of the new implementation.
               */
              function _setImplementation(address newImplementation) private {
                require(AddressUtils.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
            
                bytes32 slot = IMPLEMENTATION_SLOT;
            
                assembly {
                  sstore(slot, newImplementation)
                }
              }
            }
            
            // File: node_modules/zos-lib/contracts/upgradeability/AdminUpgradeabilityProxy.sol
            
            /**
             * @title AdminUpgradeabilityProxy
             * @dev This contract combines an upgradeability proxy with an authorization
             * mechanism for administrative tasks.
             * All external functions in this contract must be guarded by the
             * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity
             * feature proposal that would enable this to be done automatically.
             */
            contract AdminUpgradeabilityProxy is UpgradeabilityProxy {
              /**
               * @dev Emitted when the administration has been transferred.
               * @param previousAdmin Address of the previous admin.
               * @param newAdmin Address of the new admin.
               */
              event AdminChanged(address previousAdmin, address newAdmin);
            
              /**
               * @dev Storage slot with the admin of the contract.
               * This is the keccak-256 hash of "org.zeppelinos.proxy.admin", and is
               * validated in the constructor.
               */
              bytes32 private constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b;
            
              /**
               * @dev Modifier to check whether the `msg.sender` is the admin.
               * If it is, it will run the function. Otherwise, it will delegate the call
               * to the implementation.
               */
              modifier ifAdmin() {
                if (msg.sender == _admin()) {
                  _;
                } else {
                  _fallback();
                }
              }
            
              /**
               * Contract constructor.
               * It sets the `msg.sender` as the proxy administrator.
               * @param _implementation address of the initial implementation.
               */
              constructor(address _implementation) UpgradeabilityProxy(_implementation) public {
                assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin"));
            
                _setAdmin(msg.sender);
              }
            
              /**
               * @return The address of the proxy admin.
               */
              function admin() external view ifAdmin returns (address) {
                return _admin();
              }
            
              /**
               * @return The address of the implementation.
               */
              function implementation() external view ifAdmin returns (address) {
                return _implementation();
              }
            
              /**
               * @dev Changes the admin of the proxy.
               * Only the current admin can call this function.
               * @param newAdmin Address to transfer proxy administration to.
               */
              function changeAdmin(address newAdmin) external ifAdmin {
                require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
                emit AdminChanged(_admin(), newAdmin);
                _setAdmin(newAdmin);
              }
            
              /**
               * @dev Upgrade the backing implementation of the proxy.
               * Only the admin can call this function.
               * @param newImplementation Address of the new implementation.
               */
              function upgradeTo(address newImplementation) external ifAdmin {
                _upgradeTo(newImplementation);
              }
            
              /**
               * @dev Upgrade the backing implementation of the proxy and call a function
               * on the new implementation.
               * This is useful to initialize the proxied contract.
               * @param newImplementation Address of the new implementation.
               * @param data Data to send as msg.data in the low level call.
               * It should include the signature and the parameters of the function to be
               * called, as described in
               * https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding.
               */
              function upgradeToAndCall(address newImplementation, bytes data) payable external ifAdmin {
                _upgradeTo(newImplementation);
                require(address(this).call.value(msg.value)(data));
              }
            
              /**
               * @return The admin slot.
               */
              function _admin() internal view returns (address adm) {
                bytes32 slot = ADMIN_SLOT;
                assembly {
                  adm := sload(slot)
                }
              }
            
              /**
               * @dev Sets the address of the proxy admin.
               * @param newAdmin Address of the new proxy admin.
               */
              function _setAdmin(address newAdmin) internal {
                bytes32 slot = ADMIN_SLOT;
            
                assembly {
                  sstore(slot, newAdmin)
                }
              }
            
              /**
               * @dev Only fall back when the sender is not the admin.
               */
              function _willFallback() internal {
                require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
                super._willFallback();
              }
            }

            File 4 of 4: EstateRegistry
            pragma solidity ^0.4.24;
            // File: openzeppelin-zos/contracts/introspection/ERC165.sol
            /**
             * @title ERC165
             * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
             */
            interface ERC165 {
              /**
               * @notice Query if a contract implements an interface
               * @param _interfaceId The interface identifier, as specified in ERC-165
               * @dev Interface identification is specified in ERC-165. This function
               * uses less than 30,000 gas.
               */
              function supportsInterface(bytes4 _interfaceId)
                external
                view
                returns (bool);
            }
            // File: openzeppelin-zos/contracts/token/ERC721/ERC721Basic.sol
            /**
             * @title ERC721 Non-Fungible Token Standard basic interface
             * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
             */
            contract ERC721Basic is ERC165 {
              event Transfer(
                address indexed _from,
                address indexed _to,
                uint256 indexed _tokenId
              );
              event Approval(
                address indexed _owner,
                address indexed _approved,
                uint256 indexed _tokenId
              );
              event ApprovalForAll(
                address indexed _owner,
                address indexed _operator,
                bool _approved
              );
              function balanceOf(address _owner) public view returns (uint256 _balance);
              function ownerOf(uint256 _tokenId) public view returns (address _owner);
              function exists(uint256 _tokenId) public view returns (bool _exists);
              function approve(address _to, uint256 _tokenId) public;
              function getApproved(uint256 _tokenId)
                public view returns (address _operator);
              function setApprovalForAll(address _operator, bool _approved) public;
              function isApprovedForAll(address _owner, address _operator)
                public view returns (bool);
              function transferFrom(address _from, address _to, uint256 _tokenId) public;
              function safeTransferFrom(address _from, address _to, uint256 _tokenId)
                public;
              function safeTransferFrom(
                address _from,
                address _to,
                uint256 _tokenId,
                bytes _data
              )
                public;
            }
            // File: openzeppelin-zos/contracts/token/ERC721/ERC721.sol
            /**
             * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
             * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
             */
            contract ERC721Enumerable is ERC721Basic {
              function totalSupply() public view returns (uint256);
              function tokenOfOwnerByIndex(
                address _owner,
                uint256 _index
              )
                public
                view
                returns (uint256 _tokenId);
              function tokenByIndex(uint256 _index) public view returns (uint256);
            }
            /**
             * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
             * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
             */
            contract ERC721Metadata is ERC721Basic {
              function name() external view returns (string _name);
              function symbol() external view returns (string _symbol);
              function tokenURI(uint256 _tokenId) public view returns (string);
            }
            /**
             * @title ERC-721 Non-Fungible Token Standard, full implementation interface
             * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
             */
            contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata {
            }
            // File: openzeppelin-zos/contracts/token/ERC721/ERC721Receiver.sol
            /**
             * @title ERC721 token receiver interface
             * @dev Interface for any contract that wants to support safeTransfers
             * from ERC721 asset contracts.
             */
            contract ERC721Receiver {
              /**
               * @dev Magic value to be returned upon successful reception of an NFT
               *  Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`,
               *  which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
               */
              bytes4 internal constant ERC721_RECEIVED = 0x150b7a02;
              /**
               * @notice Handle the receipt of an NFT
               * @dev The ERC721 smart contract calls this function on the recipient
               * after a `safetransfer`. This function MAY throw to revert and reject the
               * transfer. Return of other than the magic value MUST result in the 
               * transaction being reverted.
               * Note: the contract address is always the message sender.
               * @param _operator The address which called `safeTransferFrom` function
               * @param _from The address which previously owned the token
               * @param _tokenId The NFT identifier which is being transfered
               * @param _data Additional data with no specified format
               * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
               */
              function onERC721Received(
                address _operator,
                address _from,
                uint256 _tokenId,
                bytes _data
              )
                public
                returns(bytes4);
            }
            // File: openzeppelin-zos/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 c) {
                if (a == 0) {
                  return 0;
                }
                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 a / b;
              }
              /**
              * @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 c) {
                c = a + b;
                assert(c >= a);
                return c;
              }
            }
            // File: openzeppelin-zos/contracts/AddressUtils.sol
            /**
             * Utility library of inline functions on addresses
             */
            library AddressUtils {
              /**
               * Returns whether the target address is a contract
               * @dev This function will return false if invoked during the constructor of a contract,
               *  as the code is not actually created until after the constructor finishes.
               * @param addr address to check
               * @return whether the target address is a contract
               */
              function isContract(address addr) internal view returns (bool) {
                uint256 size;
                // XXX Currently there is no better way to check if there is a contract in an address
                // than to check the size of the code at that address.
                // See https://ethereum.stackexchange.com/a/14016/36603
                // for more details about how this works.
                // TODO Check this again before the Serenity release, because all addresses will be
                // contracts then.
                assembly { size := extcodesize(addr) }  // solium-disable-line security/no-inline-assembly
                return size > 0;
              }
            }
            // File: openzeppelin-zos/contracts/introspection/ERC165Support.sol
            /**
             * @title ERC165Support
             * @dev Implements ERC165 returning true for ERC165 interface identifier
             */
            contract ERC165Support is ERC165 {
              bytes4 internal constant InterfaceId_ERC165 = 0x01ffc9a7;
              /**
               * 0x01ffc9a7 ===
               *   bytes4(keccak256('supportsInterface(bytes4)'))
               */
              function supportsInterface(bytes4 _interfaceId)
                external
                view
                returns (bool) 
              {
                return _supportsInterface(_interfaceId);
              }
              function _supportsInterface(bytes4 _interfaceId)
                internal
                view
                returns (bool) 
              {
                return _interfaceId == InterfaceId_ERC165;
              }
            }
            // File: openzeppelin-zos/contracts/token/ERC721/ERC721BasicToken.sol
            /**
             * @title ERC721 Non-Fungible Token Standard basic implementation
             * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
             */
            contract ERC721BasicToken is ERC165Support, ERC721Basic {
              bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd;
              /*
               * 0x80ac58cd ===
               *   bytes4(keccak256('balanceOf(address)')) ^
               *   bytes4(keccak256('ownerOf(uint256)')) ^
               *   bytes4(keccak256('approve(address,uint256)')) ^
               *   bytes4(keccak256('getApproved(uint256)')) ^
               *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^
               *   bytes4(keccak256('isApprovedForAll(address,address)')) ^
               *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^
               *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
               *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
               */
              bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79;
              /*
               * 0x4f558e79 ===
               *   bytes4(keccak256('exists(uint256)'))
               */
              using SafeMath for uint256;
              using AddressUtils for address;
              // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
              // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
              bytes4 private constant ERC721_RECEIVED = 0x150b7a02;
              // Mapping from token ID to owner
              mapping (uint256 => address) internal tokenOwner;
              // Mapping from token ID to approved address
              mapping (uint256 => address) internal tokenApprovals;
              // Mapping from owner to number of owned token
              mapping (address => uint256) internal ownedTokensCount;
              // Mapping from owner to operator approvals
              mapping (address => mapping (address => bool)) internal operatorApprovals;
              /**
               * @dev Guarantees msg.sender is owner of the given token
               * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender
               */
              modifier onlyOwnerOf(uint256 _tokenId) {
                require(ownerOf(_tokenId) == msg.sender);
                _;
              }
              /**
               * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator
               * @param _tokenId uint256 ID of the token to validate
               */
              modifier canTransfer(uint256 _tokenId) {
                require(isApprovedOrOwner(msg.sender, _tokenId));
                _;
              }
              function _supportsInterface(bytes4 _interfaceId)
                internal
                view
                returns (bool)
              {
                return super._supportsInterface(_interfaceId) || 
                  _interfaceId == InterfaceId_ERC721 || _interfaceId == InterfaceId_ERC721Exists;
              }
              /**
               * @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) public view returns (uint256) {
                require(_owner != address(0));
                return ownedTokensCount[_owner];
              }
              /**
               * @dev Gets the owner of the specified token ID
               * @param _tokenId uint256 ID of the token to query the owner of
               * @return owner address currently marked as the owner of the given token ID
               */
              function ownerOf(uint256 _tokenId) public view returns (address) {
                address owner = tokenOwner[_tokenId];
                require(owner != address(0));
                return owner;
              }
              /**
               * @dev Returns whether the specified token exists
               * @param _tokenId uint256 ID of the token to query the existence of
               * @return whether the token exists
               */
              function exists(uint256 _tokenId) public view returns (bool) {
                address owner = tokenOwner[_tokenId];
                return owner != address(0);
              }
              /**
               * @dev Approves another address to transfer the given token ID
               * The zero address indicates there is no approved address.
               * There can only be one approved address per token at a given time.
               * Can only be called by the token owner or an approved operator.
               * @param _to address to be approved for the given token ID
               * @param _tokenId uint256 ID of the token to be approved
               */
              function approve(address _to, uint256 _tokenId) public {
                address owner = ownerOf(_tokenId);
                require(_to != owner);
                require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
                tokenApprovals[_tokenId] = _to;
                emit Approval(owner, _to, _tokenId);
              }
              /**
               * @dev Gets the approved address for a token ID, or zero if no address set
               * @param _tokenId uint256 ID of the token to query the approval of
               * @return address currently approved for the given token ID
               */
              function getApproved(uint256 _tokenId) public view returns (address) {
                return tokenApprovals[_tokenId];
              }
              /**
               * @dev Sets or unsets the approval of a given operator
               * An operator is allowed to transfer all tokens of the sender on their behalf
               * @param _to operator address to set the approval
               * @param _approved representing the status of the approval to be set
               */
              function setApprovalForAll(address _to, bool _approved) public {
                require(_to != msg.sender);
                operatorApprovals[msg.sender][_to] = _approved;
                emit ApprovalForAll(msg.sender, _to, _approved);
              }
              /**
               * @dev Tells whether an operator is approved by a given owner
               * @param _owner owner address which you want to query the approval of
               * @param _operator operator address which you want to query the approval of
               * @return bool whether the given operator is approved by the given owner
               */
              function isApprovedForAll(
                address _owner,
                address _operator
              )
                public
                view
                returns (bool)
              {
                return operatorApprovals[_owner][_operator];
              }
              /**
               * @dev Transfers the ownership of a given token ID to another address
               * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
               * Requires the msg sender to be the owner, approved, or operator
               * @param _from current owner of the token
               * @param _to address to receive the ownership of the given token ID
               * @param _tokenId uint256 ID of the token to be transferred
              */
              function transferFrom(
                address _from,
                address _to,
                uint256 _tokenId
              )
                public
                canTransfer(_tokenId)
              {
                require(_from != address(0));
                require(_to != address(0));
                clearApproval(_from, _tokenId);
                removeTokenFrom(_from, _tokenId);
                addTokenTo(_to, _tokenId);
                emit Transfer(_from, _to, _tokenId);
              }
              /**
               * @dev Safely transfers the ownership of a given token ID to another address
               * If the target address is a contract, it must implement `onERC721Received`,
               * which is called upon a safe transfer, and return the magic value
               * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
               * the transfer is reverted.
               *
               * Requires the msg sender to be the owner, approved, or operator
               * @param _from current owner of the token
               * @param _to address to receive the ownership of the given token ID
               * @param _tokenId uint256 ID of the token to be transferred
              */
              function safeTransferFrom(
                address _from,
                address _to,
                uint256 _tokenId
              )
                public
                canTransfer(_tokenId)
              {
                // solium-disable-next-line arg-overflow
                safeTransferFrom(_from, _to, _tokenId, "");
              }
              /**
               * @dev Safely transfers the ownership of a given token ID to another address
               * If the target address is a contract, it must implement `onERC721Received`,
               * which is called upon a safe transfer, and return the magic value
               * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
               * the transfer is reverted.
               * Requires the msg sender to be the owner, approved, or operator
               * @param _from current owner of the token
               * @param _to address to receive the ownership of the given token ID
               * @param _tokenId uint256 ID of the token to be transferred
               * @param _data bytes data to send along with a safe transfer check
               */
              function safeTransferFrom(
                address _from,
                address _to,
                uint256 _tokenId,
                bytes _data
              )
                public
                canTransfer(_tokenId)
              {
                transferFrom(_from, _to, _tokenId);
                // solium-disable-next-line arg-overflow
                require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
              }
              /**
               * @dev Returns whether the given spender can transfer a given token ID
               * @param _spender address of the spender to query
               * @param _tokenId uint256 ID of the token to be transferred
               * @return bool whether the msg.sender is approved for the given token ID,
               *  is an operator of the owner, or is the owner of the token
               */
              function isApprovedOrOwner(
                address _spender,
                uint256 _tokenId
              )
                internal
                view
                returns (bool)
              {
                address owner = ownerOf(_tokenId);
                // Disable solium check because of
                // https://github.com/duaraghav8/Solium/issues/175
                // solium-disable-next-line operator-whitespace
                return (
                  _spender == owner ||
                  getApproved(_tokenId) == _spender ||
                  isApprovedForAll(owner, _spender)
                );
              }
              /**
               * @dev Internal function to mint a new token
               * Reverts if the given token ID already exists
               * @param _to The address that will own the minted token
               * @param _tokenId uint256 ID of the token to be minted by the msg.sender
               */
              function _mint(address _to, uint256 _tokenId) internal {
                require(_to != address(0));
                addTokenTo(_to, _tokenId);
                emit Transfer(address(0), _to, _tokenId);
              }
              /**
               * @dev Internal function to burn a specific token
               * Reverts if the token does not exist
               * @param _tokenId uint256 ID of the token being burned by the msg.sender
               */
              function _burn(address _owner, uint256 _tokenId) internal {
                clearApproval(_owner, _tokenId);
                removeTokenFrom(_owner, _tokenId);
                emit Transfer(_owner, address(0), _tokenId);
              }
              /**
               * @dev Internal function to clear current approval of a given token ID
               * Reverts if the given address is not indeed the owner of the token
               * @param _owner owner of the token
               * @param _tokenId uint256 ID of the token to be transferred
               */
              function clearApproval(address _owner, uint256 _tokenId) internal {
                require(ownerOf(_tokenId) == _owner);
                if (tokenApprovals[_tokenId] != address(0)) {
                  tokenApprovals[_tokenId] = address(0);
                }
              }
              /**
               * @dev Internal function to add a token ID to the list of a given address
               * @param _to address representing the new owner of the given token ID
               * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
               */
              function addTokenTo(address _to, uint256 _tokenId) internal {
                require(tokenOwner[_tokenId] == address(0));
                tokenOwner[_tokenId] = _to;
                ownedTokensCount[_to] = ownedTokensCount[_to].add(1);
              }
              /**
               * @dev Internal function to remove a token ID from the list of a given address
               * @param _from address representing the previous owner of the given token ID
               * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
               */
              function removeTokenFrom(address _from, uint256 _tokenId) internal {
                require(ownerOf(_tokenId) == _from);
                ownedTokensCount[_from] = ownedTokensCount[_from].sub(1);
                tokenOwner[_tokenId] = address(0);
              }
              /**
               * @dev Internal function to invoke `onERC721Received` on a target address
               * The call is not executed if the target address is not a contract
               * @param _from address representing the previous owner of the given token ID
               * @param _to target address that will receive the tokens
               * @param _tokenId uint256 ID of the token to be transferred
               * @param _data bytes optional data to send along with the call
               * @return whether the call correctly returned the expected magic value
               */
              function checkAndCallSafeTransfer(
                address _from,
                address _to,
                uint256 _tokenId,
                bytes _data
              )
                internal
                returns (bool)
              {
                if (!_to.isContract()) {
                  return true;
                }
                bytes4 retval = ERC721Receiver(_to).onERC721Received(
                  msg.sender, _from, _tokenId, _data);
                return (retval == ERC721_RECEIVED);
              }
            }
            // File: zos-lib/contracts/migrations/Migratable.sol
            /**
             * @title Migratable
             * Helper contract to support intialization and migration schemes between
             * different implementations of a contract in the context of upgradeability.
             * To use it, replace the constructor with a function that has the
             * `isInitializer` modifier starting with `"0"` as `migrationId`.
             * When you want to apply some migration code during an upgrade, increase
             * the `migrationId`. Or, if the migration code must be applied only after
             * another migration has been already applied, use the `isMigration` modifier.
             * This helper supports multiple inheritance.
             * WARNING: It is the developer's responsibility to ensure that migrations are
             * applied in a correct order, or that they are run at all.
             * See `Initializable` for a simpler version.
             */
            contract Migratable {
              /**
               * @dev Emitted when the contract applies a migration.
               * @param contractName Name of the Contract.
               * @param migrationId Identifier of the migration applied.
               */
              event Migrated(string contractName, string migrationId);
              /**
               * @dev Mapping of the already applied migrations.
               * (contractName => (migrationId => bool))
               */
              mapping (string => mapping (string => bool)) internal migrated;
              /**
               * @dev Internal migration id used to specify that a contract has already been initialized.
               */
              string constant private INITIALIZED_ID = "initialized";
              /**
               * @dev Modifier to use in the initialization function of a contract.
               * @param contractName Name of the contract.
               * @param migrationId Identifier of the migration.
               */
              modifier isInitializer(string contractName, string migrationId) {
                validateMigrationIsPending(contractName, INITIALIZED_ID);
                validateMigrationIsPending(contractName, migrationId);
                _;
                emit Migrated(contractName, migrationId);
                migrated[contractName][migrationId] = true;
                migrated[contractName][INITIALIZED_ID] = true;
              }
              /**
               * @dev Modifier to use in the migration of a contract.
               * @param contractName Name of the contract.
               * @param requiredMigrationId Identifier of the previous migration, required
               * to apply new one.
               * @param newMigrationId Identifier of the new migration to be applied.
               */
              modifier isMigration(string contractName, string requiredMigrationId, string newMigrationId) {
                require(isMigrated(contractName, requiredMigrationId), "Prerequisite migration ID has not been run yet");
                validateMigrationIsPending(contractName, newMigrationId);
                _;
                emit Migrated(contractName, newMigrationId);
                migrated[contractName][newMigrationId] = true;
              }
              /**
               * @dev Returns true if the contract migration was applied.
               * @param contractName Name of the contract.
               * @param migrationId Identifier of the migration.
               * @return true if the contract migration was applied, false otherwise.
               */
              function isMigrated(string contractName, string migrationId) public view returns(bool) {
                return migrated[contractName][migrationId];
              }
              /**
               * @dev Initializer that marks the contract as initialized.
               * It is important to run this if you had deployed a previous version of a Migratable contract.
               * For more information see https://github.com/zeppelinos/zos-lib/issues/158.
               */
              function initialize() isInitializer("Migratable", "1.2.1") public {
              }
              /**
               * @dev Reverts if the requested migration was already executed.
               * @param contractName Name of the contract.
               * @param migrationId Identifier of the migration.
               */
              function validateMigrationIsPending(string contractName, string migrationId) private view {
                require(!isMigrated(contractName, migrationId), "Requested target migration ID has already been run");
              }
            }
            // File: openzeppelin-zos/contracts/token/ERC721/ERC721Token.sol
            /**
             * @title Full ERC721 Token
             * This implementation includes all the required and some optional functionality of the ERC721 standard
             * Moreover, it includes approve all functionality using operator terminology
             * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
             */
            contract ERC721Token is Migratable, ERC165Support, ERC721BasicToken, ERC721 {
              bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63;
              /**
               * 0x780e9d63 ===
               *   bytes4(keccak256('totalSupply()')) ^
               *   bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
               *   bytes4(keccak256('tokenByIndex(uint256)'))
               */
              bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f;
              /**
               * 0x5b5e139f ===
               *   bytes4(keccak256('name()')) ^
               *   bytes4(keccak256('symbol()')) ^
               *   bytes4(keccak256('tokenURI(uint256)'))
               */
              // Token name
              string internal name_;
              // Token symbol
              string internal symbol_;
              // Mapping from owner to list of owned token IDs
              mapping(address => uint256[]) internal ownedTokens;
              // Mapping from token ID to index of the owner tokens list
              mapping(uint256 => uint256) internal ownedTokensIndex;
              // Array with all token ids, used for enumeration
              uint256[] internal allTokens;
              // Mapping from token id to position in the allTokens array
              mapping(uint256 => uint256) internal allTokensIndex;
              // Optional mapping for token URIs
              mapping(uint256 => string) internal tokenURIs;
              /**
               * @dev Constructor function
               */
              function initialize(string _name, string _symbol) public isInitializer("ERC721Token", "1.9.0") {
                name_ = _name;
                symbol_ = _symbol;
              }
              function _supportsInterface(bytes4 _interfaceId)
                internal
                view
                returns (bool)
              {
                return super._supportsInterface(_interfaceId) || 
                  _interfaceId == InterfaceId_ERC721Enumerable || _interfaceId == InterfaceId_ERC721Metadata;
              }
              /**
               * @dev Gets the token name
               * @return string representing the token name
               */
              function name() external view returns (string) {
                return name_;
              }
              /**
               * @dev Gets the token symbol
               * @return string representing the token symbol
               */
              function symbol() external view returns (string) {
                return symbol_;
              }
              /**
               * @dev Returns an URI for a given token ID
               * Throws if the token ID does not exist. May return an empty string.
               * @param _tokenId uint256 ID of the token to query
               */
              function tokenURI(uint256 _tokenId) public view returns (string) {
                require(exists(_tokenId));
                return tokenURIs[_tokenId];
              }
              /**
               * @dev Gets the token ID at a given index of the tokens list of the requested owner
               * @param _owner address owning the tokens list to be accessed
               * @param _index uint256 representing the index to be accessed of the requested tokens list
               * @return uint256 token ID at the given index of the tokens list owned by the requested address
               */
              function tokenOfOwnerByIndex(
                address _owner,
                uint256 _index
              )
                public
                view
                returns (uint256)
              {
                require(_index < balanceOf(_owner));
                return ownedTokens[_owner][_index];
              }
              /**
               * @dev Gets the total amount of tokens stored by the contract
               * @return uint256 representing the total amount of tokens
               */
              function totalSupply() public view returns (uint256) {
                return allTokens.length;
              }
              /**
               * @dev Gets the token ID at a given index of all the tokens in this contract
               * Reverts if the index is greater or equal to the total number of tokens
               * @param _index uint256 representing the index to be accessed of the tokens list
               * @return uint256 token ID at the given index of the tokens list
               */
              function tokenByIndex(uint256 _index) public view returns (uint256) {
                require(_index < totalSupply());
                return allTokens[_index];
              }
              /**
               * @dev Internal function to set the token URI for a given token
               * Reverts if the token ID does not exist
               * @param _tokenId uint256 ID of the token to set its URI
               * @param _uri string URI to assign
               */
              function _setTokenURI(uint256 _tokenId, string _uri) internal {
                require(exists(_tokenId));
                tokenURIs[_tokenId] = _uri;
              }
              /**
               * @dev Internal function to add a token ID to the list of a given address
               * @param _to address representing the new owner of the given token ID
               * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
               */
              function addTokenTo(address _to, uint256 _tokenId) internal {
                super.addTokenTo(_to, _tokenId);
                uint256 length = ownedTokens[_to].length;
                ownedTokens[_to].push(_tokenId);
                ownedTokensIndex[_tokenId] = length;
              }
              /**
               * @dev Internal function to remove a token ID from the list of a given address
               * @param _from address representing the previous owner of the given token ID
               * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
               */
              function removeTokenFrom(address _from, uint256 _tokenId) internal {
                super.removeTokenFrom(_from, _tokenId);
                uint256 tokenIndex = ownedTokensIndex[_tokenId];
                uint256 lastTokenIndex = ownedTokens[_from].length.sub(1);
                uint256 lastToken = ownedTokens[_from][lastTokenIndex];
                ownedTokens[_from][tokenIndex] = lastToken;
                ownedTokens[_from][lastTokenIndex] = 0;
                // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to
                // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping
                // the lastToken to the first position, and then dropping the element placed in the last position of the list
                ownedTokens[_from].length--;
                ownedTokensIndex[_tokenId] = 0;
                ownedTokensIndex[lastToken] = tokenIndex;
              }
              /**
               * @dev Internal function to mint a new token
               * Reverts if the given token ID already exists
               * @param _to address the beneficiary that will own the minted token
               * @param _tokenId uint256 ID of the token to be minted by the msg.sender
               */
              function _mint(address _to, uint256 _tokenId) internal {
                super._mint(_to, _tokenId);
                allTokensIndex[_tokenId] = allTokens.length;
                allTokens.push(_tokenId);
              }
              /**
               * @dev Internal function to burn a specific token
               * Reverts if the token does not exist
               * @param _owner owner of the token to burn
               * @param _tokenId uint256 ID of the token being burned by the msg.sender
               */
              function _burn(address _owner, uint256 _tokenId) internal {
                super._burn(_owner, _tokenId);
                // Clear metadata (if any)
                if (bytes(tokenURIs[_tokenId]).length != 0) {
                  delete tokenURIs[_tokenId];
                }
                // Reorg all tokens array
                uint256 tokenIndex = allTokensIndex[_tokenId];
                uint256 lastTokenIndex = allTokens.length.sub(1);
                uint256 lastToken = allTokens[lastTokenIndex];
                allTokens[tokenIndex] = lastToken;
                allTokens[lastTokenIndex] = 0;
                allTokens.length--;
                allTokensIndex[_tokenId] = 0;
                allTokensIndex[lastToken] = tokenIndex;
              }
            }
            // File: openzeppelin-zos/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 is Migratable {
              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 initialize(address _sender) public isInitializer("Ownable", "1.9.0") {
                owner = _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));
                emit OwnershipTransferred(owner, newOwner);
                owner = newOwner;
              }
            }
            // File: contracts/estate/IEstateRegistry.sol
            contract IEstateRegistry {
              function mint(address to, string metadata) external returns (uint256);
              function ownerOf(uint256 _tokenId) public view returns (address _owner); // from ERC721
              // Events
              event CreateEstate(
                address indexed _owner,
                uint256 indexed _estateId,
                string _data
              );
              event AddLand(
                uint256 indexed _estateId,
                uint256 indexed _landId
              );
              event RemoveLand(
                uint256 indexed _estateId,
                uint256 indexed _landId,
                address indexed _destinatary
              );
              event Update(
                uint256 indexed _assetId,
                address indexed _holder,
                address indexed _operator,
                string _data
              );
              event UpdateOperator(
                uint256 indexed _estateId,
                address indexed _operator
              );
              event UpdateManager(
                address indexed _owner,
                address indexed _operator,
                address indexed _caller,
                bool _approved
              );
              event SetLANDRegistry(
                address indexed _registry
              );
              event SetEstateLandBalanceToken(
                address indexed _previousEstateLandBalance,
                address indexed _newEstateLandBalance
              );
            }
            // File: contracts/minimeToken/IMinimeToken.sol
            interface IMiniMeToken {
            ////////////////
            // Generate and destroy tokens
            ////////////////
                /// @notice Generates `_amount` tokens that are assigned to `_owner`
                /// @param _owner The address that will be assigned the new tokens
                /// @param _amount The quantity of tokens generated
                /// @return True if the tokens are generated correctly
                function generateTokens(address _owner, uint _amount) external returns (bool);
                /// @notice Burns `_amount` tokens from `_owner`
                /// @param _owner The address that will lose the tokens
                /// @param _amount The quantity of tokens to burn
                /// @return True if the tokens are burned correctly
                function destroyTokens(address _owner, uint _amount) external returns (bool);
                /// @param _owner The address that's balance is being requested
                /// @return The balance of `_owner` at the current block
                function balanceOf(address _owner) external view returns (uint256 balance);
                event Transfer(address indexed _from, address indexed _to, uint256 _amount);
            }
            // File: contracts/estate/EstateStorage.sol
            contract LANDRegistry {
              function decodeTokenId(uint value) external pure returns (int, int);
              function updateLandData(int x, int y, string data) external;
              function setUpdateOperator(uint256 assetId, address operator) external;
              function setManyUpdateOperator(uint256[] landIds, address operator) external;
              function ping() public;
              function ownerOf(uint256 tokenId) public returns (address);
              function safeTransferFrom(address, address, uint256) public;
              function updateOperator(uint256 landId) public returns (address);
            }
            contract EstateStorage {
              bytes4 internal constant InterfaceId_GetMetadata = bytes4(keccak256("getMetadata(uint256)"));
              bytes4 internal constant InterfaceId_VerifyFingerprint = bytes4(
                keccak256("verifyFingerprint(uint256,bytes)")
              );
              LANDRegistry public registry;
              // From Estate to list of owned LAND ids (LANDs)
              mapping(uint256 => uint256[]) public estateLandIds;
              // From LAND id (LAND) to its owner Estate id
              mapping(uint256 => uint256) public landIdEstate;
              // From Estate id to mapping of LAND id to index on the array above (estateLandIds)
              mapping(uint256 => mapping(uint256 => uint256)) public estateLandIndex;
              // Metadata of the Estate
              mapping(uint256 => string) internal estateData;
              // Operator of the Estate
              mapping (uint256 => address) public updateOperator;
              // From account to mapping of operator to bool whether is allowed to update content or not
              mapping(address => mapping(address => bool)) public updateManager;
              // Land balance minime token
              IMiniMeToken public estateLandBalance;
              // Registered balance accounts
              mapping(address => bool) public registeredBalance;
            }
            // File: contracts/estate/EstateRegistry.sol
            /**
             * @title ERC721 registry of every minted Estate and their owned LANDs
             * @dev Usings we are inheriting and depending on:
             * From ERC721Token:
             *   - using SafeMath for uint256;
             *   - using AddressUtils for address;
             */
            // solium-disable-next-line max-len
            contract EstateRegistry is Migratable, IEstateRegistry, ERC721Token, ERC721Receiver, Ownable, EstateStorage {
              modifier canTransfer(uint256 estateId) {
                require(isApprovedOrOwner(msg.sender, estateId), "Only owner or operator can transfer");
                _;
              }
              modifier onlyRegistry() {
                require(msg.sender == address(registry), "Only the registry can make this operation");
                _;
              }
              modifier onlyUpdateAuthorized(uint256 estateId) {
                require(_isUpdateAuthorized(msg.sender, estateId), "Unauthorized user");
                _;
              }
              modifier onlyLandUpdateAuthorized(uint256 estateId, uint256 landId) {
                require(_isLandUpdateAuthorized(msg.sender, estateId, landId), "unauthorized user");
                _;
              }
              modifier canSetUpdateOperator(uint256 estateId) {
                address owner = ownerOf(estateId);
                require(
                  isApprovedOrOwner(msg.sender, estateId) || updateManager[owner][msg.sender],
                  "unauthorized user"
                );
                _;
              }
              /**
               * @dev Mint a new Estate with some metadata
               * @param to The address that will own the minted token
               * @param metadata Set an initial metadata
               * @return An uint256 representing the new token id
               */
              function mint(address to, string metadata) external onlyRegistry returns (uint256) {
                return _mintEstate(to, metadata);
              }
              /**
               * @notice Transfer a LAND owned by an Estate to a new owner
               * @param estateId Current owner of the token
               * @param landId LAND to be transfered
               * @param destinatary New owner
               */
              function transferLand(
                uint256 estateId,
                uint256 landId,
                address destinatary
              )
                external
                canTransfer(estateId)
              {
                return _transferLand(estateId, landId, destinatary);
              }
              /**
               * @notice Transfer many tokens owned by an Estate to a new owner
               * @param estateId Current owner of the token
               * @param landIds LANDs to be transfered
               * @param destinatary New owner
               */
              function transferManyLands(
                uint256 estateId,
                uint256[] landIds,
                address destinatary
              )
                external
                canTransfer(estateId)
              {
                uint length = landIds.length;
                for (uint i = 0; i < length; i++) {
                  _transferLand(estateId, landIds[i], destinatary);
                }
              }
              /**
               * @notice Get the Estate id for a given LAND id
               * @dev This information also lives on estateLandIds,
               *   but it being a mapping you need to know the Estate id beforehand.
               * @param landId LAND to search
               * @return The corresponding Estate id
               */
              function getLandEstateId(uint256 landId) external view returns (uint256) {
                return landIdEstate[landId];
              }
              function setLANDRegistry(address _registry) external onlyOwner {
                require(_registry.isContract(), "The LAND registry address should be a contract");
                require(_registry != 0, "The LAND registry address should be valid");
                registry = LANDRegistry(_registry);
                emit SetLANDRegistry(registry);
              }
              function ping() external {
                registry.ping();
              }
              /**
               * @notice Return the amount of tokens for a given Estate
               * @param estateId Estate id to search
               * @return Tokens length
               */
              function getEstateSize(uint256 estateId) external view returns (uint256) {
                return estateLandIds[estateId].length;
              }
              /**
               * @notice Return the amount of LANDs inside the Estates for a given address
               * @param _owner of the estates
               * @return the amount of LANDs
               */
              function getLANDsSize(address _owner) public view returns (uint256) {
                // Avoid balanceOf to not compute an unnecesary require
                uint256 landsSize;
                uint256 balance = ownedTokensCount[_owner];
                for (uint256 i; i < balance; i++) {
                  uint256 estateId = ownedTokens[_owner][i];
                  landsSize += estateLandIds[estateId].length;
                }
                return landsSize;
              }
              /**
               * @notice Update the metadata of an Estate
               * @dev Reverts if the Estate does not exist or the user is not authorized
               * @param estateId Estate id to update
               * @param metadata string metadata
               */
              function updateMetadata(
                uint256 estateId,
                string metadata
              )
                external
                onlyUpdateAuthorized(estateId)
              {
                _updateMetadata(estateId, metadata);
                emit Update(
                  estateId,
                  ownerOf(estateId),
                  msg.sender,
                  metadata
                );
              }
              function getMetadata(uint256 estateId) external view returns (string) {
                return estateData[estateId];
              }
              function isUpdateAuthorized(address operator, uint256 estateId) external view returns (bool) {
                return _isUpdateAuthorized(operator, estateId);
              }
              /**
              * @dev Set an updateManager for an account
              * @param _owner - address of the account to set the updateManager
              * @param _operator - address of the account to be set as the updateManager
              * @param _approved - bool whether the address will be approved or not
              */
              function setUpdateManager(address _owner, address _operator, bool _approved) external {
                require(_operator != msg.sender, "The operator should be different from owner");
                require(
                  _owner == msg.sender
                  || operatorApprovals[_owner][msg.sender],
                  "Unauthorized user"
                );
                updateManager[_owner][_operator] = _approved;
                emit UpdateManager(
                  _owner,
                  _operator,
                  msg.sender,
                  _approved
                );
              }
              /**
               * @notice Set Estate updateOperator
               * @param estateId - Estate id
               * @param operator - address of the account to be set as the updateOperator
               */
              function setUpdateOperator(
                uint256 estateId,
                address operator
              )
                public
                canSetUpdateOperator(estateId)
              {
                updateOperator[estateId] = operator;
                emit UpdateOperator(estateId, operator);
              }
              /**
               * @notice Set Estates updateOperator
               * @param _estateIds - Estate ids
               * @param _operator - address of the account to be set as the updateOperator
               */
              function setManyUpdateOperator(
                uint256[] _estateIds,
                address _operator
              )
                public
              {
                for (uint i = 0; i < _estateIds.length; i++) {
                  setUpdateOperator(_estateIds[i], _operator);
                }
              }
              /**
               * @notice Set LAND updateOperator
               * @param estateId - Estate id
               * @param landId - LAND to set the updateOperator
               * @param operator - address of the account to be set as the updateOperator
               */
              function setLandUpdateOperator(
                uint256 estateId,
                uint256 landId,
                address operator
              )
                public
                canSetUpdateOperator(estateId)
              {
                require(landIdEstate[landId] == estateId, "The LAND is not part of the Estate");
                registry.setUpdateOperator(landId, operator);
              }
             /**
               * @notice Set many LAND updateOperator
               * @param _estateId - Estate id
               * @param _landIds - LANDs to set the updateOperator
               * @param _operator - address of the account to be set as the updateOperator
               */
              function setManyLandUpdateOperator(
                uint256 _estateId,
                uint256[] _landIds,
                address _operator
              )
                public
                canSetUpdateOperator(_estateId)
              {
                for (uint i = 0; i < _landIds.length; i++) {
                  require(landIdEstate[_landIds[i]] == _estateId, "The LAND is not part of the Estate");
                }
                registry.setManyUpdateOperator(_landIds, _operator);
              }
              function initialize(
                string _name,
                string _symbol,
                address _registry
              )
                public
                isInitializer("EstateRegistry", "0.0.2")
              {
                require(_registry != 0, "The registry should be a valid address");
                ERC721Token.initialize(_name, _symbol);
                Ownable.initialize(msg.sender);
                registry = LANDRegistry(_registry);
              }
              /**
               * @notice Handle the receipt of an NFT
               * @dev The ERC721 smart contract calls this function on the recipient
               * after a `safetransfer`. This function MAY throw to revert and reject the
               * transfer. Return of other than the magic value MUST result in the
               * transaction being reverted.
               * Note: the contract address is always the message sender.
               * @param _operator The address which called `safeTransferFrom` function
               * @param _from The address which previously owned the token
               * @param _tokenId The NFT identifier which is being transferred
               * @param _data Additional data with no specified format
               * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
               */
              function onERC721Received(
                address _operator,
                address _from,
                uint256 _tokenId,
                bytes _data
              )
                public
                onlyRegistry
                returns (bytes4)
              {
                uint256 estateId = _bytesToUint(_data);
                _pushLandId(estateId, _tokenId);
                return ERC721_RECEIVED;
              }
              /**
               * @dev Creates a checksum of the contents of the Estate
               * @param estateId the estateId to be verified
               */
              function getFingerprint(uint256 estateId)
                public
                view
                returns (bytes32 result)
              {
                result = keccak256(abi.encodePacked("estateId", estateId));
                uint256 length = estateLandIds[estateId].length;
                for (uint i = 0; i < length; i++) {
                  result ^= keccak256(abi.encodePacked(estateLandIds[estateId][i]));
                }
                return result;
              }
              /**
               * @dev Verifies a checksum of the contents of the Estate
               * @param estateId the estateid to be verified
               * @param fingerprint the user provided identification of the Estate contents
               */
              function verifyFingerprint(uint256 estateId, bytes fingerprint) public view returns (bool) {
                return getFingerprint(estateId) == _bytesToBytes32(fingerprint);
              }
              /**
               * @dev Safely transfers the ownership of multiple Estate IDs to another address
               * @dev Delegates to safeTransferFrom for each transfer
               * @dev Requires the msg sender to be the owner, approved, or operator
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param estateIds uint256 array of IDs to be transferred
              */
              function safeTransferManyFrom(address from, address to, uint256[] estateIds) public {
                safeTransferManyFrom(
                  from,
                  to,
                  estateIds,
                  ""
                );
              }
              /**
               * @dev Safely transfers the ownership of multiple Estate IDs to another address
               * @dev Delegates to safeTransferFrom for each transfer
               * @dev Requires the msg sender to be the owner, approved, or operator
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param estateIds uint256 array of IDs to be transferred
               * @param data bytes data to send along with a safe transfer check
              */
              function safeTransferManyFrom(
                address from,
                address to,
                uint256[] estateIds,
                bytes data
              )
                public
              {
                for (uint i = 0; i < estateIds.length; i++) {
                  safeTransferFrom(
                    from,
                    to,
                    estateIds[i],
                    data
                  );
                }
              }
              /**
               * @dev update LAND data owned by an Estate
               * @param estateId Estate
               * @param landId LAND to be updated
               * @param data string metadata
               */
              function updateLandData(uint256 estateId, uint256 landId, string data) public {
                _updateLandData(estateId, landId, data);
              }
              /**
               * @dev update LANDs data owned by an Estate
               * @param estateId Estate id
               * @param landIds LANDs to be updated
               * @param data string metadata
               */
              function updateManyLandData(uint256 estateId, uint256[] landIds, string data) public {
                uint length = landIds.length;
                for (uint i = 0; i < length; i++) {
                  _updateLandData(estateId, landIds[i], data);
                }
              }
              function transferFrom(address _from, address _to, uint256 _tokenId)
              public
              {
                uint256 estateSize = estateLandIds[_tokenId].length;
                require(estateSize != 0, "The Estate should not be empty");
                updateOperator[_tokenId] = address(0);
                _updateEstateLandBalance(_from, _to, estateSize);
                super.transferFrom(_from, _to, _tokenId);
              }
              // check the supported interfaces via ERC165
              function _supportsInterface(bytes4 _interfaceId) internal view returns (bool) {
                // solium-disable-next-line operator-whitespace
                return super._supportsInterface(_interfaceId)
                  || _interfaceId == InterfaceId_GetMetadata
                  || _interfaceId == InterfaceId_VerifyFingerprint;
              }
              /**
               * @dev Internal function to mint a new Estate with some metadata
               * @param to The address that will own the minted token
               * @param metadata Set an initial metadata
               * @return An uint256 representing the new token id
               */
              function _mintEstate(address to, string metadata) internal returns (uint256) {
                require(to != address(0), "You can not mint to an empty address");
                uint256 estateId = _getNewEstateId();
                _mint(to, estateId);
                _updateMetadata(estateId, metadata);
                emit CreateEstate(to, estateId, metadata);
                return estateId;
              }
              /**
               * @dev Internal function to update an Estate metadata
               * @dev Does not require the Estate to exist, for a public interface use `updateMetadata`
               * @param estateId Estate id to update
               * @param metadata string metadata
               */
              function _updateMetadata(uint256 estateId, string metadata) internal {
                estateData[estateId] = metadata;
              }
              /**
               * @notice Return a new unique id
               * @dev It uses totalSupply to determine the next id
               * @return uint256 Representing the new Estate id
               */
              function _getNewEstateId() internal view returns (uint256) {
                return totalSupply().add(1);
              }
              /**
               * @dev Appends a new LAND id to an Estate updating all related storage
               * @param estateId Estate where the LAND should go
               * @param landId Transfered LAND
               */
              function _pushLandId(uint256 estateId, uint256 landId) internal {
                require(exists(estateId), "The Estate id should exist");
                require(landIdEstate[landId] == 0, "The LAND is already owned by an Estate");
                require(registry.ownerOf(landId) == address(this), "The EstateRegistry cannot manage the LAND");
                estateLandIds[estateId].push(landId);
                landIdEstate[landId] = estateId;
                estateLandIndex[estateId][landId] = estateLandIds[estateId].length;
                address owner = ownerOf(estateId);
                _updateEstateLandBalance(address(registry), owner, 1);
                emit AddLand(estateId, landId);
              }
              /**
               * @dev Removes a LAND from an Estate and transfers it to a new owner
               * @param estateId Current owner of the LAND
               * @param landId LAND to be transfered
               * @param destinatary New owner
               */
              function _transferLand(
                uint256 estateId,
                uint256 landId,
                address destinatary
              )
                internal
              {
                require(destinatary != address(0), "You can not transfer LAND to an empty address");
                uint256[] storage landIds = estateLandIds[estateId];
                mapping(uint256 => uint256) landIndex = estateLandIndex[estateId];
                /**
                 * Using 1-based indexing to be able to make this check
                 */
                require(landIndex[landId] != 0, "The LAND is not part of the Estate");
                uint lastIndexInArray = landIds.length.sub(1);
                /**
                 * Get the landIndex of this token in the landIds list
                 */
                uint indexInArray = landIndex[landId].sub(1);
                /**
                 * Get the landId at the end of the landIds list
                 */
                uint tempTokenId = landIds[lastIndexInArray];
                /**
                 * Store the last token in the position previously occupied by landId
                 */
                landIndex[tempTokenId] = indexInArray.add(1);
                landIds[indexInArray] = tempTokenId;
                /**
                 * Delete the landIds[last element]
                 */
                delete landIds[lastIndexInArray];
                landIds.length = lastIndexInArray;
                /**
                 * Drop this landId from both the landIndex and landId list
                 */
                landIndex[landId] = 0;
                /**
                 * Drop this landId Estate
                 */
                landIdEstate[landId] = 0;
                address owner = ownerOf(estateId);
                _updateEstateLandBalance(owner, address(registry), 1);
                registry.safeTransferFrom(this, destinatary, landId);
                emit RemoveLand(estateId, landId, destinatary);
              }
              function _isUpdateAuthorized(address operator, uint256 estateId) internal view returns (bool) {
                address owner = ownerOf(estateId);
                return isApprovedOrOwner(operator, estateId)
                  || updateOperator[estateId] == operator
                  || updateManager[owner][operator];
              }
              function _isLandUpdateAuthorized(
                address operator,
                uint256 estateId,
                uint256 landId
              )
                internal returns (bool)
              {
                return _isUpdateAuthorized(operator, estateId) || registry.updateOperator(landId) == operator;
              }
              function _bytesToUint(bytes b) internal pure returns (uint256) {
                return uint256(_bytesToBytes32(b));
              }
              function _bytesToBytes32(bytes b) internal pure returns (bytes32) {
                bytes32 out;
                for (uint i = 0; i < b.length; i++) {
                  out |= bytes32(b[i] & 0xFF) >> i.mul(8);
                }
                return out;
              }
              function _updateLandData(
                uint256 estateId,
                uint256 landId,
                string data
              )
                internal
                onlyLandUpdateAuthorized(estateId, landId)
              {
                require(landIdEstate[landId] == estateId, "The LAND is not part of the Estate");
                int x;
                int y;
                (x, y) = registry.decodeTokenId(landId);
                registry.updateLandData(x, y, data);
              }
              /**
               * @dev Set a new estate land balance minime token
               * @param _newEstateLandBalance address of the new estate land balance token
               */
              function _setEstateLandBalanceToken(address _newEstateLandBalance) internal {
                require(_newEstateLandBalance != address(0), "New estateLandBalance should not be zero address");
                emit SetEstateLandBalanceToken(estateLandBalance, _newEstateLandBalance);
                estateLandBalance = IMiniMeToken(_newEstateLandBalance);
              }
               /**
               * @dev Register an account balance
               * @notice Register land Balance
               */
              function registerBalance() external {
                require(!registeredBalance[msg.sender], "Register Balance::The user is already registered");
                // Get balance of the sender
                uint256 currentBalance = estateLandBalance.balanceOf(msg.sender);
                if (currentBalance > 0) {
                  require(
                    estateLandBalance.destroyTokens(msg.sender, currentBalance),
                    "Register Balance::Could not destroy tokens"
                  );
                }
                // Set balance as registered
                registeredBalance[msg.sender] = true;
                // Get LAND balance
                uint256 newBalance = getLANDsSize(msg.sender);
                // Generate Tokens
                require(
                  estateLandBalance.generateTokens(msg.sender, newBalance),
                  "Register Balance::Could not generate tokens"
                );
              }
              /**
               * @dev Unregister an account balance
               * @notice Unregister land Balance
               */
              function unregisterBalance() external {
                require(registeredBalance[msg.sender], "Unregister Balance::The user not registered");
                // Set balance as unregistered
                registeredBalance[msg.sender] = false;
                // Get balance
                uint256 currentBalance = estateLandBalance.balanceOf(msg.sender);
                // Destroy Tokens
                require(
                  estateLandBalance.destroyTokens(msg.sender, currentBalance),
                  "Unregister Balance::Could not destroy tokens"
                );
              }
              /**
               * @dev Update account balances
               * @param _from account
               * @param _to account
               * @param _amount to update
               */
              function _updateEstateLandBalance(address _from, address _to, uint256 _amount) internal {
                if (registeredBalance[_from]) {
                  estateLandBalance.destroyTokens(_from, _amount);
                }
                if (registeredBalance[_to]) {
                  estateLandBalance.generateTokens(_to, _amount);
                }
              }
              /**
               * @dev Set a estate land balance minime token hardcoded because of the
               * contraint of the proxy for using an owner
               * Mainnet: 0x8568f23f343694650370fe5e254b55bfb704a6c7
               */
              function setEstateLandBalanceToken() external {
                require(estateLandBalance == address(0), "estateLandBalance was set");
                _setEstateLandBalanceToken(address(0x8568f23f343694650370fe5e254b55bfb704a6c7));
              }
            }