ETH Price: $3,118.98 (+1.75%)

Contract

0x3EEe9C3De463a518c528Fd8cf22D2f8222DDdca3
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Buy Land With ET...102776592020-06-16 15:40:391613 days ago1592322039IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0039634440
Buy Land With ET...102775812020-06-16 15:24:331613 days ago1592321073IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0036164354
Buy Land With ET...102775812020-06-16 15:24:331613 days ago1592321073IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.003818657
Buy Land With ET...102775812020-06-16 15:24:331613 days ago1592321073IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0038179157
Buy Land With ET...102775372020-06-16 15:14:241613 days ago1592320464IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0066001155
Buy Land With ET...102775302020-06-16 15:13:191613 days ago1592320399IN
0x3EEe9C3D...222DDdca3
1.43879358 ETH0.0034915853
Buy Land With ET...102775302020-06-16 15:13:191613 days ago1592320399IN
0x3EEe9C3D...222DDdca3
1.43879358 ETH0.0054444962.7
Buy Land With ET...102775302020-06-16 15:13:191613 days ago1592320399IN
0x3EEe9C3D...222DDdca3
1.43879358 ETH0.0078039754
Buy Land With ET...102775272020-06-16 15:12:221613 days ago1592320342IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0065962655
Buy Land With ET...102775272020-06-16 15:12:221613 days ago1592320342IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0056703355
Buy Land With ET...102775262020-06-16 15:12:171613 days ago1592320337IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0026785240
Buy Land With ET...102775262020-06-16 15:12:171613 days ago1592320337IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0053490254
Buy Land With ET...102775262020-06-16 15:12:171613 days ago1592320337IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0062747355
Buy Land With ET...102775262020-06-16 15:12:171613 days ago1592320337IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.005447255
Buy Land With ET...102775232020-06-16 15:11:481613 days ago1592320308IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0044328243
Buy Land With ET...102775212020-06-16 15:11:411613 days ago1592320301IN
0x3EEe9C3D...222DDdca3
1.43879358 ETH0.0071797545
Buy Land With ET...102775192020-06-16 15:11:361613 days ago1592320296IN
0x3EEe9C3D...222DDdca3
1.43879358 ETH0.0035586554
Buy Land With ET...102775182020-06-16 15:11:321613 days ago1592320292IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0052526153
Buy Land With ET...102775182020-06-16 15:11:321613 days ago1592320292IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.005348754
Buy Land With ET...102775182020-06-16 15:11:321613 days ago1592320292IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0064775154
Buy Land With ET...102775182020-06-16 15:11:321613 days ago1592320292IN
0x3EEe9C3D...222DDdca3
1.43879358 ETH0.0066775854
Buy Land With ET...102775152020-06-16 15:10:351613 days ago1592320235IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0068382957
Buy Land With ET...102775152020-06-16 15:10:351613 days ago1592320235IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0064789254
Buy Land With ET...102775152020-06-16 15:10:351613 days ago1592320235IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0076951157
Buy Land With ET...102774932020-06-16 15:05:461613 days ago1592319946IN
0x3EEe9C3D...222DDdca3
0.16830098 ETH0.0056835449.8224852
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
102776592020-06-16 15:40:391613 days ago1592322039
0x3EEe9C3D...222DDdca3
0.16500096 ETH
102776592020-06-16 15:40:391613 days ago1592322039
0x3EEe9C3D...222DDdca3
0.00330001 ETH
102775812020-06-16 15:24:331613 days ago1592321073
0x3EEe9C3D...222DDdca3
0.16500096 ETH
102775812020-06-16 15:24:331613 days ago1592321073
0x3EEe9C3D...222DDdca3
0.00330001 ETH
102775812020-06-16 15:24:331613 days ago1592321073
0x3EEe9C3D...222DDdca3
0.16500096 ETH
102775812020-06-16 15:24:331613 days ago1592321073
0x3EEe9C3D...222DDdca3
0.00330001 ETH
102775812020-06-16 15:24:331613 days ago1592321073
0x3EEe9C3D...222DDdca3
0.16500096 ETH
102775812020-06-16 15:24:331613 days ago1592321073
0x3EEe9C3D...222DDdca3
0.00330001 ETH
102775372020-06-16 15:14:241613 days ago1592320464
0x3EEe9C3D...222DDdca3
0.14850087 ETH
102775372020-06-16 15:14:241613 days ago1592320464
0x3EEe9C3D...222DDdca3
0.01650009 ETH
102775372020-06-16 15:14:241613 days ago1592320464
0x3EEe9C3D...222DDdca3
0.00330001 ETH
102775302020-06-16 15:13:191613 days ago1592320399
0x3EEe9C3D...222DDdca3
1.41058194 ETH
102775302020-06-16 15:13:191613 days ago1592320399
0x3EEe9C3D...222DDdca3
0.02821163 ETH
102775302020-06-16 15:13:191613 days ago1592320399
0x3EEe9C3D...222DDdca3
1.26952374 ETH
102775302020-06-16 15:13:191613 days ago1592320399
0x3EEe9C3D...222DDdca3
0.14105819 ETH
102775302020-06-16 15:13:191613 days ago1592320399
0x3EEe9C3D...222DDdca3
0.02821163 ETH
102775302020-06-16 15:13:191613 days ago1592320399
0x3EEe9C3D...222DDdca3
1.26952374 ETH
102775302020-06-16 15:13:191613 days ago1592320399
0x3EEe9C3D...222DDdca3
0.14105819 ETH
102775302020-06-16 15:13:191613 days ago1592320399
0x3EEe9C3D...222DDdca3
0.02821163 ETH
102775272020-06-16 15:12:221613 days ago1592320342
0x3EEe9C3D...222DDdca3
0.14850087 ETH
102775272020-06-16 15:12:221613 days ago1592320342
0x3EEe9C3D...222DDdca3
0.01650009 ETH
102775272020-06-16 15:12:221613 days ago1592320342
0x3EEe9C3D...222DDdca3
0.00330001 ETH
102775272020-06-16 15:12:221613 days ago1592320342
0x3EEe9C3D...222DDdca3
0.16500096 ETH
102775272020-06-16 15:12:221613 days ago1592320342
0x3EEe9C3D...222DDdca3
0.00330001 ETH
102775262020-06-16 15:12:171613 days ago1592320337
0x3EEe9C3D...222DDdca3
0.16500096 ETH
View All Internal Transactions
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x126a3437...4f2F4aDAa
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
LandSaleWithReferral

Compiler Version
v0.5.9+commit.e560f70d

Optimization Enabled:
Yes with 2000 runs

Other Settings:
petersburg EvmVersion, None license
File 1 of 17 : LandSaleWithReferral.sol
/* 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);
    }
}

File 2 of 17 : Admin.sol
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");
        _;
    }

}

File 3 of 17 : MetaTransactionReceiver.sol
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];
    }
}

File 4 of 17 : SuperOperators.sol
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];
    }
}

File 5 of 17 : ERC20.sol
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
    );
}

File 6 of 17 : ERC20Basic.sol
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);
}

File 7 of 17 : ERC721Events.sol
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
    );
}

File 8 of 17 : ERC721MandatoryTokenReceiver.sol
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);
}

File 9 of 17 : ERC721TokenReceiver.sol
/* 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);
}

File 10 of 17 : Medianizer.sol
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);
}

File 11 of 17 : AddressUtils.sol
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);
    }
}

File 12 of 17 : SafeMathWithRequire.sol
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;
    }
}

File 13 of 17 : SigUtil.sol
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:\n32", hash);
    }
}

File 14 of 17 : Land.sol
/* 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;
    }
}

File 15 of 17 : ERC721BaseToken.sol
/* 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);
    }
}

File 16 of 17 : LandBaseToken.sol
/* 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 17 of 17 : ReferralValidator.sol
/* 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:\n32", 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
        );
    }
}

Settings
{
  "evmVersion": "petersburg",
  "libraries": {},
  "metadata": {
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 2000
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[],"name":"getExpiryTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"merkleRoot","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"enabled","type":"bool"}],"name":"setDAIEnabled","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"buyer","type":"address"},{"name":"to","type":"address"},{"name":"reserved","type":"address"},{"name":"x","type":"uint256"},{"name":"y","type":"uint256"},{"name":"size","type":"uint256"},{"name":"priceInSand","type":"uint256"},{"name":"salt","type":"bytes32"},{"name":"proof","type":"bytes32[]"},{"name":"referral","type":"bytes"}],"name":"buyLandWithDAI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isDAIEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isETHEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newSigningWallet","type":"address"}],"name":"updateSigningWallet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"sandAmount","type":"uint256"}],"name":"getEtherAmountWithSAND","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"referral","type":"bytes"}],"name":"decodeReferral","outputs":[{"name":"","type":"bytes"},{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getAdmin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"enabled","type":"bool"}],"name":"setSANDEnabled","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"metaTransactionProcessor","type":"address"},{"name":"enabled","type":"bool"}],"name":"setMetaTransactionProcessor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isSANDEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newWallet","type":"address"}],"name":"setReceivingWallet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"signature","type":"bytes"},{"name":"referrer","type":"address"},{"name":"referee","type":"address"},{"name":"expiryTime","type":"uint256"},{"name":"commissionRate","type":"uint256"}],"name":"isReferralValid","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"buyer","type":"address"},{"name":"to","type":"address"},{"name":"reserved","type":"address"},{"name":"x","type":"uint256"},{"name":"y","type":"uint256"},{"name":"size","type":"uint256"},{"name":"priceInSand","type":"uint256"},{"name":"salt","type":"bytes32"},{"name":"proof","type":"bytes32[]"},{"name":"referral","type":"bytes"}],"name":"buyLandWithETH","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"isMetaTransactionProcessor","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"buyer","type":"address"},{"name":"to","type":"address"},{"name":"reserved","type":"address"},{"name":"x","type":"uint256"},{"name":"y","type":"uint256"},{"name":"size","type":"uint256"},{"name":"priceInSand","type":"uint256"},{"name":"salt","type":"bytes32"},{"name":"proof","type":"bytes32[]"},{"name":"referral","type":"bytes"}],"name":"buyLandWithSand","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newMaxCommissionRate","type":"uint256"}],"name":"updateMaxCommissionRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"enabled","type":"bool"}],"name":"setETHEnabled","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"landAddress","type":"address"},{"name":"sandContractAddress","type":"address"},{"name":"initialMetaTx","type":"address"},{"name":"admin","type":"address"},{"name":"initialWalletAddress","type":"address"},{"name":"merkleRoot","type":"bytes32"},{"name":"expiryTime","type":"uint256"},{"name":"medianizerContractAddress","type":"address"},{"name":"daiTokenContractAddress","type":"address"},{"name":"initialSigningWallet","type":"address"},{"name":"initialMaxCommissionRate","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":true,"name":"topCornerId","type":"uint256"},{"indexed":false,"name":"size","type":"uint256"},{"indexed":false,"name":"price","type":"uint256"},{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"amountPaid","type":"uint256"}],"name":"LandQuadPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"referrer","type":"address"},{"indexed":true,"name":"referee","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"commission","type":"uint256"},{"indexed":false,"name":"commissionRate","type":"uint256"}],"name":"ReferralUsed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"metaTransactionProcessor","type":"address"},{"indexed":false,"name":"enabled","type":"bool"}],"name":"MetaTransactionProcessor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldAdmin","type":"address"},{"indexed":false,"name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"}]

Deployed Bytecode

0x60806040526004361061016a5760003560e01c80637c53ec4c116100cb578063c10a42081161007f578063e0a1f1c711610059578063e0a1f1c71461080c578063e56f8a9e1461091e578063e97eb0a2146109485761016a565b8063c10a420814610604578063c2bddf26146106d4578063dc5074af146107d95761016a565b80638f283970116100b05780638f28397014610589578063a7e30684146105bc578063b522ecff146105d15761016a565b80637c53ec4c146105225780638a04af6a1461054e5761016a565b80634a253778116101225780635d8e3021116101075780635d8e30211461035c57806365194ce7146103865780636e9960c3146104f15761016a565b80634a2537781461031457806358bc2944146103295761016a565b80633b7c4c15116101535780633b7c4c15146101ab5780633be3b0e2146101d9578063427b8d34146102eb5761016a565b806325cb5bc01461016f5780632eb4a7ab14610196575b600080fd5b34801561017b57600080fd5b50610184610974565b60408051918252519081900360200190f35b3480156101a257600080fd5b5061018461097a565b3480156101b757600080fd5b506101d7600480360360208110156101ce57600080fd5b50351515610980565b005b3480156101e557600080fd5b506101d760048036036101408110156101fd57600080fd5b6001600160a01b038235811692602081013582169260408201359092169160608201359160808101359160a08201359160c08101359160e08201359190810190610120810161010082013564010000000081111561025a57600080fd5b82018360208201111561026c57600080fd5b8035906020019184602083028401116401000000008311171561028e57600080fd5b9193909290916020810190356401000000008111156102ac57600080fd5b8201836020820111156102be57600080fd5b803590602001918460018302840111640100000000831117156102e057600080fd5b509092509050610a01565b3480156102f757600080fd5b50610300610b5c565b604080519115158252519081900360200190f35b34801561032057600080fd5b50610300610b6b565b34801561033557600080fd5b506101d76004803603602081101561034c57600080fd5b50356001600160a01b0316610b79565b34801561036857600080fd5b506101846004803603602081101561037f57600080fd5b5035610c24565b34801561039257600080fd5b50610439600480360360208110156103a957600080fd5b8101906020810181356401000000008111156103c457600080fd5b8201836020820111156103d657600080fd5b803590602001918460018302840111640100000000831117156103f857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c53945050505050565b6040518080602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b838110156104b257818101518382015260200161049a565b50505050905090810190601f1680156104df5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b3480156104fd57600080fd5b50610506610cf1565b604080516001600160a01b039092168252519081900360200190f35b34801561052e57600080fd5b506101d76004803603602081101561054557600080fd5b50351515610d00565b34801561055a57600080fd5b506101d76004803603604081101561057157600080fd5b506001600160a01b0381351690602001351515610d5c565b34801561059557600080fd5b506101d7600480360360208110156105ac57600080fd5b50356001600160a01b0316610db3565b3480156105c857600080fd5b50610300610e89565b3480156105dd57600080fd5b506101d7600480360360208110156105f457600080fd5b50356001600160a01b0316610e92565b34801561061057600080fd5b50610300600480360360a081101561062757600080fd5b81019060208101813564010000000081111561064257600080fd5b82018360208201111561065457600080fd5b8035906020019184600183028401116401000000008311171561067657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550506001600160a01b038335811694506020840135169260408101359250606001359050610f4f565b6101d760048036036101408110156106eb57600080fd5b6001600160a01b038235811692602081013582169260408201359092169160608201359160808101359160a08201359160c08101359160e08201359190810190610120810161010082013564010000000081111561074857600080fd5b82018360208201111561075a57600080fd5b8035906020019184602083028401116401000000008311171561077c57600080fd5b91939092909160208101903564010000000081111561079a57600080fd5b8201836020820111156107ac57600080fd5b803590602001918460018302840111640100000000831117156107ce57600080fd5b509092509050611078565b3480156107e557600080fd5b50610300600480360360208110156107fc57600080fd5b50356001600160a01b0316611211565b34801561081857600080fd5b506101d7600480360361014081101561083057600080fd5b6001600160a01b038235811692602081013582169260408201359092169160608201359160808101359160a08201359160c08101359160e08201359190810190610120810161010082013564010000000081111561088d57600080fd5b82018360208201111561089f57600080fd5b803590602001918460208302840111640100000000831117156108c157600080fd5b9193909290916020810190356401000000008111156108df57600080fd5b8201836020820111156108f157600080fd5b8035906020019184600183028401116401000000008311171561091357600080fd5b50909250905061122f565b34801561092a57600080fd5b506101d76004803603602081101561094157600080fd5b5035611350565b34801561095457600080fd5b506101d76004803603602081101561096b57600080fd5b503515156113b4565b600b5490565b600c5490565b6000546001600160a01b031633146109c95760405162461bcd60e51b815260040180806020018281038252602181526020018061203f6021913960400191505060405180910390fd5b600d805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055565b600d5462010000900460ff16610a5e576040805162461bcd60e51b815260206004820152601860248201527f646169207061796d656e7473206e6f7420656e61626c65640000000000000000604482015290519081900360640190fd5b610aa18c8b8b8b8b8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061143492505050565b6000610ad2670de0b6b3a7640000610ac689663328b944c4000063ffffffff6115f116565b9063ffffffff61166716565b9050610b288d8285858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050600a546009546001600160a01b03918216935016905061167a565b610b4d8d8d8c8c8c8c600960009054906101000a90046001600160a01b031688611937565b50505050505050505050505050565b600d5462010000900460ff1690565b600d54610100900460ff1690565b6000546001600160a01b03163314610bd8576040805162461bcd60e51b815260206004820152601060248201527f53656e646572206e6f742061646d696e00000000000000000000000000000000604482015290519081900360640190fd5b600554600280546001600160a01b03908116600090815260046020526040902042909301909255805473ffffffffffffffffffffffffffffffffffffffff191692909116919091179055565b600080610c2f611b36565b9050610c4c81610ac685663328b944c4000063ffffffff6115f116565b9392505050565b606060008060008060606000806000808a80602001905160a0811015610c7857600080fd5b810190808051640100000000811115610c9057600080fd5b82016020810184811115610ca357600080fd5b8151640100000000811182820187101715610cbd57600080fd5b5050602082015160408301516060840151608090940151929f50909d509b5090995097505050505050505091939590929450565b6000546001600160a01b031690565b6000546001600160a01b03163314610d495760405162461bcd60e51b8152600401808060200182810382526022815260200180611fef6022913960400191505060405180910390fd5b600d805460ff1916911515919091179055565b6000546001600160a01b03163314610da55760405162461bcd60e51b815260040180806020018281038252602e815260200180612011602e913960400191505060405180910390fd5b610daf8282611bb9565b5050565b6000546001600160a01b03163314610e12576040805162461bcd60e51b815260206004820152601b60248201527f6f6e6c792061646d696e2063616e206368616e67652061646d696e0000000000604482015290519081900360640190fd5b600054604080516001600160a01b039283168152918316602083015280517f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f9281900390910190a16000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600d5460ff1690565b6001600160a01b038116610ed75760405162461bcd60e51b8152600401808060200182810382526027815260200180611f9e6027913960400191505060405180910390fd5b6000546001600160a01b03163314610f205760405162461bcd60e51b815260040180806020018281038252602a815260200180611fc5602a913960400191505060405180910390fd5b600a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000600354821180610f725750836001600160a01b0316856001600160a01b0316145b80610f7c57508242115b15610f895750600061106f565b60408051606087811b6bffffffffffffffffffffffff199081166020808501919091529188901b166034830152604882018690526068808301869052835180840390910181526088830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000060a884015260c48084018290528451808503909101815260e4909301909352815191012060009061102d9089611c1d565b6001600160a01b038116600090815260046020526040902054909150421161105a5760019250505061106f565b6002546001600160a01b039081169116149150505b95945050505050565b600d54610100900460ff166110d4576040805162461bcd60e51b815260206004820152601a60248201527f6574686572207061796d656e7473206e6f7420656e61626c6564000000000000604482015290519081900360640190fd5b6111178c8b8b8b8b8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061143492505050565b600061112287610c24565b905080341015611179576040805162461bcd60e51b815260206004820152601560248201527f6e6f7420656e6f7567682065746865722073656e740000000000000000000000604482015290519081900360640190fd5b34819003156111b35760405133903483900380156108fc02916000818181858888f193505050501580156111b1573d6000803e3d6000fd5b505b6112008184848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050600a546001600160a01b03169150611cea9050565b610b4d8d8d8c8c8c8c600088611937565b6001600160a01b031660009081526001602052604090205460ff1690565b600d5460ff16611286576040805162461bcd60e51b815260206004820152601960248201527f73616e64207061796d656e7473206e6f7420656e61626c656400000000000000604482015290519081900360640190fd5b6112c98c8b8b8b8b8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061143492505050565b61131d8c8784848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050600a546007546001600160a01b03918216935016905061167a565b6113428c8c8b8b8b8b600760009054906101000a90046001600160a01b03168d611937565b505050505050505050505050565b6000546001600160a01b031633146113af576040805162461bcd60e51b815260206004820152601060248201527f53656e646572206e6f742061646d696e00000000000000000000000000000000604482015290519081900360640190fd5b600355565b6000546001600160a01b031633146113fd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611f7d6021913960400191505060405180910390fd5b600d8054911515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909216919091179055565b600b54421061148a576040805162461bcd60e51b815260206004820152600c60248201527f73616c65206973206f7665720000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0388163314806114b057503360009081526001602052604090205460ff165b611501576040805162461bcd60e51b815260206004820152600e60248201527f6e6f7420617574686f72697a6564000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03871615806115285750876001600160a01b0316876001600160a01b0316145b611579576040805162461bcd60e51b815260206004820152601860248201527f63616e6e6f7420627579207265736572766564204c616e640000000000000000604482015290519081900360640190fd5b6000611589878787878c88611e16565b90506115958282611e74565b6115e6576040805162461bcd60e51b815260206004820152601560248201527f496e76616c6964206c616e642070726f76696465640000000000000000000000604482015290519081900360640190fd5b505050505050505050565b60008261160057506000611661565b508181028183828161160e57fe5b0414611661576040805162461bcd60e51b815260206004820152600860248201527f6f766572666c6f77000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b92915050565b600081838161167257fe5b049392505050565b8251819085901561183d5760606000806000806116968a610c53565b93985091965094509250905060006116b18686868686610f4f565b1561173f576116cb6116c38d846115f1565b612710611667565b9050886001600160a01b0316846001600160a01b0316866001600160a01b03167fac7a699eb95c3c6d390ec4626de17ef9a67b35891efdb197beba7c7fdd45fac48f858760405180848152602001838152602001828152602001935050505060405180910390a461173c8782611f1f565b96505b801561183657604080517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038f811660048301528781166024830152604482018490529151918a16916323b872dd916064808201926020929091908290030181600087803b1580156117b957600080fd5b505af11580156117cd573d6000803e3d6000fd5b505050506040513d60208110156117e357600080fd5b5051611836576040805162461bcd60e51b815260206004820152601960248201527f636f6d6d6973696f6e207472616e73666572206661696c656400000000000000604482015290519081900360640190fd5b5050505050505b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b0389811660048301528681166024830152604482018490529151918416916323b872dd916064808201926020929091908290030181600087803b1580156118b157600080fd5b505af11580156118c5573d6000803e3d6000fd5b505050506040513d60208110156118db57600080fd5b505161192e576040805162461bcd60e51b815260206004820152601760248201527f7061796d656e74207472616e73666572206661696c6564000000000000000000604482015290519081900360640190fd5b50505050505050565b60408051600080825260208201909252606091509050600660009054906101000a90046001600160a01b03166001600160a01b0316636e1e3bbf89878a8a8d8760405160200180836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156119d25781810151838201526020016119ba565b5050505090500193505050506040516020818303038152906040526040518663ffffffff1660e01b815260040180866001600160a01b03166001600160a01b0316815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611a63578181015183820152602001611a4b565b50505050905090810190601f168015611a905780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b158015611ab357600080fd5b505af1158015611ac7573d6000803e3d6000fd5b505060408051888152602081018890526001600160a01b03878116828401526060820187905291516101988b028c019450828d169350918d16917fe4dfa6ac11314892f3029b34a25b1a887da3b1cab2bbf8506d87128ba6e3ac029181900360800190a4505050505050505050565b600080600860009054906101000a90046001600160a01b03166001600160a01b03166357de26a46040518163ffffffff1660e01b815260040160206040518083038186803b158015611b8757600080fd5b505afa158015611b9b573d6000803e3d6000fd5b505050506040513d6020811015611bb157600080fd5b505191505090565b6001600160a01b038216600081815260016020908152604091829020805460ff191685151590811790915582519384529083015280517fb21eb88b4e33b3f1281830a7178d74d8aa73220416215726b68ae23d539515cb9281900390910190a15050565b60008151604114611c2d57600080fd5b60208201516040830151606084015160001a601b811015611c4c57601b015b8060ff16601b1480611c6157508060ff16601c145b611c6a57600080fd5b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015611cc1573d6000803e3d6000fd5b5050604051601f1901519450506001600160a01b038416611ce157600080fd5b50505092915050565b8151839015611dd9576060600080600080611d0488610c53565b9398509196509450925090506000611d1f8686868686610f4f565b15611d9457611d316116c38b846115f1565b604080518c81526020810183905280820185905290519192506000916001600160a01b0387811692908916917fac7a699eb95c3c6d390ec4626de17ef9a67b35891efdb197beba7c7fdd45fac49181900360600190a4611d918782611f1f565b96505b8015611dd2576040516001600160a01b0386169082156108fc029083906000818181858888f19350505050158015611dd0573d6000803e3d6000fd5b505b5050505050505b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611e0f573d6000803e3d6000fd5b5050505050565b60408051602080820198909852808201969096526060808701959095526080860193909352921b6bffffffffffffffffffffffff191660a084015260b4808401929092528051808403909201825260d4909201909152805191012090565b600081815b8451811015611f13576000858281518110611e9057fe5b6020026020010151905080831015611ed85782816040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209250611f0a565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b50600101611e79565b50600c54149392505050565b600082821115611f76576040805162461bcd60e51b815260206004820152600860248201527f756e6465666c6f77000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b5090039056fe6f6e6c792061646d696e2063616e20656e61626c652f64697361626c6520455448726563656976696e672077616c6c65742063616e6e6f74206265207a65726f20616464726573736f6e6c792061646d696e2063616e206368616e67652074686520726563656976696e672077616c6c65746f6e6c792061646d696e2063616e20656e61626c652f64697361626c652053414e446f6e6c792061646d696e2063616e207365747570206d6574615472616e73616374696f6e50726f636573736f72736f6e6c792061646d696e2063616e20656e61626c652f64697361626c6520444149a265627a7a723058209987ebdf08909dce1f2ea5d2b1691f50310c456133e0dbe2241f28115fb7633964736f6c63430005090032

Deployed Bytecode Sourcemap

575:10753:15:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9402:91;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9402:91:15;;;:::i;:::-;;;;;;;;;;;;;;;;9634:88;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9634:88:15;;;:::i;2765:160::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2765:160:15;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2765:160:15;;;;:::i;:::-;;8524:751;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8524:751:15;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;8524:751:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;8524:751:15;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;8524:751:15;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;8524:751:15;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;8524:751:15;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;8524:751:15;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;8524:751:15;;-1:-1:-1;8524:751:15;-1:-1:-1;8524:751:15;:::i;3036:88::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3036:88:15;;;:::i;:::-;;;;;;;;;;;;;;;;;;3508:90;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3508:90:15;;;:::i;1231:252:16:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1231:252:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1231:252:16;-1:-1:-1;;;;;1231:252:16;;:::i;10872:192:15:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10872:192:15;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10872:192:15;;:::i;6062:582:16:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6062:582:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;6062:582:16;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;6062:582:16;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;6062:582:16;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;6062:582:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;6062:582:16;;-1:-1:-1;6062:582:16;;-1:-1:-1;;;;;6062:582:16:i;:::-;;;;;;;;-1:-1:-1;;;;;6062:582:16;-1:-1:-1;;;;;6062:582:16;;;;;;-1:-1:-1;;;;;6062:582:16;-1:-1:-1;;;;;6062:582:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;6062:582:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;264:82:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;264:82:0;;;:::i;:::-;;;;-1:-1:-1;;;;;264:82:0;;;;;;;;;;;;;;3723:163:15;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3723:163:15;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3723:163:15;;;;:::i;572:295:1:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;572:295:1;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;572:295:1;;;;;;;;;;:::i;469:197:0:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;469:197:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;469:197:0;-1:-1:-1;;;;;469:197:0;;:::i;4025:90:15:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4025:90:15;;;:::i;2385:269::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2385:269:15;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2385:269:15;-1:-1:-1;;;;;2385:269:15;;:::i;5171:885:16:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5171:885:16;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;5171:885:16;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;5171:885:16;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;5171:885:16;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;5171:885:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;5171:885:16;;-1:-1:-1;;;;;;;5171:885:16;;;;;-1:-1:-1;5171:885:16;;;;;;;;;;;-1:-1:-1;5171:885:16;;;;-1:-1:-1;5171:885:16;:::i;7070:893:15:-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;7070:893:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;7070:893:15;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;7070:893:15;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;7070:893:15;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;7070:893:15;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;7070:893:15;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;7070:893:15;;-1:-1:-1;7070:893:15;-1:-1:-1;7070:893:15;:::i;1330:131:1:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1330:131:1;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1330:131:1;-1:-1:-1;;;;;1330:131:1;;:::i;5782:673:15:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5782:673:15;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;5782:673:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;5782:673:15;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;5782:673:15;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;5782:673:15;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;5782:673:15;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;5782:673:15;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;5782:673:15;;-1:-1:-1;5782:673:15;-1:-1:-1;5782:673:15;:::i;1675:189:16:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1675:189:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1675:189:16;;:::i;3235:162:15:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3235:162:15;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3235:162:15;;;;:::i;9402:91::-;9475:11;;9402:91;:::o;9634:88::-;9704:11;;9634:88;:::o;2765:160::-;2843:6;;-1:-1:-1;;;;;2843:6:15;2829:10;:20;2821:66;;;;-1:-1:-1;;;2821:66:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2897:11;:21;;;;;;;;;;;;;;;;;2765:160::o;8524:751::-;8828:11;;;;;;;8820:48;;;;;-1:-1:-1;;;8820:48:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;8878:69;8893:5;8900:8;8910:1;8913;8916:4;8922:11;8935:4;8941:5;;8878:69;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;8878:14:15;;-1:-1:-1;;;8878:69:15:i;:::-;8958:19;8980:50;9010:19;8980:25;:11;816:17;8980:25;:15;:25;:::i;:::-;:29;:50;:29;:50;:::i;:::-;8958:72;;9041:147;9078:5;9097:11;9122:8;;9041:147;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;9144:7:15;;9173:4;;-1:-1:-1;;;;;9144:7:15;;;;-1:-1:-1;9173:4:15;;-1:-1:-1;9041:23:15;:147::i;:::-;9199:69;9205:5;9212:2;9216:1;9219;9222:4;9228:11;9249:4;;;;;;;;;-1:-1:-1;;;;;9249:4:15;9256:11;9199:5;:69::i;:::-;8524:751;;;;;;;;;;;;;:::o;3036:88::-;3106:11;;;;;;;;3036:88::o;3508:90::-;3578:13;;;;;;;;3508:90::o;1231:252:16:-;1313:6;;-1:-1:-1;;;;;1313:6:16;1323:10;1313:20;1305:49;;;;;-1:-1:-1;;;1305:49:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;1412:21;;1388:14;;;-1:-1:-1;;;;;1388:14:16;;;1364:39;;;;:23;:39;;;;;1406:3;:27;;;1364:69;;;1443:33;;-1:-1:-1;;1443:33:16;;;;;;;;;;;1231:252::o;10872:192:15:-;10945:7;10964:18;10985:15;:13;:15::i;:::-;10964:36;-1:-1:-1;11017:40:15;10964:36;11017:24;:10;816:17;11017:24;:14;:24;:::i;:40::-;11010:47;10872:192;-1:-1:-1;;;10872:192:15:o;6062:582:16:-;6153:12;6175:7;6192;6209;6226;6264:22;6300:16;6330:15;6359:18;6391:22;6437:8;6426:65;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;6426:65:16;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;213:10;;261:11;244:29;;285:43;;;282:58;-1:-1;233:115;230:2;;;361:1;358;351:12;230:2;-1:-1;;6426:65:16;;;;;;;;;;;;;;;;;;;-1:-1:-1;6426:65:16;;-1:-1:-1;6426:65:16;-1:-1:-1;6426:65:16;;-1:-1:-1;6426:65:16;-1:-1:-1;;;;;;;;6062:582:16;;;;;;;:::o;264:82:0:-;307:7;333:6;-1:-1:-1;;;;;333:6:0;264:82;:::o;3723:163:15:-;3802:6;;-1:-1:-1;;;;;3802:6:15;3788:10;:20;3780:67;;;;-1:-1:-1;;;3780:67:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3857:12;:22;;-1:-1:-1;;3857:22:15;;;;;;;;;;3723:163::o;572:295:1:-;709:6;;-1:-1:-1;;;;;709:6:1;695:10;:20;674:113;;;;-1:-1:-1;;;674:113:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;797:63;826:24;852:7;797:28;:63::i;:::-;572:295;;:::o;469:197:0:-;549:6;;-1:-1:-1;;;;;549:6:0;535:10;:20;527:60;;;;;-1:-1:-1;;;527:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;615:6;;602:30;;;-1:-1:-1;;;;;615:6:0;;;602:30;;;;;;;;;;;;;;;;;;;;;642:6;:17;;-1:-1:-1;;642:17:0;-1:-1:-1;;;;;642:17:0;;;;;;;;;;469:197::o;4025:90:15:-;4096:12;;;;4025:90;:::o;2385:269::-;-1:-1:-1;;;;;2466:23:15;;2458:75;;;;-1:-1:-1;;;2458:75:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2565:6;;-1:-1:-1;;;;;2565:6:15;2551:10;:20;2543:75;;;;-1:-1:-1;;;2543:75:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2628:7;:19;;-1:-1:-1;;2628:19:15;-1:-1:-1;;;;;2628:19:15;;;;;;;;;;2385:269::o;5171:885:16:-;5375:4;5417:18;;5400:14;:35;:58;;;;5451:7;-1:-1:-1;;;;;5439:19:16;:8;-1:-1:-1;;;;;5439:19:16;;5400:58;:78;;;;5468:10;5462:3;:16;5400:78;5396:121;;;-1:-1:-1;5501:5:16;5494:12;;5396:121;5571:141;;;;;;;-1:-1:-1;;5571:141:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;5571:141:16;;;;;5548:174;;;;;;5806:64;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;5806:64:16;;;;;;;5779:105;;;;;-1:-1:-1;;5750:167:16;;5898:9;5750:15;:167::i;:::-;-1:-1:-1;;;;;5932:31:16;;;;;;:23;:31;;;;;;5733:184;;-1:-1:-1;5967:3:16;-1:-1:-1;5928:80:16;;5993:4;5986:11;;;;;;5928:80;6025:14;;-1:-1:-1;;;;;6025:14:16;;;:24;;;;-1:-1:-1;;5171:885:16;;;;;;;;:::o;7070:893:15:-;7382:13;;;;;;;7374:52;;;;;-1:-1:-1;;;7374:52:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;7436:69;7451:5;7458:8;7468:1;7471;7474:4;7480:11;7493:4;7499:5;;7436:69;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;7436:14:15;;-1:-1:-1;;;7436:69:15:i;:::-;7516:19;7538:35;7561:11;7538:22;:35::i;:::-;7516:57;;7604:11;7591:9;:24;;7583:58;;;;;-1:-1:-1;;;7583:58:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;7656:9;:23;;;:27;7652:118;;7699:44;;:10;;7719:9;:23;;;7699:44;;;;;;;;;7719:23;7699:10;:44;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7699:44:15;7652:118;7780:99;7815:11;7840:8;;7780:99;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;7862:7:15;;-1:-1:-1;;;;;7862:7:15;;-1:-1:-1;7780:21:15;;-1:-1:-1;7780:99:15:i;:::-;7890:66;7896:5;7903:2;7907:1;7910;7913:4;7919:11;7940:1;7944:11;7890:5;:66::i;1330:131:1:-;-1:-1:-1;;;;;1424:30:1;1401:4;1424:30;;;:25;:30;;;;;;;;;1330:131::o;5782:673:15:-;6087:12;;;;6079:50;;;;;-1:-1:-1;;;6079:50:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;6139:69;6154:5;6161:8;6171:1;6174;6177:4;6183:11;6196:4;6202:5;;6139:69;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;6139:14:15;;-1:-1:-1;;;6139:69:15:i;:::-;6219:148;6256:5;6275:11;6300:8;;6219:148;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;6322:7:15;;6351:5;;-1:-1:-1;;;;;6322:7:15;;;;-1:-1:-1;6351:5:15;;-1:-1:-1;6219:23:15;:148::i;:::-;6378:70;6384:5;6391:2;6395:1;6398;6401:4;6407:11;6428:5;;;;;;;;;-1:-1:-1;;;;;6428:5:15;6436:11;6378:5;:70::i;:::-;5782:673;;;;;;;;;;;;:::o;1675:189:16:-;1765:6;;-1:-1:-1;;;;;1765:6:16;1775:10;1765:20;1757:49;;;;;-1:-1:-1;;;1757:49:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;1816:18;:41;1675:189::o;3235:162:15:-;3313:6;;-1:-1:-1;;;;;3313:6:15;3299:10;:20;3291:66;;;;-1:-1:-1;;;3291:66:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3367:13;:23;;;;;;;;;;;;;;;;;3235:162::o;4121:729::-;4452:11;;4434:15;:29;4426:54;;;;;-1:-1:-1;;;4426:54:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4498:19:15;;4507:10;4498:19;;:60;;-1:-1:-1;4547:10:15;4521:37;;;;:25;:37;;;;;;;;4498:60;4490:87;;;;;-1:-1:-1;;;4490:87:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4595:22:15;;;;:43;;;4633:5;-1:-1:-1;;;;;4621:17:15;:8;-1:-1:-1;;;;;4621:17:15;;4595:43;4587:80;;;;;-1:-1:-1;;;4587:80:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;4677:12;4692:52;4710:1;4713;4716:4;4722:5;4729:8;4739:4;4692:17;:52::i;:::-;4677:67;;4776:20;4784:5;4791:4;4776:7;:20::i;:::-;4755:88;;;;;-1:-1:-1;;;4755:88:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;4121:729;;;;;;;;;:::o;211:426:10:-;269:9;511:6;507:45;;-1:-1:-1;540:1:10;533:8;;507:45;-1:-1:-1;566:5:10;;;570:1;566;:5;:1;589:5;;;;;:10;581:31;;;;;-1:-1:-1;;;581:31:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;211:426;;;;:::o;727:290::-;785:7;1009:1;1005;:5;;;;;;;727:290;-1:-1:-1;;;727:290:10:o;3229:1545:16:-;3527:15;;3452:12;;3506:6;;3527:19;3523:1138;;3580:22;3620:16;3654:15;3687:18;3723:22;3762:24;3777:8;3762:14;:24::i;:::-;3562:224;;-1:-1:-1;3562:224:16;;-1:-1:-1;3562:224:16;-1:-1:-1;3562:224:16;-1:-1:-1;3562:224:16;-1:-1:-1;3801:18:16;3842:73;3562:224;;;;;3842:15;:73::i;:::-;3838:661;;;3948:137;3993:47;4017:6;4025:14;3993:23;:47::i;:::-;4062:5;3948:23;:137::i;:::-;3935:150;;4202:12;-1:-1:-1;;;;;4109:219:16;4173:7;-1:-1:-1;;;;;4109:219:16;4143:8;-1:-1:-1;;;;;4109:219:16;;4236:6;4264:10;4296:14;4109:219;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4369:115;4414:20;4456:10;4369:23;:115::i;:::-;4346:138;;3838:661;4517:14;;4513:138;;4559:47;;;;;;-1:-1:-1;;;;;4559:47:16;;;;;;;;;;;;;;;;;;;;;;:18;;;;;;:47;;;;;;;;;;;;;;;-1:-1:-1;4559:18:16;:47;;;5:2:-1;;;;30:1;27;20:12;5:2;4559:47:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;4559:47:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;4559:47:16;4551:85;;;;;-1:-1:-1;;;4551:85:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;3523:1138;;;;;;;4679:60;;;;;;-1:-1:-1;;;;;4679:60:16;;;;;;;;;;;;;;;;;;;;;;:18;;;;;;:60;;;;;;;;;;;;;;;-1:-1:-1;4679:18:16;:60;;;5:2:-1;;;;30:1;27;20:12;5:2;4679:60:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;4679:60:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;4679:60:16;4671:96;;;;;-1:-1:-1;;;4671:96:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;3229:1545;;;;;;;:::o;4856:364:15:-;5033:16;;;5047:1;5033:16;;;;;;;;;5004:26;;5033:16;5004:45;;5059:5;;;;;;;;;-1:-1:-1;;;;;5059:5:15;-1:-1:-1;;;;;5059:14:15;;5074:2;5078:4;5084:1;5087;5101:2;5105:9;5090:25;;;;;;-1:-1:-1;;;;;5090:25:15;-1:-1:-1;;;;;5090:25:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;5090:25:15;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;5090:25:15;;;5059:57;;;;;;;;;;;;;-1:-1:-1;;;;;5059:57:15;-1:-1:-1;;;;;5059:57:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;5059:57:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5059:57:15;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;5131:82:15;;;;;;;;;;;;-1:-1:-1;;;;;5131:82:15;;;;;;;;;;;;;;;739:3;5165:13;;5160:19;;;-1:-1:-1;5131:82:15;;;;-1:-1:-1;5131:82:15;;;;;;;;;;;;;4856:364;;;;;;;;;:::o;11189:137::-;11237:7;11256:12;11271:11;;;;;;;;;-1:-1:-1;;;;;11271:11:15;-1:-1:-1;;;;;11271:16:15;;:18;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11271:18:15;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;11271:18:15;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11271:18:15;;-1:-1:-1;;11189:137:15;:::o;873:247:1:-;-1:-1:-1;;;;;978:51:1;;;;;;:25;:51;;;;;;;;;:61;;-1:-1:-1;;978:61:1;;;;;;;;;;1054:59;;;;;;;;;;;;;;;;;;;;;873:247;;:::o;47:637:11:-;143:17;184:3;:10;198:2;184:16;176:25;;;;;;310:2;301:12;;295:19;347:2;338:12;;332:19;392:2;383:12;;377:19;212:9;369:28;516:2;512:6;;508:44;;;539:2;534:7;508:44;569:1;:7;;574:2;569:7;:18;;;;580:1;:7;;585:2;580:7;569:18;561:27;;;;;;611:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;611:24:11;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;611:24:11;;-1:-1:-1;;611:24:11;;;-1:-1:-1;;;;;;;653:23:11;;645:32;;;;;;47:637;;;;;;;:::o;1870:1353:16:-;2070:15;;2049:6;;2070:19;2066:1098;;2123:22;2163:16;2197:15;2230:18;2266:22;2305:24;2320:8;2305:14;:24::i;:::-;2105:224;;-1:-1:-1;2105:224:16;;-1:-1:-1;2105:224:16;-1:-1:-1;2105:224:16;-1:-1:-1;2105:224:16;-1:-1:-1;2344:18:16;2385:73;2105:224;;;;;2385:15;:73::i;:::-;2381:659;;;2491:137;2536:47;2560:6;2568:14;2536:23;:47::i;2491:137::-;2652:217;;;;;;;;;;;;;;;;;;;;2478:150;;-1:-1:-1;2753:1:16;;-1:-1:-1;;;;;2652:217:16;;;;;;;;;;;;;;;;;2910:115;2955:20;2997:10;2910:23;:115::i;:::-;2887:138;;2381:659;3058:14;;3054:100;;3092:47;;-1:-1:-1;;;;;3092:35:16;;;:47;;;;;3128:10;;3092:47;;;;3128:10;3092:35;:47;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3092:47:16;3054:100;2066:1098;;;;;;;3174:42;;-1:-1:-1;;;;;3174:20:16;;;:42;;;;;3195:20;;3174:42;;;;3195:20;3174;:42;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3174:42:16;1870:1353;;;;:::o;9728:428:15:-;9978:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9978:161:15;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;9978:161:15;;;;;;;9955:194;;;;;;9728:428::o;10162:541::-;10240:4;10279;10240;10294:358;10318:5;:12;10314:1;:16;10294:358;;;10351:20;10374:5;10380:1;10374:8;;;;;;;;;;;;;;10351:31;;10416:12;10401;:27;10397:245;;;10490:12;10504;10473:44;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;10473:44:15;;;10463:55;;;;;;10448:70;;10397:245;;;10599:12;10613;10582:44;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;10582:44:15;;;10572:55;;;;;;10557:70;;10397:245;-1:-1:-1;10332:3:15;;10294:358;;;-1:-1:-1;10685:11:15;;10669:27;;10162:541;-1:-1:-1;;;10162:541:15:o;1137:133:10:-;1195:7;1227:1;1222;:6;;1214:27;;;;;-1:-1:-1;;;1214:27:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1258:5:10;;;1137:133::o

Swarm Source

bzzr://9987ebdf08909dce1f2ea5d2b1691f50310c456133e0dbe2241f28115fb76339

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.