false
true
0

Contract Address Details

0x000e520b79243980C49564DDA653802ab8C471Ea

Contract Name
ScotchMarketplace
Creator
0x60ee1b–981fbf at 0x859c67–290b3d
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
26347261
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been partially verified via Sourcify. View contract in Sourcify repository
Contract name:
ScotchMarketplace




Optimization enabled
true
Compiler version
v0.8.15+commit.e14f2714




Optimization runs
200
EVM Version
london




Verified at
2026-04-22T01:58:55.300865Z

ScotchMarketplace.sol

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// File: @openzeppelin/contracts/utils/Counters.sol


// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

// File: @openzeppelin/contracts/utils/Address.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

// File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;




/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// File: @openzeppelin/contracts/utils/Context.sol


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;


/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// File: contracts/scBeneficiary.sol


pragma solidity ^0.8.8;



 

abstract contract ScotchBeneficiary is Ownable {
  using SafeERC20 for IERC20;

   // Beneficiary (commission recipient) Mode
  enum BeneficiaryMode{
    // 0: No Beneficiary Specified
    None,
    // 1: Beneficiary - simple the recipient address
    Beneficiary,
    // 2: Distributor - the service to distribute money
    Distributor
  }

  // Beneficiary Model
  struct Beneficiary {
    BeneficiaryMode mode;       // mode of the beneficiary send funds
    address payable recipient;  // beneficiary recipient address
  }

  // beneficiary - receiver of the funds - the address where the funds will be sent
  Beneficiary internal _beneficiary;


  // ===========================================
  // ======= Secondary public functions ========
  // ===========================================

  // get current beneficiary info
  function getBeneficiary() public view returns (Beneficiary memory) {
    return _beneficiary;
  }


  // ===========================================
  // =========== Owner's functions =============
  // ===========================================

  // change beneficiary of the Scotch Marketplace
  function changeBeneficiary(BeneficiaryMode mode, address payable recipient) public virtual onlyOwner {
    if (mode == BeneficiaryMode.None)
      require(recipient == address(0), "Beneficiar mode None requires zero address for recipient!");
    else
      require(recipient != address(0), "Beneficiary recipient address should be specified!");

    _beneficiary.mode = mode;
    _beneficiary.recipient = recipient;
  }

  // send accumulated funds to recipient (native-token = zero tokenContract)
  function sendFunds(uint256 amount, address tokenContract) public virtual onlyOwner {
    require(_isBeneficiaryExists(), "Beneficiary should be specified!");
    require(amount > 0, "Send Amount should be positive!");

    // address of the current contract
    address current = address(this);

    if (tokenContract == address(0)) {
      // get Scotch Marketplace balance in native token
      uint256 balance = current.balance;
      require(balance >= amount, "Send Amount exceeds Smart Contract's native token balance!");

      // send native token amount to _beneficiar
      _beneficiary.recipient.transfer(amount);
    }
    else {
      // get ERC-20 Token Contract
      IERC20 hostTokenContract = IERC20(tokenContract);
      // get Scotch Marketplace balance in ERC-20 Token
      uint256 balance = hostTokenContract.balanceOf(current);
      require(balance >= amount, "Send Amount exceeds Smart Contract's ERC-20 token balance!");
      // send ERC-20 token amount to recipient
      hostTokenContract.transfer(_beneficiary.recipient, amount);
    }
  }

  // ===========================================
  // ======= Internal helper functions =========
  // ===========================================

  // check if beneficiary is specified to send funds
  function _isBeneficiaryExists() internal view virtual returns (bool){
    return _beneficiary.mode != BeneficiaryMode.None && _beneficiary.recipient != address(0);
  }

   // charge funds from caller in native tokens
  function _chargeFunds(uint256 amount, string memory message) internal virtual {
    if (amount > 0) {
      // check payment for appropriate funds amount
      require(msg.value >= amount, message);

      // send funds to _beneficiary
      if (_isBeneficiaryExists())
        _beneficiary.recipient.transfer(msg.value);
    }
  }
}

// File: contracts/iDistributor.sol


pragma solidity ^0.8.8;

interface IDistributor {
    function distribute(uint256 marketItemId) external payable;
}
// File: contracts/scMarketplace.sol


pragma solidity ^0.8.8;
pragma experimental ABIEncoderV2;






// V1.8
contract ScotchMarketplace is ScotchBeneficiary, ReentrancyGuard {
  using SafeERC20 for IERC20;

  // Market-Item Status
  enum MarketItemStatus {
    // 0: market-item is active and can be sold
    Active,
    // 1: market-item is already sold
    Sold,
    // 2: market-item is cancelled by NFT owner
    Cancelled,
    // 3: market-item is deleted by Scotch owner
    Deleted
  }

  // input for market-item placement
  struct MarketItemInput {
    address tokenContract;
    uint256 tokenId;
    address priceContract;
    uint256 priceAmount;
    address[] whiteList;
  }

  // Market-Rate structure
  struct MarketRate {
    bool isActive;         // is market-rate active (is valid for specific address)
    uint256 listingPrice;  // listing price of a new market-item (for seller to create market-item)
    uint256 cancelPrice;   // the price for cancelling market-item on the market (by NFT owner)
    uint feePercent;       // fee % to charge from market-item price (seller will receive (100-feePercent)/100 * price)
  }

  // Market-Item structure
  struct MarketItem {
    uint256 itemId;           // id of the market-item
    address tokenContract;    // original (sellable) NFT token contract address
    uint256 tokenId;          // original (sellable) NFT token Id
    address payable seller;   // seller of the original NFT
    address payable buyer;    // buyer of the market-item - new owner of the sellable NFT
    address priceContract;    // ERC-20 price token address (Zero address => native token)
    uint256 price;            // price = amount of ERC-20 (or native token) price tokens to buy market-item
    MarketItemStatus status;  // status of the market-item
    uint256 fee;              // amount of fee (in ERC-20 price tokens) that were charged during the sale
    uint256 position;         // positive position in active market-items array (1..N)
    uint partnerId;           // Id of the partner, from which the sale was made
    address[] whiteList;      // white list of addresses that could buy market-item
  }

  // Events of Marketplace
  event MarketItemPlaced(uint256 indexed marketItemId, address indexed tokenContract, uint256 tokenId, address indexed seller, address priceContract, uint256 price);
  event MarketItemSold(uint256 indexed marketItemId, address indexed buyer);
  event MarketItemRemoved(uint256 indexed marketItemId, MarketItemStatus status);


  // counter for market items Id
  using Counters for Counters.Counter;
  Counters.Counter private _itemIds;

  // collection of market-items
  mapping(uint256 => MarketItem) private _items;

  // active-market-items collection - collection of active market-items ids only
  uint256[] private _activeItems;

  // mapping of (Token Contract, TokenID) => Active Position
  mapping(address => mapping(uint256 => uint256))  private _activeTokens;

  // collection of market-rates
  mapping(address => MarketRate) private _rates;

  // mapping of (marketItemID, buyer address) => allowed to buy flag
  mapping(uint256 => mapping(address => bool))  private _allowedToBuy;

  // maximal amount of items, that could be sold in one transaction
  uint public _maxItemsForSale;



  constructor() {
    _beneficiary = Beneficiary(BeneficiaryMode.None, payable(address(0)));
    _activeItems = new uint256[](0);
    _rates[address(0)] = MarketRate(true, 0, 0, 3);
    _maxItemsForSale = 100;
  }

  // ===========================================
  // ======= Scotch Marketplace modifiers ======
  // ===========================================

  modifier idExists(uint256 marketItemId) {
    require(marketItemId > 0 && marketItemId <= _itemIds.current(), "Invalid Market Item ID!");
    _;
  }

  modifier isActive(uint256 marketItemId) {
    require(_items[marketItemId].status == MarketItemStatus.Active, "Market Item is not Active");
    _;
  }

  // ===========================================
  // ==== MAIN Scotch Marketplace functions ====
  // ===========================================

  // create new market-item - listing of original NFT on Marketplace
  function placeMarketItem(address tokenContract, uint256 tokenId, address priceContract, uint256 price, address[] memory whiteList) public payable {
    require(price > 0, "Price must be positive (at least 1 wei)");

    // check if token is already placed in the market
    uint256 existingMarketItemId = findActiveMarketItem(tokenContract, tokenId);
    require(existingMarketItemId == 0, "That token is already placed on the market");

    // seller of the Token
    address seller = _msgSender();

    // token validation
    int validation = _checkTokenValidity(seller, tokenContract, tokenId);
    require(validation != - 1, "Only owner of the NFT can place it to the Marketplace");
    require(validation != - 2, "NFT should be approved to the Marketplace");
    require(validation == 0, "NFT is not valid to be sold on the Marketplace");

    // market-rate for seller
    uint256 listingPrice = _getValidRate(seller).listingPrice;

    // charge listing-price from seller
    _chargeFunds(listingPrice, "Listing Price should be sent to place NFT on the Marketplace");

    // build market-item input
    MarketItemInput memory input = MarketItemInput(tokenContract, tokenId, priceContract, price, whiteList);

    // create market-item
    _createMarketItem(seller, input);
  }

  function placeMarketItems(MarketItemInput[] memory input) public payable {
    require(input.length > 0, "At least one item input should be specified");
    require(input.length <= _maxItemsForSale, "Amount of specified items exceeds Maximum Allowed Amount");

    // seller of the Token
    address seller = _msgSender();

    // market-rate for seller
    uint256 listingPrice = _getValidRate(seller).listingPrice;

    // charge listing-price from seller
    _chargeFunds(listingPrice * input.length, "Listing Price should be sent to place NFT on the Marketplace");

    for (uint i = 0; i < input.length; i++)
    {
      require(input[i].priceAmount > 0, "Price must be positive (at least 1 wei)");

      // check if token is already placed in the market
      uint256 existingMarketItemId = findActiveMarketItem(input[i].tokenContract, input[i].tokenId);
      require(existingMarketItemId == 0, "That token is already placed on the market");

      // token validation
      int validation = _checkTokenValidity(seller, input[i].tokenContract, input[i].tokenId);
      require(validation != - 1, "Only owner of the NFT can place it to the Marketplace");
      require(validation != - 2, "NFT should be approved to the Marketplace");
      require(validation == 0, "NFT is not valid to be sold on the Marketplace");

      // create market-item
      _createMarketItem(seller, input[i]);
    }
  }

  // make deal on sell market-item, receive payment and transfer original NFT
  function makeMarketSale(uint256 marketItemId, uint partnerId) public payable idExists(marketItemId) isActive(marketItemId) nonReentrant {
    // address of the buyer for nft
    address buyer = _msgSender();
    // address of the market-item seller
    address payable seller = _items[marketItemId].seller;
    // original nft tokenId
    uint256 tokenId = _items[marketItemId].tokenId;

    // nft token contract && approval for nft
    IERC721 hostTokenContract = IERC721(_items[marketItemId].tokenContract);
    bool allApproved = hostTokenContract.isApprovedForAll(seller, address(this));
    if (!allApproved) {
      address approvedAddress = hostTokenContract.getApproved(tokenId);
      require(approvedAddress == address(this), "Market Item (NFT) should be approved to the Marketplace");
    }

    // check white-list if it was set up
    if (_items[marketItemId].whiteList.length > 0)
      require(_allowedToBuy[marketItemId][buyer] == true, "Your address is not specified in White-List for current Market Item");

    // charge price from seller & send to buyer & beneficiary
    uint256 feeAmount = _chargePrice(marketItemId, buyer);

    // update market-item info
    _items[marketItemId].buyer = payable(buyer);
    _items[marketItemId].fee = feeAmount;
    _items[marketItemId].partnerId = partnerId;

    // transfer original nft from seller to buyer
    hostTokenContract.safeTransferFrom(seller, buyer, tokenId);

    // remove market-item with Sold status
    _removeMarketItem(marketItemId, MarketItemStatus.Sold);

    // if beneficiary 'Distributor' mode specified => call distribute method for current marketItemId
    if (_beneficiary.mode == BeneficiaryMode.Distributor && _beneficiary.recipient != address(0))
    {
      // build distributor Host Contract
      IDistributor distributorHost = IDistributor(_beneficiary.recipient);
      distributorHost.distribute(marketItemId);
    }

    emit MarketItemSold(marketItemId, buyer);
  }

  // cancel market-item placement on Scotch Marketplace
  function cancelMarketItem(uint256 marketItemId) public payable idExists(marketItemId) isActive(marketItemId) nonReentrant {
    // address of the market-item seller
    address payable seller = _items[marketItemId].seller;
    // check market-item Seller is cancelling the market-item
    require(_msgSender() == seller, "Only Seller can cancel Market Item");
    // market-rate for seller
    uint256 cancelPrice = _getValidRate(seller).cancelPrice;

    // charge cancel-price from seller
    _chargeFunds(cancelPrice, "Cancel Price should be sent to cancel NFT placement on the Marketplace");

    // remove market-item with Cancelled status
    _removeMarketItem(marketItemId, MarketItemStatus.Cancelled);
  }


  // ===========================================
  // ======= Secondary public functions ========
  // ===========================================

  // get Rate for sender address
  function getRate() public view returns (MarketRate memory) {
    return _getValidRate(_msgSender());
  }

  // get market-item info by id
  function getMarketItem(uint256 marketItemId) public view idExists(marketItemId) returns (MarketItem memory) {
    return _items[marketItemId];
  }

  // get count of all market-items
  function getAllMarketItemsCount() public view returns (uint256) {
    return _itemIds.current();
  }

  // get count of active (not sold and not removed) market-items
  function getActiveMarketItemsCount() public view returns (uint256) {
    return _activeItems.length;
  }

  // get active active market-item by index (1 based)
  function getActiveMarketItem(uint256 position) public view returns (MarketItem memory) {
    require(_activeItems.length > 0, "There are no any Active Market Items yet!");
    require(position >= 1 && position <= _activeItems.length, "Position should be positive number in Active Market Items Count range (1..N)");
    return _items[_activeItems[position - 1]];
  }

  // find existing active market-item by tokenContract & tokenId
  function findActiveMarketItem(address tokenContract, uint256 tokenId) public view returns (uint256) {
    return _activeTokens[tokenContract][tokenId];
  }


  // ===========================================
  // =========== Owner's functions =============
  // ===========================================

  // set maximum amount of items that could be sold
  function setMaxItemsForSale(uint maxItemsForSale) public onlyOwner {
    _maxItemsForSale = maxItemsForSale;
  }

  // get Rate for specific address
  function getCustomRate(address adr) public view onlyOwner returns (MarketRate memory){
    return _getCustomRate(adr);
  }

  // set market-rate for specific address
  function setCustomRate(address adr, uint256 newListingPrice, uint256 newCancelPrice, uint newFeePercent) public onlyOwner {
    _rates[adr] = MarketRate(true, newListingPrice, newCancelPrice, newFeePercent);
  }

  // remove market-rate for specific address
  function removeCustomRate(address adr) public onlyOwner {
    if (adr == address(0))
      return;

    delete _rates[adr];
  }

  // remove market-item placement on Scotch Marketplace
  function deleteMarketItem(uint256 marketItemId) public onlyOwner idExists(marketItemId) isActive(marketItemId) nonReentrant {
    // remove market-item with Deleted status
    _removeMarketItem(marketItemId, MarketItemStatus.Deleted);
  }


  // ===========================================
  // ======= Internal helper functions =========
  // ===========================================
  // get Rate for specific address
  function _getCustomRate(address adr) private view returns (MarketRate memory) {
    return _rates[adr];
  }

  // get Rate for specific address
  function _getValidRate(address adr) private view returns (MarketRate memory) {
    // get active market-rate for specific address
    if (_rates[adr].isActive)
      return _rates[adr];

    // return default market-rate
    return _rates[address(0)];
  }

  // check if original NFT is valid to be placed on Marketplace
  function _checkTokenValidity(address seller, address tokenContract, uint256 tokenId) private view returns (int) {
    IERC721 hostTokenContract = IERC721(tokenContract);

    // get owner of the NFT (seller should be the owner of the NFT)
    address tokenOwner = hostTokenContract.ownerOf(tokenId);
    if (tokenOwner != seller)
      return - 1;

    // check approval for all
    bool allApproved = hostTokenContract.isApprovedForAll(seller, address(this));
    if (!allApproved)
    {
      // get approved address of the NFT (NFT should be approved to Marketplace)
      address tokenApproved = hostTokenContract.getApproved(tokenId);
      if (tokenApproved != address(this))
        return - 2;
    }

    return 0;
  }

  // add new MaketItem to Marketplace
  function _createMarketItem(address seller, MarketItemInput memory input) private {
    // new market-item ID
    _itemIds.increment();
    uint256 marketItemId = _itemIds.current();

    // push active market-item in array
    _activeItems.push(marketItemId);
    // position in active market-item array
    uint256 position = _activeItems.length;

    // create new market-item
    _items[marketItemId] = MarketItem(
      marketItemId, // ID of the market item
      input.tokenContract, // token Contract
      input.tokenId, // token ID
      payable(seller), // seller
      payable(address(0)), // buyer
      input.priceContract, // price Contract
      input.priceAmount, // price value
      MarketItemStatus.Active, // status
      0, // fee value
      position, // position
      0, // partnerId
      input.whiteList           // white list
    );

    // update token position to active market-item position
    _activeTokens[input.tokenContract][input.tokenId] = position;

    // setup white list for market item
    if (input.whiteList.length > 0)
    {
      for (uint i; i < input.whiteList.length; i++)
        _allowedToBuy[marketItemId][input.whiteList[i]] = true;
    }

    emit MarketItemPlaced(marketItemId, input.tokenContract, input.tokenId, seller, input.priceContract, input.priceAmount);
  }

  // remove market-item from marketplace
  function _removeMarketItem(uint256 marketItemId, MarketItemStatus status) private idExists(marketItemId) isActive(marketItemId) {
    // define index of market-item in active array
    uint index = _items[marketItemId].position - 1;
    // check market-item has position in active-market-item array
    require(index >= 0 && index < _activeItems.length, "Market Item has no position in Active Items array");
    // check market-item position in active-market-items array
    require(_activeItems[index] == marketItemId, "Market Item is not on the position in Active Items array!");
    // check that new status should NOT be Active
    require(status != MarketItemStatus.Active, "Specify correct status to remove Market Item!");

    // update market-item status & position
    _items[marketItemId].status = status;
    _items[marketItemId].position = 0;

    // replacing current active-market-item with last element
    if (index < _activeItems.length - 1) {
      // define last active-market-item ID
      uint256 lastItemId = _activeItems[_activeItems.length - 1];
      // replacing with last element
      _activeItems[index] = lastItemId;
      // update last active-market-item position
      _items[lastItemId].position = index + 1;
      _activeTokens[_items[lastItemId].tokenContract][_items[lastItemId].tokenId] = index + 1;
    }

    // remove last element from array = deleting item in array
    _activeItems.pop();

    // remove token position for current market-item
    delete _activeTokens[_items[marketItemId].tokenContract][_items[marketItemId].tokenId];

    emit MarketItemRemoved(marketItemId, status);
  }


  // charge price and fees during the deal
  function _chargePrice(
    uint256 marketItemId,
    address buyer)
  private returns (uint256) {
    // address of the market-item seller
    address payable seller = _items[marketItemId].seller;
    // price amount
    uint256 priceAmount = _items[marketItemId].price;
    // price contract
    address priceContract = _items[marketItemId].priceContract;


    // market-rate for seller
    uint feePercent = _getValidRate(seller).feePercent;
    // commission fee amount
    uint256 feeAmount = feePercent * priceAmount / 100;

    // amount that should be send to Seller
    uint256 sellerAmount = priceAmount - feeAmount;
    require(sellerAmount > 0, "Invalid Seller Amount calculated!");


    // charge price and fees in Native Token
    if (priceContract == address(0))
    {
      require(msg.value >= priceAmount, "Please submit the Price amount in order to complete the purchase");

      // transfer seller-amount to seller
      seller.transfer(sellerAmount);

      // send fee funds to _beneficiary
      if (_isBeneficiaryExists() && feeAmount > 0)
        _beneficiary.recipient.transfer(feeAmount);
    }
    // charge price and fees in ERC20 Token
    else
    {
      // address of the Scotch Marketplace
      address marketplace = address(this);

      // check price amount allowance to marketplace
      IERC20 hostPriceContract = IERC20(priceContract);
      uint256 priceAllowance = hostPriceContract.allowance(buyer, marketplace);
      require(priceAllowance >= priceAmount, "Please allow Price amount of ERC-20 Token in order to complete purchase");

      // transfer price amount to marketplace
      hostPriceContract.safeTransferFrom(buyer, marketplace, priceAmount);

      // transfer seller-amount to seller
      hostPriceContract.transfer(seller, sellerAmount);

      // send fee funds to _beneficiary
      if (_isBeneficiaryExists() && feeAmount > 0)
        hostPriceContract.transfer(_beneficiary.recipient, feeAmount);
    }

    return feeAmount;
  }
}
        

Compiler Settings

{"remappings":[],"optimizer":{"runs":200,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"london","compilationTarget":{"ScotchMarketplace.sol":"ScotchMarketplace"}}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"MarketItemPlaced","inputs":[{"type":"uint256","name":"marketItemId","internalType":"uint256","indexed":true},{"type":"address","name":"tokenContract","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false},{"type":"address","name":"seller","internalType":"address","indexed":true},{"type":"address","name":"priceContract","internalType":"address","indexed":false},{"type":"uint256","name":"price","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MarketItemRemoved","inputs":[{"type":"uint256","name":"marketItemId","internalType":"uint256","indexed":true},{"type":"uint8","name":"status","internalType":"enum ScotchMarketplace.MarketItemStatus","indexed":false}],"anonymous":false},{"type":"event","name":"MarketItemSold","inputs":[{"type":"uint256","name":"marketItemId","internalType":"uint256","indexed":true},{"type":"address","name":"buyer","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"_maxItemsForSale","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"cancelMarketItem","inputs":[{"type":"uint256","name":"marketItemId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeBeneficiary","inputs":[{"type":"uint8","name":"mode","internalType":"enum ScotchBeneficiary.BeneficiaryMode"},{"type":"address","name":"recipient","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteMarketItem","inputs":[{"type":"uint256","name":"marketItemId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"findActiveMarketItem","inputs":[{"type":"address","name":"tokenContract","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct ScotchMarketplace.MarketItem","components":[{"type":"uint256","name":"itemId","internalType":"uint256"},{"type":"address","name":"tokenContract","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"seller","internalType":"address payable"},{"type":"address","name":"buyer","internalType":"address payable"},{"type":"address","name":"priceContract","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint8","name":"status","internalType":"enum ScotchMarketplace.MarketItemStatus"},{"type":"uint256","name":"fee","internalType":"uint256"},{"type":"uint256","name":"position","internalType":"uint256"},{"type":"uint256","name":"partnerId","internalType":"uint256"},{"type":"address[]","name":"whiteList","internalType":"address[]"}]}],"name":"getActiveMarketItem","inputs":[{"type":"uint256","name":"position","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getActiveMarketItemsCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getAllMarketItemsCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct ScotchBeneficiary.Beneficiary","components":[{"type":"uint8","name":"mode","internalType":"enum ScotchBeneficiary.BeneficiaryMode"},{"type":"address","name":"recipient","internalType":"address payable"}]}],"name":"getBeneficiary","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct ScotchMarketplace.MarketRate","components":[{"type":"bool","name":"isActive","internalType":"bool"},{"type":"uint256","name":"listingPrice","internalType":"uint256"},{"type":"uint256","name":"cancelPrice","internalType":"uint256"},{"type":"uint256","name":"feePercent","internalType":"uint256"}]}],"name":"getCustomRate","inputs":[{"type":"address","name":"adr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct ScotchMarketplace.MarketItem","components":[{"type":"uint256","name":"itemId","internalType":"uint256"},{"type":"address","name":"tokenContract","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"seller","internalType":"address payable"},{"type":"address","name":"buyer","internalType":"address payable"},{"type":"address","name":"priceContract","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint8","name":"status","internalType":"enum ScotchMarketplace.MarketItemStatus"},{"type":"uint256","name":"fee","internalType":"uint256"},{"type":"uint256","name":"position","internalType":"uint256"},{"type":"uint256","name":"partnerId","internalType":"uint256"},{"type":"address[]","name":"whiteList","internalType":"address[]"}]}],"name":"getMarketItem","inputs":[{"type":"uint256","name":"marketItemId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct ScotchMarketplace.MarketRate","components":[{"type":"bool","name":"isActive","internalType":"bool"},{"type":"uint256","name":"listingPrice","internalType":"uint256"},{"type":"uint256","name":"cancelPrice","internalType":"uint256"},{"type":"uint256","name":"feePercent","internalType":"uint256"}]}],"name":"getRate","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"makeMarketSale","inputs":[{"type":"uint256","name":"marketItemId","internalType":"uint256"},{"type":"uint256","name":"partnerId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"placeMarketItem","inputs":[{"type":"address","name":"tokenContract","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"priceContract","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"address[]","name":"whiteList","internalType":"address[]"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"placeMarketItems","inputs":[{"type":"tuple[]","name":"input","internalType":"struct ScotchMarketplace.MarketItemInput[]","components":[{"type":"address","name":"tokenContract","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"priceContract","internalType":"address"},{"type":"uint256","name":"priceAmount","internalType":"uint256"},{"type":"address[]","name":"whiteList","internalType":"address[]"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeCustomRate","inputs":[{"type":"address","name":"adr","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"sendFunds","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"tokenContract","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setCustomRate","inputs":[{"type":"address","name":"adr","internalType":"address"},{"type":"uint256","name":"newListingPrice","internalType":"uint256"},{"type":"uint256","name":"newCancelPrice","internalType":"uint256"},{"type":"uint256","name":"newFeePercent","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxItemsForSale","inputs":[{"type":"uint256","name":"maxItemsForSale","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
              

Contract Creation Code

Verify & Publish
0x60806040523480156200001157600080fd5b506200001d336200013b565b600160028190556040805180820182526000808252602091820181905283546001600160a81b0319169093558151928352820190819052905162000064916005916200018b565b50604080516080810182526001815260006020808301828152938301828152600360608501908152928052600790915291517f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6df805460ff191691151591909117905591517f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e055517f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e155517f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e2556064600955620001f2565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b828054828255906000526020600020908101928215620001c9579160200282015b82811115620001c9578251825591602001919060010190620001ac565b50620001d7929150620001db565b5090565b5b80821115620001d75760008155600101620001dc565b6135ee80620002026000396000f3fe6080604052600436106101355760003560e01c80636e2d5a13116100ab578063abb8334b1161006f578063abb8334b14610348578063b26867741461035e578063b2dcecbe1461037e578063c7be7a491461039e578063f2fde38b146103be578063f33c80ee146103de57600080fd5b80636e2d5a13146102b8578063715018a6146102d85780638da5cb5b146102ed578063a6e22b0214610315578063a9c071451461032857600080fd5b80634229eef2116100fd5780634229eef2146101d557806343c06213146101ea578063565a2e2c1461020a5780635d3e8b081461022c578063679aefce1461025957806368220e87146102a357600080fd5b806317de01351461013a57806318d3a1be1461014f57806318eb81ed1461016257806327cdb4b314610182578063347149fc146101a2575b600080fd5b61014d610148366004612d35565b6103f1565b005b61014d61015d366004612dab565b610539565b34801561016e57600080fd5b5061014d61017d366004612ed0565b6107ea565b34801561018e57600080fd5b5061014d61019d366004612f0b565b610856565b3480156101ae57600080fd5b506101c26101bd366004612f28565b6108a3565b6040519081526020015b60405180910390f35b3480156101e157600080fd5b506101c26108ce565b3480156101f657600080fd5b5061014d610205366004612f54565b6108de565b34801561021657600080fd5b5061021f610a3e565b6040516101cc9190612fa7565b34801561023857600080fd5b5061024c610247366004612fda565b610aa4565b6040516101cc919061304b565b34801561026557600080fd5b5061026e610d05565b6040516101cc919081511515815260208083015190820152604080830151908201526060918201519181019190915260800190565b3480156102af57600080fd5b506005546101c2565b3480156102c457600080fd5b5061014d6102d3366004612fda565b610d3b565b3480156102e457600080fd5b5061014d610d48565b3480156102f957600080fd5b506000546040516001600160a01b0390911681526020016101cc565b61014d610323366004612fda565b610d5c565b34801561033457600080fd5b5061014d610343366004612fda565b610eb4565b34801561035457600080fd5b506101c260095481565b34801561036a57600080fd5b5061014d610379366004613121565b610f6a565b34801561038a57600080fd5b5061026e610399366004612f0b565b611257565b3480156103aa57600080fd5b5061024c6103b9366004612fda565b611295565b3480156103ca57600080fd5b5061014d6103d9366004612f0b565b6113f9565b61014d6103ec366004613146565b61146f565b6000821161041a5760405162461bcd60e51b815260040161041190613168565b60405180910390fd5b600061042686866108a3565b905080156104465760405162461bcd60e51b8152600401610411906131af565b3360006104548289896118ff565b905080196104745760405162461bcd60e51b8152600401610411906131f9565b80600119036104955760405162461bcd60e51b81526004016104119061324e565b80156104b35760405162461bcd60e51b815260040161041190613297565b60006104be83611aae565b6020015190506104e6816040518060600160405280603c8152602001613537603c9139611c08565b60006040518060a001604052808b6001600160a01b031681526020018a8152602001896001600160a01b0316815260200188815260200187815250905061052d8482611c83565b50505050505050505050565b600081511161059e5760405162461bcd60e51b815260206004820152602b60248201527f4174206c65617374206f6e65206974656d20696e7075742073686f756c64206260448201526a19481cdc1958da599a595960aa1b6064820152608401610411565b600954815111156106175760405162461bcd60e51b815260206004820152603860248201527f416d6f756e74206f6620737065636966696564206974656d732065786365656460448201527f73204d6178696d756d20416c6c6f77656420416d6f756e7400000000000000006064820152608401610411565b33600061062382611aae565b60200151905061065783518261063991906132fb565b6040518060600160405280603c8152602001613537603c9139611c08565b60005b83518110156107e45760008482815181106106775761067761331a565b602002602001015160600151116106a05760405162461bcd60e51b815260040161041190613168565b60006106e68583815181106106b7576106b761331a565b6020026020010151600001518684815181106106d5576106d561331a565b6020026020010151602001516108a3565b905080156107065760405162461bcd60e51b8152600401610411906131af565b600061074d8587858151811061071e5761071e61331a565b60200260200101516000015188868151811061073c5761073c61331a565b6020026020010151602001516118ff565b9050801961076d5760405162461bcd60e51b8152600401610411906131f9565b806001190361078e5760405162461bcd60e51b81526004016104119061324e565b80156107ac5760405162461bcd60e51b815260040161041190613297565b6107cf858785815181106107c2576107c261331a565b6020026020010151611c83565b505080806107dc90613330565b91505061065a565b50505050565b6107f2611f84565b6040805160808101825260018082526020808301968752828401958652606083019485526001600160a01b039790971660009081526007909752919095209451855460ff191690151517855592519284019290925551600283015551600390910155565b61085e611f84565b6001600160a01b038116156108a0576001600160a01b0381166000908152600760205260408120805460ff191681556001810182905560028101829055600301555b50565b6001600160a01b03821660009081526006602090815260408083208484529091529020545b92915050565b60006108d960035490565b905090565b6108e6611f84565b60008260028111156108fa576108fa612f91565b03610981576001600160a01b0381161561097c5760405162461bcd60e51b815260206004820152603960248201527f42656e65666963696172206d6f6465204e6f6e65207265717569726573207a6560448201527f726f206164647265737320666f7220726563697069656e7421000000000000006064820152608401610411565b6109f2565b6001600160a01b0381166109f25760405162461bcd60e51b815260206004820152603260248201527f42656e656669636961727920726563697069656e7420616464726573732073686044820152716f756c64206265207370656369666965642160701b6064820152608401610411565b6001805483919060ff191681836002811115610a1057610a10612f91565b0217905550600180546001600160a01b0390921661010002610100600160a81b031990921691909117905550565b60408051808201909152600080825260208201526040805180820190915260018054829060ff166002811115610a7657610a76612f91565b6002811115610a8757610a87612f91565b8152905461010090046001600160a01b0316602090910152919050565b610aac612b3d565b600554610b0d5760405162461bcd60e51b815260206004820152602960248201527f546865726520617265206e6f20616e7920416374697665204d61726b6574204960448201526874656d73207965742160b81b6064820152608401610411565b60018210158015610b2057506005548211155b610ba75760405162461bcd60e51b815260206004820152604c60248201527f506f736974696f6e2073686f756c6420626520706f736974697665206e756d6260448201527f657220696e20416374697665204d61726b6574204974656d7320436f756e742060648201526b72616e67652028312e2e4e2960a01b608482015260a401610411565b600460006005610bb8600186613349565b81548110610bc857610bc861331a565b6000918252602080832090910154835282810193909352604091820190208151610180810183528154815260018201546001600160a01b039081169482019490945260028201549281019290925260038082015484166060840152600482015484166080840152600582015490931660a0830152600681015460c083015260078101549192909160e084019160ff90911690811115610c6957610c69612f91565b6003811115610c7a57610c7a612f91565b81526020016008820154815260200160098201548152602001600a8201548152602001600b8201805480602002602001604051908101604052809291908181526020018280548015610cf557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cd7575b5050505050815250509050919050565b610d3260405180608001604052806000151581526020016000815260200160008152602001600081525090565b6108d933611aae565b610d43611f84565b600955565b610d50611f84565b610d5a6000611fde565b565b80600081118015610d6f57506003548111155b610d8b5760405162461bcd60e51b815260040161041190613360565b816000808281526004602052604090206007015460ff166003811115610db357610db3612f91565b14610dd05760405162461bcd60e51b815260040161041190613397565b6002805403610df15760405162461bcd60e51b8152600401610411906133ce565b600280556000838152600460205260409020600301546001600160a01b0316338114610e6a5760405162461bcd60e51b815260206004820152602260248201527f4f6e6c792053656c6c65722063616e2063616e63656c204d61726b6574204974604482015261656d60f01b6064820152608401610411565b6000610e7582611aae565b604001519050610e9d8160405180608001604052806046815260200161357360469139611c08565b610ea885600261202e565b50506001600255505050565b610ebc611f84565b80600081118015610ecf57506003548111155b610eeb5760405162461bcd60e51b815260040161041190613360565b816000808281526004602052604090206007015460ff166003811115610f1357610f13612f91565b14610f305760405162461bcd60e51b815260040161041190613397565b6002805403610f515760405162461bcd60e51b8152600401610411906133ce565b60028055610f6083600361202e565b5050600160025550565b610f72611f84565b610f7a6123e2565b610fc65760405162461bcd60e51b815260206004820181905260248201527f42656e65666963696172792073686f756c6420626520737065636966696564216044820152606401610411565b600082116110165760405162461bcd60e51b815260206004820152601f60248201527f53656e6420416d6f756e742073686f756c6420626520706f73697469766521006044820152606401610411565b306001600160a01b0382166110eb576001600160a01b03811631838110156110a65760405162461bcd60e51b815260206004820152603a60248201527f53656e6420416d6f756e74206578636565647320536d61727420436f6e74726160448201527f63742773206e617469766520746f6b656e2062616c616e6365210000000000006064820152608401610411565b6001546040516101009091046001600160a01b0316906108fc8615029086906000818181858888f193505050501580156110e4573d6000803e3d6000fd5b5050505050565b6040516370a0823160e01b81526001600160a01b03828116600483015283916000918316906370a0823190602401602060405180830381865afa158015611136573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115a9190613405565b9050848110156111d25760405162461bcd60e51b815260206004820152603a60248201527f53656e6420416d6f756e74206578636565647320536d61727420436f6e74726160448201527f63742773204552432d323020746f6b656e2062616c616e6365210000000000006064820152608401610411565b60015460405163a9059cbb60e01b81526101009091046001600160a01b0390811660048301526024820187905283169063a9059cbb906044016020604051808303816000875af115801561122a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124e919061341e565b5050505b505050565b61128460405180608001604052806000151581526020016000815260200160008152602001600081525090565b61128c611f84565b6108c88261241d565b61129d612b3d565b816000811180156112b057506003548111155b6112cc5760405162461bcd60e51b815260040161041190613360565b6000838152600460208181526040928390208351610180810185528154815260018201546001600160a01b0390811693820193909352600282015494810194909452600380820154831660608601529281015482166080850152600581015490911660a0840152600681015460c08401526007810154909160e084019160ff169081111561135c5761135c612f91565b600381111561136d5761136d612f91565b81526020016008820154815260200160098201548152602001600a8201548152602001600b82018054806020026020016040519081016040528092919081815260200182805480156113e857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116113ca575b505050505081525050915050919050565b611401611f84565b6001600160a01b0381166114665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610411565b6108a081611fde565b8160008111801561148257506003548111155b61149e5760405162461bcd60e51b815260040161041190613360565b826000808281526004602052604090206007015460ff1660038111156114c6576114c6612f91565b146114e35760405162461bcd60e51b815260040161041190613397565b60028054036115045760405162461bcd60e51b8152600401610411906133ce565b60028055600033600086815260046020819052604080832060038101546002820154600190920154925163e985e9c560e01b81526001600160a01b0391821694810185905230602482015295965092949093929091169190829063e985e9c590604401602060405180830381865afa158015611584573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a8919061341e565b90508061169d5760405163020604bf60e21b8152600481018490526000906001600160a01b0384169063081812fc90602401602060405180830381865afa1580156115f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161b9190613440565b90506001600160a01b038116301461169b5760405162461bcd60e51b815260206004820152603760248201527f4d61726b6574204974656d20284e4654292073686f756c64206265206170707260448201527f6f76656420746f20746865204d61726b6574706c6163650000000000000000006064820152608401610411565b505b6000898152600460205260409020600b01541561175d5760008981526008602090815260408083206001600160a01b038916845290915290205460ff16151560011461175d5760405162461bcd60e51b815260206004820152604360248201527f596f75722061646472657373206973206e6f742073706563696669656420696e60448201527f2057686974652d4c69737420666f722063757272656e74204d61726b6574204960648201526274656d60e81b608482015260a401610411565b60006117698a8761249d565b60008b81526004602081905260409182902080820180546001600160a01b0319166001600160a01b038c811691821790925560088301869055600a9092018e90559251632142170760e11b8152898416928101929092526024820152604481018790529192508416906342842e0e90606401600060405180830381600087803b1580156117f557600080fd5b505af1158015611809573d6000803e3d6000fd5b505050506118188a600161202e565b600260015460ff16600281111561183157611831612f91565b14801561184d575060015461010090046001600160a01b031615155b156118b8576001546040516391c05b0b60e01b8152600481018c90526101009091046001600160a01b03169081906391c05b0b90602401600060405180830381600087803b15801561189e57600080fd5b505af11580156118b2573d6000803e3d6000fd5b50505050505b6040516001600160a01b038716908b907f2073b2706c235effb1e3840575370a51749afd8181b4018f93bff955d50792cb90600090a3505060016002555050505050505050565b6040516331a9108f60e11b815260048101829052600090839082906001600160a01b03831690636352211e90602401602060405180830381865afa15801561194b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196f9190613440565b9050856001600160a01b0316816001600160a01b0316146119965760001992505050611aa7565b60405163e985e9c560e01b81526001600160a01b0387811660048301523060248301526000919084169063e985e9c590604401602060405180830381865afa1580156119e6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0a919061341e565b905080611a9f5760405163020604bf60e21b8152600481018690526000906001600160a01b0385169063081812fc90602401602060405180830381865afa158015611a59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7d9190613440565b90506001600160a01b0381163014611a9d57600119945050505050611aa7565b505b600093505050505b9392505050565b611adb60405180608001604052806000151581526020016000815260200160008152602001600081525090565b6001600160a01b03821660009081526007602052604090205460ff1615611b4f57506001600160a01b03166000908152600760209081526040918290208251608081018452815460ff1615158152600182015492810192909252600281015492820192909252600390910154606082015290565b50506000805260076020908152604080516080810182527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6df5460ff16151581527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e054928101929092527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e154908201527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e254606082015290565b8115611c7f57813410158190611c315760405162461bcd60e51b81526004016104119190613489565b50611c3a6123e2565b15611c7f576001546040516001600160a01b0361010090920491909116903480156108fc02916000818181858888f19350505050158015611252573d6000803e3d6000fd5b5050565b611c91600380546001019055565b6000611c9c60035490565b6005805460018101825560008281527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db09091018390559054604080516101808101825284815286516001600160a01b039081166020838101919091528801518284015288811660608084019190915260808301869052928801511660a08201529086015160c0820152929350919060e082019081526000602080830182905260408084018690526060808501849052608089810151958101959095528784526004808452938290208651815592860151600180850180546001600160a01b03199081166001600160a01b0394851617909155938801516002860155918701516003808601805486169284169290921790915595870151948401805484169582169590951790945560a0860151600584018054909316941693909317905560c0840151600682015560e084015160078201805492949193909260ff1916918490811115611e0a57611e0a612f91565b021790555061010082015160088201556101208201516009820155610140820151600a8201556101608201518051611e4c91600b840191602090910190612b9e565b505083516001600160a01b0316600090815260066020908152604080832082880151845290915290208290555060808301515115611f045760005b836080015151811015611f0257600083815260086020526040812060808601518051600193919085908110611ebe57611ebe61331a565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580611efa81613330565b915050611e87565b505b836001600160a01b031683600001516001600160a01b0316837fc48e6ef63d8ee5c32e1a12522041571cc6929dbabed66a5eba6b0e9c65ca8471866020015187604001518860600151604051611f76939291909283526001600160a01b03919091166020830152604082015260600190565b60405180910390a450505050565b6000546001600160a01b03163314610d5a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610411565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8160008111801561204157506003548111155b61205d5760405162461bcd60e51b815260040161041190613360565b826000808281526004602052604090206007015460ff16600381111561208557612085612f91565b146120a25760405162461bcd60e51b815260040161041190613397565b6000848152600460205260408120600901546120c090600190613349565b9050600554811061212d5760405162461bcd60e51b815260206004820152603160248201527f4d61726b6574204974656d20686173206e6f20706f736974696f6e20696e20416044820152706374697665204974656d7320617272617960781b6064820152608401610411565b84600582815481106121415761214161331a565b9060005260206000200154146121bf5760405162461bcd60e51b815260206004820152603960248201527f4d61726b6574204974656d206973206e6f74206f6e2074686520706f7369746960448201527f6f6e20696e20416374697665204974656d7320617272617921000000000000006064820152608401610411565b60008460038111156121d3576121d3612f91565b036122365760405162461bcd60e51b815260206004820152602d60248201527f5370656369667920636f72726563742073746174757320746f2072656d6f766560448201526c204d61726b6574204974656d2160981b6064820152608401610411565b6000858152600460205260409020600701805485919060ff1916600183600381111561226457612264612f91565b021790555060008581526004602052604081206009015560055461228a90600190613349565b8110156123425760058054600091906122a590600190613349565b815481106122b5576122b561331a565b9060005260206000200154905080600583815481106122d6576122d661331a565b6000918252602090912001556122ed8260016134bc565b60008281526004602052604090206009015561230a8260016134bc565b600091825260046020908152604080842060018101546001600160a01b03168552600683528185206002909101548552909152909120555b6005805480612353576123536134d4565b60008281526020808220830160001990810183905590920190925586825260048152604080832060018101546001600160a01b03168452600683528184206002909101548452909152808220919091555185907f471936d15caaa62c7c9222e363a0323e64ed408a1c87a4ef46c7596655eb1b3d906123d39087906134ea565b60405180910390a25050505050565b60008060015460ff1660028111156123fc576123fc612f91565b141580156108d9575060015461010090046001600160a01b03161515905090565b61244a60405180608001604052806000151581526020016000815260200160008152602001600081525090565b506001600160a01b03166000908152600760209081526040918290208251608081018452815460ff1615158152600182015492810192909252600281015492820192909252600390910154606082015290565b6000828152600460205260408120600381015460068201546005909201546001600160a01b03918216929116836124d384611aae565b606001519050600060646124e785846132fb565b6124f191906134f8565b905060006124ff8286613349565b90506000811161255b5760405162461bcd60e51b815260206004820152602160248201527f496e76616c69642053656c6c657220416d6f756e742063616c63756c617465646044820152602160f81b6064820152608401610411565b6001600160a01b03841661267657843410156125e1576040805162461bcd60e51b81526020600482015260248101919091527f506c65617365207375626d69742074686520507269636520616d6f756e74206960448201527f6e206f7264657220746f20636f6d706c657465207468652070757263686173656064820152608401610411565b6040516001600160a01b0387169082156108fc029083906000818181858888f19350505050158015612617573d6000803e3d6000fd5b506126206123e2565b801561262c5750600082115b15612671576001546040516101009091046001600160a01b0316906108fc8415029084906000818181858888f1935050505015801561266f573d6000803e3d6000fd5b505b61289b565b604051636eb1769f60e11b81526001600160a01b03898116600483015230602483018190529186916000919083169063dd62ed3e90604401602060405180830381865afa1580156126cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ef9190613405565b9050878110156127775760405162461bcd60e51b815260206004820152604760248201527f506c6561736520616c6c6f7720507269636520616d6f756e74206f662045524360448201527f2d323020546f6b656e20696e206f7264657220746f20636f6d706c65746520706064820152667572636861736560c81b608482015260a401610411565b61278c6001600160a01b0383168c858b6128a7565b60405163a9059cbb60e01b81526001600160a01b038a811660048301526024820186905283169063a9059cbb906044016020604051808303816000875af11580156127db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ff919061341e565b506128086123e2565b80156128145750600085115b156128975760015460405163a9059cbb60e01b81526101009091046001600160a01b0390811660048301526024820187905283169063a9059cbb906044016020604051808303816000875af1158015612871573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612895919061341e565b505b5050505b50979650505050505050565b604080516001600160a01b038581166024830152848116604483015260648083018590528351808403909101815260849092018352602080830180516001600160e01b03166323b872dd60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908401526107e49287929160009161293f9185169084906129bc565b805190915015611252578080602001905181019061295d919061341e565b6112525760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610411565b60606129cb84846000856129d3565b949350505050565b606082471015612a345760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610411565b6001600160a01b0385163b612a8b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610411565b600080866001600160a01b03168587604051612aa7919061351a565b60006040518083038185875af1925050503d8060008114612ae4576040519150601f19603f3d011682016040523d82523d6000602084013e612ae9565b606091505b5091509150612af9828286612b04565b979650505050505050565b60608315612b13575081611aa7565b825115612b235782518084602001fd5b8160405162461bcd60e51b81526004016104119190613489565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529060e08201908152602001600081526020016000815260200160008152602001606081525090565b828054828255906000526020600020908101928215612bf3579160200282015b82811115612bf357825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612bbe565b50612bff929150612c03565b5090565b5b80821115612bff5760008155600101612c04565b6001600160a01b03811681146108a057600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612c6657612c66612c2d565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612c9557612c95612c2d565b604052919050565b600067ffffffffffffffff821115612cb757612cb7612c2d565b5060051b60200190565b600082601f830112612cd257600080fd5b81356020612ce7612ce283612c9d565b612c6c565b82815260059290921b84018101918181019086841115612d0657600080fd5b8286015b84811015612d2a578035612d1d81612c18565b8352918301918301612d0a565b509695505050505050565b600080600080600060a08688031215612d4d57600080fd5b8535612d5881612c18565b9450602086013593506040860135612d6f81612c18565b925060608601359150608086013567ffffffffffffffff811115612d9257600080fd5b612d9e88828901612cc1565b9150509295509295909350565b60006020808385031215612dbe57600080fd5b823567ffffffffffffffff80821115612dd657600080fd5b818501915085601f830112612dea57600080fd5b8135612df8612ce282612c9d565b81815260059190911b83018401908481019088831115612e1757600080fd5b8585015b83811015612ec357803585811115612e335760008081fd5b860160a0818c03601f1901811315612e4b5760008081fd5b612e53612c43565b89830135612e6081612c18565b81526040838101358b830152606080850135612e7b81612c18565b8083850152506080915081850135818401525082840135925088831115612ea25760008081fd5b612eb08e8c85870101612cc1565b9082015285525050918601918601612e1b565b5098975050505050505050565b60008060008060808587031215612ee657600080fd5b8435612ef181612c18565b966020860135965060408601359560600135945092505050565b600060208284031215612f1d57600080fd5b8135611aa781612c18565b60008060408385031215612f3b57600080fd5b8235612f4681612c18565b946020939093013593505050565b60008060408385031215612f6757600080fd5b823560038110612f7657600080fd5b91506020830135612f8681612c18565b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b8151604082019060038110612fbe57612fbe612f91565b82526020928301516001600160a01b0316929091019190915290565b600060208284031215612fec57600080fd5b5035919050565b6004811061300357613003612f91565b9052565b600081518084526020808501945080840160005b838110156130405781516001600160a01b03168752958201959082019060010161301b565b509495945050505050565b60208152815160208201526000602083015161307260408401826001600160a01b03169052565b5060408301516060830152606083015161309760808401826001600160a01b03169052565b5060808301516001600160a01b03811660a08401525060a08301516001600160a01b03811660c08401525060c083015160e083015260e08301516101006130e081850183612ff3565b8401516101208481019190915284015161014080850191909152840151610160808501919091528401516101808085015290506129cb6101a0840182613007565b6000806040838503121561313457600080fd5b823591506020830135612f8681612c18565b6000806040838503121561315957600080fd5b50508035926020909101359150565b60208082526027908201527f5072696365206d75737420626520706f73697469766520286174206c656173746040820152662031207765692960c81b606082015260800190565b6020808252602a908201527f5468617420746f6b656e20697320616c726561647920706c61636564206f6e206040820152691d1a19481b585c9ad95d60b21b606082015260800190565b60208082526035908201527f4f6e6c79206f776e6572206f6620746865204e46542063616e20706c61636520604082015274697420746f20746865204d61726b6574706c61636560581b606082015260800190565b60208082526029908201527f4e46542073686f756c6420626520617070726f76656420746f20746865204d61604082015268726b6574706c61636560b81b606082015260800190565b6020808252602e908201527f4e4654206973206e6f742076616c696420746f20626520736f6c64206f6e207460408201526d6865204d61726b6574706c61636560901b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615613315576133156132e5565b500290565b634e487b7160e01b600052603260045260246000fd5b600060018201613342576133426132e5565b5060010190565b60008282101561335b5761335b6132e5565b500390565b60208082526017908201527f496e76616c6964204d61726b6574204974656d20494421000000000000000000604082015260600190565b60208082526019908201527f4d61726b6574204974656d206973206e6f742041637469766500000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60006020828403121561341757600080fd5b5051919050565b60006020828403121561343057600080fd5b81518015158114611aa757600080fd5b60006020828403121561345257600080fd5b8151611aa781612c18565b60005b83811015613478578181015183820152602001613460565b838111156107e45750506000910152565b60208152600082518060208401526134a881604085016020870161345d565b601f01601f19169190910160400192915050565b600082198211156134cf576134cf6132e5565b500190565b634e487b7160e01b600052603160045260246000fd5b602081016108c88284612ff3565b60008261351557634e487b7160e01b600052601260045260246000fd5b500490565b6000825161352c81846020870161345d565b919091019291505056fe4c697374696e672050726963652073686f756c642062652073656e7420746f20706c616365204e4654206f6e20746865204d61726b6574706c61636543616e63656c2050726963652073686f756c642062652073656e7420746f2063616e63656c204e465420706c6163656d656e74206f6e20746865204d61726b6574706c616365a2646970667358221220139357d19635522a0cf149b44ac663c7327db6cea258dca874a00b4dcc80b84d64736f6c634300080f0033

Deployed ByteCode

0x6080604052600436106101355760003560e01c80636e2d5a13116100ab578063abb8334b1161006f578063abb8334b14610348578063b26867741461035e578063b2dcecbe1461037e578063c7be7a491461039e578063f2fde38b146103be578063f33c80ee146103de57600080fd5b80636e2d5a13146102b8578063715018a6146102d85780638da5cb5b146102ed578063a6e22b0214610315578063a9c071451461032857600080fd5b80634229eef2116100fd5780634229eef2146101d557806343c06213146101ea578063565a2e2c1461020a5780635d3e8b081461022c578063679aefce1461025957806368220e87146102a357600080fd5b806317de01351461013a57806318d3a1be1461014f57806318eb81ed1461016257806327cdb4b314610182578063347149fc146101a2575b600080fd5b61014d610148366004612d35565b6103f1565b005b61014d61015d366004612dab565b610539565b34801561016e57600080fd5b5061014d61017d366004612ed0565b6107ea565b34801561018e57600080fd5b5061014d61019d366004612f0b565b610856565b3480156101ae57600080fd5b506101c26101bd366004612f28565b6108a3565b6040519081526020015b60405180910390f35b3480156101e157600080fd5b506101c26108ce565b3480156101f657600080fd5b5061014d610205366004612f54565b6108de565b34801561021657600080fd5b5061021f610a3e565b6040516101cc9190612fa7565b34801561023857600080fd5b5061024c610247366004612fda565b610aa4565b6040516101cc919061304b565b34801561026557600080fd5b5061026e610d05565b6040516101cc919081511515815260208083015190820152604080830151908201526060918201519181019190915260800190565b3480156102af57600080fd5b506005546101c2565b3480156102c457600080fd5b5061014d6102d3366004612fda565b610d3b565b3480156102e457600080fd5b5061014d610d48565b3480156102f957600080fd5b506000546040516001600160a01b0390911681526020016101cc565b61014d610323366004612fda565b610d5c565b34801561033457600080fd5b5061014d610343366004612fda565b610eb4565b34801561035457600080fd5b506101c260095481565b34801561036a57600080fd5b5061014d610379366004613121565b610f6a565b34801561038a57600080fd5b5061026e610399366004612f0b565b611257565b3480156103aa57600080fd5b5061024c6103b9366004612fda565b611295565b3480156103ca57600080fd5b5061014d6103d9366004612f0b565b6113f9565b61014d6103ec366004613146565b61146f565b6000821161041a5760405162461bcd60e51b815260040161041190613168565b60405180910390fd5b600061042686866108a3565b905080156104465760405162461bcd60e51b8152600401610411906131af565b3360006104548289896118ff565b905080196104745760405162461bcd60e51b8152600401610411906131f9565b80600119036104955760405162461bcd60e51b81526004016104119061324e565b80156104b35760405162461bcd60e51b815260040161041190613297565b60006104be83611aae565b6020015190506104e6816040518060600160405280603c8152602001613537603c9139611c08565b60006040518060a001604052808b6001600160a01b031681526020018a8152602001896001600160a01b0316815260200188815260200187815250905061052d8482611c83565b50505050505050505050565b600081511161059e5760405162461bcd60e51b815260206004820152602b60248201527f4174206c65617374206f6e65206974656d20696e7075742073686f756c64206260448201526a19481cdc1958da599a595960aa1b6064820152608401610411565b600954815111156106175760405162461bcd60e51b815260206004820152603860248201527f416d6f756e74206f6620737065636966696564206974656d732065786365656460448201527f73204d6178696d756d20416c6c6f77656420416d6f756e7400000000000000006064820152608401610411565b33600061062382611aae565b60200151905061065783518261063991906132fb565b6040518060600160405280603c8152602001613537603c9139611c08565b60005b83518110156107e45760008482815181106106775761067761331a565b602002602001015160600151116106a05760405162461bcd60e51b815260040161041190613168565b60006106e68583815181106106b7576106b761331a565b6020026020010151600001518684815181106106d5576106d561331a565b6020026020010151602001516108a3565b905080156107065760405162461bcd60e51b8152600401610411906131af565b600061074d8587858151811061071e5761071e61331a565b60200260200101516000015188868151811061073c5761073c61331a565b6020026020010151602001516118ff565b9050801961076d5760405162461bcd60e51b8152600401610411906131f9565b806001190361078e5760405162461bcd60e51b81526004016104119061324e565b80156107ac5760405162461bcd60e51b815260040161041190613297565b6107cf858785815181106107c2576107c261331a565b6020026020010151611c83565b505080806107dc90613330565b91505061065a565b50505050565b6107f2611f84565b6040805160808101825260018082526020808301968752828401958652606083019485526001600160a01b039790971660009081526007909752919095209451855460ff191690151517855592519284019290925551600283015551600390910155565b61085e611f84565b6001600160a01b038116156108a0576001600160a01b0381166000908152600760205260408120805460ff191681556001810182905560028101829055600301555b50565b6001600160a01b03821660009081526006602090815260408083208484529091529020545b92915050565b60006108d960035490565b905090565b6108e6611f84565b60008260028111156108fa576108fa612f91565b03610981576001600160a01b0381161561097c5760405162461bcd60e51b815260206004820152603960248201527f42656e65666963696172206d6f6465204e6f6e65207265717569726573207a6560448201527f726f206164647265737320666f7220726563697069656e7421000000000000006064820152608401610411565b6109f2565b6001600160a01b0381166109f25760405162461bcd60e51b815260206004820152603260248201527f42656e656669636961727920726563697069656e7420616464726573732073686044820152716f756c64206265207370656369666965642160701b6064820152608401610411565b6001805483919060ff191681836002811115610a1057610a10612f91565b0217905550600180546001600160a01b0390921661010002610100600160a81b031990921691909117905550565b60408051808201909152600080825260208201526040805180820190915260018054829060ff166002811115610a7657610a76612f91565b6002811115610a8757610a87612f91565b8152905461010090046001600160a01b0316602090910152919050565b610aac612b3d565b600554610b0d5760405162461bcd60e51b815260206004820152602960248201527f546865726520617265206e6f20616e7920416374697665204d61726b6574204960448201526874656d73207965742160b81b6064820152608401610411565b60018210158015610b2057506005548211155b610ba75760405162461bcd60e51b815260206004820152604c60248201527f506f736974696f6e2073686f756c6420626520706f736974697665206e756d6260448201527f657220696e20416374697665204d61726b6574204974656d7320436f756e742060648201526b72616e67652028312e2e4e2960a01b608482015260a401610411565b600460006005610bb8600186613349565b81548110610bc857610bc861331a565b6000918252602080832090910154835282810193909352604091820190208151610180810183528154815260018201546001600160a01b039081169482019490945260028201549281019290925260038082015484166060840152600482015484166080840152600582015490931660a0830152600681015460c083015260078101549192909160e084019160ff90911690811115610c6957610c69612f91565b6003811115610c7a57610c7a612f91565b81526020016008820154815260200160098201548152602001600a8201548152602001600b8201805480602002602001604051908101604052809291908181526020018280548015610cf557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cd7575b5050505050815250509050919050565b610d3260405180608001604052806000151581526020016000815260200160008152602001600081525090565b6108d933611aae565b610d43611f84565b600955565b610d50611f84565b610d5a6000611fde565b565b80600081118015610d6f57506003548111155b610d8b5760405162461bcd60e51b815260040161041190613360565b816000808281526004602052604090206007015460ff166003811115610db357610db3612f91565b14610dd05760405162461bcd60e51b815260040161041190613397565b6002805403610df15760405162461bcd60e51b8152600401610411906133ce565b600280556000838152600460205260409020600301546001600160a01b0316338114610e6a5760405162461bcd60e51b815260206004820152602260248201527f4f6e6c792053656c6c65722063616e2063616e63656c204d61726b6574204974604482015261656d60f01b6064820152608401610411565b6000610e7582611aae565b604001519050610e9d8160405180608001604052806046815260200161357360469139611c08565b610ea885600261202e565b50506001600255505050565b610ebc611f84565b80600081118015610ecf57506003548111155b610eeb5760405162461bcd60e51b815260040161041190613360565b816000808281526004602052604090206007015460ff166003811115610f1357610f13612f91565b14610f305760405162461bcd60e51b815260040161041190613397565b6002805403610f515760405162461bcd60e51b8152600401610411906133ce565b60028055610f6083600361202e565b5050600160025550565b610f72611f84565b610f7a6123e2565b610fc65760405162461bcd60e51b815260206004820181905260248201527f42656e65666963696172792073686f756c6420626520737065636966696564216044820152606401610411565b600082116110165760405162461bcd60e51b815260206004820152601f60248201527f53656e6420416d6f756e742073686f756c6420626520706f73697469766521006044820152606401610411565b306001600160a01b0382166110eb576001600160a01b03811631838110156110a65760405162461bcd60e51b815260206004820152603a60248201527f53656e6420416d6f756e74206578636565647320536d61727420436f6e74726160448201527f63742773206e617469766520746f6b656e2062616c616e6365210000000000006064820152608401610411565b6001546040516101009091046001600160a01b0316906108fc8615029086906000818181858888f193505050501580156110e4573d6000803e3d6000fd5b5050505050565b6040516370a0823160e01b81526001600160a01b03828116600483015283916000918316906370a0823190602401602060405180830381865afa158015611136573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115a9190613405565b9050848110156111d25760405162461bcd60e51b815260206004820152603a60248201527f53656e6420416d6f756e74206578636565647320536d61727420436f6e74726160448201527f63742773204552432d323020746f6b656e2062616c616e6365210000000000006064820152608401610411565b60015460405163a9059cbb60e01b81526101009091046001600160a01b0390811660048301526024820187905283169063a9059cbb906044016020604051808303816000875af115801561122a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124e919061341e565b5050505b505050565b61128460405180608001604052806000151581526020016000815260200160008152602001600081525090565b61128c611f84565b6108c88261241d565b61129d612b3d565b816000811180156112b057506003548111155b6112cc5760405162461bcd60e51b815260040161041190613360565b6000838152600460208181526040928390208351610180810185528154815260018201546001600160a01b0390811693820193909352600282015494810194909452600380820154831660608601529281015482166080850152600581015490911660a0840152600681015460c08401526007810154909160e084019160ff169081111561135c5761135c612f91565b600381111561136d5761136d612f91565b81526020016008820154815260200160098201548152602001600a8201548152602001600b82018054806020026020016040519081016040528092919081815260200182805480156113e857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116113ca575b505050505081525050915050919050565b611401611f84565b6001600160a01b0381166114665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610411565b6108a081611fde565b8160008111801561148257506003548111155b61149e5760405162461bcd60e51b815260040161041190613360565b826000808281526004602052604090206007015460ff1660038111156114c6576114c6612f91565b146114e35760405162461bcd60e51b815260040161041190613397565b60028054036115045760405162461bcd60e51b8152600401610411906133ce565b60028055600033600086815260046020819052604080832060038101546002820154600190920154925163e985e9c560e01b81526001600160a01b0391821694810185905230602482015295965092949093929091169190829063e985e9c590604401602060405180830381865afa158015611584573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a8919061341e565b90508061169d5760405163020604bf60e21b8152600481018490526000906001600160a01b0384169063081812fc90602401602060405180830381865afa1580156115f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161b9190613440565b90506001600160a01b038116301461169b5760405162461bcd60e51b815260206004820152603760248201527f4d61726b6574204974656d20284e4654292073686f756c64206265206170707260448201527f6f76656420746f20746865204d61726b6574706c6163650000000000000000006064820152608401610411565b505b6000898152600460205260409020600b01541561175d5760008981526008602090815260408083206001600160a01b038916845290915290205460ff16151560011461175d5760405162461bcd60e51b815260206004820152604360248201527f596f75722061646472657373206973206e6f742073706563696669656420696e60448201527f2057686974652d4c69737420666f722063757272656e74204d61726b6574204960648201526274656d60e81b608482015260a401610411565b60006117698a8761249d565b60008b81526004602081905260409182902080820180546001600160a01b0319166001600160a01b038c811691821790925560088301869055600a9092018e90559251632142170760e11b8152898416928101929092526024820152604481018790529192508416906342842e0e90606401600060405180830381600087803b1580156117f557600080fd5b505af1158015611809573d6000803e3d6000fd5b505050506118188a600161202e565b600260015460ff16600281111561183157611831612f91565b14801561184d575060015461010090046001600160a01b031615155b156118b8576001546040516391c05b0b60e01b8152600481018c90526101009091046001600160a01b03169081906391c05b0b90602401600060405180830381600087803b15801561189e57600080fd5b505af11580156118b2573d6000803e3d6000fd5b50505050505b6040516001600160a01b038716908b907f2073b2706c235effb1e3840575370a51749afd8181b4018f93bff955d50792cb90600090a3505060016002555050505050505050565b6040516331a9108f60e11b815260048101829052600090839082906001600160a01b03831690636352211e90602401602060405180830381865afa15801561194b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196f9190613440565b9050856001600160a01b0316816001600160a01b0316146119965760001992505050611aa7565b60405163e985e9c560e01b81526001600160a01b0387811660048301523060248301526000919084169063e985e9c590604401602060405180830381865afa1580156119e6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0a919061341e565b905080611a9f5760405163020604bf60e21b8152600481018690526000906001600160a01b0385169063081812fc90602401602060405180830381865afa158015611a59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7d9190613440565b90506001600160a01b0381163014611a9d57600119945050505050611aa7565b505b600093505050505b9392505050565b611adb60405180608001604052806000151581526020016000815260200160008152602001600081525090565b6001600160a01b03821660009081526007602052604090205460ff1615611b4f57506001600160a01b03166000908152600760209081526040918290208251608081018452815460ff1615158152600182015492810192909252600281015492820192909252600390910154606082015290565b50506000805260076020908152604080516080810182527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6df5460ff16151581527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e054928101929092527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e154908201527f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e254606082015290565b8115611c7f57813410158190611c315760405162461bcd60e51b81526004016104119190613489565b50611c3a6123e2565b15611c7f576001546040516001600160a01b0361010090920491909116903480156108fc02916000818181858888f19350505050158015611252573d6000803e3d6000fd5b5050565b611c91600380546001019055565b6000611c9c60035490565b6005805460018101825560008281527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db09091018390559054604080516101808101825284815286516001600160a01b039081166020838101919091528801518284015288811660608084019190915260808301869052928801511660a08201529086015160c0820152929350919060e082019081526000602080830182905260408084018690526060808501849052608089810151958101959095528784526004808452938290208651815592860151600180850180546001600160a01b03199081166001600160a01b0394851617909155938801516002860155918701516003808601805486169284169290921790915595870151948401805484169582169590951790945560a0860151600584018054909316941693909317905560c0840151600682015560e084015160078201805492949193909260ff1916918490811115611e0a57611e0a612f91565b021790555061010082015160088201556101208201516009820155610140820151600a8201556101608201518051611e4c91600b840191602090910190612b9e565b505083516001600160a01b0316600090815260066020908152604080832082880151845290915290208290555060808301515115611f045760005b836080015151811015611f0257600083815260086020526040812060808601518051600193919085908110611ebe57611ebe61331a565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580611efa81613330565b915050611e87565b505b836001600160a01b031683600001516001600160a01b0316837fc48e6ef63d8ee5c32e1a12522041571cc6929dbabed66a5eba6b0e9c65ca8471866020015187604001518860600151604051611f76939291909283526001600160a01b03919091166020830152604082015260600190565b60405180910390a450505050565b6000546001600160a01b03163314610d5a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610411565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8160008111801561204157506003548111155b61205d5760405162461bcd60e51b815260040161041190613360565b826000808281526004602052604090206007015460ff16600381111561208557612085612f91565b146120a25760405162461bcd60e51b815260040161041190613397565b6000848152600460205260408120600901546120c090600190613349565b9050600554811061212d5760405162461bcd60e51b815260206004820152603160248201527f4d61726b6574204974656d20686173206e6f20706f736974696f6e20696e20416044820152706374697665204974656d7320617272617960781b6064820152608401610411565b84600582815481106121415761214161331a565b9060005260206000200154146121bf5760405162461bcd60e51b815260206004820152603960248201527f4d61726b6574204974656d206973206e6f74206f6e2074686520706f7369746960448201527f6f6e20696e20416374697665204974656d7320617272617921000000000000006064820152608401610411565b60008460038111156121d3576121d3612f91565b036122365760405162461bcd60e51b815260206004820152602d60248201527f5370656369667920636f72726563742073746174757320746f2072656d6f766560448201526c204d61726b6574204974656d2160981b6064820152608401610411565b6000858152600460205260409020600701805485919060ff1916600183600381111561226457612264612f91565b021790555060008581526004602052604081206009015560055461228a90600190613349565b8110156123425760058054600091906122a590600190613349565b815481106122b5576122b561331a565b9060005260206000200154905080600583815481106122d6576122d661331a565b6000918252602090912001556122ed8260016134bc565b60008281526004602052604090206009015561230a8260016134bc565b600091825260046020908152604080842060018101546001600160a01b03168552600683528185206002909101548552909152909120555b6005805480612353576123536134d4565b60008281526020808220830160001990810183905590920190925586825260048152604080832060018101546001600160a01b03168452600683528184206002909101548452909152808220919091555185907f471936d15caaa62c7c9222e363a0323e64ed408a1c87a4ef46c7596655eb1b3d906123d39087906134ea565b60405180910390a25050505050565b60008060015460ff1660028111156123fc576123fc612f91565b141580156108d9575060015461010090046001600160a01b03161515905090565b61244a60405180608001604052806000151581526020016000815260200160008152602001600081525090565b506001600160a01b03166000908152600760209081526040918290208251608081018452815460ff1615158152600182015492810192909252600281015492820192909252600390910154606082015290565b6000828152600460205260408120600381015460068201546005909201546001600160a01b03918216929116836124d384611aae565b606001519050600060646124e785846132fb565b6124f191906134f8565b905060006124ff8286613349565b90506000811161255b5760405162461bcd60e51b815260206004820152602160248201527f496e76616c69642053656c6c657220416d6f756e742063616c63756c617465646044820152602160f81b6064820152608401610411565b6001600160a01b03841661267657843410156125e1576040805162461bcd60e51b81526020600482015260248101919091527f506c65617365207375626d69742074686520507269636520616d6f756e74206960448201527f6e206f7264657220746f20636f6d706c657465207468652070757263686173656064820152608401610411565b6040516001600160a01b0387169082156108fc029083906000818181858888f19350505050158015612617573d6000803e3d6000fd5b506126206123e2565b801561262c5750600082115b15612671576001546040516101009091046001600160a01b0316906108fc8415029084906000818181858888f1935050505015801561266f573d6000803e3d6000fd5b505b61289b565b604051636eb1769f60e11b81526001600160a01b03898116600483015230602483018190529186916000919083169063dd62ed3e90604401602060405180830381865afa1580156126cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ef9190613405565b9050878110156127775760405162461bcd60e51b815260206004820152604760248201527f506c6561736520616c6c6f7720507269636520616d6f756e74206f662045524360448201527f2d323020546f6b656e20696e206f7264657220746f20636f6d706c65746520706064820152667572636861736560c81b608482015260a401610411565b61278c6001600160a01b0383168c858b6128a7565b60405163a9059cbb60e01b81526001600160a01b038a811660048301526024820186905283169063a9059cbb906044016020604051808303816000875af11580156127db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ff919061341e565b506128086123e2565b80156128145750600085115b156128975760015460405163a9059cbb60e01b81526101009091046001600160a01b0390811660048301526024820187905283169063a9059cbb906044016020604051808303816000875af1158015612871573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612895919061341e565b505b5050505b50979650505050505050565b604080516001600160a01b038581166024830152848116604483015260648083018590528351808403909101815260849092018352602080830180516001600160e01b03166323b872dd60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908401526107e49287929160009161293f9185169084906129bc565b805190915015611252578080602001905181019061295d919061341e565b6112525760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610411565b60606129cb84846000856129d3565b949350505050565b606082471015612a345760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610411565b6001600160a01b0385163b612a8b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610411565b600080866001600160a01b03168587604051612aa7919061351a565b60006040518083038185875af1925050503d8060008114612ae4576040519150601f19603f3d011682016040523d82523d6000602084013e612ae9565b606091505b5091509150612af9828286612b04565b979650505050505050565b60608315612b13575081611aa7565b825115612b235782518084602001fd5b8160405162461bcd60e51b81526004016104119190613489565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529060e08201908152602001600081526020016000815260200160008152602001606081525090565b828054828255906000526020600020908101928215612bf3579160200282015b82811115612bf357825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612bbe565b50612bff929150612c03565b5090565b5b80821115612bff5760008155600101612c04565b6001600160a01b03811681146108a057600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612c6657612c66612c2d565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612c9557612c95612c2d565b604052919050565b600067ffffffffffffffff821115612cb757612cb7612c2d565b5060051b60200190565b600082601f830112612cd257600080fd5b81356020612ce7612ce283612c9d565b612c6c565b82815260059290921b84018101918181019086841115612d0657600080fd5b8286015b84811015612d2a578035612d1d81612c18565b8352918301918301612d0a565b509695505050505050565b600080600080600060a08688031215612d4d57600080fd5b8535612d5881612c18565b9450602086013593506040860135612d6f81612c18565b925060608601359150608086013567ffffffffffffffff811115612d9257600080fd5b612d9e88828901612cc1565b9150509295509295909350565b60006020808385031215612dbe57600080fd5b823567ffffffffffffffff80821115612dd657600080fd5b818501915085601f830112612dea57600080fd5b8135612df8612ce282612c9d565b81815260059190911b83018401908481019088831115612e1757600080fd5b8585015b83811015612ec357803585811115612e335760008081fd5b860160a0818c03601f1901811315612e4b5760008081fd5b612e53612c43565b89830135612e6081612c18565b81526040838101358b830152606080850135612e7b81612c18565b8083850152506080915081850135818401525082840135925088831115612ea25760008081fd5b612eb08e8c85870101612cc1565b9082015285525050918601918601612e1b565b5098975050505050505050565b60008060008060808587031215612ee657600080fd5b8435612ef181612c18565b966020860135965060408601359560600135945092505050565b600060208284031215612f1d57600080fd5b8135611aa781612c18565b60008060408385031215612f3b57600080fd5b8235612f4681612c18565b946020939093013593505050565b60008060408385031215612f6757600080fd5b823560038110612f7657600080fd5b91506020830135612f8681612c18565b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b8151604082019060038110612fbe57612fbe612f91565b82526020928301516001600160a01b0316929091019190915290565b600060208284031215612fec57600080fd5b5035919050565b6004811061300357613003612f91565b9052565b600081518084526020808501945080840160005b838110156130405781516001600160a01b03168752958201959082019060010161301b565b509495945050505050565b60208152815160208201526000602083015161307260408401826001600160a01b03169052565b5060408301516060830152606083015161309760808401826001600160a01b03169052565b5060808301516001600160a01b03811660a08401525060a08301516001600160a01b03811660c08401525060c083015160e083015260e08301516101006130e081850183612ff3565b8401516101208481019190915284015161014080850191909152840151610160808501919091528401516101808085015290506129cb6101a0840182613007565b6000806040838503121561313457600080fd5b823591506020830135612f8681612c18565b6000806040838503121561315957600080fd5b50508035926020909101359150565b60208082526027908201527f5072696365206d75737420626520706f73697469766520286174206c656173746040820152662031207765692960c81b606082015260800190565b6020808252602a908201527f5468617420746f6b656e20697320616c726561647920706c61636564206f6e206040820152691d1a19481b585c9ad95d60b21b606082015260800190565b60208082526035908201527f4f6e6c79206f776e6572206f6620746865204e46542063616e20706c61636520604082015274697420746f20746865204d61726b6574706c61636560581b606082015260800190565b60208082526029908201527f4e46542073686f756c6420626520617070726f76656420746f20746865204d61604082015268726b6574706c61636560b81b606082015260800190565b6020808252602e908201527f4e4654206973206e6f742076616c696420746f20626520736f6c64206f6e207460408201526d6865204d61726b6574706c61636560901b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615613315576133156132e5565b500290565b634e487b7160e01b600052603260045260246000fd5b600060018201613342576133426132e5565b5060010190565b60008282101561335b5761335b6132e5565b500390565b60208082526017908201527f496e76616c6964204d61726b6574204974656d20494421000000000000000000604082015260600190565b60208082526019908201527f4d61726b6574204974656d206973206e6f742041637469766500000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60006020828403121561341757600080fd5b5051919050565b60006020828403121561343057600080fd5b81518015158114611aa757600080fd5b60006020828403121561345257600080fd5b8151611aa781612c18565b60005b83811015613478578181015183820152602001613460565b838111156107e45750506000910152565b60208152600082518060208401526134a881604085016020870161345d565b601f01601f19169190910160400192915050565b600082198211156134cf576134cf6132e5565b500190565b634e487b7160e01b600052603160045260246000fd5b602081016108c88284612ff3565b60008261351557634e487b7160e01b600052601260045260246000fd5b500490565b6000825161352c81846020870161345d565b919091019291505056fe4c697374696e672050726963652073686f756c642062652073656e7420746f20706c616365204e4654206f6e20746865204d61726b6574706c61636543616e63656c2050726963652073686f756c642062652073656e7420746f2063616e63656c204e465420706c6163656d656e74206f6e20746865204d61726b6574706c616365a2646970667358221220139357d19635522a0cf149b44ac663c7327db6cea258dca874a00b4dcc80b84d64736f6c634300080f0033