ETH Price: $2,447.80 (+0.72%)

Transaction Decoder

Block:
9779690 at Mar-31-2020 01:08:24 PM +UTC
Transaction Fee:
0.0008751438 ETH $2.14
Gas Used:
102,356 Gas / 8.55 Gwei

Emitted Events:

137 MultiSigWalletWithDailyLimit.Deposit( sender=[Receiver] LandSaleWithReferral, value=291508596151656609 )
138 Land.Transfer( _from=0x00000000...000000000, _to=[Sender] 0xddd3964d75d59b6b6d5c31eb313bba5ebf076364, _tokenId=76253 )
139 LandSaleWithReferral.LandQuadPurchased( buyer=[Sender] 0xddd3964d75d59b6b6d5c31eb313bba5ebf076364, to=[Sender] 0xddd3964d75d59b6b6d5c31eb313bba5ebf076364, topCornerId=76253, size=1, price=2667000000000000000000, token=0x00000000...000000000, amountPaid=291508596151656609 )

Account State Difference:

  Address   Before After State Difference Code
0x50f54747...809Fd6d4a
(Spark Pool)
25.500146542790334555 Eth25.501021686590334555 Eth0.0008751438
0x9695ed50...cBc8FF60b 2,322.398044287937852763 Eth2,322.689552884089509372 Eth0.291508596151656609
0xDDd3964D...EBF076364
112.31140146442634714 Eth
Nonce: 5689
112.019017724474690531 Eth
Nonce: 5690
0.292383739951656609

Execution Trace

ETH 0.297338768074689741 LandSaleWithReferral.buyLandWithETH( )
  • Medianizer.STATICCALL( )
  • ETH 0.005830171923033132 0xddd3964d75d59b6b6d5c31eb313bba5ebf076364.CALL( )
  • ETH 0.291508596151656609 MultiSigWalletWithDailyLimit.CALL( )
  • Land.mintQuad( to=0xDDd3964D75D59B6B6d5c31eB313BBA5EBF076364, size=1, x=365, y=186, data=0x000000000000000000000000DDD3964D75D59B6B6D5C31EB313BBA5EBF07636400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000 )
    File 1 of 4: LandSaleWithReferral
    pragma solidity ^0.5.2;
    contract Admin {
        address internal _admin;
        event AdminChanged(address oldAdmin, address newAdmin);
        /// @notice gives the current administrator of this contract.
        /// @return the current administrator of this contract.
        function getAdmin() external view returns (address) {
            return _admin;
        }
        /// @notice change the administrator to be `newAdmin`.
        /// @param newAdmin address of the new administrator.
        function changeAdmin(address newAdmin) external {
            require(msg.sender == _admin, "only admin can change admin");
            emit AdminChanged(_admin, newAdmin);
            _admin = newAdmin;
        }
        modifier onlyAdmin() {
            require (msg.sender == _admin, "only admin allowed");
            _;
        }
    }
    pragma solidity ^0.5.2;
    import "./Admin.sol";
    contract MetaTransactionReceiver is Admin{
        mapping(address => bool) internal _metaTransactionContracts;
        event MetaTransactionProcessor(address metaTransactionProcessor, bool enabled);
        /// @notice Enable or disable the ability of `metaTransactionProcessor` to perform meta-tx (metaTransactionProcessor rights).
        /// @param metaTransactionProcessor address that will be given/removed metaTransactionProcessor rights.
        /// @param enabled set whether the metaTransactionProcessor is enabled or disabled.
        function setMetaTransactionProcessor(address metaTransactionProcessor, bool enabled) public {
            require(
                msg.sender == _admin,
                "only admin can setup metaTransactionProcessors"
            );
            _setMetaTransactionProcessor(metaTransactionProcessor, enabled);
        }
        function _setMetaTransactionProcessor(address metaTransactionProcessor, bool enabled) internal {
            _metaTransactionContracts[metaTransactionProcessor] = enabled;
            emit MetaTransactionProcessor(metaTransactionProcessor, enabled);
        }
        /// @notice check whether address `who` is given meta-transaction execution rights.
        /// @param who The address to query.
        /// @return whether the address has meta-transaction execution rights.
        function isMetaTransactionProcessor(address who) external view returns(bool) {
            return _metaTransactionContracts[who];
        }
    }pragma solidity ^0.5.2;
    import "./Admin.sol";
    contract SuperOperators is Admin {
        mapping(address => bool) internal _superOperators;
        event SuperOperator(address superOperator, bool enabled);
        /// @notice Enable or disable the ability of `superOperator` to transfer tokens of all (superOperator rights).
        /// @param superOperator address that will be given/removed superOperator right.
        /// @param enabled set whether the superOperator is enabled or disabled.
        function setSuperOperator(address superOperator, bool enabled) external {
            require(
                msg.sender == _admin,
                "only admin is allowed to add super operators"
            );
            _superOperators[superOperator] = enabled;
            emit SuperOperator(superOperator, enabled);
        }
        /// @notice check whether address `who` is given superOperator rights.
        /// @param who The address to query.
        /// @return whether the address has superOperator rights.
        function isSuperOperator(address who) public view returns (bool) {
            return _superOperators[who];
        }
    }
    pragma solidity ^0.5.2;
    import "./ERC20Basic.sol";
    /**
     * @title ERC20 interface
     * @dev see https://eips.ethereum.org/EIPS/eip-20
     */
    /* interface */
    contract ERC20 is ERC20Basic {
        function transferFrom(address from, address to, uint256 value)
            public
            returns (bool);
        function approve(address spender, uint256 value) public returns (bool);
        function allowance(address owner, address spender)
            public
            view
            returns (uint256);
        event Approval(
            address indexed owner,
            address indexed spender,
            uint256 value
        );
    }
    pragma solidity ^0.5.2;
    /**
     * @title ERC20Basic DRAFT
     * @dev Simpler version of ERC20 interface
     * See https://github.com/ethereum/EIPs/issues/179
     */
    /* interface */
    contract ERC20Basic {
        function totalSupply() public view returns (uint256);
        function balanceOf(address who) public view returns (uint256);
        function transfer(address to, uint256 value) public returns (bool);
        event Transfer(address indexed from, address indexed to, uint256 value);
    }
    pragma solidity ^0.5.2;
    /**
     * @title ERC721 Non-Fungible Token Standard basic interface
     * @dev see https://eips.ethereum.org/EIPS/eip-721
     */
    interface ERC721Events {
        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
        );
    }
    pragma solidity ^0.5.2;
    /**
        Note: The ERC-165 identifier for this interface is 0x5e8bf644.
    */
    interface ERC721MandatoryTokenReceiver {
        function onERC721BatchReceived(
            address operator,
            address from,
            uint256[] calldata ids,
            bytes calldata data
        ) external returns (bytes4); // needs to return 0x4b808c46
        function onERC721Received(
            address operator,
            address from,
            uint256 tokenId,
            bytes calldata data
        ) external returns (bytes4); // needs to return 0x150b7a02
        // needs to implements EIP-165
        // function supportsInterface(bytes4 interfaceId)
        //     external
        //     view
        //     returns (bool);
    }
    /* This Source Code Form is subject to the terms of the Mozilla Public
     * License, v. 2.0. If a copy of the MPL was not distributed with this
     * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     *
     * This code has not been reviewed.
     * Do not use or deploy this code before reviewing it personally first.
     */
    // solhint-disable-next-line compiler-fixed
    pragma solidity ^0.5.2;
    interface ERC721TokenReceiver {
        function onERC721Received(
            address operator,
            address from,
            uint256 tokenId,
            bytes calldata data
        ) external returns (bytes4);
    }
    pragma solidity ^0.5.2;
    /**
     * @title Medianizer contract
     * @dev From MakerDAO (https://etherscan.io/address/0x729D19f657BD0614b4985Cf1D82531c67569197B#code)
     */
    interface Medianizer {
        function read() external view returns (bytes32);
    }
    pragma solidity ^0.5.2;
    library AddressUtils {
        function toPayable(address _address) internal pure returns (address payable _payable) {
            return address(uint160(_address));
        }
        function isContract(address addr) internal view returns (bool) {
            // for accounts without code, i.e. `keccak256('')`:
            bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
            bytes32 codehash;
            // solium-disable-next-line security/no-inline-assembly
            assembly {
                codehash := extcodehash(addr)
            }
            return (codehash != 0x0 && codehash != accountHash);
        }
    }
    pragma solidity ^0.5.2;
    /**
     * @title SafeMath
     * @dev Math operations with safety checks that revert
     */
    library SafeMathWithRequire {
        /**
        * @dev Multiplies two numbers, throws on overflow.
        */
        function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
            // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
            if (a == 0) {
                return 0;
            }
            c = a * b;
            require(c / a == b, "overflow");
            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) {
            require(b <= a, "undeflow");
            return a - b;
        }
        /**
        * @dev Adds two numbers, throws on overflow.
        */
        function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
            c = a + b;
            require(c >= a, "overflow");
            return c;
        }
    }
    pragma solidity ^0.5.2;
    library SigUtil {
        function recover(bytes32 hash, bytes memory sig)
            internal
            pure
            returns (address recovered)
        {
            require(sig.length == 65);
            bytes32 r;
            bytes32 s;
            uint8 v;
            assembly {
                r := mload(add(sig, 32))
                s := mload(add(sig, 64))
                v := byte(0, mload(add(sig, 96)))
            }
            // Version of signature should be 27 or 28, but 0 and 1 are also possible versions
            if (v < 27) {
                v += 27;
            }
            require(v == 27 || v == 28);
            recovered = ecrecover(hash, v, r, s);
            require(recovered != address(0));
        }
        function recoverWithZeroOnFailure(bytes32 hash, bytes memory sig)
            internal
            pure
            returns (address)
        {
            if (sig.length != 65) {
                return (address(0));
            }
            bytes32 r;
            bytes32 s;
            uint8 v;
            assembly {
                r := mload(add(sig, 32))
                s := mload(add(sig, 64))
                v := byte(0, mload(add(sig, 96)))
            }
            // Version of signature should be 27 or 28, but 0 and 1 are also possible versions
            if (v < 27) {
                v += 27;
            }
            if (v != 27 && v != 28) {
                return (address(0));
            } else {
                return ecrecover(hash, v, r, s);
            }
        }
        // Builds a prefixed hash to mimic the behavior of eth_sign.
        function prefixed(bytes32 hash) internal pure returns (bytes memory) {
            return abi.encodePacked("\\x19Ethereum Signed Message:\
    32", hash);
        }
    }
    /* solhint-disable no-empty-blocks */
    pragma solidity 0.5.9;
    import "./Land/erc721/LandBaseToken.sol";
    contract Land is LandBaseToken {
        constructor(
            address metaTransactionContract,
            address admin
        ) public LandBaseToken(
            metaTransactionContract,
            admin
        ) {
        }
        /**
         * @notice Return the name of the token contract
         * @return The name of the token contract
         */
        function name() external pure returns (string memory) {
            return "Sandbox's LANDs";
        }
        /**
         * @notice Return the symbol of the token contract
         * @return The symbol of the token contract
         */
        function symbol() external pure returns (string memory) {
            return "LAND";
        }
        // solium-disable-next-line security/no-assign-params
        function uint2str(uint _i) internal pure returns (string memory) {
            if (_i == 0) {
                return "0";
            }
            uint j = _i;
            uint len;
            while (j != 0) {
                len++;
                j /= 10;
            }
            bytes memory bstr = new bytes(len);
            uint k = len - 1;
            while (_i != 0) {
                bstr[k--] = byte(uint8(48 + _i % 10));
                _i /= 10;
            }
            return string(bstr);
        }
        /**
         * @notice Return the URI of a specific token
         * @param id The id of the token
         * @return The URI of the token
         */
        function tokenURI(uint256 id) public view returns (string memory) {
            require(_ownerOf(id) != address(0), "Id does not exist");
            return
                string(
                    abi.encodePacked(
                        "https://api.sandbox.game/lands/",
                        uint2str(id),
                        "/metadata.json"
                    )
                );
        }
        /**
         * @notice Check if the contract supports an interface
         * 0x01ffc9a7 is ERC-165
         * 0x80ac58cd is ERC-721
         * 0x5b5e139f is ERC-721 metadata
         * @param id The id of the interface
         * @return True if the interface is supported
         */
        function supportsInterface(bytes4 id) external pure returns (bool) {
            return id == 0x01ffc9a7 || id == 0x80ac58cd || id == 0x5b5e139f;
        }
    }
    /* solhint-disable func-order, code-complexity */
    pragma solidity 0.5.9;
    import "../../../contracts_common/src/Libraries/AddressUtils.sol";
    import "../../../contracts_common/src/Interfaces/ERC721TokenReceiver.sol";
    import "../../../contracts_common/src/Interfaces/ERC721Events.sol";
    import "../../../contracts_common/src/BaseWithStorage/SuperOperators.sol";
    import "../../../contracts_common/src/BaseWithStorage/MetaTransactionReceiver.sol";
    import "../../../contracts_common/src/Interfaces/ERC721MandatoryTokenReceiver.sol";
    contract ERC721BaseToken is ERC721Events, SuperOperators, MetaTransactionReceiver {
        using AddressUtils for address;
        bytes4 internal constant _ERC721_RECEIVED = 0x150b7a02;
        bytes4 internal constant _ERC721_BATCH_RECEIVED = 0x4b808c46;
        bytes4 internal constant ERC165ID = 0x01ffc9a7;
        bytes4 internal constant ERC721_MANDATORY_RECEIVER = 0x5e8bf644;
        mapping (address => uint256) public _numNFTPerAddress;
        mapping (uint256 => uint256) public _owners;
        mapping (address => mapping(address => bool)) public _operatorsForAll;
        mapping (uint256 => address) public _operators;
        constructor(
            address metaTransactionContract,
            address admin
        ) internal {
            _admin = admin;
            _setMetaTransactionProcessor(metaTransactionContract, true);
        }
        function _transferFrom(address from, address to, uint256 id) internal {
            _numNFTPerAddress[from]--;
            _numNFTPerAddress[to]++;
            _owners[id] = uint256(to);
            emit Transfer(from, to, id);
        }
        /**
         * @notice Return the number of Land owned by an address
         * @param owner The address to look for
         * @return The number of Land token owned by the address
         */
        function balanceOf(address owner) external view returns (uint256) {
            require(owner != address(0), "owner is zero address");
            return _numNFTPerAddress[owner];
        }
        function _ownerOf(uint256 id) internal view returns (address) {
            return address(_owners[id]);
        }
        function _ownerAndOperatorEnabledOf(uint256 id) internal view returns (address owner, bool operatorEnabled) {
            uint256 data = _owners[id];
            owner = address(data);
            operatorEnabled = (data / 2**255) == 1;
        }
        /**
         * @notice Return the owner of a Land
         * @param id The id of the Land
         * @return The address of the owner
         */
        function ownerOf(uint256 id) external view returns (address owner) {
            owner = _ownerOf(id);
            require(owner != address(0), "token does not exist");
        }
        function _approveFor(address owner, address operator, uint256 id) internal {
            if(operator == address(0)) {
                _owners[id] = uint256(owner); // no need to resset the operator, it will be overriden next time
            } else {
                _owners[id] = uint256(owner) + 2**255;
                _operators[id] = operator;
            }
            emit Approval(owner, operator, id);
        }
        /**
         * @notice Approve an operator to spend tokens on the sender behalf
         * @param sender The address giving the approval
         * @param operator The address receiving the approval
         * @param id The id of the token
         */
        function approveFor(
            address sender,
            address operator,
            uint256 id
        ) external {
            address owner = _ownerOf(id);
            require(sender != address(0), "sender is zero address");
            require(
                msg.sender == sender ||
                _metaTransactionContracts[msg.sender] ||
                _superOperators[msg.sender] ||
                _operatorsForAll[sender][msg.sender],
                "not authorized to approve"
            );
            require(owner == sender, "owner != sender");
            _approveFor(owner, operator, id);
        }
        /**
         * @notice Approve an operator to spend tokens on the sender behalf
         * @param operator The address receiving the approval
         * @param id The id of the token
         */
        function approve(address operator, uint256 id) external {
            address owner = _ownerOf(id);
            require(owner != address(0), "token does not exist");
            require(
                owner == msg.sender ||
                _superOperators[msg.sender] ||
                _operatorsForAll[owner][msg.sender],
                "not authorized to approve"
            );
            _approveFor(owner, operator, id);
        }
        /**
         * @notice Get the approved operator for a specific token
         * @param id The id of the token
         * @return The address of the operator
         */
        function getApproved(uint256 id) external view returns (address) {
            (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
            require(owner != address(0), "token does not exist");
            if (operatorEnabled) {
                return _operators[id];
            } else {
                return address(0);
            }
        }
        function _checkTransfer(address from, address to, uint256 id) internal view returns (bool isMetaTx) {
            (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
            require(owner != address(0), "token does not exist");
            require(owner == from, "not owner in _checkTransfer");
            require(to != address(0), "can't send to zero address");
            isMetaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
            if (msg.sender != from && !isMetaTx) {
                require(
                    _superOperators[msg.sender] ||
                    _operatorsForAll[from][msg.sender] ||
                    (operatorEnabled && _operators[id] == msg.sender),
                    "not approved to transfer"
                );
            }
        }
        function _checkInterfaceWith10000Gas(address _contract, bytes4 interfaceId)
            internal
            view
            returns (bool)
        {
            bool success;
            bool result;
            bytes memory call_data = abi.encodeWithSelector(
                ERC165ID,
                interfaceId
            );
            // solium-disable-next-line security/no-inline-assembly
            assembly {
                let call_ptr := add(0x20, call_data)
                let call_size := mload(call_data)
                let output := mload(0x40) // Find empty storage location using "free memory pointer"
                mstore(output, 0x0)
                success := staticcall(
                    10000,
                    _contract,
                    call_ptr,
                    call_size,
                    output,
                    0x20
                ) // 32 bytes
                result := mload(output)
            }
            // (10000 / 63) "not enough for supportsInterface(...)" // consume all gas, so caller can potentially know that there was not enough gas
            assert(gasleft() > 158);
            return success && result;
        }
        /**
         * @notice Transfer a token between 2 addresses
         * @param from The sender of the token
         * @param to The recipient of the token
         * @param id The id of the token
        */
        function transferFrom(address from, address to, uint256 id) external {
            bool metaTx = _checkTransfer(from, to, id);
            _transferFrom(from, to, id);
            if (to.isContract() && _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER)) {
                require(
                    _checkOnERC721Received(metaTx ? from : msg.sender, from, to, id, ""),
                    "erc721 transfer rejected by to"
                );
            }
        }
        /**
         * @notice Transfer a token between 2 addresses letting the receiver knows of the transfer
         * @param from The sender of the token
         * @param to The recipient of the token
         * @param id The id of the token
         * @param data Additional data
         */
        function safeTransferFrom(address from, address to, uint256 id, bytes memory data) public {
            bool metaTx = _checkTransfer(from, to, id);
            _transferFrom(from, to, id);
            if (to.isContract()) {
                require(
                    _checkOnERC721Received(metaTx ? from : msg.sender, from, to, id, data),
                    "ERC721: transfer rejected by to"
                );
            }
        }
        /**
         * @notice Transfer a token between 2 addresses letting the receiver knows of the transfer
         * @param from The send of the token
         * @param to The recipient of the token
         * @param id The id of the token
         */
        function safeTransferFrom(address from, address to, uint256 id) external {
            safeTransferFrom(from, to, id, "");
        }
        /**
         * @notice Transfer many tokens between 2 addresses
         * @param from The sender of the token
         * @param to The recipient of the token
         * @param ids The ids of the tokens
         * @param data additional data
        */
        function batchTransferFrom(address from, address to, uint256[] calldata ids, bytes calldata data) external {
            _batchTransferFrom(from, to, ids, data, false);
        }
        function _batchTransferFrom(address from, address to, uint256[] memory ids, bytes memory data, bool safe) internal {
            bool metaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
            bool authorized = msg.sender == from ||
                metaTx ||
                _superOperators[msg.sender] ||
                _operatorsForAll[from][msg.sender];
            require(from != address(0), "from is zero address");
            require(to != address(0), "can't send to zero address");
            uint256 numTokens = ids.length;
            for(uint256 i = 0; i < numTokens; i ++) {
                uint256 id = ids[i];
                (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
                require(owner == from, "not owner in batchTransferFrom");
                require(authorized || (operatorEnabled && _operators[id] == msg.sender), "not authorized");
                _owners[id] = uint256(to);
                emit Transfer(from, to, id);
            }
            if (from != to) {
                _numNFTPerAddress[from] -= numTokens;
                _numNFTPerAddress[to] += numTokens;
            }
            if (to.isContract() && (safe || _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER))) {
                require(
                    _checkOnERC721BatchReceived(metaTx ? from : msg.sender, from, to, ids, data),
                    "erc721 batch transfer rejected by to"
                );
            }
        }
        /**
         * @notice Transfer many tokens between 2 addresses ensuring the receiving contract has a receiver method
         * @param from The sender of the token
         * @param to The recipient of the token
         * @param ids The ids of the tokens
         * @param data additional data
        */
        function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, bytes calldata data) external {
            _batchTransferFrom(from, to, ids, data, true);
        }
        /**
         * @notice Check if the contract supports an interface
         * 0x01ffc9a7 is ERC-165
         * 0x80ac58cd is ERC-721
         * @param id The id of the interface
         * @return True if the interface is supported
         */
        function supportsInterface(bytes4 id) external pure returns (bool) {
            return id == 0x01ffc9a7 || id == 0x80ac58cd;
        }
        /**
         * @notice Set the approval for an operator to manage all the tokens of the sender
         * @param sender The address giving the approval
         * @param operator The address receiving the approval
         * @param approved The determination of the approval
         */
        function setApprovalForAllFor(
            address sender,
            address operator,
            bool approved
        ) external {
            require(sender != address(0), "Invalid sender address");
            require(
                msg.sender == sender ||
                _metaTransactionContracts[msg.sender] ||
                _superOperators[msg.sender],
                "not authorized to approve for all"
            );
            _setApprovalForAll(sender, operator, approved);
        }
        /**
         * @notice Set the approval for an operator to manage all the tokens of the sender
         * @param operator The address receiving the approval
         * @param approved The determination of the approval
         */
        function setApprovalForAll(address operator, bool approved) external {
            _setApprovalForAll(msg.sender, operator, approved);
        }
        function _setApprovalForAll(
            address sender,
            address operator,
            bool approved
        ) internal {
            require(
                !_superOperators[operator],
                "super operator can't have their approvalForAll changed"
            );
            _operatorsForAll[sender][operator] = approved;
            emit ApprovalForAll(sender, operator, approved);
        }
        /**
         * @notice Check if the sender approved the operator
         * @param owner The address of the owner
         * @param operator The address of the operator
         * @return The status of the approval
         */
        function isApprovedForAll(address owner, address operator)
            external
            view
            returns (bool isOperator)
        {
            return _operatorsForAll[owner][operator] || _superOperators[operator];
        }
        function _burn(address from, address owner, uint256 id) public {
            require(from == owner, "not owner");
            _owners[id] = 2**160; // cannot mint it again
            _numNFTPerAddress[from]--;
            emit Transfer(from, address(0), id);
        }
        /// @notice Burns token `id`.
        /// @param id token which will be burnt.
        function burn(uint256 id) external {
            _burn(msg.sender, _ownerOf(id), id);
        }
        /// @notice Burn token`id` from `from`.
        /// @param from address whose token is to be burnt.
        /// @param id token which will be burnt.
        function burnFrom(address from, uint256 id) external {
            require(from != address(0), "Invalid sender address");
            (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
            require(
                msg.sender == from ||
                _metaTransactionContracts[msg.sender] ||
                (operatorEnabled && _operators[id] == msg.sender) ||
                _superOperators[msg.sender] ||
                _operatorsForAll[from][msg.sender],
                "not authorized to burn"
            );
            _burn(from, owner, id);
        }
        function _checkOnERC721Received(address operator, address from, address to, uint256 tokenId, bytes memory _data)
            internal returns (bool)
        {
            bytes4 retval = ERC721TokenReceiver(to).onERC721Received(operator, from, tokenId, _data);
            return (retval == _ERC721_RECEIVED);
        }
        function _checkOnERC721BatchReceived(address operator, address from, address to, uint256[] memory ids, bytes memory _data)
            internal returns (bool)
        {
            bytes4 retval = ERC721MandatoryTokenReceiver(to).onERC721BatchReceived(operator, from, ids, _data);
            return (retval == _ERC721_BATCH_RECEIVED);
        }
    }
    /* solhint-disable func-order, code-complexity */
    pragma solidity 0.5.9;
    import "./ERC721BaseToken.sol";
    contract LandBaseToken is ERC721BaseToken {
        // Our grid is 408 x 408 lands
        uint256 internal constant GRID_SIZE = 408;
        uint256 internal constant LAYER =          0xFF00000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_1x1 =      0x0000000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_3x3 =      0x0100000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_6x6 =      0x0200000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_12x12 =    0x0300000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_24x24 =    0x0400000000000000000000000000000000000000000000000000000000000000;
        mapping(address => bool) internal _minters;
        event Minter(address superOperator, bool enabled);
        /// @notice Enable or disable the ability of `minter` to mint tokens
        /// @param minter address that will be given/removed minter right.
        /// @param enabled set whether the minter is enabled or disabled.
        function setMinter(address minter, bool enabled) external {
            require(
                msg.sender == _admin,
                "only admin is allowed to add minters"
            );
            _minters[minter] = enabled;
            emit Minter(minter, enabled);
        }
        /// @notice check whether address `who` is given minter rights.
        /// @param who The address to query.
        /// @return whether the address has minter rights.
        function isMinter(address who) public view returns (bool) {
            return _minters[who];
        }
        constructor(
            address metaTransactionContract,
            address admin
        ) public ERC721BaseToken(metaTransactionContract, admin) {
        }
        /// @notice total width of the map
        /// @return width
        function width() external returns(uint256) {
            return GRID_SIZE;
        }
        /// @notice total height of the map
        /// @return height
        function height() external returns(uint256) {
            return GRID_SIZE;
        }
        /// @notice x coordinate of Land token
        /// @param id tokenId
        /// @return the x coordinates
        function x(uint256 id) external returns(uint256) {
            require(_ownerOf(id) != address(0), "token does not exist");
            return id % GRID_SIZE;
        }
        /// @notice y coordinate of Land token
        /// @param id tokenId
        /// @return the y coordinates
        function y(uint256 id) external returns(uint256) {
            require(_ownerOf(id) != address(0), "token does not exist");
            return id / GRID_SIZE;
        }
        /**
         * @notice Mint a new quad (aligned to a quad tree with size 3, 6, 12 or 24 only)
         * @param to The recipient of the new quad
         * @param size The size of the new quad
         * @param x The top left x coordinate of the new quad
         * @param y The top left y coordinate of the new quad
         * @param data extra data to pass to the transfer
         */
        function mintQuad(address to, uint256 size, uint256 x, uint256 y, bytes calldata data) external {
            require(to != address(0), "to is zero address");
            require(
                isMinter(msg.sender),
                "Only a minter can mint"
            );
            require(x % size == 0 && y % size == 0, "Invalid coordinates");
            require(x <= GRID_SIZE - size && y <= GRID_SIZE - size, "Out of bounds");
            uint256 quadId;
            uint256 id = x + y * GRID_SIZE;
            if (size == 1) {
                quadId = id;
            } else if (size == 3) {
                quadId = LAYER_3x3 + id;
            } else if (size == 6) {
                quadId = LAYER_6x6 + id;
            } else if (size == 12) {
                quadId = LAYER_12x12 + id;
            } else if (size == 24) {
                quadId = LAYER_24x24 + id;
            } else {
                require(false, "Invalid size");
            }
            require(_owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE] == 0, "Already minted as 24x24");
            uint256 toX = x+size;
            uint256 toY = y+size;
            if (size <= 12) {
                require(
                    _owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE] == 0,
                    "Already minted as 12x12"
                );
            } else {
                for (uint256 x12i = x; x12i < toX; x12i += 12) {
                    for (uint256 y12i = y; y12i < toY; y12i += 12) {
                        uint256 id12x12 = LAYER_12x12 + x12i + y12i * GRID_SIZE;
                        require(_owners[id12x12] == 0, "Already minted as 12x12");
                    }
                }
            }
            if (size <= 6) {
                require(_owners[LAYER_6x6 + (x/6) * 6 + ((y/6) * 6) * GRID_SIZE] == 0, "Already minted as 6x6");
            } else {
                for (uint256 x6i = x; x6i < toX; x6i += 6) {
                    for (uint256 y6i = y; y6i < toY; y6i += 6) {
                        uint256 id6x6 = LAYER_6x6 + x6i + y6i * GRID_SIZE;
                        require(_owners[id6x6] == 0, "Already minted as 6x6");
                    }
                }
            }
            if (size <= 3) {
                require(_owners[LAYER_3x3 + (x/3) * 3 + ((y/3) * 3) * GRID_SIZE] == 0, "Already minted as 3x3");
            } else {
                for (uint256 x3i = x; x3i < toX; x3i += 3) {
                    for (uint256 y3i = y; y3i < toY; y3i += 3) {
                        uint256 id3x3 = LAYER_3x3 + x3i + y3i * GRID_SIZE;
                        require(_owners[id3x3] == 0, "Already minted as 3x3");
                    }
                }
            }
            for (uint256 i = 0; i < size*size; i++) {
                uint256 id = _idInPath(i, size, x, y);
                require(_owners[id] == 0, "Already minted");
                emit Transfer(address(0), to, id);
            }
            _owners[quadId] = uint256(to);
            _numNFTPerAddress[to] += size * size;
            _checkBatchReceiverAcceptQuad(msg.sender, address(0), to, size, x, y, data);
        }
        function _idInPath(uint256 i, uint256 size, uint256 x, uint256 y) internal pure returns(uint256) {
            uint256 row = i / size;
            if(row % 2 == 0) { // alow ids to follow a path in a quad
                return (x + (i%size)) + ((y + row) * GRID_SIZE);
            } else {
                return ((x + size) - (1 + i%size)) + ((y + row) * GRID_SIZE);
            }
        }
        /// @notice transfer one quad (aligned to a quad tree with size 3, 6, 12 or 24 only)
        /// @param from current owner of the quad
        /// @param to destination
        /// @param size size of the quad
        /// @param x The top left x coordinate of the quad
        /// @param y The top left y coordinate of the quad
        /// @param data additional data
        function transferQuad(address from, address to, uint256 size, uint256 x, uint256 y, bytes calldata data) external {
            require(from != address(0), "from is zero address");
            require(to != address(0), "can't send to zero address");
            bool metaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
            if (msg.sender != from && !metaTx) {
                require(
                    _superOperators[msg.sender] ||
                    _operatorsForAll[from][msg.sender],
                    "not authorized to transferQuad"
                );
            }
            _transferQuad(from, to, size, x, y);
            _numNFTPerAddress[from] -= size * size;
            _numNFTPerAddress[to] += size * size;
            _checkBatchReceiverAcceptQuad(metaTx ? from : msg.sender, from, to, size, x, y, data);
        }
        function _checkBatchReceiverAcceptQuad(
            address operator,
            address from,
            address to,
            uint256 size,
            uint256 x,
            uint256 y,
            bytes memory data
        ) internal {
            if (to.isContract() && _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER)) {
                uint256[] memory ids = new uint256[](size*size);
                for (uint256 i = 0; i < size*size; i++) {
                    ids[i] = _idInPath(i, size, x, y);
                }
                require(
                    _checkOnERC721BatchReceived(operator, from, to, ids, data),
                    "erc721 batch transfer rejected by to"
                );
            }
        }
        /// @notice transfer multiple quad (aligned to a quad tree with size 3, 6, 12 or 24 only)
        /// @param from current owner of the quad
        /// @param to destination
        /// @param sizes list of sizes for each quad
        /// @param xs list of top left x coordinates for each quad
        /// @param ys list of top left y coordinates for each quad
        /// @param data additional data
        function batchTransferQuad(
            address from,
            address to,
            uint256[] calldata sizes,
            uint256[] calldata xs,
            uint256[] calldata ys,
            bytes calldata data
        ) external {
            require(from != address(0), "from is zero address");
            require(to != address(0), "can't send to zero address");
            require(sizes.length == xs.length && xs.length == ys.length, "invalid data");
            bool metaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
            if (msg.sender != from && !metaTx) {
                require(
                    _superOperators[msg.sender] ||
                    _operatorsForAll[from][msg.sender],
                    "not authorized to transferMultiQuads"
                );
            }
            uint256 numTokensTransfered = 0;
            for (uint256 i = 0; i < sizes.length; i++) {
                uint256 size = sizes[i];
                _transferQuad(from, to, size, xs[i], ys[i]);
                numTokensTransfered += size * size;
            }
            _numNFTPerAddress[from] -= numTokensTransfered;
            _numNFTPerAddress[to] += numTokensTransfered;
            if (to.isContract() && _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER)) {
                uint256[] memory ids = new uint256[](numTokensTransfered);
                uint256 counter = 0;
                for (uint256 j = 0; j < sizes.length; j++) {
                    uint256 size = sizes[j];
                    for (uint256 i = 0; i < size*size; i++) {
                        ids[counter] = _idInPath(i, size, xs[j], ys[j]);
                        counter++;
                    }
                }
                require(
                    _checkOnERC721BatchReceived(metaTx ? from : msg.sender, from, to, ids, data),
                    "erc721 batch transfer rejected by to"
                );
            }
        }
        function _transferQuad(address from, address to, uint256 size, uint256 x, uint256 y) internal {
            if (size == 1) {
                uint256 id1x1 = x + y * GRID_SIZE;
                address owner = _ownerOf(id1x1);
                require(owner != address(0), "token does not exist");
                require(owner == from, "not owner in _transferQuad");
                _owners[id1x1] = uint256(to);
            } else {
                _regroup(from, to, size, x, y);
            }
            for (uint256 i = 0; i < size*size; i++) {
                emit Transfer(from, to, _idInPath(i, size, x, y));
            }
        }
        function _checkAndClear(address from, uint256 id) internal returns(bool) {
            uint256 owner = _owners[id];
            if (owner != 0) {
                require(address(owner) == from, "not owner");
                _owners[id] = 0;
                return true;
            }
            return false;
        }
        function _regroup(address from, address to, uint256 size, uint256 x, uint256 y) internal {
            require(x % size == 0 && y % size == 0, "Invalid coordinates");
            require(x <= GRID_SIZE - size && y <= GRID_SIZE - size, "Out of bounds");
            if (size == 3) {
                _regroup3x3(from, to, x, y, true);
            } else if (size == 6) {
                _regroup6x6(from, to, x, y, true);
            } else if (size == 12) {
                _regroup12x12(from, to, x, y, true);
            } else if (size == 24) {
                _regroup24x24(from, to, x, y, true);
            } else {
                require(false, "Invalid size");
            }
        }
        function _regroup3x3(address from, address to, uint256 x, uint256 y, bool set) internal returns (bool) {
            uint256 id = x + y * GRID_SIZE;
            uint256 quadId = LAYER_3x3 + id;
            bool ownerOfAll = true;
            for (uint256 xi = x; xi < x+3; xi++) {
                for (uint256 yi = y; yi < y+3; yi++) {
                    ownerOfAll = _checkAndClear(from, xi + yi * GRID_SIZE) && ownerOfAll;
                }
            }
            if(set) {
                if(!ownerOfAll) {
                    require(
                        _owners[quadId] == uint256(from) ||
                        _owners[LAYER_6x6 + (x/6) * 6 + ((y/6) * 6) * GRID_SIZE] == uint256(from) ||
                        _owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE] == uint256(from) ||
                        _owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE] == uint256(from),
                        "not owner of all sub quads nor parent quads"
                    );
                }
                _owners[quadId] = uint256(to);
                return true;
            }
            return ownerOfAll;
        }
        function _regroup6x6(address from, address to, uint256 x, uint256 y, bool set) internal returns (bool) {
            uint256 id = x + y * GRID_SIZE;
            uint256 quadId = LAYER_6x6 + id;
            bool ownerOfAll = true;
            for (uint256 xi = x; xi < x+6; xi += 3) {
                for (uint256 yi = y; yi < y+6; yi += 3) {
                    bool ownAllIndividual = _regroup3x3(from, to, xi, yi, false);
                    uint256 id3x3 = LAYER_3x3 + xi + yi * GRID_SIZE;
                    uint256 owner3x3 = _owners[id3x3];
                    if (owner3x3 != 0) {
                        if(!ownAllIndividual) {
                            require(owner3x3 == uint256(from), "not owner of 3x3 quad");
                        }
                        _owners[id3x3] = 0;
                    }
                    ownerOfAll = (ownAllIndividual || owner3x3 != 0) && ownerOfAll;
                }
            }
            if(set) {
                if(!ownerOfAll) {
                    require(
                        _owners[quadId] == uint256(from) ||
                        _owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE] == uint256(from) ||
                        _owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE] == uint256(from),
                        "not owner of all sub quads nor parent quads"
                    );
                }
                _owners[quadId] = uint256(to);
                return true;
            }
            return ownerOfAll;
        }
        function _regroup12x12(address from, address to, uint256 x, uint256 y, bool set) internal returns (bool) {
            uint256 id = x + y * GRID_SIZE;
            uint256 quadId = LAYER_12x12 + id;
            bool ownerOfAll = true;
            for (uint256 xi = x; xi < x+12; xi += 6) {
                for (uint256 yi = y; yi < y+12; yi += 6) {
                    bool ownAllIndividual = _regroup6x6(from, to, xi, yi, false);
                    uint256 id6x6 = LAYER_6x6 + xi + yi * GRID_SIZE;
                    uint256 owner6x6 = _owners[id6x6];
                    if (owner6x6 != 0) {
                        if(!ownAllIndividual) {
                            require(owner6x6 == uint256(from), "not owner of 6x6 quad");
                        }
                        _owners[id6x6] = 0;
                    }
                    ownerOfAll = (ownAllIndividual || owner6x6 != 0) && ownerOfAll;
                }
            }
            if(set) {
                if(!ownerOfAll) {
                    require(
                        _owners[quadId] == uint256(from) ||
                        _owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE] == uint256(from),
                        "not owner of all sub quads nor parent quads"
                    );
                }
                _owners[quadId] = uint256(to);
                return true;
            }
            return ownerOfAll;
        }
        function _regroup24x24(address from, address to, uint256 x, uint256 y, bool set) internal returns (bool) {
            uint256 id = x + y * GRID_SIZE;
            uint256 quadId = LAYER_24x24 + id;
            bool ownerOfAll = true;
            for (uint256 xi = x; xi < x+24; xi += 12) {
                for (uint256 yi = y; yi < y+24; yi += 12) {
                    bool ownAllIndividual = _regroup12x12(from, to, xi, yi, false);
                    uint256 id12x12 = LAYER_12x12 + xi + yi * GRID_SIZE;
                    uint256 owner12x12 = _owners[id12x12];
                    if (owner12x12 != 0) {
                        if(!ownAllIndividual) {
                            require(owner12x12 == uint256(from), "not owner of 12x12 quad");
                        }
                        _owners[id12x12] = 0;
                    }
                    ownerOfAll = (ownAllIndividual || owner12x12 != 0) && ownerOfAll;
                }
            }
            if(set) {
                if(!ownerOfAll) {
                    require(
                        _owners[quadId] == uint256(from),
                        "not owner of all sub quads not parent quad"
                    );
                }
                _owners[quadId] = uint256(to);
                return true;
            }
            return ownerOfAll || _owners[quadId] == uint256(from);
        }
        function _ownerOf(uint256 id) internal view returns (address) {
            require(id & LAYER == 0, "Invalid token id");
            uint256 x = id % GRID_SIZE;
            uint256 y = id / GRID_SIZE;
            uint256 owner1x1 = _owners[id];
            if (owner1x1 != 0) {
                return address(owner1x1); // cast to zero
            } else {
                address owner3x3 = address(_owners[LAYER_3x3 + (x/3) * 3 + ((y/3) * 3) * GRID_SIZE]);
                if (owner3x3 != address(0)) {
                    return owner3x3;
                } else {
                    address owner6x6 = address(_owners[LAYER_6x6 + (x/6) * 6 + ((y/6) * 6) * GRID_SIZE]);
                    if (owner6x6 != address(0)) {
                        return owner6x6;
                    } else {
                        address owner12x12 = address(_owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE]);
                        if (owner12x12 != address(0)) {
                            return owner12x12;
                        } else {
                            return address(_owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE]);
                        }
                    }
                }
            }
        }
        function _ownerAndOperatorEnabledOf(uint256 id) internal view returns (address owner, bool operatorEnabled) {
            require(id & LAYER == 0, "Invalid token id");
            uint256 x = id % GRID_SIZE;
            uint256 y = id / GRID_SIZE;
            uint256 owner1x1 = _owners[id];
            if (owner1x1 != 0) {
                owner = address(owner1x1);
                operatorEnabled = (owner1x1 / 2**255) == 1;
            } else {
                address owner3x3 = address(_owners[LAYER_3x3 + (x/3) * 3 + ((y/3) * 3) * GRID_SIZE]);
                if (owner3x3 != address(0)) {
                    owner = owner3x3;
                    operatorEnabled = false;
                } else {
                    address owner6x6 = address(_owners[LAYER_6x6 + (x/6) * 6 + ((y/6) * 6) * GRID_SIZE]);
                    if (owner6x6 != address(0)) {
                        owner = owner6x6;
                        operatorEnabled = false;
                    } else {
                        address owner12x12 = address(_owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE]);
                        if (owner12x12 != address(0)) {
                            owner = owner12x12;
                            operatorEnabled = false;
                        } else {
                            owner = address(_owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE]);
                            operatorEnabled = false;
                        }
                    }
                }
            }
        }
    }
    /* solhint-disable not-rely-on-time, func-order */
    pragma solidity 0.5.9;
    import "../../contracts_common/src/Libraries/SafeMathWithRequire.sol";
    import "../Land.sol";
    import "../../contracts_common/src/Interfaces/ERC20.sol";
    import "../../contracts_common/src/BaseWithStorage/MetaTransactionReceiver.sol";
    import "../../contracts_common/src/Interfaces/Medianizer.sol";
    import "../ReferralValidator/ReferralValidator.sol";
    /**
     * @title Land Sale contract with referral that supports also DAI and ETH as payment
     * @notice This contract mananges the sale of our lands
     */
    contract LandSaleWithReferral is MetaTransactionReceiver, ReferralValidator {
        using SafeMathWithRequire for uint256;
        uint256 internal constant GRID_SIZE = 408; // 408 is the size of the Land
        uint256 internal constant daiPrice = 14400000000000000;
        Land internal _land;
        ERC20 internal _sand;
        Medianizer private _medianizer;
        ERC20 private _dai;
        address payable internal _wallet;
        uint256 internal _expiryTime;
        bytes32 internal _merkleRoot;
        bool _sandEnabled = false;
        bool _etherEnabled = true;
        bool _daiEnabled = false;
        event LandQuadPurchased(
            address indexed buyer,
            address indexed to,
            uint256 indexed topCornerId,
            uint256 size,
            uint256 price,
            address token,
            uint256 amountPaid
        );
        constructor(
            address landAddress,
            address sandContractAddress,
            address initialMetaTx,
            address admin,
            address payable initialWalletAddress,
            bytes32 merkleRoot,
            uint256 expiryTime,
            address medianizerContractAddress,
            address daiTokenContractAddress,
            address initialSigningWallet,
            uint256 initialMaxCommissionRate
        ) public ReferralValidator(
            initialSigningWallet,
            initialMaxCommissionRate
        ) {
            _land = Land(landAddress);
            _sand = ERC20(sandContractAddress);
            _setMetaTransactionProcessor(initialMetaTx, true);
            _wallet = initialWalletAddress;
            _merkleRoot = merkleRoot;
            _expiryTime = expiryTime;
            _medianizer = Medianizer(medianizerContractAddress);
            _dai = ERC20(daiTokenContractAddress);
            _admin = admin;
        }
        /// @notice set the wallet receiving the proceeds
        /// @param newWallet address of the new receiving wallet
        function setReceivingWallet(address payable newWallet) external{
            require(newWallet != address(0), "receiving wallet cannot be zero address");
            require(msg.sender == _admin, "only admin can change the receiving wallet");
            _wallet = newWallet;
        }
        /// @notice enable/disable DAI payment for Lands
        /// @param enabled whether to enable or disable
        function setDAIEnabled(bool enabled) external {
            require(msg.sender == _admin, "only admin can enable/disable DAI");
            _daiEnabled = enabled;
        }
        /// @notice return whether DAI payments are enabled
        /// @return whether DAI payments are enabled
        function isDAIEnabled() external view returns (bool) {
            return _daiEnabled;
        }
        /// @notice enable/disable ETH payment for Lands
        /// @param enabled whether to enable or disable
        function setETHEnabled(bool enabled) external {
            require(msg.sender == _admin, "only admin can enable/disable ETH");
            _etherEnabled = enabled;
        }
        /// @notice return whether ETH payments are enabled
        /// @return whether ETH payments are enabled
        function isETHEnabled() external view returns (bool) {
            return _etherEnabled;
        }
        /// @notice enable/disable the specific SAND payment for Lands
        /// @param enabled whether to enable or disable
        function setSANDEnabled(bool enabled) external {
            require(msg.sender == _admin, "only admin can enable/disable SAND");
            _sandEnabled = enabled;
        }
        /// @notice return whether the specific SAND payments are enabled
        /// @return whether the specific SAND payments are enabled
        function isSANDEnabled() external view returns (bool) {
            return _sandEnabled;
        }
        function _checkValidity(
            address buyer,
            address reserved,
            uint256 x,
            uint256 y,
            uint256 size,
            uint256 price,
            bytes32 salt,
            bytes32[] memory proof
        ) internal view {
            /* solium-disable-next-line security/no-block-members */
            require(block.timestamp < _expiryTime, "sale is over");
            require(buyer == msg.sender || _metaTransactionContracts[msg.sender], "not authorized");
            require(reserved == address(0) || reserved == buyer, "cannot buy reserved Land");
            bytes32 leaf = _generateLandHash(x, y, size, price, reserved, salt);
            require(
                _verify(proof, leaf),
                "Invalid land provided"
            );
        }
        function _mint(address buyer, address to, uint256 x, uint256 y, uint256 size, uint256 price, address token, uint256 tokenAmount) internal {
            uint256[] memory junctions = new uint256[](0);
            _land.mintQuad(to, size, x, y, abi.encode(to, junctions));
            emit LandQuadPurchased(buyer, to, x + (y * GRID_SIZE), size, price, token, tokenAmount);
        }
        /**
         * @notice buy Land with SAND using the merkle proof associated with it
         * @param buyer address that perform the payment
         * @param to address that will own the purchased Land
         * @param reserved the reserved address (if any)
         * @param x x coordinate of the Land
         * @param y y coordinate of the Land
         * @param size size of the pack of Land to purchase
         * @param priceInSand price in SAND to purchase that Land
         * @param proof merkleProof for that particular Land
         * @return The address of the operator
         */
        function buyLandWithSand(
            address buyer,
            address to,
            address reserved,
            uint256 x,
            uint256 y,
            uint256 size,
            uint256 priceInSand,
            bytes32 salt,
            bytes32[] calldata proof,
            bytes calldata referral
        ) external {
            require(_sandEnabled, "sand payments not enabled");
            _checkValidity(buyer, reserved, x, y, size, priceInSand, salt, proof);
            handleReferralWithERC20(
                buyer,
                priceInSand,
                referral,
                _wallet,
                address(_sand)
            );
            _mint(buyer, to, x, y, size, priceInSand, address(_sand), priceInSand);
        }
        /**
         * @notice buy Land with ETH using the merkle proof associated with it
         * @param buyer address that perform the payment
         * @param to address that will own the purchased Land
         * @param reserved the reserved address (if any)
         * @param x x coordinate of the Land
         * @param y y coordinate of the Land
         * @param size size of the pack of Land to purchase
         * @param priceInSand price in SAND to purchase that Land
         * @param proof merkleProof for that particular Land
         * @param referral the referral used by the buyer
         * @return The address of the operator
         */
        function buyLandWithETH(
            address buyer,
            address to,
            address reserved,
            uint256 x,
            uint256 y,
            uint256 size,
            uint256 priceInSand,
            bytes32 salt,
            bytes32[] calldata proof,
            bytes calldata referral
        ) external payable {
            require(_etherEnabled, "ether payments not enabled");
            _checkValidity(buyer, reserved, x, y, size, priceInSand, salt, proof);
            uint256 ETHRequired = getEtherAmountWithSAND(priceInSand);
            require(msg.value >= ETHRequired, "not enough ether sent");
            if (msg.value - ETHRequired > 0) {
                msg.sender.transfer(msg.value - ETHRequired); // refund extra
            }
            handleReferralWithETH(
                ETHRequired,
                referral,
                _wallet
            );
            _mint(buyer, to, x, y, size, priceInSand, address(0), ETHRequired);
        }
        /**
         * @notice buy Land with DAI using the merkle proof associated with it
         * @param buyer address that perform the payment
         * @param to address that will own the purchased Land
         * @param reserved the reserved address (if any)
         * @param x x coordinate of the Land
         * @param y y coordinate of the Land
         * @param size size of the pack of Land to purchase
         * @param priceInSand price in SAND to purchase that Land
         * @param proof merkleProof for that particular Land
         * @return The address of the operator
         */
        function buyLandWithDAI(
            address buyer,
            address to,
            address reserved,
            uint256 x,
            uint256 y,
            uint256 size,
            uint256 priceInSand,
            bytes32 salt,
            bytes32[] calldata proof,
            bytes calldata referral
        ) external {
            require(_daiEnabled, "dai payments not enabled");
            _checkValidity(buyer, reserved, x, y, size, priceInSand, salt, proof);
            uint256 DAIRequired = priceInSand.mul(daiPrice).div(1000000000000000000);
            handleReferralWithERC20(
                buyer,
                DAIRequired,
                referral,
                _wallet,
                address(_dai)
            );
            _mint(buyer, to, x, y, size, priceInSand, address(_dai), DAIRequired);
        }
        /**
         * @notice Gets the expiry time for the current sale
         * @return The expiry time, as a unix epoch
         */
        function getExpiryTime() external view returns(uint256) {
            return _expiryTime;
        }
        /**
         * @notice Gets the Merkle root associated with the current sale
         * @return The Merkle root, as a bytes32 hash
         */
        function merkleRoot() external view returns(bytes32) {
            return _merkleRoot;
        }
        function _generateLandHash(
            uint256 x,
            uint256 y,
            uint256 size,
            uint256 price,
            address reserved,
            bytes32 salt
        ) internal pure returns (
            bytes32
        ) {
            return keccak256(
                abi.encodePacked(
                    x,
                    y,
                    size,
                    price,
                    reserved,
                    salt
                )
            );
        }
        function _verify(bytes32[] memory proof, bytes32 leaf) internal view returns (bool) {
            bytes32 computedHash = leaf;
            for (uint256 i = 0; i < proof.length; i++) {
                bytes32 proofElement = proof[i];
                if (computedHash < proofElement) {
                    computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
                } else {
                    computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
                }
            }
            return computedHash == _merkleRoot;
        }
        /**
         * @notice Returns the amount of ETH for a specific amount of SAND
         * @param sandAmount An amount of SAND
         * @return The amount of ETH
         */
        function getEtherAmountWithSAND(uint256 sandAmount) public view returns (uint256) {
            uint256 ethUsdPair = getEthUsdPair();
            return sandAmount.mul(daiPrice).div(ethUsdPair);
        }
        /**
         * @notice Gets the ETHUSD pair from the Medianizer contract
         * @return The pair as an uint256
         */
        function getEthUsdPair() internal view returns (uint256) {
            bytes32 pair = _medianizer.read();
            return uint256(pair);
        }
    }
    /* solhint-disable not-rely-on-time, func-order */
    pragma solidity 0.5.9;
    import "../../contracts_common/src/Libraries/SigUtil.sol";
    import "../../contracts_common/src/Libraries/SafeMathWithRequire.sol";
    import "../../contracts_common/src/Interfaces/ERC20.sol";
    import "../../contracts_common/src/BaseWithStorage/Admin.sol";
    /**
     * @title Referral Validator
     * @notice This contract verifies if a referral is valid
     */
    contract ReferralValidator is Admin {
        address private _signingWallet;
        uint256 private _maxCommissionRate;
        mapping (address => uint256) private _previousSigningWallets;
        uint256 private _previousSigningDelay = 60 * 60 * 24 * 10;
        event ReferralUsed(
            address indexed referrer,
            address indexed referee,
            address indexed token,
            uint256 amount,
            uint256 commission,
            uint256 commissionRate
        );
        constructor(
            address initialSigningWallet,
            uint256 initialMaxCommissionRate
        ) public {
            _signingWallet = initialSigningWallet;
            _maxCommissionRate = initialMaxCommissionRate;
        }
        /**
         * @notice Update the signing wallet
         * @param newSigningWallet The new address of the signing wallet
         */
        function updateSigningWallet(address newSigningWallet) external {
            require(_admin == msg.sender, "Sender not admin");
            _previousSigningWallets[_signingWallet] = now + _previousSigningDelay;
            _signingWallet = newSigningWallet;
        }
        // TODO: Check if this function is really useful
        /**
         * @notice Update the maximum commission rate
         * @param newMaxCommissionRate The new maximum commission rate
         */
        function updateMaxCommissionRate(uint256 newMaxCommissionRate) external {
            require(_admin == msg.sender, "Sender not admin");
            _maxCommissionRate = newMaxCommissionRate;
        }
        function handleReferralWithETH(
            uint256 amount,
            bytes memory referral,
            address payable destination
        ) internal {
            uint256 amountForDestination = amount;
            if (referral.length > 0) {
                (
                    bytes memory signature,
                    address referrer,
                    address referee,
                    uint256 expiryTime,
                    uint256 commissionRate
                ) = decodeReferral(referral);
                uint256 commission = 0;
                if (isReferralValid(signature, referrer, referee, expiryTime, commissionRate)) {
                    commission = SafeMathWithRequire.div(
                        SafeMathWithRequire.mul(amount, commissionRate),
                        10000
                    );
                    emit ReferralUsed(
                        referrer,
                        referee,
                        address(0),
                        amount,
                        commission,
                        commissionRate
                    );
                    amountForDestination = SafeMathWithRequire.sub(
                        amountForDestination,
                        commission
                    );
                }
                if (commission > 0) {
                    address(uint160(referrer)).transfer(commission);
                }
            }
            destination.transfer(amountForDestination);
        }
        function handleReferralWithERC20(
            address buyer,
            uint256 amount,
            bytes memory referral,
            address payable destination,
            address tokenAddress
        ) internal {
            ERC20 token = ERC20(tokenAddress);
            uint256 amountForDestination = amount;
            if (referral.length > 0) {
                (
                    bytes memory signature,
                    address referrer,
                    address referee,
                    uint256 expiryTime,
                    uint256 commissionRate
                ) = decodeReferral(referral);
                uint256 commission = 0;
                if (isReferralValid(signature, referrer, referee, expiryTime, commissionRate)) {
                    commission = SafeMathWithRequire.div(
                        SafeMathWithRequire.mul(amount, commissionRate),
                        10000
                    );
                    emit ReferralUsed(
                        referrer,
                        referee,
                        tokenAddress,
                        amount,
                        commission,
                        commissionRate
                    );
                    amountForDestination = SafeMathWithRequire.sub(
                        amountForDestination,
                        commission
                    );
                }
                if (commission > 0) {
                    require(token.transferFrom(buyer, referrer, commission), "commision transfer failed");
                }
            }
            require(token.transferFrom(buyer, destination, amountForDestination), "payment transfer failed");
        }
        /**
         * @notice Check if a referral is valid
         * @param signature The signature to check (signed referral)
         * @param referrer The address of the referrer
         * @param referee The address of the referee
         * @param expiryTime The expiry time of the referral
         * @param commissionRate The commissionRate of the referral
         * @return True if the referral is valid
         */
        function isReferralValid(
            bytes memory signature,
            address referrer,
            address referee,
            uint256 expiryTime,
            uint256 commissionRate
        ) public view returns (
            bool
        ) {
            if (commissionRate > _maxCommissionRate || referrer == referee || now > expiryTime) {
                return false;
            }
            bytes32 hashedData = keccak256(
                abi.encodePacked(
                    referrer,
                    referee,
                    expiryTime,
                    commissionRate
                )
            );
            address signer = SigUtil.recover(
                keccak256(
                    abi.encodePacked("\\x19Ethereum Signed Message:\
    32", hashedData)
                ),
                signature
            );
            if (_previousSigningWallets[signer] >= now) {
                return true;
            }
            return _signingWallet == signer;
        }
        function decodeReferral(
            bytes memory referral
        ) public pure returns (
            bytes memory,
            address,
            address,
            uint256,
            uint256
        ) {
            (
                bytes memory signature,
                address referrer,
                address referee,
                uint256 expiryTime,
                uint256 commissionRate
            ) = abi.decode(referral, (bytes, address, address, uint256, uint256));
            return (
                signature,
                referrer,
                referee,
                expiryTime,
                commissionRate
            );
        }
    }
    

    File 2 of 4: MultiSigWalletWithDailyLimit
    contract Factory {
    
        /*
         *  Events
         */
        event ContractInstantiation(address sender, address instantiation);
    
        /*
         *  Storage
         */
        mapping(address => bool) public isInstantiation;
        mapping(address => address[]) public instantiations;
    
        /*
         * Public functions
         */
        /// @dev Returns number of instantiations by creator.
        /// @param creator Contract creator.
        /// @return Returns number of instantiations by creator.
        function getInstantiationCount(address creator)
            public
            constant
            returns (uint)
        {
            return instantiations[creator].length;
        }
    
        /*
         * Internal functions
         */
        /// @dev Registers contract in factory registry.
        /// @param instantiation Address of contract instantiation.
        function register(address instantiation)
            internal
        {
            isInstantiation[instantiation] = true;
            instantiations[msg.sender].push(instantiation);
            ContractInstantiation(msg.sender, instantiation);
        }
    }
    
    /// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution.
    /// @author Stefan George - <[email protected]>
    contract MultiSigWallet {
    
        /*
         *  Events
         */
        event Confirmation(address indexed sender, uint indexed transactionId);
        event Revocation(address indexed sender, uint indexed transactionId);
        event Submission(uint indexed transactionId);
        event Execution(uint indexed transactionId);
        event ExecutionFailure(uint indexed transactionId);
        event Deposit(address indexed sender, uint value);
        event OwnerAddition(address indexed owner);
        event OwnerRemoval(address indexed owner);
        event RequirementChange(uint required);
    
        /*
         *  Constants
         */
        uint constant public MAX_OWNER_COUNT = 50;
    
        /*
         *  Storage
         */
        mapping (uint => Transaction) public transactions;
        mapping (uint => mapping (address => bool)) public confirmations;
        mapping (address => bool) public isOwner;
        address[] public owners;
        uint public required;
        uint public transactionCount;
    
        struct Transaction {
            address destination;
            uint value;
            bytes data;
            bool executed;
        }
    
        /*
         *  Modifiers
         */
        modifier onlyWallet() {
            require(msg.sender == address(this));
            _;
        }
    
        modifier ownerDoesNotExist(address owner) {
            require(!isOwner[owner]);
            _;
        }
    
        modifier ownerExists(address owner) {
            require(isOwner[owner]);
            _;
        }
    
        modifier transactionExists(uint transactionId) {
            require(transactions[transactionId].destination != 0);
            _;
        }
    
        modifier confirmed(uint transactionId, address owner) {
            require(confirmations[transactionId][owner]);
            _;
        }
    
        modifier notConfirmed(uint transactionId, address owner) {
            require(!confirmations[transactionId][owner]);
            _;
        }
    
        modifier notExecuted(uint transactionId) {
            require(!transactions[transactionId].executed);
            _;
        }
    
        modifier notNull(address _address) {
            require(_address != 0);
            _;
        }
    
        modifier validRequirement(uint ownerCount, uint _required) {
            require(ownerCount <= MAX_OWNER_COUNT
                && _required <= ownerCount
                && _required != 0
                && ownerCount != 0);
            _;
        }
    
        /// @dev Fallback function allows to deposit ether.
        function()
            payable
        {
            if (msg.value > 0)
                Deposit(msg.sender, msg.value);
        }
    
        /*
         * Public functions
         */
        /// @dev Contract constructor sets initial owners and required number of confirmations.
        /// @param _owners List of initial owners.
        /// @param _required Number of required confirmations.
        function MultiSigWallet(address[] _owners, uint _required)
            public
            validRequirement(_owners.length, _required)
        {
            for (uint i=0; i<_owners.length; i++) {
                require(!isOwner[_owners[i]] && _owners[i] != 0);
                isOwner[_owners[i]] = true;
            }
            owners = _owners;
            required = _required;
        }
    
        /// @dev Allows to add a new owner. Transaction has to be sent by wallet.
        /// @param owner Address of new owner.
        function addOwner(address owner)
            public
            onlyWallet
            ownerDoesNotExist(owner)
            notNull(owner)
            validRequirement(owners.length + 1, required)
        {
            isOwner[owner] = true;
            owners.push(owner);
            OwnerAddition(owner);
        }
    
        /// @dev Allows to remove an owner. Transaction has to be sent by wallet.
        /// @param owner Address of owner.
        function removeOwner(address owner)
            public
            onlyWallet
            ownerExists(owner)
        {
            isOwner[owner] = false;
            for (uint i=0; i<owners.length - 1; i++)
                if (owners[i] == owner) {
                    owners[i] = owners[owners.length - 1];
                    break;
                }
            owners.length -= 1;
            if (required > owners.length)
                changeRequirement(owners.length);
            OwnerRemoval(owner);
        }
    
        /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet.
        /// @param owner Address of owner to be replaced.
        /// @param newOwner Address of new owner.
        function replaceOwner(address owner, address newOwner)
            public
            onlyWallet
            ownerExists(owner)
            ownerDoesNotExist(newOwner)
        {
            for (uint i=0; i<owners.length; i++)
                if (owners[i] == owner) {
                    owners[i] = newOwner;
                    break;
                }
            isOwner[owner] = false;
            isOwner[newOwner] = true;
            OwnerRemoval(owner);
            OwnerAddition(newOwner);
        }
    
        /// @dev Allows to change the number of required confirmations. Transaction has to be sent by wallet.
        /// @param _required Number of required confirmations.
        function changeRequirement(uint _required)
            public
            onlyWallet
            validRequirement(owners.length, _required)
        {
            required = _required;
            RequirementChange(_required);
        }
    
        /// @dev Allows an owner to submit and confirm a transaction.
        /// @param destination Transaction target address.
        /// @param value Transaction ether value.
        /// @param data Transaction data payload.
        /// @return Returns transaction ID.
        function submitTransaction(address destination, uint value, bytes data)
            public
            returns (uint transactionId)
        {
            transactionId = addTransaction(destination, value, data);
            confirmTransaction(transactionId);
        }
    
        /// @dev Allows an owner to confirm a transaction.
        /// @param transactionId Transaction ID.
        function confirmTransaction(uint transactionId)
            public
            ownerExists(msg.sender)
            transactionExists(transactionId)
            notConfirmed(transactionId, msg.sender)
        {
            confirmations[transactionId][msg.sender] = true;
            Confirmation(msg.sender, transactionId);
            executeTransaction(transactionId);
        }
    
        /// @dev Allows an owner to revoke a confirmation for a transaction.
        /// @param transactionId Transaction ID.
        function revokeConfirmation(uint transactionId)
            public
            ownerExists(msg.sender)
            confirmed(transactionId, msg.sender)
            notExecuted(transactionId)
        {
            confirmations[transactionId][msg.sender] = false;
            Revocation(msg.sender, transactionId);
        }
    
        /// @dev Allows anyone to execute a confirmed transaction.
        /// @param transactionId Transaction ID.
        function executeTransaction(uint transactionId)
            public
            ownerExists(msg.sender)
            confirmed(transactionId, msg.sender)
            notExecuted(transactionId)
        {
            if (isConfirmed(transactionId)) {
                Transaction storage txn = transactions[transactionId];
                txn.executed = true;
                if (txn.destination.call.value(txn.value)(txn.data))
                    Execution(transactionId);
                else {
                    ExecutionFailure(transactionId);
                    txn.executed = false;
                }
            }
        }
    
        /// @dev Returns the confirmation status of a transaction.
        /// @param transactionId Transaction ID.
        /// @return Confirmation status.
        function isConfirmed(uint transactionId)
            public
            constant
            returns (bool)
        {
            uint count = 0;
            for (uint i=0; i<owners.length; i++) {
                if (confirmations[transactionId][owners[i]])
                    count += 1;
                if (count == required)
                    return true;
            }
        }
    
        /*
         * Internal functions
         */
        /// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet.
        /// @param destination Transaction target address.
        /// @param value Transaction ether value.
        /// @param data Transaction data payload.
        /// @return Returns transaction ID.
        function addTransaction(address destination, uint value, bytes data)
            internal
            notNull(destination)
            returns (uint transactionId)
        {
            transactionId = transactionCount;
            transactions[transactionId] = Transaction({
                destination: destination,
                value: value,
                data: data,
                executed: false
            });
            transactionCount += 1;
            Submission(transactionId);
        }
    
        /*
         * Web3 call functions
         */
        /// @dev Returns number of confirmations of a transaction.
        /// @param transactionId Transaction ID.
        /// @return Number of confirmations.
        function getConfirmationCount(uint transactionId)
            public
            constant
            returns (uint count)
        {
            for (uint i=0; i<owners.length; i++)
                if (confirmations[transactionId][owners[i]])
                    count += 1;
        }
    
        /// @dev Returns total number of transactions after filers are applied.
        /// @param pending Include pending transactions.
        /// @param executed Include executed transactions.
        /// @return Total number of transactions after filters are applied.
        function getTransactionCount(bool pending, bool executed)
            public
            constant
            returns (uint count)
        {
            for (uint i=0; i<transactionCount; i++)
                if (   pending && !transactions[i].executed
                    || executed && transactions[i].executed)
                    count += 1;
        }
    
        /// @dev Returns list of owners.
        /// @return List of owner addresses.
        function getOwners()
            public
            constant
            returns (address[])
        {
            return owners;
        }
    
        /// @dev Returns array with owner addresses, which confirmed transaction.
        /// @param transactionId Transaction ID.
        /// @return Returns array of owner addresses.
        function getConfirmations(uint transactionId)
            public
            constant
            returns (address[] _confirmations)
        {
            address[] memory confirmationsTemp = new address[](owners.length);
            uint count = 0;
            uint i;
            for (i=0; i<owners.length; i++)
                if (confirmations[transactionId][owners[i]]) {
                    confirmationsTemp[count] = owners[i];
                    count += 1;
                }
            _confirmations = new address[](count);
            for (i=0; i<count; i++)
                _confirmations[i] = confirmationsTemp[i];
        }
    
        /// @dev Returns list of transaction IDs in defined range.
        /// @param from Index start position of transaction array.
        /// @param to Index end position of transaction array.
        /// @param pending Include pending transactions.
        /// @param executed Include executed transactions.
        /// @return Returns array of transaction IDs.
        function getTransactionIds(uint from, uint to, bool pending, bool executed)
            public
            constant
            returns (uint[] _transactionIds)
        {
            uint[] memory transactionIdsTemp = new uint[](transactionCount);
            uint count = 0;
            uint i;
            for (i=0; i<transactionCount; i++)
                if (   pending && !transactions[i].executed
                    || executed && transactions[i].executed)
                {
                    transactionIdsTemp[count] = i;
                    count += 1;
                }
            _transactionIds = new uint[](to - from);
            for (i=from; i<to; i++)
                _transactionIds[i - from] = transactionIdsTemp[i];
        }
    }
    
    /// @title Multisignature wallet with daily limit - Allows an owner to withdraw a daily limit without multisig.
    /// @author Stefan George - <[email protected]>
    contract MultiSigWalletWithDailyLimit is MultiSigWallet {
    
        /*
         *  Events
         */
        event DailyLimitChange(uint dailyLimit);
    
        /*
         *  Storage
         */
        uint public dailyLimit;
        uint public lastDay;
        uint public spentToday;
    
        /*
         * Public functions
         */
        /// @dev Contract constructor sets initial owners, required number of confirmations and daily withdraw limit.
        /// @param _owners List of initial owners.
        /// @param _required Number of required confirmations.
        /// @param _dailyLimit Amount in wei, which can be withdrawn without confirmations on a daily basis.
        function MultiSigWalletWithDailyLimit(address[] _owners, uint _required, uint _dailyLimit)
            public
            MultiSigWallet(_owners, _required)
        {
            dailyLimit = _dailyLimit;
        }
    
        /// @dev Allows to change the daily limit. Transaction has to be sent by wallet.
        /// @param _dailyLimit Amount in wei.
        function changeDailyLimit(uint _dailyLimit)
            public
            onlyWallet
        {
            dailyLimit = _dailyLimit;
            DailyLimitChange(_dailyLimit);
        }
    
        /// @dev Allows anyone to execute a confirmed transaction or ether withdraws until daily limit is reached.
        /// @param transactionId Transaction ID.
        function executeTransaction(uint transactionId)
            public
            ownerExists(msg.sender)
            confirmed(transactionId, msg.sender)
            notExecuted(transactionId)
        {
            Transaction storage txn = transactions[transactionId];
            bool _confirmed = isConfirmed(transactionId);
            if (_confirmed || txn.data.length == 0 && isUnderLimit(txn.value)) {
                txn.executed = true;
                if (!_confirmed)
                    spentToday += txn.value;
                if (txn.destination.call.value(txn.value)(txn.data))
                    Execution(transactionId);
                else {
                    ExecutionFailure(transactionId);
                    txn.executed = false;
                    if (!_confirmed)
                        spentToday -= txn.value;
                }
            }
        }
    
        /*
         * Internal functions
         */
        /// @dev Returns if amount is within daily limit and resets spentToday after one day.
        /// @param amount Amount to withdraw.
        /// @return Returns if amount is under daily limit.
        function isUnderLimit(uint amount)
            internal
            returns (bool)
        {
            if (now > lastDay + 24 hours) {
                lastDay = now;
                spentToday = 0;
            }
            if (spentToday + amount > dailyLimit || spentToday + amount < spentToday)
                return false;
            return true;
        }
    
        /*
         * Web3 call functions
         */
        /// @dev Returns maximum withdraw amount.
        /// @return Returns amount.
        function calcMaxWithdraw()
            public
            constant
            returns (uint)
        {
            if (now > lastDay + 24 hours)
                return dailyLimit;
            if (dailyLimit < spentToday)
                return 0;
            return dailyLimit - spentToday;
        }
    }

    File 3 of 4: Land
    pragma solidity ^0.5.2;
    contract Admin {
        address internal _admin;
        event AdminChanged(address oldAdmin, address newAdmin);
        /// @notice gives the current administrator of this contract.
        /// @return the current administrator of this contract.
        function getAdmin() external view returns (address) {
            return _admin;
        }
        /// @notice change the administrator to be `newAdmin`.
        /// @param newAdmin address of the new administrator.
        function changeAdmin(address newAdmin) external {
            require(msg.sender == _admin, "only admin can change admin");
            emit AdminChanged(_admin, newAdmin);
            _admin = newAdmin;
        }
        modifier onlyAdmin() {
            require (msg.sender == _admin, "only admin allowed");
            _;
        }
    }
    pragma solidity ^0.5.2;
    import "./Admin.sol";
    contract MetaTransactionReceiver is Admin{
        mapping(address => bool) internal _metaTransactionContracts;
        event MetaTransactionProcessor(address metaTransactionProcessor, bool enabled);
        /// @notice Enable or disable the ability of `metaTransactionProcessor` to perform meta-tx (metaTransactionProcessor rights).
        /// @param metaTransactionProcessor address that will be given/removed metaTransactionProcessor rights.
        /// @param enabled set whether the metaTransactionProcessor is enabled or disabled.
        function setMetaTransactionProcessor(address metaTransactionProcessor, bool enabled) public {
            require(
                msg.sender == _admin,
                "only admin can setup metaTransactionProcessors"
            );
            _setMetaTransactionProcessor(metaTransactionProcessor, enabled);
        }
        function _setMetaTransactionProcessor(address metaTransactionProcessor, bool enabled) internal {
            _metaTransactionContracts[metaTransactionProcessor] = enabled;
            emit MetaTransactionProcessor(metaTransactionProcessor, enabled);
        }
        /// @notice check whether address `who` is given meta-transaction execution rights.
        /// @param who The address to query.
        /// @return whether the address has meta-transaction execution rights.
        function isMetaTransactionProcessor(address who) external view returns(bool) {
            return _metaTransactionContracts[who];
        }
    }pragma solidity ^0.5.2;
    import "./Admin.sol";
    contract SuperOperators is Admin {
        mapping(address => bool) internal _superOperators;
        event SuperOperator(address superOperator, bool enabled);
        /// @notice Enable or disable the ability of `superOperator` to transfer tokens of all (superOperator rights).
        /// @param superOperator address that will be given/removed superOperator right.
        /// @param enabled set whether the superOperator is enabled or disabled.
        function setSuperOperator(address superOperator, bool enabled) external {
            require(
                msg.sender == _admin,
                "only admin is allowed to add super operators"
            );
            _superOperators[superOperator] = enabled;
            emit SuperOperator(superOperator, enabled);
        }
        /// @notice check whether address `who` is given superOperator rights.
        /// @param who The address to query.
        /// @return whether the address has superOperator rights.
        function isSuperOperator(address who) public view returns (bool) {
            return _superOperators[who];
        }
    }
    pragma solidity ^0.5.2;
    /**
     * @title ERC721 Non-Fungible Token Standard basic interface
     * @dev see https://eips.ethereum.org/EIPS/eip-721
     */
    interface ERC721Events {
        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
        );
    }
    pragma solidity ^0.5.2;
    /**
        Note: The ERC-165 identifier for this interface is 0x5e8bf644.
    */
    interface ERC721MandatoryTokenReceiver {
        function onERC721BatchReceived(
            address operator,
            address from,
            uint256[] calldata ids,
            bytes calldata data
        ) external returns (bytes4); // needs to return 0x4b808c46
        function onERC721Received(
            address operator,
            address from,
            uint256 tokenId,
            bytes calldata data
        ) external returns (bytes4); // needs to return 0x150b7a02
        // needs to implements EIP-165
        // function supportsInterface(bytes4 interfaceId)
        //     external
        //     view
        //     returns (bool);
    }
    /* This Source Code Form is subject to the terms of the Mozilla Public
     * License, v. 2.0. If a copy of the MPL was not distributed with this
     * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     *
     * This code has not been reviewed.
     * Do not use or deploy this code before reviewing it personally first.
     */
    // solhint-disable-next-line compiler-fixed
    pragma solidity ^0.5.2;
    interface ERC721TokenReceiver {
        function onERC721Received(
            address operator,
            address from,
            uint256 tokenId,
            bytes calldata data
        ) external returns (bytes4);
    }
    pragma solidity ^0.5.2;
    library AddressUtils {
        function toPayable(address _address) internal pure returns (address payable _payable) {
            return address(uint160(_address));
        }
        function isContract(address addr) internal view returns (bool) {
            // for accounts without code, i.e. `keccak256('')`:
            bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
            bytes32 codehash;
            // solium-disable-next-line security/no-inline-assembly
            assembly {
                codehash := extcodehash(addr)
            }
            return (codehash != 0x0 && codehash != accountHash);
        }
    }
    /* solhint-disable no-empty-blocks */
    pragma solidity 0.5.9;
    import "./Land/erc721/LandBaseToken.sol";
    contract Land is LandBaseToken {
        constructor(
            address metaTransactionContract,
            address admin
        ) public LandBaseToken(
            metaTransactionContract,
            admin
        ) {
        }
        /**
         * @notice Return the name of the token contract
         * @return The name of the token contract
         */
        function name() external pure returns (string memory) {
            return "Sandbox's LANDs";
        }
        /**
         * @notice Return the symbol of the token contract
         * @return The symbol of the token contract
         */
        function symbol() external pure returns (string memory) {
            return "LAND";
        }
        // solium-disable-next-line security/no-assign-params
        function uint2str(uint _i) internal pure returns (string memory) {
            if (_i == 0) {
                return "0";
            }
            uint j = _i;
            uint len;
            while (j != 0) {
                len++;
                j /= 10;
            }
            bytes memory bstr = new bytes(len);
            uint k = len - 1;
            while (_i != 0) {
                bstr[k--] = byte(uint8(48 + _i % 10));
                _i /= 10;
            }
            return string(bstr);
        }
        /**
         * @notice Return the URI of a specific token
         * @param id The id of the token
         * @return The URI of the token
         */
        function tokenURI(uint256 id) public view returns (string memory) {
            require(_ownerOf(id) != address(0), "Id does not exist");
            return
                string(
                    abi.encodePacked(
                        "https://api.sandbox.game/lands/",
                        uint2str(id),
                        "/metadata.json"
                    )
                );
        }
        /**
         * @notice Check if the contract supports an interface
         * 0x01ffc9a7 is ERC-165
         * 0x80ac58cd is ERC-721
         * 0x5b5e139f is ERC-721 metadata
         * @param id The id of the interface
         * @return True if the interface is supported
         */
        function supportsInterface(bytes4 id) external pure returns (bool) {
            return id == 0x01ffc9a7 || id == 0x80ac58cd || id == 0x5b5e139f;
        }
    }
    /* solhint-disable func-order, code-complexity */
    pragma solidity 0.5.9;
    import "../../../contracts_common/src/Libraries/AddressUtils.sol";
    import "../../../contracts_common/src/Interfaces/ERC721TokenReceiver.sol";
    import "../../../contracts_common/src/Interfaces/ERC721Events.sol";
    import "../../../contracts_common/src/BaseWithStorage/SuperOperators.sol";
    import "../../../contracts_common/src/BaseWithStorage/MetaTransactionReceiver.sol";
    import "../../../contracts_common/src/Interfaces/ERC721MandatoryTokenReceiver.sol";
    contract ERC721BaseToken is ERC721Events, SuperOperators, MetaTransactionReceiver {
        using AddressUtils for address;
        bytes4 internal constant _ERC721_RECEIVED = 0x150b7a02;
        bytes4 internal constant _ERC721_BATCH_RECEIVED = 0x4b808c46;
        bytes4 internal constant ERC165ID = 0x01ffc9a7;
        bytes4 internal constant ERC721_MANDATORY_RECEIVER = 0x5e8bf644;
        mapping (address => uint256) public _numNFTPerAddress;
        mapping (uint256 => uint256) public _owners;
        mapping (address => mapping(address => bool)) public _operatorsForAll;
        mapping (uint256 => address) public _operators;
        constructor(
            address metaTransactionContract,
            address admin
        ) internal {
            _admin = admin;
            _setMetaTransactionProcessor(metaTransactionContract, true);
        }
        function _transferFrom(address from, address to, uint256 id) internal {
            _numNFTPerAddress[from]--;
            _numNFTPerAddress[to]++;
            _owners[id] = uint256(to);
            emit Transfer(from, to, id);
        }
        /**
         * @notice Return the number of Land owned by an address
         * @param owner The address to look for
         * @return The number of Land token owned by the address
         */
        function balanceOf(address owner) external view returns (uint256) {
            require(owner != address(0), "owner is zero address");
            return _numNFTPerAddress[owner];
        }
        function _ownerOf(uint256 id) internal view returns (address) {
            return address(_owners[id]);
        }
        function _ownerAndOperatorEnabledOf(uint256 id) internal view returns (address owner, bool operatorEnabled) {
            uint256 data = _owners[id];
            owner = address(data);
            operatorEnabled = (data / 2**255) == 1;
        }
        /**
         * @notice Return the owner of a Land
         * @param id The id of the Land
         * @return The address of the owner
         */
        function ownerOf(uint256 id) external view returns (address owner) {
            owner = _ownerOf(id);
            require(owner != address(0), "token does not exist");
        }
        function _approveFor(address owner, address operator, uint256 id) internal {
            if(operator == address(0)) {
                _owners[id] = uint256(owner); // no need to resset the operator, it will be overriden next time
            } else {
                _owners[id] = uint256(owner) + 2**255;
                _operators[id] = operator;
            }
            emit Approval(owner, operator, id);
        }
        /**
         * @notice Approve an operator to spend tokens on the sender behalf
         * @param sender The address giving the approval
         * @param operator The address receiving the approval
         * @param id The id of the token
         */
        function approveFor(
            address sender,
            address operator,
            uint256 id
        ) external {
            address owner = _ownerOf(id);
            require(sender != address(0), "sender is zero address");
            require(
                msg.sender == sender ||
                _metaTransactionContracts[msg.sender] ||
                _superOperators[msg.sender] ||
                _operatorsForAll[sender][msg.sender],
                "not authorized to approve"
            );
            require(owner == sender, "owner != sender");
            _approveFor(owner, operator, id);
        }
        /**
         * @notice Approve an operator to spend tokens on the sender behalf
         * @param operator The address receiving the approval
         * @param id The id of the token
         */
        function approve(address operator, uint256 id) external {
            address owner = _ownerOf(id);
            require(owner != address(0), "token does not exist");
            require(
                owner == msg.sender ||
                _superOperators[msg.sender] ||
                _operatorsForAll[owner][msg.sender],
                "not authorized to approve"
            );
            _approveFor(owner, operator, id);
        }
        /**
         * @notice Get the approved operator for a specific token
         * @param id The id of the token
         * @return The address of the operator
         */
        function getApproved(uint256 id) external view returns (address) {
            (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
            require(owner != address(0), "token does not exist");
            if (operatorEnabled) {
                return _operators[id];
            } else {
                return address(0);
            }
        }
        function _checkTransfer(address from, address to, uint256 id) internal view returns (bool isMetaTx) {
            (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
            require(owner != address(0), "token does not exist");
            require(owner == from, "not owner in _checkTransfer");
            require(to != address(0), "can't send to zero address");
            isMetaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
            if (msg.sender != from && !isMetaTx) {
                require(
                    _superOperators[msg.sender] ||
                    _operatorsForAll[from][msg.sender] ||
                    (operatorEnabled && _operators[id] == msg.sender),
                    "not approved to transfer"
                );
            }
        }
        function _checkInterfaceWith10000Gas(address _contract, bytes4 interfaceId)
            internal
            view
            returns (bool)
        {
            bool success;
            bool result;
            bytes memory call_data = abi.encodeWithSelector(
                ERC165ID,
                interfaceId
            );
            // solium-disable-next-line security/no-inline-assembly
            assembly {
                let call_ptr := add(0x20, call_data)
                let call_size := mload(call_data)
                let output := mload(0x40) // Find empty storage location using "free memory pointer"
                mstore(output, 0x0)
                success := staticcall(
                    10000,
                    _contract,
                    call_ptr,
                    call_size,
                    output,
                    0x20
                ) // 32 bytes
                result := mload(output)
            }
            // (10000 / 63) "not enough for supportsInterface(...)" // consume all gas, so caller can potentially know that there was not enough gas
            assert(gasleft() > 158);
            return success && result;
        }
        /**
         * @notice Transfer a token between 2 addresses
         * @param from The sender of the token
         * @param to The recipient of the token
         * @param id The id of the token
        */
        function transferFrom(address from, address to, uint256 id) external {
            bool metaTx = _checkTransfer(from, to, id);
            _transferFrom(from, to, id);
            if (to.isContract() && _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER)) {
                require(
                    _checkOnERC721Received(metaTx ? from : msg.sender, from, to, id, ""),
                    "erc721 transfer rejected by to"
                );
            }
        }
        /**
         * @notice Transfer a token between 2 addresses letting the receiver knows of the transfer
         * @param from The sender of the token
         * @param to The recipient of the token
         * @param id The id of the token
         * @param data Additional data
         */
        function safeTransferFrom(address from, address to, uint256 id, bytes memory data) public {
            bool metaTx = _checkTransfer(from, to, id);
            _transferFrom(from, to, id);
            if (to.isContract()) {
                require(
                    _checkOnERC721Received(metaTx ? from : msg.sender, from, to, id, data),
                    "ERC721: transfer rejected by to"
                );
            }
        }
        /**
         * @notice Transfer a token between 2 addresses letting the receiver knows of the transfer
         * @param from The send of the token
         * @param to The recipient of the token
         * @param id The id of the token
         */
        function safeTransferFrom(address from, address to, uint256 id) external {
            safeTransferFrom(from, to, id, "");
        }
        /**
         * @notice Transfer many tokens between 2 addresses
         * @param from The sender of the token
         * @param to The recipient of the token
         * @param ids The ids of the tokens
         * @param data additional data
        */
        function batchTransferFrom(address from, address to, uint256[] calldata ids, bytes calldata data) external {
            _batchTransferFrom(from, to, ids, data, false);
        }
        function _batchTransferFrom(address from, address to, uint256[] memory ids, bytes memory data, bool safe) internal {
            bool metaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
            bool authorized = msg.sender == from ||
                metaTx ||
                _superOperators[msg.sender] ||
                _operatorsForAll[from][msg.sender];
            require(from != address(0), "from is zero address");
            require(to != address(0), "can't send to zero address");
            uint256 numTokens = ids.length;
            for(uint256 i = 0; i < numTokens; i ++) {
                uint256 id = ids[i];
                (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
                require(owner == from, "not owner in batchTransferFrom");
                require(authorized || (operatorEnabled && _operators[id] == msg.sender), "not authorized");
                _owners[id] = uint256(to);
                emit Transfer(from, to, id);
            }
            if (from != to) {
                _numNFTPerAddress[from] -= numTokens;
                _numNFTPerAddress[to] += numTokens;
            }
            if (to.isContract() && (safe || _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER))) {
                require(
                    _checkOnERC721BatchReceived(metaTx ? from : msg.sender, from, to, ids, data),
                    "erc721 batch transfer rejected by to"
                );
            }
        }
        /**
         * @notice Transfer many tokens between 2 addresses ensuring the receiving contract has a receiver method
         * @param from The sender of the token
         * @param to The recipient of the token
         * @param ids The ids of the tokens
         * @param data additional data
        */
        function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, bytes calldata data) external {
            _batchTransferFrom(from, to, ids, data, true);
        }
        /**
         * @notice Check if the contract supports an interface
         * 0x01ffc9a7 is ERC-165
         * 0x80ac58cd is ERC-721
         * @param id The id of the interface
         * @return True if the interface is supported
         */
        function supportsInterface(bytes4 id) external pure returns (bool) {
            return id == 0x01ffc9a7 || id == 0x80ac58cd;
        }
        /**
         * @notice Set the approval for an operator to manage all the tokens of the sender
         * @param sender The address giving the approval
         * @param operator The address receiving the approval
         * @param approved The determination of the approval
         */
        function setApprovalForAllFor(
            address sender,
            address operator,
            bool approved
        ) external {
            require(sender != address(0), "Invalid sender address");
            require(
                msg.sender == sender ||
                _metaTransactionContracts[msg.sender] ||
                _superOperators[msg.sender],
                "not authorized to approve for all"
            );
            _setApprovalForAll(sender, operator, approved);
        }
        /**
         * @notice Set the approval for an operator to manage all the tokens of the sender
         * @param operator The address receiving the approval
         * @param approved The determination of the approval
         */
        function setApprovalForAll(address operator, bool approved) external {
            _setApprovalForAll(msg.sender, operator, approved);
        }
        function _setApprovalForAll(
            address sender,
            address operator,
            bool approved
        ) internal {
            require(
                !_superOperators[operator],
                "super operator can't have their approvalForAll changed"
            );
            _operatorsForAll[sender][operator] = approved;
            emit ApprovalForAll(sender, operator, approved);
        }
        /**
         * @notice Check if the sender approved the operator
         * @param owner The address of the owner
         * @param operator The address of the operator
         * @return The status of the approval
         */
        function isApprovedForAll(address owner, address operator)
            external
            view
            returns (bool isOperator)
        {
            return _operatorsForAll[owner][operator] || _superOperators[operator];
        }
        function _burn(address from, address owner, uint256 id) public {
            require(from == owner, "not owner");
            _owners[id] = 2**160; // cannot mint it again
            _numNFTPerAddress[from]--;
            emit Transfer(from, address(0), id);
        }
        /// @notice Burns token `id`.
        /// @param id token which will be burnt.
        function burn(uint256 id) external {
            _burn(msg.sender, _ownerOf(id), id);
        }
        /// @notice Burn token`id` from `from`.
        /// @param from address whose token is to be burnt.
        /// @param id token which will be burnt.
        function burnFrom(address from, uint256 id) external {
            require(from != address(0), "Invalid sender address");
            (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
            require(
                msg.sender == from ||
                _metaTransactionContracts[msg.sender] ||
                (operatorEnabled && _operators[id] == msg.sender) ||
                _superOperators[msg.sender] ||
                _operatorsForAll[from][msg.sender],
                "not authorized to burn"
            );
            _burn(from, owner, id);
        }
        function _checkOnERC721Received(address operator, address from, address to, uint256 tokenId, bytes memory _data)
            internal returns (bool)
        {
            bytes4 retval = ERC721TokenReceiver(to).onERC721Received(operator, from, tokenId, _data);
            return (retval == _ERC721_RECEIVED);
        }
        function _checkOnERC721BatchReceived(address operator, address from, address to, uint256[] memory ids, bytes memory _data)
            internal returns (bool)
        {
            bytes4 retval = ERC721MandatoryTokenReceiver(to).onERC721BatchReceived(operator, from, ids, _data);
            return (retval == _ERC721_BATCH_RECEIVED);
        }
    }
    /* solhint-disable func-order, code-complexity */
    pragma solidity 0.5.9;
    import "./ERC721BaseToken.sol";
    contract LandBaseToken is ERC721BaseToken {
        // Our grid is 408 x 408 lands
        uint256 internal constant GRID_SIZE = 408;
        uint256 internal constant LAYER =          0xFF00000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_1x1 =      0x0000000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_3x3 =      0x0100000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_6x6 =      0x0200000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_12x12 =    0x0300000000000000000000000000000000000000000000000000000000000000;
        uint256 internal constant LAYER_24x24 =    0x0400000000000000000000000000000000000000000000000000000000000000;
        mapping(address => bool) internal _minters;
        event Minter(address superOperator, bool enabled);
        /// @notice Enable or disable the ability of `minter` to mint tokens
        /// @param minter address that will be given/removed minter right.
        /// @param enabled set whether the minter is enabled or disabled.
        function setMinter(address minter, bool enabled) external {
            require(
                msg.sender == _admin,
                "only admin is allowed to add minters"
            );
            _minters[minter] = enabled;
            emit Minter(minter, enabled);
        }
        /// @notice check whether address `who` is given minter rights.
        /// @param who The address to query.
        /// @return whether the address has minter rights.
        function isMinter(address who) public view returns (bool) {
            return _minters[who];
        }
        constructor(
            address metaTransactionContract,
            address admin
        ) public ERC721BaseToken(metaTransactionContract, admin) {
        }
        /// @notice total width of the map
        /// @return width
        function width() external returns(uint256) {
            return GRID_SIZE;
        }
        /// @notice total height of the map
        /// @return height
        function height() external returns(uint256) {
            return GRID_SIZE;
        }
        /// @notice x coordinate of Land token
        /// @param id tokenId
        /// @return the x coordinates
        function x(uint256 id) external returns(uint256) {
            require(_ownerOf(id) != address(0), "token does not exist");
            return id % GRID_SIZE;
        }
        /// @notice y coordinate of Land token
        /// @param id tokenId
        /// @return the y coordinates
        function y(uint256 id) external returns(uint256) {
            require(_ownerOf(id) != address(0), "token does not exist");
            return id / GRID_SIZE;
        }
        /**
         * @notice Mint a new quad (aligned to a quad tree with size 3, 6, 12 or 24 only)
         * @param to The recipient of the new quad
         * @param size The size of the new quad
         * @param x The top left x coordinate of the new quad
         * @param y The top left y coordinate of the new quad
         * @param data extra data to pass to the transfer
         */
        function mintQuad(address to, uint256 size, uint256 x, uint256 y, bytes calldata data) external {
            require(to != address(0), "to is zero address");
            require(
                isMinter(msg.sender),
                "Only a minter can mint"
            );
            require(x % size == 0 && y % size == 0, "Invalid coordinates");
            require(x <= GRID_SIZE - size && y <= GRID_SIZE - size, "Out of bounds");
            uint256 quadId;
            uint256 id = x + y * GRID_SIZE;
            if (size == 1) {
                quadId = id;
            } else if (size == 3) {
                quadId = LAYER_3x3 + id;
            } else if (size == 6) {
                quadId = LAYER_6x6 + id;
            } else if (size == 12) {
                quadId = LAYER_12x12 + id;
            } else if (size == 24) {
                quadId = LAYER_24x24 + id;
            } else {
                require(false, "Invalid size");
            }
            require(_owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE] == 0, "Already minted as 24x24");
            uint256 toX = x+size;
            uint256 toY = y+size;
            if (size <= 12) {
                require(
                    _owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE] == 0,
                    "Already minted as 12x12"
                );
            } else {
                for (uint256 x12i = x; x12i < toX; x12i += 12) {
                    for (uint256 y12i = y; y12i < toY; y12i += 12) {
                        uint256 id12x12 = LAYER_12x12 + x12i + y12i * GRID_SIZE;
                        require(_owners[id12x12] == 0, "Already minted as 12x12");
                    }
                }
            }
            if (size <= 6) {
                require(_owners[LAYER_6x6 + (x/6) * 6 + ((y/6) * 6) * GRID_SIZE] == 0, "Already minted as 6x6");
            } else {
                for (uint256 x6i = x; x6i < toX; x6i += 6) {
                    for (uint256 y6i = y; y6i < toY; y6i += 6) {
                        uint256 id6x6 = LAYER_6x6 + x6i + y6i * GRID_SIZE;
                        require(_owners[id6x6] == 0, "Already minted as 6x6");
                    }
                }
            }
            if (size <= 3) {
                require(_owners[LAYER_3x3 + (x/3) * 3 + ((y/3) * 3) * GRID_SIZE] == 0, "Already minted as 3x3");
            } else {
                for (uint256 x3i = x; x3i < toX; x3i += 3) {
                    for (uint256 y3i = y; y3i < toY; y3i += 3) {
                        uint256 id3x3 = LAYER_3x3 + x3i + y3i * GRID_SIZE;
                        require(_owners[id3x3] == 0, "Already minted as 3x3");
                    }
                }
            }
            for (uint256 i = 0; i < size*size; i++) {
                uint256 id = _idInPath(i, size, x, y);
                require(_owners[id] == 0, "Already minted");
                emit Transfer(address(0), to, id);
            }
            _owners[quadId] = uint256(to);
            _numNFTPerAddress[to] += size * size;
            _checkBatchReceiverAcceptQuad(msg.sender, address(0), to, size, x, y, data);
        }
        function _idInPath(uint256 i, uint256 size, uint256 x, uint256 y) internal pure returns(uint256) {
            uint256 row = i / size;
            if(row % 2 == 0) { // alow ids to follow a path in a quad
                return (x + (i%size)) + ((y + row) * GRID_SIZE);
            } else {
                return ((x + size) - (1 + i%size)) + ((y + row) * GRID_SIZE);
            }
        }
        /// @notice transfer one quad (aligned to a quad tree with size 3, 6, 12 or 24 only)
        /// @param from current owner of the quad
        /// @param to destination
        /// @param size size of the quad
        /// @param x The top left x coordinate of the quad
        /// @param y The top left y coordinate of the quad
        /// @param data additional data
        function transferQuad(address from, address to, uint256 size, uint256 x, uint256 y, bytes calldata data) external {
            require(from != address(0), "from is zero address");
            require(to != address(0), "can't send to zero address");
            bool metaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
            if (msg.sender != from && !metaTx) {
                require(
                    _superOperators[msg.sender] ||
                    _operatorsForAll[from][msg.sender],
                    "not authorized to transferQuad"
                );
            }
            _transferQuad(from, to, size, x, y);
            _numNFTPerAddress[from] -= size * size;
            _numNFTPerAddress[to] += size * size;
            _checkBatchReceiverAcceptQuad(metaTx ? from : msg.sender, from, to, size, x, y, data);
        }
        function _checkBatchReceiverAcceptQuad(
            address operator,
            address from,
            address to,
            uint256 size,
            uint256 x,
            uint256 y,
            bytes memory data
        ) internal {
            if (to.isContract() && _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER)) {
                uint256[] memory ids = new uint256[](size*size);
                for (uint256 i = 0; i < size*size; i++) {
                    ids[i] = _idInPath(i, size, x, y);
                }
                require(
                    _checkOnERC721BatchReceived(operator, from, to, ids, data),
                    "erc721 batch transfer rejected by to"
                );
            }
        }
        /// @notice transfer multiple quad (aligned to a quad tree with size 3, 6, 12 or 24 only)
        /// @param from current owner of the quad
        /// @param to destination
        /// @param sizes list of sizes for each quad
        /// @param xs list of top left x coordinates for each quad
        /// @param ys list of top left y coordinates for each quad
        /// @param data additional data
        function batchTransferQuad(
            address from,
            address to,
            uint256[] calldata sizes,
            uint256[] calldata xs,
            uint256[] calldata ys,
            bytes calldata data
        ) external {
            require(from != address(0), "from is zero address");
            require(to != address(0), "can't send to zero address");
            require(sizes.length == xs.length && xs.length == ys.length, "invalid data");
            bool metaTx = msg.sender != from && _metaTransactionContracts[msg.sender];
            if (msg.sender != from && !metaTx) {
                require(
                    _superOperators[msg.sender] ||
                    _operatorsForAll[from][msg.sender],
                    "not authorized to transferMultiQuads"
                );
            }
            uint256 numTokensTransfered = 0;
            for (uint256 i = 0; i < sizes.length; i++) {
                uint256 size = sizes[i];
                _transferQuad(from, to, size, xs[i], ys[i]);
                numTokensTransfered += size * size;
            }
            _numNFTPerAddress[from] -= numTokensTransfered;
            _numNFTPerAddress[to] += numTokensTransfered;
            if (to.isContract() && _checkInterfaceWith10000Gas(to, ERC721_MANDATORY_RECEIVER)) {
                uint256[] memory ids = new uint256[](numTokensTransfered);
                uint256 counter = 0;
                for (uint256 j = 0; j < sizes.length; j++) {
                    uint256 size = sizes[j];
                    for (uint256 i = 0; i < size*size; i++) {
                        ids[counter] = _idInPath(i, size, xs[j], ys[j]);
                        counter++;
                    }
                }
                require(
                    _checkOnERC721BatchReceived(metaTx ? from : msg.sender, from, to, ids, data),
                    "erc721 batch transfer rejected by to"
                );
            }
        }
        function _transferQuad(address from, address to, uint256 size, uint256 x, uint256 y) internal {
            if (size == 1) {
                uint256 id1x1 = x + y * GRID_SIZE;
                address owner = _ownerOf(id1x1);
                require(owner != address(0), "token does not exist");
                require(owner == from, "not owner in _transferQuad");
                _owners[id1x1] = uint256(to);
            } else {
                _regroup(from, to, size, x, y);
            }
            for (uint256 i = 0; i < size*size; i++) {
                emit Transfer(from, to, _idInPath(i, size, x, y));
            }
        }
        function _checkAndClear(address from, uint256 id) internal returns(bool) {
            uint256 owner = _owners[id];
            if (owner != 0) {
                require(address(owner) == from, "not owner");
                _owners[id] = 0;
                return true;
            }
            return false;
        }
        function _regroup(address from, address to, uint256 size, uint256 x, uint256 y) internal {
            require(x % size == 0 && y % size == 0, "Invalid coordinates");
            require(x <= GRID_SIZE - size && y <= GRID_SIZE - size, "Out of bounds");
            if (size == 3) {
                _regroup3x3(from, to, x, y, true);
            } else if (size == 6) {
                _regroup6x6(from, to, x, y, true);
            } else if (size == 12) {
                _regroup12x12(from, to, x, y, true);
            } else if (size == 24) {
                _regroup24x24(from, to, x, y, true);
            } else {
                require(false, "Invalid size");
            }
        }
        function _regroup3x3(address from, address to, uint256 x, uint256 y, bool set) internal returns (bool) {
            uint256 id = x + y * GRID_SIZE;
            uint256 quadId = LAYER_3x3 + id;
            bool ownerOfAll = true;
            for (uint256 xi = x; xi < x+3; xi++) {
                for (uint256 yi = y; yi < y+3; yi++) {
                    ownerOfAll = _checkAndClear(from, xi + yi * GRID_SIZE) && ownerOfAll;
                }
            }
            if(set) {
                if(!ownerOfAll) {
                    require(
                        _owners[quadId] == uint256(from) ||
                        _owners[LAYER_6x6 + (x/6) * 6 + ((y/6) * 6) * GRID_SIZE] == uint256(from) ||
                        _owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE] == uint256(from) ||
                        _owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE] == uint256(from),
                        "not owner of all sub quads nor parent quads"
                    );
                }
                _owners[quadId] = uint256(to);
                return true;
            }
            return ownerOfAll;
        }
        function _regroup6x6(address from, address to, uint256 x, uint256 y, bool set) internal returns (bool) {
            uint256 id = x + y * GRID_SIZE;
            uint256 quadId = LAYER_6x6 + id;
            bool ownerOfAll = true;
            for (uint256 xi = x; xi < x+6; xi += 3) {
                for (uint256 yi = y; yi < y+6; yi += 3) {
                    bool ownAllIndividual = _regroup3x3(from, to, xi, yi, false);
                    uint256 id3x3 = LAYER_3x3 + xi + yi * GRID_SIZE;
                    uint256 owner3x3 = _owners[id3x3];
                    if (owner3x3 != 0) {
                        if(!ownAllIndividual) {
                            require(owner3x3 == uint256(from), "not owner of 3x3 quad");
                        }
                        _owners[id3x3] = 0;
                    }
                    ownerOfAll = (ownAllIndividual || owner3x3 != 0) && ownerOfAll;
                }
            }
            if(set) {
                if(!ownerOfAll) {
                    require(
                        _owners[quadId] == uint256(from) ||
                        _owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE] == uint256(from) ||
                        _owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE] == uint256(from),
                        "not owner of all sub quads nor parent quads"
                    );
                }
                _owners[quadId] = uint256(to);
                return true;
            }
            return ownerOfAll;
        }
        function _regroup12x12(address from, address to, uint256 x, uint256 y, bool set) internal returns (bool) {
            uint256 id = x + y * GRID_SIZE;
            uint256 quadId = LAYER_12x12 + id;
            bool ownerOfAll = true;
            for (uint256 xi = x; xi < x+12; xi += 6) {
                for (uint256 yi = y; yi < y+12; yi += 6) {
                    bool ownAllIndividual = _regroup6x6(from, to, xi, yi, false);
                    uint256 id6x6 = LAYER_6x6 + xi + yi * GRID_SIZE;
                    uint256 owner6x6 = _owners[id6x6];
                    if (owner6x6 != 0) {
                        if(!ownAllIndividual) {
                            require(owner6x6 == uint256(from), "not owner of 6x6 quad");
                        }
                        _owners[id6x6] = 0;
                    }
                    ownerOfAll = (ownAllIndividual || owner6x6 != 0) && ownerOfAll;
                }
            }
            if(set) {
                if(!ownerOfAll) {
                    require(
                        _owners[quadId] == uint256(from) ||
                        _owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE] == uint256(from),
                        "not owner of all sub quads nor parent quads"
                    );
                }
                _owners[quadId] = uint256(to);
                return true;
            }
            return ownerOfAll;
        }
        function _regroup24x24(address from, address to, uint256 x, uint256 y, bool set) internal returns (bool) {
            uint256 id = x + y * GRID_SIZE;
            uint256 quadId = LAYER_24x24 + id;
            bool ownerOfAll = true;
            for (uint256 xi = x; xi < x+24; xi += 12) {
                for (uint256 yi = y; yi < y+24; yi += 12) {
                    bool ownAllIndividual = _regroup12x12(from, to, xi, yi, false);
                    uint256 id12x12 = LAYER_12x12 + xi + yi * GRID_SIZE;
                    uint256 owner12x12 = _owners[id12x12];
                    if (owner12x12 != 0) {
                        if(!ownAllIndividual) {
                            require(owner12x12 == uint256(from), "not owner of 12x12 quad");
                        }
                        _owners[id12x12] = 0;
                    }
                    ownerOfAll = (ownAllIndividual || owner12x12 != 0) && ownerOfAll;
                }
            }
            if(set) {
                if(!ownerOfAll) {
                    require(
                        _owners[quadId] == uint256(from),
                        "not owner of all sub quads not parent quad"
                    );
                }
                _owners[quadId] = uint256(to);
                return true;
            }
            return ownerOfAll || _owners[quadId] == uint256(from);
        }
        function _ownerOf(uint256 id) internal view returns (address) {
            require(id & LAYER == 0, "Invalid token id");
            uint256 x = id % GRID_SIZE;
            uint256 y = id / GRID_SIZE;
            uint256 owner1x1 = _owners[id];
            if (owner1x1 != 0) {
                return address(owner1x1); // cast to zero
            } else {
                address owner3x3 = address(_owners[LAYER_3x3 + (x/3) * 3 + ((y/3) * 3) * GRID_SIZE]);
                if (owner3x3 != address(0)) {
                    return owner3x3;
                } else {
                    address owner6x6 = address(_owners[LAYER_6x6 + (x/6) * 6 + ((y/6) * 6) * GRID_SIZE]);
                    if (owner6x6 != address(0)) {
                        return owner6x6;
                    } else {
                        address owner12x12 = address(_owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE]);
                        if (owner12x12 != address(0)) {
                            return owner12x12;
                        } else {
                            return address(_owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE]);
                        }
                    }
                }
            }
        }
        function _ownerAndOperatorEnabledOf(uint256 id) internal view returns (address owner, bool operatorEnabled) {
            require(id & LAYER == 0, "Invalid token id");
            uint256 x = id % GRID_SIZE;
            uint256 y = id / GRID_SIZE;
            uint256 owner1x1 = _owners[id];
            if (owner1x1 != 0) {
                owner = address(owner1x1);
                operatorEnabled = (owner1x1 / 2**255) == 1;
            } else {
                address owner3x3 = address(_owners[LAYER_3x3 + (x/3) * 3 + ((y/3) * 3) * GRID_SIZE]);
                if (owner3x3 != address(0)) {
                    owner = owner3x3;
                    operatorEnabled = false;
                } else {
                    address owner6x6 = address(_owners[LAYER_6x6 + (x/6) * 6 + ((y/6) * 6) * GRID_SIZE]);
                    if (owner6x6 != address(0)) {
                        owner = owner6x6;
                        operatorEnabled = false;
                    } else {
                        address owner12x12 = address(_owners[LAYER_12x12 + (x/12) * 12 + ((y/12) * 12) * GRID_SIZE]);
                        if (owner12x12 != address(0)) {
                            owner = owner12x12;
                            operatorEnabled = false;
                        } else {
                            owner = address(_owners[LAYER_24x24 + (x/24) * 24 + ((y/24) * 24) * GRID_SIZE]);
                            operatorEnabled = false;
                        }
                    }
                }
            }
        }
    }
    

    File 4 of 4: Medianizer
    /// return median value of feeds
    
    // Copyright (C) 2017  DappHub, LLC
    
    // Licensed under the Apache License, Version 2.0 (the "License").
    // You may not use this file except in compliance with the License.
    
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND (express or implied).
    
    pragma solidity ^0.4.8;
    
    contract DSAuthority {
        function canCall(
            address src, address dst, bytes4 sig
        ) constant returns (bool);
    }
    
    contract DSAuthEvents {
        event LogSetAuthority (address indexed authority);
        event LogSetOwner     (address indexed owner);
    }
    
    contract DSAuth is DSAuthEvents {
        DSAuthority  public  authority;
        address      public  owner;
    
        function DSAuth() {
            owner = msg.sender;
            LogSetOwner(msg.sender);
        }
    
        function setOwner(address owner_)
            auth
        {
            owner = owner_;
            LogSetOwner(owner);
        }
    
        function setAuthority(DSAuthority authority_)
            auth
        {
            authority = authority_;
            LogSetAuthority(authority);
        }
    
        modifier auth {
            assert(isAuthorized(msg.sender, msg.sig));
            _;
        }
    
        modifier authorized(bytes4 sig) {
            assert(isAuthorized(msg.sender, sig));
            _;
        }
    
        function isAuthorized(address src, bytes4 sig) internal returns (bool) {
            if (src == address(this)) {
                return true;
            } else if (src == owner) {
                return true;
            } else if (authority == DSAuthority(0)) {
                return false;
            } else {
                return authority.canCall(src, this, sig);
            }
        }
    
        function assert(bool x) internal {
            if (!x) throw;
        }
    }
    
    contract DSNote {
        event LogNote(
            bytes4   indexed  sig,
            address  indexed  guy,
            bytes32  indexed  foo,
            bytes32  indexed  bar,
    	uint	 	  wad,
            bytes             fax
        ) anonymous;
    
        modifier note {
            bytes32 foo;
            bytes32 bar;
    
            assembly {
                foo := calldataload(4)
                bar := calldataload(36)
            }
    
            LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
    
            _;
        }
    }
    
    contract DSMath {
        
        /*
        standard uint256 functions
         */
    
        function add(uint256 x, uint256 y) constant internal returns (uint256 z) {
            assert((z = x + y) >= x);
        }
    
        function sub(uint256 x, uint256 y) constant internal returns (uint256 z) {
            assert((z = x - y) <= x);
        }
    
        function mul(uint256 x, uint256 y) constant internal returns (uint256 z) {
            assert((z = x * y) >= x);
        }
    
        function div(uint256 x, uint256 y) constant internal returns (uint256 z) {
            z = x / y;
        }
    
        function min(uint256 x, uint256 y) constant internal returns (uint256 z) {
            return x <= y ? x : y;
        }
        function max(uint256 x, uint256 y) constant internal returns (uint256 z) {
            return x >= y ? x : y;
        }
    
        /*
        uint128 functions (h is for half)
         */
    
    
        function hadd(uint128 x, uint128 y) constant internal returns (uint128 z) {
            assert((z = x + y) >= x);
        }
    
        function hsub(uint128 x, uint128 y) constant internal returns (uint128 z) {
            assert((z = x - y) <= x);
        }
    
        function hmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
            assert((z = x * y) >= x);
        }
    
        function hdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
            z = x / y;
        }
    
        function hmin(uint128 x, uint128 y) constant internal returns (uint128 z) {
            return x <= y ? x : y;
        }
        function hmax(uint128 x, uint128 y) constant internal returns (uint128 z) {
            return x >= y ? x : y;
        }
    
    
        /*
        int256 functions
         */
    
        function imin(int256 x, int256 y) constant internal returns (int256 z) {
            return x <= y ? x : y;
        }
        function imax(int256 x, int256 y) constant internal returns (int256 z) {
            return x >= y ? x : y;
        }
    
        /*
        WAD math
         */
    
        uint128 constant WAD = 10 ** 18;
    
        function wadd(uint128 x, uint128 y) constant internal returns (uint128) {
            return hadd(x, y);
        }
    
        function wsub(uint128 x, uint128 y) constant internal returns (uint128) {
            return hsub(x, y);
        }
    
        function wmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
            z = cast((uint256(x) * y + WAD / 2) / WAD);
        }
    
        function wdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
            z = cast((uint256(x) * WAD + y / 2) / y);
        }
    
        function wmin(uint128 x, uint128 y) constant internal returns (uint128) {
            return hmin(x, y);
        }
        function wmax(uint128 x, uint128 y) constant internal returns (uint128) {
            return hmax(x, y);
        }
    
        /*
        RAY math
         */
    
        uint128 constant RAY = 10 ** 27;
    
        function radd(uint128 x, uint128 y) constant internal returns (uint128) {
            return hadd(x, y);
        }
    
        function rsub(uint128 x, uint128 y) constant internal returns (uint128) {
            return hsub(x, y);
        }
    
        function rmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
            z = cast((uint256(x) * y + RAY / 2) / RAY);
        }
    
        function rdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
            z = cast((uint256(x) * RAY + y / 2) / y);
        }
    
        function rpow(uint128 x, uint64 n) constant internal returns (uint128 z) {
            // This famous algorithm is called "exponentiation by squaring"
            // and calculates x^n with x as fixed-point and n as regular unsigned.
            //
            // It's O(log n), instead of O(n) for naive repeated multiplication.
            //
            // These facts are why it works:
            //
            //  If n is even, then x^n = (x^2)^(n/2).
            //  If n is odd,  then x^n = x * x^(n-1),
            //   and applying the equation for even x gives
            //    x^n = x * (x^2)^((n-1) / 2).
            //
            //  Also, EVM division is flooring and
            //    floor[(n-1) / 2] = floor[n / 2].
    
            z = n % 2 != 0 ? x : RAY;
    
            for (n /= 2; n != 0; n /= 2) {
                x = rmul(x, x);
    
                if (n % 2 != 0) {
                    z = rmul(z, x);
                }
            }
        }
    
        function rmin(uint128 x, uint128 y) constant internal returns (uint128) {
            return hmin(x, y);
        }
        function rmax(uint128 x, uint128 y) constant internal returns (uint128) {
            return hmax(x, y);
        }
    
        function cast(uint256 x) constant internal returns (uint128 z) {
            assert((z = uint128(x)) == x);
        }
    
    }
    
    contract DSThing is DSAuth, DSNote, DSMath {
    }
    
    contract DSValue is DSThing {
        bool    has;
        bytes32 val;
        function peek() constant returns (bytes32, bool) {
            return (val,has);
        }
        function read() constant returns (bytes32) {
            var (wut, has) = peek();
            assert(has);
            return wut;
        }
        function poke(bytes32 wut) note auth {
            val = wut;
            has = true;
        }
        function void() note auth { // unset the value
            has = false;
        }
    }
    
    contract Medianizer is DSValue {
        mapping (bytes12 => address) public values;
        mapping (address => bytes12) public indexes;
        bytes12 public next = 0x1;
    
        uint96 public min = 0x1;
    
        function set(address wat) auth {
            bytes12 nextId = bytes12(uint96(next) + 1);
            assert(nextId != 0x0);
            set(next, wat);
            next = nextId;
        }
    
        function set(bytes12 pos, address wat) note auth {
            if (pos == 0x0) throw;
    
            if (wat != 0 && indexes[wat] != 0) throw;
    
            indexes[values[pos]] = 0; // Making sure to remove a possible existing address in that position
    
            if (wat != 0) {
                indexes[wat] = pos;
            }
    
            values[pos] = wat;
        }
    
        function setMin(uint96 min_) note auth {
            if (min_ == 0x0) throw;
            min = min_;
        }
    
        function setNext(bytes12 next_) note auth {
            if (next_ == 0x0) throw;
            next = next_;
        }
    
        function unset(bytes12 pos) {
            set(pos, 0);
        }
    
        function unset(address wat) {
            set(indexes[wat], 0);
        }
    
        function poke() {
            poke(0);
        }
    
        function poke(bytes32) note {
            (val, has) = compute();
        }
    
        function compute() constant returns (bytes32, bool) {
            bytes32[] memory wuts = new bytes32[](uint96(next) - 1);
            uint96 ctr = 0;
            for (uint96 i = 1; i < uint96(next); i++) {
                if (values[bytes12(i)] != 0) {
                    var (wut, wuz) = DSValue(values[bytes12(i)]).peek();
                    if (wuz) {
                        if (ctr == 0 || wut >= wuts[ctr - 1]) {
                            wuts[ctr] = wut;
                        } else {
                            uint96 j = 0;
                            while (wut >= wuts[j]) {
                                j++;
                            }
                            for (uint96 k = ctr; k > j; k--) {
                                wuts[k] = wuts[k - 1];
                            }
                            wuts[j] = wut;
                        }
                        ctr++;
                    }
                }
            }
    
            if (ctr < min) return (val, false);
    
            bytes32 value;
            if (ctr % 2 == 0) {
                uint128 val1 = uint128(wuts[(ctr / 2) - 1]);
                uint128 val2 = uint128(wuts[ctr / 2]);
                value = bytes32(wdiv(hadd(val1, val2), 2 ether));
            } else {
                value = wuts[(ctr - 1) / 2];
            }
    
            return (value, true);
        }
    
    }