ETH Price: $3,351.17 (-1.09%)
Gas: 11 Gwei

Contract

0x80bC578aC3d5611A3cD63b078E6d1FECa2EE6164
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
0x61016060126929772021-06-23 21:55:371098 days ago1624485337IN
 Contract Creation
0 ETH0.0229896811

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To Value
126972952021-06-24 14:13:021098 days ago1624543982
0x80bC578a...Ca2EE6164
0.00000001 ETH
Loading...
Loading

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

Contract Name:
EstateSaleWithFee

Compiler Version
v0.6.5+commit.f956cc89

Optimization Enabled:
Yes with 2000 runs

Other Settings:
default evmVersion, MIT license
File 1 of 9 : EstateSaleWithFee.sol
/* solhint-disable not-rely-on-time, func-order */
pragma solidity 0.6.5;

import "../common/Libraries/SafeMathWithRequire.sol";
import "./LandToken.sol";
import "../common/Interfaces/ERC1155.sol";
import "../common/Interfaces/ERC20.sol";
import "../common/BaseWithStorage/MetaTransactionReceiver.sol";
import "../ReferralValidator/ReferralValidator.sol";


/// @title Estate Sale contract with referral
/// @notice This contract manages the sale of our lands as Estates
contract EstateSaleWithFee is MetaTransactionReceiver, ReferralValidator {
    using SafeMathWithRequire for uint256;

    event LandQuadPurchased(
        address indexed buyer,
        address indexed to,
        uint256 indexed topCornerId,
        uint256 size,
        uint256 price,
        address token,
        uint256 amountPaid
    );

    /// @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), "ZERO_ADDRESS");
        require(msg.sender == _admin, "NOT_AUTHORIZED");
        _wallet = newWallet;
    }

    function rebalanceSand(uint256 newMultiplier) external {
        require(msg.sender == _admin, "NOT_AUTHORIZED");
        _multiplier = newMultiplier;
    }

    function getSandMultiplier() external view returns (uint256) {
        return _multiplier;
    }

    /// @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
    function buyLandWithSand(
        address buyer,
        address to,
        address reserved,
        uint256 x,
        uint256 y,
        uint256 size,
        uint256 priceInSand,
        uint256 adjustedPriceInSand,
        bytes32 salt,
        uint256[] calldata assetIds,
        bytes32[] calldata proof,
        bytes calldata referral
    ) external {
        _checkPrices(priceInSand, adjustedPriceInSand);
        _checkValidity(buyer, reserved, x, y, size, priceInSand, salt, assetIds, proof);
        _handleFeeAndReferral(buyer, adjustedPriceInSand, referral);
        _mint(buyer, to, x, y, size, adjustedPriceInSand, address(_sand), adjustedPriceInSand);
        _sendAssets(to, assetIds);
    }

    /// @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 getMerkleRoot() external view returns (bytes32) {
        return _merkleRoot;
    }

    /// @notice enable Admin to withdraw remaining assets from EstateSaleWithFee contract
    /// @param to intended recipient of the asset tokens
    /// @param assetIds the assetIds to be transferred
    /// @param values the quantities of the assetIds to be transferred
    function withdrawAssets(
        address to,
        uint256[] calldata assetIds,
        uint256[] calldata values
    ) external {
        require(msg.sender == _admin, "NOT_AUTHORIZED");
        // require(block.timestamp > _expiryTime, "SALE_NOT_OVER"); // removed to recover in case of misconfigured sales
        _asset.safeBatchTransferFrom(address(this), to, assetIds, values, "");
    }

    function onERC1155Received(
        address, /*operator*/
        address, /*from*/
        uint256, /*id*/
        uint256, /*value*/
        bytes calldata /*data*/
    ) external pure returns (bytes4) {
        return 0xf23a6e61;
    }

    function onERC1155BatchReceived(
        address, /*operator*/
        address, /*from*/
        uint256[] calldata, /*ids*/
        uint256[] calldata, /*values*/
        bytes calldata /*data*/
    ) external pure returns (bytes4) {
        return 0xbc197c81;
    }

    function _sendAssets(address to, uint256[] memory assetIds) internal {
        uint256[] memory values = new uint256[](assetIds.length);
        for (uint256 i = 0; i < assetIds.length; i++) {
            values[i] = 1;
        }
        _asset.safeBatchTransferFrom(address(this), to, assetIds, values, "");
    }

    function _checkPrices(uint256 priceInSand, uint256 adjustedPriceInSand) internal view {
        require(adjustedPriceInSand == priceInSand.mul(_multiplier).div(MULTIPLIER_DECIMALS), "INVALID_PRICE");
    }

    function _checkValidity(
        address buyer,
        address reserved,
        uint256 x,
        uint256 y,
        uint256 size,
        uint256 price,
        bytes32 salt,
        uint256[] memory assetIds,
        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, "RESERVED_LAND");
        bytes32 leaf = _generateLandHash(x, y, size, price, reserved, salt, assetIds);

        require(_verify(proof, leaf), "INVALID_LAND");
    }

    function _mint(
        address buyer,
        address to,
        uint256 x,
        uint256 y,
        uint256 size,
        uint256 price,
        address token,
        uint256 tokenAmount
    ) internal {
        if (size == 1 || _estate == address(0)) {
            _land.mintQuad(to, size, x, y, "");
        } else {
            _land.mintQuad(_estate, size, x, y, abi.encode(to));
        }
        emit LandQuadPurchased(buyer, to, x + (y * GRID_SIZE), size, price, token, tokenAmount);
    }

    function _generateLandHash(
        uint256 x,
        uint256 y,
        uint256 size,
        uint256 price,
        address reserved,
        bytes32 salt,
        uint256[] memory assetIds
    ) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(x, y, size, price, reserved, salt, assetIds));
    }

    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;
    }

    function _handleFeeAndReferral(
        address buyer,
        uint256 priceInSand,
        bytes memory referral
    ) internal {
        // send 5% fee to a specially configured instance of FeeDistributor.sol
        uint256 remainingAmountInSand = _handleSandFee(buyer, priceInSand);

        // calculate referral based on 95% of original priceInSand
        handleReferralWithERC20(buyer, remainingAmountInSand, referral, _wallet, address(_sand));
    }

    function _handleSandFee(address buyer, uint256 priceInSand) internal returns (uint256) {
        uint256 feeAmountInSand = priceInSand.mul(FEE).div(100);
        require(_sand.transferFrom(buyer, address(_feeDistributor), feeAmountInSand), "FEE_TRANSFER_FAILED");
        return priceInSand.sub(feeAmountInSand);
    }

    uint256 internal constant GRID_SIZE = 408; // 408 is the size of the Land

    ERC1155 internal immutable _asset;
    LandToken internal immutable _land;
    ERC20 internal immutable _sand;
    address internal immutable _estate;
    address internal immutable _feeDistributor;

    address payable internal _wallet;
    uint256 internal immutable _expiryTime;
    bytes32 internal immutable _merkleRoot;

    uint256 private constant FEE = 5; // percentage of land sale price to be diverted to a specially configured instance of FeeDistributor, shown as an integer

    uint256 private _multiplier = 1000; // multiplier used for rebalancing SAND values, 3 decimal places
    uint256 private constant MULTIPLIER_DECIMALS = 1000;

    constructor(
        address landAddress,
        address sandContractAddress,
        address initialMetaTx,
        address admin,
        address payable initialWalletAddress,
        bytes32 merkleRoot,
        uint256 expiryTime,
        address initialSigningWallet,
        uint256 initialMaxCommissionRate,
        address estate,
        address asset,
        address feeDistributor
    ) public ReferralValidator(initialSigningWallet, initialMaxCommissionRate) {
        _land = LandToken(landAddress);
        _sand = ERC20(sandContractAddress);
        _setMetaTransactionProcessor(initialMetaTx, true);
        _wallet = initialWalletAddress;
        _merkleRoot = merkleRoot;
        _expiryTime = expiryTime;
        _admin = admin;
        _estate = estate;
        _asset = ERC1155(asset);
        _feeDistributor = feeDistributor;
    }
}

File 2 of 9 : LandToken.sol
pragma solidity 0.6.5;


interface LandToken {
    function mintQuad(
        address to,
        uint256 size,
        uint256 x,
        uint256 y,
        bytes calldata data
    ) external;
}

File 3 of 9 : ReferralValidator.sol
/* solhint-disable not-rely-on-time, func-order */
pragma solidity 0.6.5;

import "../common/Libraries/SigUtil.sol";
import "../common/Libraries/SafeMathWithRequire.sol";
import "../common/Interfaces/ERC20.sol";
import "../common/BaseWithStorage/Admin.sol";


/// @dev 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;
    }

    /**
     * @dev 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;
    }

    /**
     * @dev signing wallet authorized for referral
     * @return the address of the signing wallet
     */
    function getSigningWallet() external view returns (address) {
        return _signingWallet;
    }

    /**
     * @notice the max commision rate
     * @return the maximum commision rate that a referral can give
     */
    function getMaxCommisionRate() external view returns (uint256) {
        return _maxCommissionRate;
    }

    /**
     * @dev 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) {
                payable(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);
    }
}

File 4 of 9 : Admin.sol
pragma solidity 0.6.5;


contract Admin {
    address internal _admin;

    /// @dev emitted when the contract administrator is changed.
    /// @param oldAdmin address of the previous administrator.
    /// @param newAdmin address of the new administrator.
    event AdminChanged(address oldAdmin, address newAdmin);

    /// @dev gives the current administrator of this contract.
    /// @return the current administrator of this contract.
    function getAdmin() external view returns (address) {
        return _admin;
    }

    /// @dev 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 5 of 9 : MetaTransactionReceiver.sol
pragma solidity 0.6.5;

import "./Admin.sol";


contract MetaTransactionReceiver is Admin {
    mapping(address => bool) internal _metaTransactionContracts;

    /// @dev emiited when a meta transaction processor is enabled/disabled
    /// @param metaTransactionProcessor address that will be given/removed metaTransactionProcessor rights.
    /// @param enabled set whether the metaTransactionProcessor is enabled or disabled.
    event MetaTransactionProcessor(address metaTransactionProcessor, bool enabled);

    /// @dev 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);
    }

    /// @dev 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 6 of 9 : ERC1155.sol
pragma solidity 0.6.5;


/**
    @title ERC-1155 Multi Token Standard
    @dev See https://eips.ethereum.org/EIPS/eip-1155
    Note: The ERC-165 identifier for this interface is 0xd9b67a26.
 */
interface ERC1155 {
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event URI(string value, uint256 indexed id);

    /**
        @notice Transfers `value` amount of an `id` from  `from` to `to`  (with safety call).
        @dev Caller must be approved to manage the tokens being transferred out of the `from` account (see "Approval" section of the standard).
        MUST revert if `to` is the zero address.
        MUST revert if balance of holder for token `id` is lower than the `value` sent.
        MUST revert on any other error.
        MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard).
        After the above conditions are met, this function MUST check if `to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `to` and act appropriately (see "Safe Transfer Rules" section of the standard).
        @param from    Source address
        @param to      Target address
        @param id      ID of the token type
        @param value   Transfer amount
        @param data    Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `to`
    */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external;

    /**
        @notice Transfers `values` amount(s) of `ids` from the `from` address to the `to` address specified (with safety call).
        @dev Caller must be approved to manage the tokens being transferred out of the `from` account (see "Approval" section of the standard).
        MUST revert if `to` is the zero address.
        MUST revert if length of `ids` is not the same as length of `values`.
        MUST revert if any of the balance(s) of the holder(s) for token(s) in `ids` is lower than the respective amount(s) in `values` sent to the recipient.
        MUST revert on any other error.
        MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard).
        Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
        After the above conditions for the transfer(s) in the batch are met, this function MUST check if `to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `to` and act appropriately (see "Safe Transfer Rules" section of the standard).
        @param from    Source address
        @param to      Target address
        @param ids     IDs of each token type (order and length must match _values array)
        @param values  Transfer amounts per token type (order and length must match _ids array)
        @param data    Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `to`
    */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external;

    /**
        @notice Get the balance of an account's tokens.
        @param owner  The address of the token holder
        @param id     ID of the token
        @return        The _owner's balance of the token type requested
     */
    function balanceOf(address owner, uint256 id) external view returns (uint256);

    /**
        @notice Get the balance of multiple account/token pairs
        @param owners The addresses of the token holders
        @param ids    ID of the tokens
        @return        The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair)
     */
    function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory);

    /**
        @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens.
        @dev MUST emit the ApprovalForAll event on success.
        @param operator  Address to add to the set of authorized operators
        @param approved  True if the operator is approved, false to revoke approval
    */
    function setApprovalForAll(address operator, bool approved) external;

    /**
        @notice Queries the approval status of an operator for a given owner.
        @param owner     The owner of the tokens
        @param operator  Address of authorized operator
        @return           True if the operator is approved, false if not
    */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 7 of 9 : ERC20.sol
pragma solidity 0.6.5;


/// @dev see https://eips.ethereum.org/EIPS/eip-20
interface ERC20 {
    /// @notice emitted when tokens are transfered from one address to another.
    /// @param from address from which the token are transfered from (zero means tokens are minted).
    /// @param to destination address which the token are transfered to (zero means tokens are burnt).
    /// @param value amount of tokens transferred.
    event Transfer(address indexed from, address indexed to, uint256 value);

    /// @notice emitted when owner grant transfer rights to another address
    /// @param owner address allowing its token to be transferred.
    /// @param spender address allowed to spend on behalf of `owner`
    /// @param value amount of tokens allowed.
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /// @notice return the current total amount of tokens owned by all holders.
    /// @return supply total number of tokens held.
    function totalSupply() external view returns (uint256 supply);

    /// @notice return the number of tokens held by a particular address.
    /// @param who address being queried.
    /// @return balance number of token held by that address.
    function balanceOf(address who) external view returns (uint256 balance);

    /// @notice transfer tokens to a specific address.
    /// @param to destination address receiving the tokens.
    /// @param value number of tokens to transfer.
    /// @return success whether the transfer succeeded.
    function transfer(address to, uint256 value) external returns (bool success);

    /// @notice transfer tokens from one address to another.
    /// @param from address tokens will be sent from.
    /// @param to destination address receiving the tokens.
    /// @param value number of tokens to transfer.
    /// @return success whether the transfer succeeded.
    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool success);

    /// @notice approve an address to spend on your behalf.
    /// @param spender address entitled to transfer on your behalf.
    /// @param value amount allowed to be transfered.
    /// @param success whether the approval succeeded.
    function approve(address spender, uint256 value) external returns (bool success);

    /// @notice return the current allowance for a particular owner/spender pair.
    /// @param owner address allowing spender.
    /// @param spender address allowed to spend.
    /// @return amount number of tokens `spender` can spend on behalf of `owner`.
    function allowance(address owner, address spender) external view returns (uint256 amount);
}

File 8 of 9 : SafeMathWithRequire.sol
pragma solidity 0.6.5;


/**
 * @title SafeMath
 * @dev Math operations with safety checks that revert
 */
library SafeMathWithRequire {
    using SafeMathWithRequire for uint256;

    uint256 constant DECIMALS_18 = 1000000000000000000;
    uint256 constant DECIMALS_12 = 1000000000000;
    uint256 constant DECIMALS_9 = 1000000000;
    uint256 constant DECIMALS_6 = 1000000;

    /**
     * @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) {
        require(b != 0, "divbyzero");
        // 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;
    }

    function sqrt6(uint256 a) internal pure returns (uint256 c) {
        a = a.mul(DECIMALS_12);
        uint256 tmp = a.add(1) / 2;
        c = a;
        // tmp cannot be zero unless a = 0 which skip the loop
        while (tmp < c) {
            c = tmp;
            tmp = ((a / tmp) + tmp) / 2;
        }
    }

    function sqrt3(uint256 a) internal pure returns (uint256 c) {
        a = a.mul(DECIMALS_6);
        uint256 tmp = a.add(1) / 2;
        c = a;
        // tmp cannot be zero unless a = 0 which skip the loop
        while (tmp < c) {
            c = tmp;
            tmp = ((a / tmp) + tmp) / 2;
        }
    }

    function cbrt6(uint256 a) internal pure returns (uint256 c) {
        a = a.mul(DECIMALS_18);
        uint256 tmp = a.add(2) / 3;
        c = a;
        // tmp cannot be zero unless a = 0 which skip the loop
        while (tmp < c) {
            c = tmp;
            uint256 tmpSquare = tmp**2;
            require(tmpSquare > tmp, "overflow");
            tmp = ((a / tmpSquare) + (tmp * 2)) / 3;
        }
        return c;
    }

    function cbrt3(uint256 a) internal pure returns (uint256 c) {
        a = a.mul(DECIMALS_9);
        uint256 tmp = a.add(2) / 3;
        c = a;
        // tmp cannot be zero unless a = 0 which skip the loop
        while (tmp < c) {
            c = tmp;
            uint256 tmpSquare = tmp**2;
            require(tmpSquare > tmp, "overflow");
            tmp = ((a / tmpSquare) + (tmp * 2)) / 3;
        }
        return c;
    }

    // TODO test
    function rt6_3(uint256 a) internal pure returns (uint256 c) {
        a = a.mul(DECIMALS_18);
        uint256 tmp = a.add(5) / 6;
        c = a;
        // tmp cannot be zero unless a = 0 which skip the loop
        while (tmp < c) {
            c = tmp;
            uint256 tmpFive = tmp**5;
            require(tmpFive > tmp, "overflow");
            tmp = ((a / tmpFive) + (tmp * 5)) / 6;
        }
    }
}

File 9 of 9 : SigUtil.sol
pragma solidity 0.6.5;


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);
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"landAddress","type":"address"},{"internalType":"address","name":"sandContractAddress","type":"address"},{"internalType":"address","name":"initialMetaTx","type":"address"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address payable","name":"initialWalletAddress","type":"address"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"expiryTime","type":"uint256"},{"internalType":"address","name":"initialSigningWallet","type":"address"},{"internalType":"uint256","name":"initialMaxCommissionRate","type":"uint256"},{"internalType":"address","name":"estate","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"feeDistributor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"topCornerId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountPaid","type":"uint256"}],"name":"LandQuadPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"metaTransactionProcessor","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"MetaTransactionProcessor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"referee","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"commission","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"commissionRate","type":"uint256"}],"name":"ReferralUsed","type":"event"},{"inputs":[{"internalType":"address","name":"buyer","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"reserved","type":"address"},{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"uint256","name":"priceInSand","type":"uint256"},{"internalType":"uint256","name":"adjustedPriceInSand","type":"uint256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"assetIds","type":"uint256[]"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes","name":"referral","type":"bytes"}],"name":"buyLandWithSand","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"referral","type":"bytes"}],"name":"decodeReferral","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExpiryTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxCommisionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSandMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSigningWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"isMetaTransactionProcessor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"referee","type":"address"},{"internalType":"uint256","name":"expiryTime","type":"uint256"},{"internalType":"uint256","name":"commissionRate","type":"uint256"}],"name":"isReferralValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMultiplier","type":"uint256"}],"name":"rebalanceSand","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"metaTransactionProcessor","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setMetaTransactionProcessor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newWallet","type":"address"}],"name":"setReceivingWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxCommissionRate","type":"uint256"}],"name":"updateMaxCommissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSigningWallet","type":"address"}],"name":"updateSigningWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"assetIds","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"withdrawAssets","outputs":[],"stateMutability":"nonpayable","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063984d6252116100cd578063dc5074af11610081578063ecb255b511610066578063ecb255b514610857578063f23a6e6114610874578063f2e7b3811461090957610151565b8063dc5074af14610814578063e56f8a9e1461083a57610151565b8063bc197c81116100b2578063bc197c81146105d3578063c10a420814610735578063caed35001461080c57610151565b8063984d6252146104db578063b522ecff146105ad57610151565b80636e9960c3116101245780638a04af6a116101095780638a04af6a1461032a5780638a12b82f146103585780638f283970146104b557610151565b80636e9960c3146102fe57806377f1c3ac1461032257610151565b806325cb5bc014610156578063495906571461017057806358bc29441461017857806365194ce7146101a0575b600080fd5b61015e610911565b60408051918252519081900360200190f35b61015e610935565b61019e6004803603602081101561018e57600080fd5b50356001600160a01b0316610959565b005b610246600480360360208110156101b657600080fd5b8101906020810181356401000000008111156101d157600080fd5b8201836020820111156101e357600080fd5b8035906020019184600183028401116401000000008311171561020557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610a04945050505050565b6040518080602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b838110156102bf5781810151838201526020016102a7565b50505050905090810190601f1680156102ec5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b610306610b09565b604080516001600160a01b039092168252519081900360200190f35b61015e610b18565b61019e6004803603604081101561034057600080fd5b506001600160a01b0381351690602001351515610b1e565b61019e600480360361018081101561036f57600080fd5b6001600160a01b038235811692602081013582169260408201359092169160608201359160808101359160a08201359160c08101359160e0820135916101008101359181019061014081016101208201356401000000008111156103d257600080fd5b8201836020820111156103e457600080fd5b8035906020019184602083028401116401000000008311171561040657600080fd5b91939092909160208101903564010000000081111561042457600080fd5b82018360208201111561043657600080fd5b8035906020019184602083028401116401000000008311171561045857600080fd5b91939092909160208101903564010000000081111561047657600080fd5b82018360208201111561048857600080fd5b803590602001918460018302840111640100000000831117156104aa57600080fd5b509092509050610b75565b61019e600480360360208110156104cb57600080fd5b50356001600160a01b0316610cc3565b61019e600480360360608110156104f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561051c57600080fd5b82018360208201111561052e57600080fd5b8035906020019184602083028401116401000000008311171561055057600080fd5b91939092909160208101903564010000000081111561056e57600080fd5b82018360208201111561058057600080fd5b803590602001918460208302840111640100000000831117156105a257600080fd5b509092509050610d99565b61019e600480360360208110156105c357600080fd5b50356001600160a01b0316610f24565b610700600480360360a08110156105e957600080fd5b6001600160a01b03823581169260208101359091169181019060608101604082013564010000000081111561061d57600080fd5b82018360208201111561062f57600080fd5b8035906020019184602083028401116401000000008311171561065157600080fd5b91939092909160208101903564010000000081111561066f57600080fd5b82018360208201111561068157600080fd5b803590602001918460208302840111640100000000831117156106a357600080fd5b9193909290916020810190356401000000008111156106c157600080fd5b8201836020820111156106d357600080fd5b803590602001918460018302840111640100000000831117156106f557600080fd5b50909250905061100d565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b6107f8600480360360a081101561074b57600080fd5b81019060208101813564010000000081111561076657600080fd5b82018360208201111561077857600080fd5b8035906020019184600183028401116401000000008311171561079a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550506001600160a01b03833581169450602084013516926040810135925060600135905061103a565b604080519115158252519081900360200190f35b610306611176565b6107f86004803603602081101561082a57600080fd5b50356001600160a01b0316611185565b61019e6004803603602081101561085057600080fd5b50356111a3565b61019e6004803603602081101561086d57600080fd5b5035611207565b610700600480360360a081101561088a57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156108ca57600080fd5b8201836020820111156108dc57600080fd5b803590602001918460018302840111640100000000831117156108fe57600080fd5b50909250905061126b565b61015e611296565b7f0000000000000000000000000000000000000000000000000000000060ddbc5090565b7feed9fe83a3ce1e3ad33543aad26a29dfa0ef4834eabee940b9f94b781ae944b590565b6000546001600160a01b031633146109b8576040805162461bcd60e51b815260206004820152601060248201527f53656e646572206e6f742061646d696e00000000000000000000000000000000604482015290519081900360640190fd5b600554600280546001600160a01b03908116600090815260046020526040902042909301909255805473ffffffffffffffffffffffffffffffffffffffff191692909116919091179055565b606060008060008060606000806000808a80602001905160a0811015610a2957600080fd5b8101908080516040519392919084640100000000821115610a4957600080fd5b908301906020820185811115610a5e57600080fd5b8251640100000000811182820188101715610a7857600080fd5b82525081516020918201929091019080838360005b83811015610aa5578181015183820152602001610a8d565b50505050905090810190601f168015610ad25780820380516001836020036101000a031916815260200191505b5060409081526020820151908201516060830151608090930151959f50909d509b5099509197505050505050505091939590929450565b6000546001600160a01b031690565b60035490565b6000546001600160a01b03163314610b675760405162461bcd60e51b815260040180806020018281038252602e815260200180612198602e913960400191505060405180910390fd5b610b71828261129c565b5050565b610b7f898961131e565b610c048f8e8e8e8e8e8d8d8d80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508c8c8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061139892505050565b610c458f8984848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061157592505050565b610c758f8f8e8e8e8d7f0000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d08f6115c6565b610cb28e87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061189192505050565b505050505050505050505050505050565b6000546001600160a01b03163314610d22576040805162461bcd60e51b815260206004820152601b60248201527f6f6e6c792061646d696e2063616e206368616e67652061646d696e0000000000604482015290519081900360640190fd5b600054604080516001600160a01b039283168152918316602083015280517f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f9281900390910190a16000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610df8576040805162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a4544000000000000000000000000000000000000604482015290519081900360640190fd5b7f000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db56001600160a01b0316632eb2c2d63087878787876040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b031681526020018060200180602001806020018481038452888882818152602001925060200280828437600083820152601f01601f19169091018581038452868152602090810191508790870280828437600081840152601f19601f8201169050808301925050508481038252600081526020016020019950505050505050505050600060405180830381600087803b158015610f0557600080fd5b505af1158015610f19573d6000803e3d6000fd5b505050505050505050565b6001600160a01b038116610f7f576040805162461bcd60e51b815260206004820152600c60248201527f5a45524f5f414444524553530000000000000000000000000000000000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610fde576040805162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a4544000000000000000000000000000000000000604482015290519081900360640190fd5b6006805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b7fbc197c810000000000000000000000000000000000000000000000000000000098975050505050505050565b600060035482118061105d5750836001600160a01b0316856001600160a01b0316145b8061106757508242115b156110745750600061116d565b60408051606087811b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081166020808501919091529188901b166034830152604882018690526068808301869052835180840390910181526088830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000060a884015260c48084018290528451808503909101815260e4909301909352815191012060009061112b9089611a55565b6001600160a01b03811660009081526004602052604090205490915042116111585760019250505061116d565b6002546001600160a01b039081169116149150505b95945050505050565b6002546001600160a01b031690565b6001600160a01b031660009081526001602052604090205460ff1690565b6000546001600160a01b03163314611202576040805162461bcd60e51b815260206004820152601060248201527f53656e646572206e6f742061646d696e00000000000000000000000000000000604482015290519081900360640190fd5b600355565b6000546001600160a01b03163314611266576040805162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a4544000000000000000000000000000000000000604482015290519081900360640190fd5b600755565b7ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b60075490565b6001600160a01b03821660008181526001602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915582519384529083015280517fb21eb88b4e33b3f1281830a7178d74d8aa73220416215726b68ae23d539515cb9281900390910190a15050565b6113456103e861133960075485611b2290919063ffffffff16565b9063ffffffff611b9816565b8114610b71576040805162461bcd60e51b815260206004820152600d60248201527f494e56414c49445f505249434500000000000000000000000000000000000000604482015290519081900360640190fd5b7f0000000000000000000000000000000000000000000000000000000060ddbc50421061140c576040805162461bcd60e51b815260206004820152600c60248201527f53414c455f49535f4f5645520000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03891633148061143257503360009081526001602052604090205460ff165b611483576040805162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a4544000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03881615806114aa5750886001600160a01b0316886001600160a01b0316145b6114fb576040805162461bcd60e51b815260206004820152600d60248201527f52455345525645445f4c414e4400000000000000000000000000000000000000604482015290519081900360640190fd5b600061150c888888888d8989611bfd565b90506115188282611ca2565b611569576040805162461bcd60e51b815260206004820152600c60248201527f494e56414c49445f4c414e440000000000000000000000000000000000000000604482015290519081900360640190fd5b50505050505050505050565b60006115818484611d6b565b6006549091506115c0908590839085906001600160a01b03167f0000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d0611eb8565b50505050565b83600114806115fc57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316155b156116c357604080517f6e1e3bbf0000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015260248201879052604482018990526064820188905260a06084830152600060a4830181905292517f00000000000000000000000050f5474724e0ee42d9a4e711ccfb275809fd6d4a90911692636e1e3bbf9260e4808201939182900301818387803b1580156116a657600080fd5b505af11580156116ba573d6000803e3d6000fd5b50505050611827565b7f00000000000000000000000050f5474724e0ee42d9a4e711ccfb275809fd6d4a6001600160a01b0316636e1e3bbf7f00000000000000000000000000000000000000000000000000000000000000008689898c60405160200180826001600160a01b03166001600160a01b031681526020019150506040516020818303038152906040526040518663ffffffff1660e01b815260040180866001600160a01b03166001600160a01b0316815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117be5781810151838201526020016117a6565b50505050905090810190601f1680156117eb5780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b15801561180e57600080fd5b505af1158015611822573d6000803e3d6000fd5b505050505b60408051858152602081018590526001600160a01b03848116828401526060820184905291516101988802890192808b1692908c16917fe4dfa6ac11314892f3029b34a25b1a887da3b1cab2bbf8506d87128ba6e3ac029181900360800190a45050505050505050565b6060815167ffffffffffffffff811180156118ab57600080fd5b506040519080825280602002602001820160405280156118d5578160200160208202803683370190505b50905060005b82518110156119055760018282815181106118f257fe5b60209081029190910101526001016118db565b507f000000000000000000000000a342f5d851e866e18ff98f351f2c6637f4478db56001600160a01b0316632eb2c2d6308585856040518563ffffffff1660e01b815260040180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b03168152602001806020018060200180602001848103845286818151815260200191508051906020019060200280838360005b838110156119c05781810151838201526020016119a8565b50505050905001848103835285818151815260200191508051906020019060200280838360005b838110156119ff5781810151838201526020016119e7565b50505050905001848103825260008152602001602001975050505050505050600060405180830381600087803b158015611a3857600080fd5b505af1158015611a4c573d6000803e3d6000fd5b50505050505050565b60008151604114611a6557600080fd5b60208201516040830151606084015160001a601b811015611a8457601b015b8060ff16601b1480611a9957508060ff16601c145b611aa257600080fd5b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015611af9573d6000803e3d6000fd5b5050604051601f1901519450506001600160a01b038416611b1957600080fd5b50505092915050565b600082611b3157506000611b92565b5081810281838281611b3f57fe5b0414611b92576040805162461bcd60e51b815260206004820152600860248201527f6f766572666c6f77000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b92915050565b600081611bec576040805162461bcd60e51b815260206004820152600960248201527f64697662797a65726f0000000000000000000000000000000000000000000000604482015290519081900360640190fd5b818381611bf557fe5b049392505050565b60008787878787878760405160200180888152602001878152602001868152602001858152602001846001600160a01b03166001600160a01b031660601b8152601401838152602001828051906020019060200280838360005b83811015611c6f578181015183820152602001611c57565b50505050905001975050505050505050604051602081830303815290604052805190602001209050979650505050505050565b600081815b8451811015611d41576000858281518110611cbe57fe5b6020026020010151905080831015611d065782816040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209250611d38565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b50600101611ca7565b507feed9fe83a3ce1e3ad33543aad26a29dfa0ef4834eabee940b9f94b781ae944b5149392505050565b600080611d84606461133985600563ffffffff611b2216565b604080516323b872dd60e01b81526001600160a01b0387811660048301527f0000000000000000000000000eb04462d69b1d267d269377e34f60b9de1c8510811660248301526044820184905291519293507f0000000000000000000000003845badade8e6dff049820680d1f14bd3903a5d0909116916323b872dd916064808201926020929091908290030181600087803b158015611e2357600080fd5b505af1158015611e37573d6000803e3d6000fd5b505050506040513d6020811015611e4d57600080fd5b5051611ea0576040805162461bcd60e51b815260206004820152601360248201527f4645455f5452414e534645525f4641494c454400000000000000000000000000604482015290519081900360640190fd5b611eb0838263ffffffff61213a16565b949350505050565b82518190859015612062576060600080600080611ed48a610a04565b9398509196509450925090506000611eef868686868661103a565b15611f7d57611f09611f018d84611b22565b612710611b98565b9050886001600160a01b0316846001600160a01b0316866001600160a01b03167fac7a699eb95c3c6d390ec4626de17ef9a67b35891efdb197beba7c7fdd45fac48f858760405180848152602001838152602001828152602001935050505060405180910390a4611f7a878261213a565b96505b801561205b57604080516323b872dd60e01b81526001600160a01b038f811660048301528781166024830152604482018490529151918a16916323b872dd916064808201926020929091908290030181600087803b158015611fde57600080fd5b505af1158015611ff2573d6000803e3d6000fd5b505050506040513d602081101561200857600080fd5b505161205b576040805162461bcd60e51b815260206004820152601960248201527f636f6d6d6973696f6e207472616e73666572206661696c656400000000000000604482015290519081900360640190fd5b5050505050505b604080516323b872dd60e01b81526001600160a01b0389811660048301528681166024830152604482018490529151918416916323b872dd916064808201926020929091908290030181600087803b1580156120bd57600080fd5b505af11580156120d1573d6000803e3d6000fd5b505050506040513d60208110156120e757600080fd5b5051611a4c576040805162461bcd60e51b815260206004820152601760248201527f7061796d656e74207472616e73666572206661696c6564000000000000000000604482015290519081900360640190fd5b600082821115612191576040805162461bcd60e51b815260206004820152600860248201527f756e6465666c6f77000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b5090039056fe6f6e6c792061646d696e2063616e207365747570206d6574615472616e73616374696f6e50726f636573736f7273a26469706673582212200ff38c5741c66b2a22a9a9ee2abe0f55626323082b6b4443921fd3b25484584a64736f6c63430006050033

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.