ETH Price: $2,783.05 (+4.13%)

Contract

0x58CE6CaA5B3C25804D9EBE59C1803f213A54575B
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Purchase For141190452022-02-01 8:22:581117 days ago1643703778IN
0x58CE6CaA...13A54575B
0 ETH0.00439035126.63270617
Purchase For141060952022-01-30 8:36:441119 days ago1643531804IN
0x58CE6CaA...13A54575B
0 ETH0.00424998122.58405178
Purchase For140983772022-01-29 3:59:121120 days ago1643428752IN
0x58CE6CaA...13A54575B
0 ETH0.01540745105.53992464
Purchase For140983652022-01-29 3:56:341120 days ago1643428594IN
0x58CE6CaA...13A54575B
0 ETH0.01974174130.92469875
Purchase For140983582022-01-29 3:54:351120 days ago1643428475IN
0x58CE6CaA...13A54575B
0 ETH0.02051382136.04502416
Purchase For140983502022-01-29 3:52:081120 days ago1643428328IN
0x58CE6CaA...13A54575B
0 ETH0.02322119154
Purchase For140983382022-01-29 3:48:241120 days ago1643428104IN
0x58CE6CaA...13A54575B
0 ETH0.01850163122.70046738
Purchase For140983312022-01-29 3:45:401120 days ago1643427940IN
0x58CE6CaA...13A54575B
0 ETH0.01475397.8400239
Purchase For140983222022-01-29 3:43:351120 days ago1643427815IN
0x58CE6CaA...13A54575B
0 ETH0.01808852119.96075443
Purchase For140983092022-01-29 3:40:141120 days ago1643427614IN
0x58CE6CaA...13A54575B
0 ETH0.01530137101.47677627
Purchase For140982892022-01-29 3:36:591120 days ago1643427419IN
0x58CE6CaA...13A54575B
0 ETH0.01102139100.56388811
Purchase For140982872022-01-29 3:36:201120 days ago1643427380IN
0x58CE6CaA...13A54575B
0 ETH0.0103247490.2544456
Purchase For140982862022-01-29 3:36:131120 days ago1643427373IN
0x58CE6CaA...13A54575B
0 ETH0.010545192.18075803
Purchase For140982852022-01-29 3:35:481120 days ago1643427348IN
0x58CE6CaA...13A54575B
0 ETH0.0095286283.29510713
Purchase For140982842022-01-29 3:35:431120 days ago1643427343IN
0x58CE6CaA...13A54575B
0 ETH0.0099931187.35543945
Purchase For140982802022-01-29 3:35:161120 days ago1643427316IN
0x58CE6CaA...13A54575B
0 ETH0.01176712102.86305213
Purchase For140982772022-01-29 3:34:261120 days ago1643427266IN
0x58CE6CaA...13A54575B
0 ETH0.0094182382.33008568
Purchase For140982722022-01-29 3:33:531120 days ago1643427233IN
0x58CE6CaA...13A54575B
0 ETH0.0113224298.97568401
Purchase For140982702022-01-29 3:33:461120 days ago1643427226IN
0x58CE6CaA...13A54575B
0 ETH0.01355402118.48342434
Purchase For140982682022-01-29 3:33:241120 days ago1643427204IN
0x58CE6CaA...13A54575B
0 ETH0.01418577124.0058936
Purchase For140981812022-01-29 3:15:121120 days ago1643426112IN
0x58CE6CaA...13A54575B
0 ETH0.01299511122.50292506
Purchase For140981782022-01-29 3:14:291120 days ago1643426069IN
0x58CE6CaA...13A54575B
0 ETH0.01376055124.10312014
Purchase For140981762022-01-29 3:14:111120 days ago1643426051IN
0x58CE6CaA...13A54575B
0 ETH0.01480082133.48509448
Purchase For140981752022-01-29 3:13:361120 days ago1643426016IN
0x58CE6CaA...13A54575B
0 ETH0.0142832128.8168254
Purchase For140981732022-01-29 3:13:291120 days ago1643426009IN
0x58CE6CaA...13A54575B
0 ETH0.01247285112.48965712
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TokenLaunchpadVoucherPacksSale

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 2000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-11-02
*/

// Sources flattened with hardhat v2.6.5 https://hardhat.org

// File @animoca/ethereum-contracts-core-1.1.2/contracts/utils/types/[email protected]

// SPDX-License-Identifier: MIT

// Partially derived from OpenZeppelin:
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/406c83649bd6169fc1b578e08506d78f0873b276/contracts/utils/Address.sol

pragma solidity >=0.7.6 <0.8.0;

/**
 * @dev Upgrades the address type to check if it is a contract.
 */
library AddressIsContract {
    /**
     * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }
}


// File @animoca/ethereum-contracts-core-1.1.2/contracts/utils/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * @title ERC20Wrapper
 * Wraps ERC20 functions to support non-standard implementations which do not return a bool value.
 * Calls to the wrapped functions revert only if they throw or if they return false.
 */
library ERC20Wrapper {
    using AddressIsContract for address;

    function wrappedTransfer(
        IWrappedERC20 token,
        address to,
        uint256 value
    ) internal {
        _callWithOptionalReturnData(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function wrappedTransferFrom(
        IWrappedERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callWithOptionalReturnData(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function wrappedApprove(
        IWrappedERC20 token,
        address spender,
        uint256 value
    ) internal {
        _callWithOptionalReturnData(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function _callWithOptionalReturnData(IWrappedERC20 token, bytes memory callData) internal {
        address target = address(token);
        require(target.isContract(), "ERC20Wrapper: non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory data) = target.call(callData);
        if (success) {
            if (data.length != 0) {
                require(abi.decode(data, (bool)), "ERC20Wrapper: operation failed");
            }
        } else {
            // revert using a standard revert message
            if (data.length == 0) {
                revert("ERC20Wrapper: operation failed");
            }

            // revert using the revert message coming from the call
            assembly {
                let size := mload(data)
                revert(add(32, data), size)
            }
        }
    }
}

interface IWrappedERC20 {
    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function approve(address spender, uint256 value) external returns (bool);
}


// File @animoca/ethereum-contracts-core-1.1.2/contracts/algo/[email protected]

// Derived from OpenZeppelin:
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/406c83649bd6169fc1b578e08506d78f0873b276/contracts/utils/structs/EnumerableMap.sol

pragma solidity >=0.7.6 <0.8.0;

/**
 * @dev Library for managing an enumerable variant of Solidity's
 * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
 * type.
 *
 * Maps have the following properties:
 *
 * - Entries are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Entries are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumMap for EnumMap.Map;
 *
 *     // Declare a set state variable
 *     EnumMap.Map private myMap;
 * }
 * ```
 */
library EnumMap {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Map type with
    // bytes32 keys and values.
    // This means that we can only create new EnumMaps for types that fit
    // in bytes32.

    struct MapEntry {
        bytes32 key;
        bytes32 value;
    }

    struct Map {
        // Storage of map keys and values
        MapEntry[] entries;
        // Position of the entry defined by a key in the `entries` array, plus 1
        // because index 0 means a key is not in the map.
        mapping(bytes32 => uint256) indexes;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(
        Map storage map,
        bytes32 key,
        bytes32 value
    ) internal returns (bool) {
        // We read and store the key's index to prevent multiple reads from the same storage slot
        uint256 keyIndex = map.indexes[key];

        if (keyIndex == 0) {
            // Equivalent to !contains(map, key)
            map.entries.push(MapEntry({key: key, value: value}));
            // The entry is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            map.indexes[key] = map.entries.length;
            return true;
        } else {
            map.entries[keyIndex - 1].value = value;
            return false;
        }
    }

    /**
     * @dev Removes a key-value pair from a map. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function remove(Map storage map, bytes32 key) internal returns (bool) {
        // We read and store the key's index to prevent multiple reads from the same storage slot
        uint256 keyIndex = map.indexes[key];

        if (keyIndex != 0) {
            // Equivalent to contains(map, key)
            // To delete a key-value pair from the entries array in O(1), we swap the entry to delete with the last one
            // in the array, and then remove the last entry (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = keyIndex - 1;
            uint256 lastIndex = map.entries.length - 1;

            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            MapEntry storage lastEntry = map.entries[lastIndex];

            // Move the last entry to the index where the entry to delete is
            map.entries[toDeleteIndex] = lastEntry;
            // Update the index for the moved entry
            map.indexes[lastEntry.key] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved entry was stored
            map.entries.pop();

            // Delete the index for the deleted slot
            delete map.indexes[key];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function contains(Map storage map, bytes32 key) internal view returns (bool) {
        return map.indexes[key] != 0;
    }

    /**
     * @dev Returns the number of key-value pairs in the map. O(1).
     */
    function length(Map storage map) internal view returns (uint256) {
        return map.entries.length;
    }

    /**
     * @dev Returns the key-value pair stored at position `index` in the map. O(1).
     *
     * Note that there are no guarantees on the ordering of entries inside the
     * array, and it may change when more entries are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Map storage map, uint256 index) internal view returns (bytes32, bytes32) {
        require(map.entries.length > index, "EnumMap: index out of bounds");

        MapEntry storage entry = map.entries[index];
        return (entry.key, entry.value);
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(Map storage map, bytes32 key) internal view returns (bytes32) {
        uint256 keyIndex = map.indexes[key];
        require(keyIndex != 0, "EnumMap: nonexistent key"); // Equivalent to contains(map, key)
        return map.entries[keyIndex - 1].value; // All indexes are 1-based
    }
}


// File @animoca/ethereum-contracts-core-1.1.2/contracts/algo/[email protected]

// Derived from OpenZeppelin:
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/406c83649bd6169fc1b578e08506d78f0873b276/contracts/utils/structs/EnumerableSet.sol

pragma solidity >=0.7.6 <0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumSet for EnumSet.Set;
 *
 *     // Declare a set state variable
 *     EnumSet.Set private mySet;
 * }
 * ```
 */
library EnumSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Set storage set, bytes32 value) internal returns (bool) {
        if (!contains(set, value)) {
            set.values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set.indexes[value] = set.values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Set storage set, bytes32 value) internal returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set.indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set.values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set.values[lastIndex];

            // Move the last value to the index where the value to delete is
            set.values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set.indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set.values.pop();

            // Delete the index for the deleted slot
            delete set.indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Set storage set, bytes32 value) internal view returns (bool) {
        return set.indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(Set storage set) internal view returns (uint256) {
        return set.values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Set storage set, uint256 index) internal view returns (bytes32) {
        require(set.values.length > index, "EnumSet: index out of bounds");
        return set.values[index];
    }
}


// File @animoca/ethereum-contracts-core-1.1.2/contracts/metatx/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/*
 * 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.
 */
abstract contract ManagedIdentity {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

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


// File @animoca/ethereum-contracts-core-1.1.2/contracts/access/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * @title ERC-173 Contract Ownership Standard
 * Note: the ERC-165 identifier for this interface is 0x7f5828d0
 */
interface IERC173 {
    /**
     * Event emited when ownership of a contract changes.
     * @param previousOwner the previous owner.
     * @param newOwner the new owner.
     */
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * Get the address of the owner
     * @return The address of the owner.
     */
    function owner() external view returns (address);

    /**
     * Set the address of the new owner of the contract
     * Set newOwner to address(0) to renounce any ownership.
     * @dev Emits an {OwnershipTransferred} event.
     * @param newOwner The address of the new owner of the contract. Using the zero address means renouncing ownership.
     */
    function transferOwnership(address newOwner) external;
}


// File @animoca/ethereum-contracts-core-1.1.2/contracts/access/[email protected]

pragma solidity >=0.7.6 <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 ManagedIdentity, IERC173 {
    address internal _owner;

    /**
     * Initializes the contract, setting the deployer as the initial owner.
     * @dev Emits an {IERC173-OwnershipTransferred(address,address)} event.
     */
    constructor(address owner_) {
        _owner = owner_;
        emit OwnershipTransferred(address(0), owner_);
    }

    /**
     * Gets the address of the current contract owner.
     */
    function owner() public view virtual override returns (address) {
        return _owner;
    }

    /**
     * See {IERC173-transferOwnership(address)}
     * @dev Reverts if the sender is not the current contract owner.
     * @param newOwner the address of the new owner. Use the zero address to renounce the ownership.
     */
    function transferOwnership(address newOwner) public virtual override {
        _requireOwnership(_msgSender());
        _owner = newOwner;
        emit OwnershipTransferred(_owner, newOwner);
    }

    /**
     * @dev Reverts if `account` is not the contract owner.
     * @param account the account to test.
     */
    function _requireOwnership(address account) internal virtual {
        require(account == this.owner(), "Ownable: not the owner");
    }
}


// File @animoca/ethereum-contracts-core-1.1.2/contracts/payment/[email protected]

pragma solidity >=0.7.6 <0.8.0;


/**
    @title PayoutWallet
    @dev adds support for a payout wallet
    Note: .
 */
abstract contract PayoutWallet is ManagedIdentity, Ownable {
    event PayoutWalletSet(address payoutWallet_);

    address payable public payoutWallet;

    constructor(address owner, address payable payoutWallet_) Ownable(owner) {
        require(payoutWallet_ != address(0), "Payout: zero address");
        payoutWallet = payoutWallet_;
        emit PayoutWalletSet(payoutWallet_);
    }

    function setPayoutWallet(address payable payoutWallet_) public {
        _requireOwnership(_msgSender());
        require(payoutWallet_ != address(0), "Payout: zero address");
        payoutWallet = payoutWallet_;
        emit PayoutWalletSet(payoutWallet);
    }
}


// File @animoca/ethereum-contracts-core-1.1.2/contracts/lifecycle/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * Contract module which allows derived contracts to implement a mechanism for
 * activating, or 'starting', a contract.
 *
 * This module is used through inheritance. It will make available the modifiers
 * `whenNotStarted` and `whenStarted`, which can be applied to the functions of
 * your contract. Those functions will only be 'startable' once the modifiers
 * are put in place.
 */
abstract contract Startable is ManagedIdentity {
    event Started(address account);

    uint256 private _startedAt;

    /**
     * Modifier to make a function callable only when the contract has not started.
     */
    modifier whenNotStarted() {
        require(_startedAt == 0, "Startable: started");
        _;
    }

    /**
     * Modifier to make a function callable only when the contract has started.
     */
    modifier whenStarted() {
        require(_startedAt != 0, "Startable: not started");
        _;
    }

    /**
     * Constructor.
     */
    constructor() {}

    /**
     * Returns the timestamp when the contract entered the started state.
     * @return The timestamp when the contract entered the started state.
     */
    function startedAt() public view returns (uint256) {
        return _startedAt;
    }

    /**
     * Triggers the started state.
     * @dev Emits the Started event when the function is successfully called.
     */
    function _start() internal virtual whenNotStarted {
        _startedAt = block.timestamp;
        emit Started(_msgSender());
    }
}


// File @animoca/ethereum-contracts-core-1.1.2/contracts/lifecycle/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * @dev Contract which allows children to implement pausability.
 */
abstract contract Pausable is ManagedIdentity {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool public paused;

    constructor(bool paused_) {
        paused = paused_;
    }

    function _requireNotPaused() internal view {
        require(!paused, "Pausable: paused");
    }

    function _requirePaused() internal view {
        require(paused, "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual {
        _requireNotPaused();
        paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual {
        _requirePaused();
        paused = false;
        emit Unpaused(_msgSender());
    }
}


// File @openzeppelin/contracts/math/[email protected]

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}


// File @animoca/ethereum-contracts-sale-2.0.0/contracts/sale/interfaces/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * @title ISale
 *
 * An interface for a contract which allows merchants to display products and customers to purchase them.
 *
 *  Products, designated as SKUs, are represented by bytes32 identifiers so that an identifier can carry an
 *  explicit name under the form of a fixed-length string. Each SKU can be priced via up to several payment
 *  tokens which can be ETH and/or ERC20(s). ETH token is represented by the magic value TOKEN_ETH, which means
 *  this value can be used as the 'token' argument of the purchase-related functions to indicate ETH payment.
 *
 *  The total available supply for a SKU is fixed at its creation. The magic value SUPPLY_UNLIMITED is used
 *  to represent a SKU with an infinite, never-decreasing supply. An optional purchase notifications receiver
 *  contract address can be set for a SKU at its creation: if the value is different from the zero address,
 *  the function `onPurchaseNotificationReceived` will be called on this address upon every purchase of the SKU.
 *
 *  This interface is designed to be consistent while managing a variety of implementation scenarios. It is
 *  also intended to be developer-friendly: all vital information is consistently deductible from the events
 *  (backend-oriented), as well as retrievable through calls to public functions (frontend-oriented).
 */
interface ISale {
    /**
     * Event emitted to notify about the magic values necessary for interfacing with this contract.
     * @param names An array of names for the magic values used by the contract.
     * @param values An array of values for the magic values used by the contract.
     */
    event MagicValues(bytes32[] names, bytes32[] values);

    /**
     * Event emitted to notify about the creation of a SKU.
     * @param sku The identifier of the created SKU.
     * @param totalSupply The initial total supply for sale.
     * @param maxQuantityPerPurchase The maximum allowed quantity for a single purchase.
     * @param notificationsReceiver If not the zero address, the address of a contract on which `onPurchaseNotificationReceived` will be called after
     *  each purchase. If this is the zero address, the call is not enabled.
     */
    event SkuCreation(bytes32 sku, uint256 totalSupply, uint256 maxQuantityPerPurchase, address notificationsReceiver);

    /**
     * Event emitted to notify about a change in the pricing of a SKU.
     * @dev `tokens` and `prices` arrays MUST have the same length.
     * @param sku The identifier of the updated SKU.
     * @param tokens An array of updated payment tokens. If empty, interpret as all payment tokens being disabled.
     * @param prices An array of updated prices for each of the payment tokens.
     *  Zero price values are used for payment tokens being disabled.
     */
    event SkuPricingUpdate(bytes32 indexed sku, address[] tokens, uint256[] prices);

    /**
     * Event emitted to notify about a purchase.
     * @param purchaser The initiater and buyer of the purchase.
     * @param recipient The recipient of the purchase.
     * @param token The token used as the currency for the payment.
     * @param sku The identifier of the purchased SKU.
     * @param quantity The purchased quantity.
     * @param userData Optional extra user input data.
     * @param totalPrice The amount of `token` paid.
     * @param extData Implementation-specific extra purchase data, such as
     *  details about discounts applied, conversion rates, purchase receipts, etc.
     */
    event Purchase(
        address indexed purchaser,
        address recipient,
        address indexed token,
        bytes32 indexed sku,
        uint256 quantity,
        bytes userData,
        uint256 totalPrice,
        bytes extData
    );

    /**
     * Returns the magic value used to represent the ETH payment token.
     * @dev MUST NOT be the zero address.
     * @return the magic value used to represent the ETH payment token.
     */
    // solhint-disable-next-line func-name-mixedcase
    function TOKEN_ETH() external pure returns (address);

    /**
     * Returns the magic value used to represent an infinite, never-decreasing SKU's supply.
     * @dev MUST NOT be zero.
     * @return the magic value used to represent an infinite, never-decreasing SKU's supply.
     */
    // solhint-disable-next-line func-name-mixedcase
    function SUPPLY_UNLIMITED() external pure returns (uint256);

    /**
     * Performs a purchase.
     * @dev Reverts if `recipient` is the zero address.
     * @dev Reverts if `token` is the address zero.
     * @dev Reverts if `quantity` is zero.
     * @dev Reverts if `quantity` is greater than the maximum purchase quantity.
     * @dev Reverts if `quantity` is greater than the remaining supply.
     * @dev Reverts if `sku` does not exist.
     * @dev Reverts if `sku` exists but does not have a price set for `token`.
     * @dev Emits the Purchase event.
     * @param recipient The recipient of the purchase.
     * @param token The token to use as the payment currency.
     * @param sku The identifier of the SKU to purchase.
     * @param quantity The quantity to purchase.
     * @param userData Optional extra user input data.
     */
    function purchaseFor(
        address payable recipient,
        address token,
        bytes32 sku,
        uint256 quantity,
        bytes calldata userData
    ) external payable;

    /**
     * Estimates the computed final total amount to pay for a purchase, including any potential discount.
     * @dev This function MUST compute the same price as `purchaseFor` would in identical conditions (same arguments, same point in time).
     * @dev If an implementer contract uses the `pricingData` field, it SHOULD document how to interpret the values.
     * @dev Reverts if `recipient` is the zero address.
     * @dev Reverts if `token` is the zero address.
     * @dev Reverts if `quantity` is zero.
     * @dev Reverts if `quantity` is greater than the maximum purchase quantity.
     * @dev Reverts if `quantity` is greater than the remaining supply.
     * @dev Reverts if `sku` does not exist.
     * @dev Reverts if `sku` exists but does not have a price set for `token`.
     * @param recipient The recipient of the purchase used to calculate the total price amount.
     * @param token The payment token used to calculate the total price amount.
     * @param sku The identifier of the SKU used to calculate the total price amount.
     * @param quantity The quantity used to calculate the total price amount.
     * @param userData Optional extra user input data.
     * @return totalPrice The computed total price to pay.
     * @return pricingData Implementation-specific extra pricing data, such as details about discounts applied.
     *  If not empty, the implementer MUST document how to interepret the values.
     */
    function estimatePurchase(
        address payable recipient,
        address token,
        bytes32 sku,
        uint256 quantity,
        bytes calldata userData
    ) external view returns (uint256 totalPrice, bytes32[] memory pricingData);

    /**
     * Returns the information relative to a SKU.
     * @dev WARNING: it is the responsibility of the implementer to ensure that the
     *  number of payment tokens is bounded, so that this function does not run out of gas.
     * @dev Reverts if `sku` does not exist.
     * @param sku The SKU identifier.
     * @return totalSupply The initial total supply for sale.
     * @return remainingSupply The remaining supply for sale.
     * @return maxQuantityPerPurchase The maximum allowed quantity for a single purchase.
     * @return notificationsReceiver The address of a contract on which to call the `onPurchaseNotificationReceived` function.
     * @return tokens The list of supported payment tokens.
     * @return prices The list of associated prices for each of the `tokens`.
     */
    function getSkuInfo(bytes32 sku)
        external
        view
        returns (
            uint256 totalSupply,
            uint256 remainingSupply,
            uint256 maxQuantityPerPurchase,
            address notificationsReceiver,
            address[] memory tokens,
            uint256[] memory prices
        );

    /**
     * Returns the list of created SKU identifiers.
     * @dev WARNING: it is the responsibility of the implementer to ensure that the
     *  number of SKUs is bounded, so that this function does not run out of gas.
     * @return skus the list of created SKU identifiers.
     */
    function getSkus() external view returns (bytes32[] memory skus);
}


// File @animoca/ethereum-contracts-sale-2.0.0/contracts/sale/interfaces/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * @title IPurchaseNotificationsReceiver
 * Interface for any contract that wants to support purchase notifications from a Sale contract.
 */
interface IPurchaseNotificationsReceiver {
    /**
     * Handles the receipt of a purchase notification.
     * @dev This function MUST return the function selector, otherwise the caller will revert the transaction.
     *  The selector to be returned can be obtained as `this.onPurchaseNotificationReceived.selector`
     * @dev This function MAY throw.
     * @param purchaser The purchaser of the purchase.
     * @param recipient The recipient of the purchase.
     * @param token The token to use as the payment currency.
     * @param sku The identifier of the SKU to purchase.
     * @param quantity The quantity to purchase.
     * @param userData Optional extra user input data.
     * @param totalPrice The total price paid.
     * @param pricingData Implementation-specific extra pricing data, such as details about discounts applied.
     * @param paymentData Implementation-specific extra payment data, such as conversion rates.
     * @param deliveryData Implementation-specific extra delivery data, such as purchase receipts.
     * @return `bytes4(keccak256(
     *  "onPurchaseNotificationReceived(address,address,address,bytes32,uint256,bytes,uint256,bytes32[],bytes32[],bytes32[])"))`
     */
    function onPurchaseNotificationReceived(
        address purchaser,
        address recipient,
        address token,
        bytes32 sku,
        uint256 quantity,
        bytes calldata userData,
        uint256 totalPrice,
        bytes32[] calldata pricingData,
        bytes32[] calldata paymentData,
        bytes32[] calldata deliveryData
    ) external returns (bytes4);
}


// File @animoca/ethereum-contracts-sale-2.0.0/contracts/sale/abstract/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * @title PurchaseLifeCycles
 * An abstract contract which define the life cycles for a purchase implementer.
 */
abstract contract PurchaseLifeCycles {
    /**
     * Wrapper for the purchase data passed as argument to the life cycle functions and down to their step functions.
     */
    struct PurchaseData {
        address payable purchaser;
        address payable recipient;
        address token;
        bytes32 sku;
        uint256 quantity;
        bytes userData;
        uint256 totalPrice;
        bytes32[] pricingData;
        bytes32[] paymentData;
        bytes32[] deliveryData;
    }

    /*                               Internal Life Cycle Functions                               */

    /**
     * `estimatePurchase` lifecycle.
     * @param purchase The purchase conditions.
     */
    function _estimatePurchase(PurchaseData memory purchase) internal view virtual returns (uint256 totalPrice, bytes32[] memory pricingData) {
        _validation(purchase);
        _pricing(purchase);

        totalPrice = purchase.totalPrice;
        pricingData = purchase.pricingData;
    }

    /**
     * `purchaseFor` lifecycle.
     * @param purchase The purchase conditions.
     */
    function _purchaseFor(PurchaseData memory purchase) internal virtual {
        _validation(purchase);
        _pricing(purchase);
        _payment(purchase);
        _delivery(purchase);
        _notification(purchase);
    }

    /*                            Internal Life Cycle Step Functions                             */

    /**
     * Lifecycle step which validates the purchase pre-conditions.
     * @dev Responsibilities:
     *  - Ensure that the purchase pre-conditions are met and revert if not.
     * @param purchase The purchase conditions.
     */
    function _validation(PurchaseData memory purchase) internal view virtual;

    /**
     * Lifecycle step which computes the purchase price.
     * @dev Responsibilities:
     *  - Computes the pricing formula, including any discount logic and price conversion;
     *  - Set the value of `purchase.totalPrice`;
     *  - Add any relevant extra data related to pricing in `purchase.pricingData` and document how to interpret it.
     * @param purchase The purchase conditions.
     */
    function _pricing(PurchaseData memory purchase) internal view virtual;

    /**
     * Lifecycle step which manages the transfer of funds from the purchaser.
     * @dev Responsibilities:
     *  - Ensure the payment reaches destination in the expected output token;
     *  - Handle any token swap logic;
     *  - Add any relevant extra data related to payment in `purchase.paymentData` and document how to interpret it.
     * @param purchase The purchase conditions.
     */
    function _payment(PurchaseData memory purchase) internal virtual;

    /**
     * Lifecycle step which delivers the purchased SKUs to the recipient.
     * @dev Responsibilities:
     *  - Ensure the product is delivered to the recipient, if that is the contract's responsibility.
     *  - Handle any internal logic related to the delivery, including the remaining supply update;
     *  - Add any relevant extra data related to delivery in `purchase.deliveryData` and document how to interpret it.
     * @param purchase The purchase conditions.
     */
    function _delivery(PurchaseData memory purchase) internal virtual;

    /**
     * Lifecycle step which notifies of the purchase.
     * @dev Responsibilities:
     *  - Manage after-purchase event(s) emission.
     *  - Handle calls to the notifications receiver contract's `onPurchaseNotificationReceived` function, if applicable.
     * @param purchase The purchase conditions.
     */
    function _notification(PurchaseData memory purchase) internal virtual;
}


// File @animoca/ethereum-contracts-sale-2.0.0/contracts/sale/abstract/[email protected]

pragma solidity >=0.7.6 <0.8.0;










/**
 * @title Sale
 * An abstract base sale contract with a minimal implementation of ISale and administration functions.
 *  A minimal implementation of the `_validation`, `_delivery` and `notification` life cycle step functions
 *  are provided, but the inheriting contract must implement `_pricing` and `_payment`.
 */
abstract contract Sale is PurchaseLifeCycles, ISale, PayoutWallet, Startable, Pausable {
    using AddressIsContract for address;
    using SafeMath for uint256;
    using EnumSet for EnumSet.Set;
    using EnumMap for EnumMap.Map;

    struct SkuInfo {
        uint256 totalSupply;
        uint256 remainingSupply;
        uint256 maxQuantityPerPurchase;
        address notificationsReceiver;
        EnumMap.Map prices;
    }

    address public constant override TOKEN_ETH = address(0x00eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee);
    uint256 public constant override SUPPLY_UNLIMITED = type(uint256).max;

    EnumSet.Set internal _skus;
    mapping(bytes32 => SkuInfo) internal _skuInfos;

    uint256 internal immutable _skusCapacity;
    uint256 internal immutable _tokensPerSkuCapacity;

    /**
     * Constructor.
     * @dev Emits the `MagicValues` event.
     * @dev Emits the `Paused` event.
     * @param payoutWallet_ the payout wallet.
     * @param skusCapacity the cap for the number of managed SKUs.
     * @param tokensPerSkuCapacity the cap for the number of tokens managed per SKU.
     */
    constructor(
        address payable payoutWallet_,
        uint256 skusCapacity,
        uint256 tokensPerSkuCapacity
    ) PayoutWallet(msg.sender, payoutWallet_) Pausable(true) {
        _skusCapacity = skusCapacity;
        _tokensPerSkuCapacity = tokensPerSkuCapacity;
        bytes32[] memory names = new bytes32[](2);
        bytes32[] memory values = new bytes32[](2);
        (names[0], values[0]) = ("TOKEN_ETH", bytes32(uint256(TOKEN_ETH)));
        (names[1], values[1]) = ("SUPPLY_UNLIMITED", bytes32(uint256(SUPPLY_UNLIMITED)));
        emit MagicValues(names, values);
    }

    /*                                   Public Admin Functions                                  */

    /**
     * Actvates, or 'starts', the contract.
     * @dev Emits the `Started` event.
     * @dev Emits the `Unpaused` event.
     * @dev Reverts if called by any other than the contract owner.
     * @dev Reverts if the contract has already been started.
     * @dev Reverts if the contract is not paused.
     */
    function start() public virtual {
        _requireOwnership(_msgSender());
        _start();
        _unpause();
    }

    /**
     * Pauses the contract.
     * @dev Emits the `Paused` event.
     * @dev Reverts if called by any other than the contract owner.
     * @dev Reverts if the contract has not been started yet.
     * @dev Reverts if the contract is already paused.
     */
    function pause() public virtual whenStarted {
        _requireOwnership(_msgSender());
        _pause();
    }

    /**
     * Resumes the contract.
     * @dev Emits the `Unpaused` event.
     * @dev Reverts if called by any other than the contract owner.
     * @dev Reverts if the contract has not been started yet.
     * @dev Reverts if the contract is not paused.
     */
    function unpause() public virtual whenStarted {
        _requireOwnership(_msgSender());
        _unpause();
    }

    /**
     * Sets the token prices for the specified product SKU.
     * @dev Reverts if called by any other than the contract owner.
     * @dev Reverts if `tokens` and `prices` have different lengths.
     * @dev Reverts if `sku` does not exist.
     * @dev Reverts if one of the `tokens` is the zero address.
     * @dev Reverts if the update results in too many tokens for the SKU.
     * @dev Emits the `SkuPricingUpdate` event.
     * @param sku The identifier of the SKU.
     * @param tokens The list of payment tokens to update.
     *  If empty, disable all the existing payment tokens.
     * @param prices The list of prices to apply for each payment token.
     *  Zero price values are used to disable a payment token.
     */
    function updateSkuPricing(
        bytes32 sku,
        address[] memory tokens,
        uint256[] memory prices
    ) public virtual {
        _requireOwnership(_msgSender());
        uint256 length = tokens.length;
        require(length == prices.length, "Sale: inconsistent arrays");
        SkuInfo storage skuInfo = _skuInfos[sku];
        require(skuInfo.totalSupply != 0, "Sale: non-existent sku");

        EnumMap.Map storage tokenPrices = skuInfo.prices;
        if (length == 0) {
            uint256 currentLength = tokenPrices.length();
            for (uint256 i = 0; i < currentLength; ++i) {
                // TODO add a clear function in EnumMap and EnumSet and use it
                (bytes32 token, ) = tokenPrices.at(0);
                tokenPrices.remove(token);
            }
        } else {
            _setTokenPrices(tokenPrices, tokens, prices);
        }

        emit SkuPricingUpdate(sku, tokens, prices);
    }

    /*                                   ISale Public Functions                                  */

    /**
     * Performs a purchase.
     * @dev Reverts if the sale has not started.
     * @dev Reverts if the sale is paused.
     * @dev Reverts if `recipient` is the zero address.
     * @dev Reverts if `token` is the zero address.
     * @dev Reverts if `quantity` is zero.
     * @dev Reverts if `quantity` is greater than the maximum purchase quantity.
     * @dev Reverts if `quantity` is greater than the remaining supply.
     * @dev Reverts if `sku` does not exist.
     * @dev Reverts if `sku` exists but does not have a price set for `token`.
     * @dev Emits the Purchase event.
     * @param recipient The recipient of the purchase.
     * @param token The token to use as the payment currency.
     * @param sku The identifier of the SKU to purchase.
     * @param quantity The quantity to purchase.
     * @param userData Optional extra user input data.
     */
    function purchaseFor(
        address payable recipient,
        address token,
        bytes32 sku,
        uint256 quantity,
        bytes calldata userData
    ) external payable virtual override whenStarted {
        _requireNotPaused();
        PurchaseData memory purchase;
        purchase.purchaser = _msgSender();
        purchase.recipient = recipient;
        purchase.token = token;
        purchase.sku = sku;
        purchase.quantity = quantity;
        purchase.userData = userData;

        _purchaseFor(purchase);
    }

    /**
     * Estimates the computed final total amount to pay for a purchase, including any potential discount.
     * @dev This function MUST compute the same price as `purchaseFor` would in identical conditions (same arguments, same point in time).
     * @dev If an implementer contract uses the `pricingData` field, it SHOULD document how to interpret the values.
     * @dev Reverts if the sale has not started.
     * @dev Reverts if the sale is paused.
     * @dev Reverts if `recipient` is the zero address.
     * @dev Reverts if `token` is the zero address.
     * @dev Reverts if `quantity` is zero.
     * @dev Reverts if `quantity` is greater than the maximum purchase quantity.
     * @dev Reverts if `quantity` is greater than the remaining supply.
     * @dev Reverts if `sku` does not exist.
     * @dev Reverts if `sku` exists but does not have a price set for `token`.
     * @param recipient The recipient of the purchase used to calculate the total price amount.
     * @param token The payment token used to calculate the total price amount.
     * @param sku The identifier of the SKU used to calculate the total price amount.
     * @param quantity The quantity used to calculate the total price amount.
     * @param userData Optional extra user input data.
     * @return totalPrice The computed total price.
     * @return pricingData Implementation-specific extra pricing data, such as details about discounts applied.
     *  If not empty, the implementer MUST document how to interepret the values.
     */
    function estimatePurchase(
        address payable recipient,
        address token,
        bytes32 sku,
        uint256 quantity,
        bytes calldata userData
    ) external view virtual override whenStarted returns (uint256 totalPrice, bytes32[] memory pricingData) {
        _requireNotPaused();
        PurchaseData memory purchase;
        purchase.purchaser = _msgSender();
        purchase.recipient = recipient;
        purchase.token = token;
        purchase.sku = sku;
        purchase.quantity = quantity;
        purchase.userData = userData;

        return _estimatePurchase(purchase);
    }

    /**
     * Returns the information relative to a SKU.
     * @dev WARNING: it is the responsibility of the implementer to ensure that the
     * number of payment tokens is bounded, so that this function does not run out of gas.
     * @dev Reverts if `sku` does not exist.
     * @param sku The SKU identifier.
     * @return totalSupply The initial total supply for sale.
     * @return remainingSupply The remaining supply for sale.
     * @return maxQuantityPerPurchase The maximum allowed quantity for a single purchase.
     * @return notificationsReceiver The address of a contract on which to call the `onPurchaseNotificationReceived` function.
     * @return tokens The list of supported payment tokens.
     * @return prices The list of associated prices for each of the `tokens`.
     */
    function getSkuInfo(bytes32 sku)
        external
        view
        override
        returns (
            uint256 totalSupply,
            uint256 remainingSupply,
            uint256 maxQuantityPerPurchase,
            address notificationsReceiver,
            address[] memory tokens,
            uint256[] memory prices
        )
    {
        SkuInfo storage skuInfo = _skuInfos[sku];
        uint256 length = skuInfo.prices.length();

        totalSupply = skuInfo.totalSupply;
        require(totalSupply != 0, "Sale: non-existent sku");
        remainingSupply = skuInfo.remainingSupply;
        maxQuantityPerPurchase = skuInfo.maxQuantityPerPurchase;
        notificationsReceiver = skuInfo.notificationsReceiver;

        tokens = new address[](length);
        prices = new uint256[](length);
        for (uint256 i = 0; i < length; ++i) {
            (bytes32 token, bytes32 price) = skuInfo.prices.at(i);
            tokens[i] = address(uint256(token));
            prices[i] = uint256(price);
        }
    }

    /**
     * Returns the list of created SKU identifiers.
     * @return skus the list of created SKU identifiers.
     */
    function getSkus() external view override returns (bytes32[] memory skus) {
        skus = _skus.values;
    }

    /*                               Internal Utility Functions                                  */

    /**
     * Creates an SKU.
     * @dev Reverts if `totalSupply` is zero.
     * @dev Reverts if `sku` already exists.
     * @dev Reverts if `notificationsReceiver` is not the zero address and is not a contract address.
     * @dev Reverts if the update results in too many SKUs.
     * @dev Emits the `SkuCreation` event.
     * @param sku the SKU identifier.
     * @param totalSupply the initial total supply.
     * @param maxQuantityPerPurchase The maximum allowed quantity for a single purchase.
     * @param notificationsReceiver The purchase notifications receiver contract address.
     *  If set to the zero address, the notification is not enabled.
     */
    function _createSku(
        bytes32 sku,
        uint256 totalSupply,
        uint256 maxQuantityPerPurchase,
        address notificationsReceiver
    ) internal virtual {
        require(totalSupply != 0, "Sale: zero supply");
        require(_skus.length() < _skusCapacity, "Sale: too many skus");
        require(_skus.add(sku), "Sale: sku already created");
        if (notificationsReceiver != address(0)) {
            require(notificationsReceiver.isContract(), "Sale: non-contract receiver");
        }
        SkuInfo storage skuInfo = _skuInfos[sku];
        skuInfo.totalSupply = totalSupply;
        skuInfo.remainingSupply = totalSupply;
        skuInfo.maxQuantityPerPurchase = maxQuantityPerPurchase;
        skuInfo.notificationsReceiver = notificationsReceiver;
        emit SkuCreation(sku, totalSupply, maxQuantityPerPurchase, notificationsReceiver);
    }

    /**
     * Updates SKU token prices.
     * @dev Reverts if one of the `tokens` is the zero address.
     * @dev Reverts if the update results in too many tokens for the SKU.
     * @param tokenPrices Storage pointer to a mapping of SKU token prices to update.
     * @param tokens The list of payment tokens to update.
     * @param prices The list of prices to apply for each payment token.
     *  Zero price values are used to disable a payment token.
     */
    function _setTokenPrices(
        EnumMap.Map storage tokenPrices,
        address[] memory tokens,
        uint256[] memory prices
    ) internal virtual {
        for (uint256 i = 0; i < tokens.length; ++i) {
            address token = tokens[i];
            require(token != address(0), "Sale: zero address token");
            uint256 price = prices[i];
            if (price == 0) {
                tokenPrices.remove(bytes32(uint256(token)));
            } else {
                tokenPrices.set(bytes32(uint256(token)), bytes32(price));
            }
        }
        require(tokenPrices.length() <= _tokensPerSkuCapacity, "Sale: too many tokens");
    }

    /*                            Internal Life Cycle Step Functions                             */

    /**
     * Lifecycle step which validates the purchase pre-conditions.
     * @dev Responsibilities:
     *  - Ensure that the purchase pre-conditions are met and revert if not.
     * @dev Reverts if `purchase.recipient` is the zero address.
     * @dev Reverts if `purchase.token` is the zero address.
     * @dev Reverts if `purchase.quantity` is zero.
     * @dev Reverts if `purchase.quantity` is greater than the SKU's `maxQuantityPerPurchase`.
     * @dev Reverts if `purchase.quantity` is greater than the available supply.
     * @dev Reverts if `purchase.sku` does not exist.
     * @dev Reverts if `purchase.sku` exists but does not have a price set for `purchase.token`.
     * @dev If this function is overriden, the implementer SHOULD super call this before.
     * @param purchase The purchase conditions.
     */
    function _validation(PurchaseData memory purchase) internal view virtual override {
        require(purchase.recipient != address(0), "Sale: zero address recipient");
        require(purchase.token != address(0), "Sale: zero address token");
        require(purchase.quantity != 0, "Sale: zero quantity purchase");
        SkuInfo storage skuInfo = _skuInfos[purchase.sku];
        require(skuInfo.totalSupply != 0, "Sale: non-existent sku");
        require(skuInfo.maxQuantityPerPurchase >= purchase.quantity, "Sale: above max quantity");
        if (skuInfo.totalSupply != SUPPLY_UNLIMITED) {
            require(skuInfo.remainingSupply >= purchase.quantity, "Sale: insufficient supply");
        }
        bytes32 priceKey = bytes32(uint256(purchase.token));
        require(skuInfo.prices.contains(priceKey), "Sale: non-existent sku token");
    }

    /**
     * Lifecycle step which delivers the purchased SKUs to the recipient.
     * @dev Responsibilities:
     *  - Ensure the product is delivered to the recipient, if that is the contract's responsibility.
     *  - Handle any internal logic related to the delivery, including the remaining supply update;
     *  - Add any relevant extra data related to delivery in `purchase.deliveryData` and document how to interpret it.
     * @dev Reverts if there is not enough available supply.
     * @dev If this function is overriden, the implementer SHOULD super call it.
     * @param purchase The purchase conditions.
     */
    function _delivery(PurchaseData memory purchase) internal virtual override {
        SkuInfo storage skuInfo = _skuInfos[purchase.sku];
        if (skuInfo.totalSupply != SUPPLY_UNLIMITED) {
            _skuInfos[purchase.sku].remainingSupply = skuInfo.remainingSupply.sub(purchase.quantity);
        }
    }

    /**
     * Lifecycle step which notifies of the purchase.
     * @dev Responsibilities:
     *  - Manage after-purchase event(s) emission.
     *  - Handle calls to the notifications receiver contract's `onPurchaseNotificationReceived` function, if applicable.
     * @dev Reverts if `onPurchaseNotificationReceived` throws or returns an incorrect value.
     * @dev Emits the `Purchase` event. The values of `purchaseData` are the concatenated values of `priceData`, `paymentData`
     * and `deliveryData`. If not empty, the implementer MUST document how to interpret these values.
     * @dev If this function is overriden, the implementer SHOULD super call it.
     * @param purchase The purchase conditions.
     */
    function _notification(PurchaseData memory purchase) internal virtual override {
        emit Purchase(
            purchase.purchaser,
            purchase.recipient,
            purchase.token,
            purchase.sku,
            purchase.quantity,
            purchase.userData,
            purchase.totalPrice,
            abi.encodePacked(purchase.pricingData, purchase.paymentData, purchase.deliveryData)
        );

        address notificationsReceiver = _skuInfos[purchase.sku].notificationsReceiver;
        if (notificationsReceiver != address(0)) {
            require(
                IPurchaseNotificationsReceiver(notificationsReceiver).onPurchaseNotificationReceived(
                    purchase.purchaser,
                    purchase.recipient,
                    purchase.token,
                    purchase.sku,
                    purchase.quantity,
                    purchase.userData,
                    purchase.totalPrice,
                    purchase.pricingData,
                    purchase.paymentData,
                    purchase.deliveryData
                ) == IPurchaseNotificationsReceiver(address(0)).onPurchaseNotificationReceived.selector, // TODO precompute return value
                "Sale: notification refused"
            );
        }
    }
}


// File @animoca/ethereum-contracts-sale-2.0.0/contracts/sale/[email protected]

pragma solidity >=0.7.6 <0.8.0;


/**
 * @title FixedPricesSale
 * An Sale which implements a fixed prices strategy.
 *  The final implementer is responsible for implementing any additional pricing and/or delivery logic.
 */
abstract contract FixedPricesSale is Sale {
    using ERC20Wrapper for IWrappedERC20;
    using SafeMath for uint256;
    using EnumMap for EnumMap.Map;

    /**
     * Constructor.
     * @dev Emits the `MagicValues` event.
     * @dev Emits the `Paused` event.
     * @param payoutWallet_ the payout wallet.
     * @param skusCapacity the cap for the number of managed SKUs.
     * @param tokensPerSkuCapacity the cap for the number of tokens managed per SKU.
     */
    constructor(
        address payable payoutWallet_,
        uint256 skusCapacity,
        uint256 tokensPerSkuCapacity
    ) Sale(payoutWallet_, skusCapacity, tokensPerSkuCapacity) {}

    /*                               Internal Life Cycle Functions                               */

    /**
     * Lifecycle step which computes the purchase price.
     * @dev Responsibilities:
     *  - Computes the pricing formula, including any discount logic and price conversion;
     *  - Set the value of `purchase.totalPrice`;
     *  - Add any relevant extra data related to pricing in `purchase.pricingData` and document how to interpret it.
     * @dev Reverts if `purchase.sku` does not exist.
     * @dev Reverts if `purchase.token` is not supported by the SKU.
     * @dev Reverts in case of price overflow.
     * @param purchase The purchase conditions.
     */
    function _pricing(PurchaseData memory purchase) internal view virtual override {
        SkuInfo storage skuInfo = _skuInfos[purchase.sku];
        require(skuInfo.totalSupply != 0, "Sale: unsupported SKU");
        EnumMap.Map storage prices = skuInfo.prices;
        uint256 unitPrice = _unitPrice(purchase, prices);
        purchase.totalPrice = unitPrice.mul(purchase.quantity);
    }

    /**
     * Lifecycle step which manages the transfer of funds from the purchaser.
     * @dev Responsibilities:
     *  - Ensure the payment reaches destination in the expected output token;
     *  - Handle any token swap logic;
     *  - Add any relevant extra data related to payment in `purchase.paymentData` and document how to interpret it.
     * @dev Reverts in case of payment failure.
     * @param purchase The purchase conditions.
     */
    function _payment(PurchaseData memory purchase) internal virtual override {
        if (purchase.token == TOKEN_ETH) {
            require(msg.value >= purchase.totalPrice, "Sale: insufficient ETH");

            payoutWallet.transfer(purchase.totalPrice);

            uint256 change = msg.value.sub(purchase.totalPrice);

            if (change != 0) {
                purchase.purchaser.transfer(change);
            }
        } else {
            IWrappedERC20(purchase.token).wrappedTransferFrom(_msgSender(), payoutWallet, purchase.totalPrice);
        }
    }

    /*                               Internal Utility Functions                                  */

    /**
     * Retrieves the unit price of a SKU for the specified payment token.
     * @dev Reverts if the specified payment token is unsupported.
     * @param purchase The purchase conditions specifying the payment token with which the unit price will be retrieved.
     * @param prices Storage pointer to a mapping of SKU token prices to retrieve the unit price from.
     * @return unitPrice The unit price of a SKU for the specified payment token.
     */
    function _unitPrice(PurchaseData memory purchase, EnumMap.Map storage prices) internal view virtual returns (uint256 unitPrice) {
        unitPrice = uint256(prices.get(bytes32(uint256(purchase.token))));
        require(unitPrice != 0, "Sale: unsupported payment token");
    }
}


// File @animoca/ethereum-contracts-core-1.1.2/contracts/utils/[email protected]

pragma solidity >=0.7.6 <0.8.0;



abstract contract Recoverable is ManagedIdentity, Ownable {
    using ERC20Wrapper for IWrappedERC20;

    /**
     * Extract ERC20 tokens which were accidentally sent to the contract to a list of accounts.
     * Warning: this function should be overriden for contracts which are supposed to hold ERC20 tokens
     * so that the extraction is limited to only amounts sent accidentally.
     * @dev Reverts if the sender is not the contract owner.
     * @dev Reverts if `accounts`, `tokens` and `amounts` do not have the same length.
     * @dev Reverts if one of `tokens` is does not implement the ERC20 transfer function.
     * @dev Reverts if one of the ERC20 transfers fail for any reason.
     * @param accounts the list of accounts to transfer the tokens to.
     * @param tokens the list of ERC20 token addresses.
     * @param amounts the list of token amounts to transfer.
     */
    function recoverERC20s(
        address[] calldata accounts,
        address[] calldata tokens,
        uint256[] calldata amounts
    ) external virtual {
        _requireOwnership(_msgSender());
        uint256 length = accounts.length;
        require(length == tokens.length && length == amounts.length, "Recov: inconsistent arrays");
        for (uint256 i = 0; i != length; ++i) {
            IWrappedERC20(tokens[i]).wrappedTransfer(accounts[i], amounts[i]);
        }
    }

    /**
     * Extract ERC721 tokens which were accidentally sent to the contract to a list of accounts.
     * Warning: this function should be overriden for contracts which are supposed to hold ERC721 tokens
     * so that the extraction is limited to only tokens sent accidentally.
     * @dev Reverts if the sender is not the contract owner.
     * @dev Reverts if `accounts`, `contracts` and `amounts` do not have the same length.
     * @dev Reverts if one of `contracts` is does not implement the ERC721 transferFrom function.
     * @dev Reverts if one of the ERC721 transfers fail for any reason.
     * @param accounts the list of accounts to transfer the tokens to.
     * @param contracts the list of ERC721 contract addresses.
     * @param tokenIds the list of token ids to transfer.
     */
    function recoverERC721s(
        address[] calldata accounts,
        address[] calldata contracts,
        uint256[] calldata tokenIds
    ) external virtual {
        _requireOwnership(_msgSender());
        uint256 length = accounts.length;
        require(length == contracts.length && length == tokenIds.length, "Recov: inconsistent arrays");
        for (uint256 i = 0; i != length; ++i) {
            IRecoverableERC721(contracts[i]).transferFrom(address(this), accounts[i], tokenIds[i]);
        }
    }
}

interface IRecoverableERC721 {
    /// See {IERC721-transferFrom(address,address,uint256)}
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;
}


// File contracts/sale/TokenLaunchpadVoucherPacksSale.sol

pragma solidity >=0.7.6 <0.8.0;


/**
 * @title TokenLaunchpad Vouchers Sale
 * A FixedPricesSale contract that handles the purchase and delivery of TokenLaunchpad vouchers.
 */
contract TokenLaunchpadVoucherPacksSale is FixedPricesSale, Recoverable {
    IVouchersContract public immutable vouchersContract;

    struct SkuAdditionalInfo {
        uint256[] tokenIds;
        uint256 startTimestamp;
        uint256 endTimestamp;
    }

    mapping(bytes32 => SkuAdditionalInfo) internal _skuAdditionalInfo;

    /**
     * Constructor.
     * @dev Emits the `MagicValues` event.
     * @dev Emits the `Paused` event.
     * @param vouchersContract_ The inventory contract from which the sale supply is attributed from.
     * @param payoutWallet the payout wallet.
     * @param skusCapacity the cap for the number of managed SKUs.
     * @param tokensPerSkuCapacity the cap for the number of tokens managed per SKU.
     */
    constructor(
        IVouchersContract vouchersContract_,
        address payable payoutWallet,
        uint256 skusCapacity,
        uint256 tokensPerSkuCapacity
    ) FixedPricesSale(payoutWallet, skusCapacity, tokensPerSkuCapacity) {
        vouchersContract = vouchersContract_;
    }

    /**
     * Creates an SKU.
     * @dev Reverts if `totalSupply` is zero.
     * @dev Reverts if `sku` already exists.
     * @dev Reverts if the update results in too many SKUs.
     * @dev Reverts if one of `tokenIds` is not a fungible token identifier.
     * @dev Emits the `SkuCreation` event.
     * @param sku The SKU identifier.
     * @param totalSupply The initial total supply.
     * @param maxQuantityPerPurchase The maximum allowed quantity for a single purchase.
     * @param tokenIds The inventory contract token IDs to associate with the SKU, used for purchase delivery.
     * @param startTimestamp The start timestamp of the sale.
     * @param endTimestamp The end timestamp of the sale, or zero to indicate there is no end.
     */
    function createSku(
        bytes32 sku,
        uint256 totalSupply,
        uint256 maxQuantityPerPurchase,
        uint256[] calldata tokenIds,
        uint256 startTimestamp,
        uint256 endTimestamp
    ) external {
        _requireOwnership(_msgSender());
        uint256 length = tokenIds.length;
        require(length != 0, "Sale: empty tokens");
        for (uint256 i; i != length; ++i) {
            require(vouchersContract.isFungible(tokenIds[i]), "Sale: not a fungible token");
        }
        _skuAdditionalInfo[sku] = SkuAdditionalInfo(tokenIds, startTimestamp, endTimestamp);
        _createSku(sku, totalSupply, maxQuantityPerPurchase, address(0));
    }

    /**
     * Updates start and end timestamps of a SKU.
     * @dev Reverts if not sent by the contract owner.
     * @dev Reverts if the SKU does not exist.
     * @param sku the SKU identifier.
     * @param startTimestamp The start timestamp of the sale.
     * @param endTimestamp The end timestamp of the sale, or zero to indicate there is no end.
     */
    function updateSkuTimestamps(
        bytes32 sku,
        uint256 startTimestamp,
        uint256 endTimestamp
    ) external {
        _requireOwnership(_msgSender());
        require(_skuInfos[sku].totalSupply != 0, "Sale: non-existent sku");
        SkuAdditionalInfo storage info = _skuAdditionalInfo[sku];
        info.startTimestamp = startTimestamp;
        info.endTimestamp = endTimestamp;
    }

    /**
     * Gets the additional sku info.
     * @dev Reverts if the SKU does not exist.
     * @param sku the SKU identifier.
     * @return tokenIds The identifiers of the tokens delivered via this SKU.
     * @return startTimestamp The start timestamp of the SKU sale.
     * @return endTimestamp The end timestamp of the SKU sale (zero if there is no end).
     */
    function getSkuAdditionalInfo(bytes32 sku)
        external
        view
        returns (
            uint256[] memory tokenIds,
            uint256 startTimestamp,
            uint256 endTimestamp
        )
    {
        require(_skuInfos[sku].totalSupply != 0, "Sale: non-existent sku");
        SkuAdditionalInfo memory info = _skuAdditionalInfo[sku];
        return (info.tokenIds, info.startTimestamp, info.endTimestamp);
    }

    /**
     * Returns whether a SKU is currently within the sale time range.
     * @dev Reverts if the SKU does not exist.
     * @param sku the SKU identifier.
     * @return true if `sku` is currently within the sale time range, false otherwise.
     */
    function canPurchaseSku(bytes32 sku) external view returns (bool) {
        require(_skuInfos[sku].totalSupply != 0, "Sale: non-existent sku");
        SkuAdditionalInfo memory info = _skuAdditionalInfo[sku];
        return block.timestamp > info.startTimestamp && (info.endTimestamp == 0 || block.timestamp < info.endTimestamp);
    }

    /// @inheritdoc Sale
    function _delivery(PurchaseData memory purchase) internal override {
        super._delivery(purchase);
        SkuAdditionalInfo memory info = _skuAdditionalInfo[purchase.sku];
        uint256 startTimestamp = info.startTimestamp;
        uint256 endTimestamp = info.endTimestamp;
        require(block.timestamp > startTimestamp, "Sale: not started yet");
        require(endTimestamp == 0 || block.timestamp < endTimestamp, "Sale: already ended");

        uint256 length = info.tokenIds.length;
        if (length == 1) {
            vouchersContract.safeMint(purchase.recipient, info.tokenIds[0], purchase.quantity, "");
        } else {
            uint256 purchaseQuantity = purchase.quantity;
            uint256[] memory quantities = new uint256[](length);
            for (uint256 i; i != length; ++i) {
                quantities[i] = purchaseQuantity;
            }
            vouchersContract.safeBatchMint(purchase.recipient, info.tokenIds, quantities, "");
        }
    }
}

interface IVouchersContract {
    function isFungible(uint256 id) external pure returns (bool);

    function safeMint(
        address to,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external;

    function safeBatchMint(
        address to,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external;
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IVouchersContract","name":"vouchersContract_","type":"address"},{"internalType":"address payable","name":"payoutWallet","type":"address"},{"internalType":"uint256","name":"skusCapacity","type":"uint256"},{"internalType":"uint256","name":"tokensPerSkuCapacity","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32[]","name":"names","type":"bytes32[]"},{"indexed":false,"internalType":"bytes32[]","name":"values","type":"bytes32[]"}],"name":"MagicValues","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"payoutWallet_","type":"address"}],"name":"PayoutWalletSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"purchaser","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bytes32","name":"sku","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"userData","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"totalPrice","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extData","type":"bytes"}],"name":"Purchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"sku","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxQuantityPerPurchase","type":"uint256"},{"indexed":false,"internalType":"address","name":"notificationsReceiver","type":"address"}],"name":"SkuCreation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"sku","type":"bytes32"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"prices","type":"uint256[]"}],"name":"SkuPricingUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Started","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"SUPPLY_UNLIMITED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_ETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sku","type":"bytes32"}],"name":"canPurchaseSku","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sku","type":"bytes32"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerPurchase","type":"uint256"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"name":"createSku","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"sku","type":"bytes32"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"estimatePurchase","outputs":[{"internalType":"uint256","name":"totalPrice","type":"uint256"},{"internalType":"bytes32[]","name":"pricingData","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sku","type":"bytes32"}],"name":"getSkuAdditionalInfo","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sku","type":"bytes32"}],"name":"getSkuInfo","outputs":[{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"remainingSupply","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerPurchase","type":"uint256"},{"internalType":"address","name":"notificationsReceiver","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"prices","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSkus","outputs":[{"internalType":"bytes32[]","name":"skus","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payoutWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"sku","type":"bytes32"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"purchaseFor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"recoverERC20s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"recoverERC721s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"payoutWallet_","type":"address"}],"name":"setPayoutWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"start","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sku","type":"bytes32"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"prices","type":"uint256[]"}],"name":"updateSkuPricing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sku","type":"bytes32"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"name":"updateSkuTimestamps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vouchersContract","outputs":[{"internalType":"contract IVouchersContract","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60e06040523480156200001157600080fd5b50604051620039e2380380620039e2833981810160405260808110156200003757600080fd5b5080516020820151604080840151606090940151600080546001600160a01b031916339081178255925194959394919285928592859285928592859260019290918691839182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b03811662000100576040805162461bcd60e51b815260206004820152601460248201527f5061796f75743a207a65726f2061646472657373000000000000000000000000604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fdd880d24a789958a6398c99c2e54ce31bc10a638cbc42f7dd34285479ae0f8559181900360200190a150506003805460ff1916911515919091179055608082905260a081905260408051600280825260608201835260009260208301908036833750506040805160028082526060820183529394506000939092509060208301908036833750508351919250680a89e968a9cbe8aa8960bb1b9173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee91508490600090620001e557fe5b6020026020010183600081518110620001fa57fe5b602002602001018281525082815250505060001960001b6f14d55414131657d5539312535255115160821b90836001815181106200023457fe5b60200260200101836001815181106200024957fe5b60200260200101828152508281525050507fabb92614f53337043b55dc996a83ebb09adce78ec336ca188ea02180b61d1c148282604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015620002c3578181015183820152602001620002a9565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101562000304578181015183820152602001620002ea565b5050505090500194505050505060405180910390a15050506001600160601b031960609990991b9890981660c052505050505050505060805160a05160c05160601c6136696200037960003980610c4352806110e85280612b3b5280612c7e525080612012525080611b7952506136696000f3fe6080604052600436106101805760003560e01c8063717838f4116100d65780639e0495451161007f578063c3666c3611610059578063c3666c3614610976578063f21f537d14610a97578063f2fde38b14610aac57610180565b80639e049545146108a5578063a963b257146108cc578063be9a65551461096157610180565b80638488bb4e116100b05780638488bb4e146108515780638be262ba146108665780638da5cb5b1461089057610180565b8063717838f4146106e557806373c8a9581461071b5780638456cb591461083c57610180565b8063474f2891116101385780635e6e9f70116101125780635e6e9f701461051257806361bd38511461064d5780636b8f9c43146106b257610180565b8063474f2891146104a35780635c4fafc7146104d45780635c975abb146104e957610180565b80632a8a45bc116101695780632a8a45bc1461031a5780632e890782146104025780633f4ba83a1461048e57610180565b80631323b06614610185578063298f53f714610282575b600080fd5b34801561019157600080fd5b50610227600480360360a08110156101a857600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156101e857600080fd5b8201836020820111156101fa57600080fd5b8035906020019184600183028401116401000000008311171561021c57600080fd5b509092509050610adf565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561026d578181015183820152602001610255565b50505050905001935050505060405180910390f35b34801561028e57600080fd5b50610318600480360360c08110156102a557600080fd5b813591602081013591604082013591908101906080810160608201356401000000008111156102d357600080fd5b8201836020820111156102e557600080fd5b8035906020019184602083028401116401000000008311171561030757600080fd5b919350915080359060200135610bd4565b005b34801561032657600080fd5b506103446004803603602081101561033d57600080fd5b5035610dda565b60405180878152602001868152602001858152602001846001600160a01b031681526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156103a9578181015183820152602001610391565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156103e85781810151838201526020016103d0565b505050509050019850505050505050505060405180910390f35b34801561040e57600080fd5b5061042c6004803603602081101561042557600080fd5b5035610f7f565b6040518080602001848152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015610478578181015183820152602001610460565b5050505090500194505050505060405180910390f35b34801561049a57600080fd5b5061031861107d565b3480156104af57600080fd5b506104b86110e6565b604080516001600160a01b039092168252519081900360200190f35b3480156104e057600080fd5b506104b861110a565b3480156104f557600080fd5b506104fe611122565b604080519115158252519081900360200190f35b34801561051e57600080fd5b506103186004803603606081101561053557600080fd5b8135919081019060408101602082013564010000000081111561055757600080fd5b82018360208201111561056957600080fd5b8035906020019184602083028401116401000000008311171561058b57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092959493602081019350359150506401000000008111156105db57600080fd5b8201836020820111156105ed57600080fd5b8035906020019184602083028401116401000000008311171561060f57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061112b945050505050565b34801561065957600080fd5b50610662611308565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561069e578181015183820152602001610686565b505050509050019250505060405180910390f35b3480156106be57600080fd5b50610318600480360360208110156106d557600080fd5b50356001600160a01b0316611363565b3480156106f157600080fd5b506103186004803603606081101561070857600080fd5b5080359060208101359060400135611430565b34801561072757600080fd5b506103186004803603606081101561073e57600080fd5b81019060208101813564010000000081111561075957600080fd5b82018360208201111561076b57600080fd5b8035906020019184602083028401116401000000008311171561078d57600080fd5b9193909290916020810190356401000000008111156107ab57600080fd5b8201836020820111156107bd57600080fd5b803590602001918460208302840111640100000000831117156107df57600080fd5b9193909290916020810190356401000000008111156107fd57600080fd5b82018360208201111561080f57600080fd5b8035906020019184602083028401116401000000008311171561083157600080fd5b5090925090506114b8565b34801561084857600080fd5b5061031861159b565b34801561085d57600080fd5b506104b8611602565b34801561087257600080fd5b506104fe6004803603602081101561088957600080fd5b5035611611565b34801561089c57600080fd5b506104b8611719565b3480156108b157600080fd5b506108ba611728565b60408051918252519081900360200190f35b610318600480360360a08110156108e257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a08101608082013564010000000081111561092257600080fd5b82018360208201111561093457600080fd5b8035906020019184600183028401116401000000008311171561095657600080fd5b50909250905061172e565b34801561096d57600080fd5b50610318611814565b34801561098257600080fd5b506103186004803603606081101561099957600080fd5b8101906020810181356401000000008111156109b457600080fd5b8201836020820111156109c657600080fd5b803590602001918460208302840111640100000000831117156109e857600080fd5b919390929091602081019035640100000000811115610a0657600080fd5b820183602082011115610a1857600080fd5b80359060200191846020830284011164010000000083111715610a3a57600080fd5b919390929091602081019035640100000000811115610a5857600080fd5b820183602082011115610a6a57600080fd5b80359060200191846020830284011164010000000083111715610a8c57600080fd5b509092509050611827565b348015610aa357600080fd5b506108ba61196f565b348015610ab857600080fd5b5061031860048036036020811015610acf57600080fd5b50356001600160a01b0316611975565b6000606060025460001415610b3b576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b610b436119db565b610b4b613541565b610b53611a33565b6001600160a01b03908116825289811660208084019190915290891660408084019190915260608301899052608083018890528051601f870183900483028101830190915285815290869086908190840183828082843760009201919091525050505060a0820152610bc481611a37565b9250925050965096945050505050565b610be4610bdf611a33565b611a5e565b8280610c37576040805162461bcd60e51b815260206004820152601260248201527f53616c653a20656d70747920746f6b656e730000000000000000000000000000604482015290519081900360640190fd5b60005b818114610d3c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663adebf6f2878784818110610c7c57fe5b905060200201356040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610cb757600080fd5b505afa158015610ccb573d6000803e3d6000fd5b505050506040513d6020811015610ce157600080fd5b5051610d34576040805162461bcd60e51b815260206004820152601a60248201527f53616c653a206e6f7420612066756e6769626c6520746f6b656e000000000000604482015290519081900360640190fd5b600101610c3a565b5060405180606001604052808686808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250938552505050602080830187905260409283018690528b825260078152919020825180519192610dac928492909101906135b2565b5060208201516001820155604090910151600290910155610dd08888886000611b25565b5050505050505050565b6000818152600660205260408120819081908190606090819083610e0060048301611d5c565b82549850905087610e58576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b60018201546002830154600384015491985096506001600160a01b031694508067ffffffffffffffff81118015610e8e57600080fd5b50604051908082528060200260200182016040528015610eb8578160200160208202803683370190505b5093508067ffffffffffffffff81118015610ed257600080fd5b50604051908082528060200260200182016040528015610efc578160200160208202803683370190505b50925060005b81811015610f7357600080610f1a6004860184611d60565b915091508160001c878481518110610f2e57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508060001c868481518110610f5e57fe5b60209081029190910101525050600101610f02565b50505091939550919395565b600081815260066020526040812054606091908190610fe5576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b6000848152600760209081526040808320815181546080948102820185019093526060810183815290939192849284919084018282801561104557602002820191906000526020600020905b815481526020019060010190808311611031575b505050918352505060018201546020808301919091526002909201546040918201528251918301519201519097919650945092505050565b6002546110d1576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b6110dc610bdf611a33565b6110e4611df1565b565b7f000000000000000000000000000000000000000000000000000000000000000081565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b60035460ff1681565b611136610bdf611a33565b81518151811461118d576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20696e636f6e73697374656e742061727261797300000000000000604482015290519081900360640190fd5b600084815260066020526040902080546111ee576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b600481018261123957600061120282611d5c565b905060005b8181101561123257600061121b8482611d60565b5090506112288482611e49565b5050600101611207565b5050611244565b611244818686611f29565b857fcb3fe5489e0cd43d0f4a33d1e09a4a0463a03d0d38f56165530854e5540db1438686604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156112ac578181015183820152602001611294565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156112eb5781810151838201526020016112d3565b5050505090500194505050505060405180910390a2505050505050565b6060600460000180548060200260200160405190810160405280929190818152602001828054801561135957602002820191906000526020600020905b815481526020019060010190808311611345575b5050505050905090565b61136e610bdf611a33565b6001600160a01b0381166113c9576040805162461bcd60e51b815260206004820152601460248201527f5061796f75743a207a65726f2061646472657373000000000000000000000000604482015290519081900360640190fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03838116919091179182905560408051929091168252517fdd880d24a789958a6398c99c2e54ce31bc10a638cbc42f7dd34285479ae0f855916020908290030190a150565b61143b610bdf611a33565b60008381526006602052604090205461149b576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b600092835260076020526040909220600181019190915560020155565b6114c3610bdf611a33565b8483811480156114d257508082145b611523576040805162461bcd60e51b815260206004820152601a60248201527f5265636f763a20696e636f6e73697374656e7420617272617973000000000000604482015290519081900360640190fd5b60005b818114610dd05761159388888381811061153c57fe5b905060200201356001600160a01b031685858481811061155857fe5b9050602002013588888581811061156b57fe5b905060200201356001600160a01b03166001600160a01b03166120929092919063ffffffff16565b600101611526565b6002546115ef576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b6115fa610bdf611a33565b6110e4612112565b6001546001600160a01b031681565b600081815260066020526040812054611671576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b600082815260076020908152604080832081518154608094810282018501909352606081018381529093919284928491908401828280156116d157602002820191906000526020600020905b8154815260200190600101908083116116bd575b505050505081526020016001820154815260200160028201548152505090508060200151421180156117125750604081015115806117125750806040015142105b9392505050565b6000546001600160a01b031690565b60001981565b600254611782576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b61178a6119db565b611792613541565b61179a611a33565b6001600160a01b03908116825287811660208084019190915290871660408084019190915260608301879052608083018690528051601f850183900483028101830190915283815290849084908190840183828082843760009201919091525050505060a082015261180b81612150565b50505050505050565b61181f610bdf611a33565b6110dc61217d565b611832610bdf611a33565b84838114801561184157508082145b611892576040805162461bcd60e51b815260206004820152601a60248201527f5265636f763a20696e636f6e73697374656e7420617272617973000000000000604482015290519081900360640190fd5b60005b818114610dd0578585828181106118a857fe5b905060200201356001600160a01b03166001600160a01b03166323b872dd308a8a858181106118d357fe5b905060200201356001600160a01b03168787868181106118ef57fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561194c57600080fd5b505af1158015611960573d6000803e3d6000fd5b50505050806001019050611895565b60025490565b611980610bdf611a33565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821780845560405192939116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60035460ff16156110e4576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3390565b60006060611a44836121ff565b611a4d836124a9565b505060c081015160e0909101519091565b306001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a9757600080fd5b505afa158015611aab573d6000803e3d6000fd5b505050506040513d6020811015611ac157600080fd5b50516001600160a01b03828116911614611b22576040805162461bcd60e51b815260206004820152601660248201527f4f776e61626c653a206e6f7420746865206f776e657200000000000000000000604482015290519081900360640190fd5b50565b82611b77576040805162461bcd60e51b815260206004820152601160248201527f53616c653a207a65726f20737570706c79000000000000000000000000000000604482015290519081900360640190fd5b7f0000000000000000000000000000000000000000000000000000000000000000611ba26004611d5c565b10611bf4576040805162461bcd60e51b815260206004820152601360248201527f53616c653a20746f6f206d616e7920736b757300000000000000000000000000604482015290519081900360640190fd5b611bff600485612546565b611c50576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20736b7520616c7265616479206372656174656400000000000000604482015290519081900360640190fd5b6001600160a01b03811615611cc257611c71816001600160a01b0316612590565b611cc2576040805162461bcd60e51b815260206004820152601b60248201527f53616c653a206e6f6e2d636f6e74726163742072656365697665720000000000604482015290519081900360640190fd5b60008481526006602090815260409182902085815560018101869055600281018590556003810180546001600160a01b03861673ffffffffffffffffffffffffffffffffffffffff1990911681179091558351888152928301879052828401869052606083015291517f38bd4aabce684540cd61351b91f2f5facf9d6963934347e25aab93d87ae7ac149181900360800190a15050505050565b5490565b815460009081908310611dba576040805162461bcd60e51b815260206004820152601c60248201527f456e756d4d61703a20696e646578206f7574206f6620626f756e647300000000604482015290519081900360640190fd5b6000846000018481548110611dcb57fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b611df9612596565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611e2c611a33565b604080516001600160a01b039092168252519081900360200190a1565b60008181526001830160205260408120548015611f1d5783546000198083019190810190600090879083908110611e7c57fe5b9060005260206000209060020201905080876000018481548110611e9c57fe5b600091825260208083208454600290930201918255600193840154918401919091558354825289830190526040902090840190558654879080611edb57fe5b6000828152602080822060026000199094019384020182815560019081018390559290935588815289820190925260408220919091559450611f239350505050565b60009150505b92915050565b60005b825181101561200f576000838281518110611f4357fe5b6020026020010151905060006001600160a01b0316816001600160a01b03161415611fb5576040805162461bcd60e51b815260206004820152601860248201527f53616c653a207a65726f206164647265737320746f6b656e0000000000000000604482015290519081900360640190fd5b6000838381518110611fc357fe5b602002602001015190508060001415611fef57611fe9866001600160a01b038416611e49565b50612005565b612003866001600160a01b038416836125ed565b505b5050600101611f2c565b507f000000000000000000000000000000000000000000000000000000000000000061203a84611d5c565b111561208d576040805162461bcd60e51b815260206004820152601560248201527f53616c653a20746f6f206d616e7920746f6b656e730000000000000000000000604482015290519081900360640190fd5b505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261208d908490612686565b61211a6119db565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611e2c611a33565b612159816121ff565b612162816124a9565b61216b8161288e565b612174816129dd565b611b2281612db1565b600254156121d2576040805162461bcd60e51b815260206004820152601260248201527f537461727461626c653a20737461727465640000000000000000000000000000604482015290519081900360640190fd5b426002557f27029695aa5f602a4ee81f4c32dfa86e562f200a17966496f3a7c3f2ec0f9417611e2c611a33565b60208101516001600160a01b031661225e576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a207a65726f206164647265737320726563697069656e7400000000604482015290519081900360640190fd5b60408101516001600160a01b03166122bd576040805162461bcd60e51b815260206004820152601860248201527f53616c653a207a65726f206164647265737320746f6b656e0000000000000000604482015290519081900360640190fd5b6080810151612313576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a207a65726f207175616e7469747920707572636861736500000000604482015290519081900360640190fd5b606081015160009081526006602052604090208054612379576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b8160800151816002015410156123d6576040805162461bcd60e51b815260206004820152601860248201527f53616c653a2061626f7665206d6178207175616e746974790000000000000000604482015290519081900360640190fd5b80546000191461243d5781608001518160010154101561243d576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20696e73756666696369656e7420737570706c7900000000000000604482015290519081900360640190fd5b60408201516001600160a01b0316612458600483018261329a565b61208d576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a206e6f6e2d6578697374656e7420736b7520746f6b656e00000000604482015290519081900360640190fd5b60608101516000908152600660205260409020805461250f576040805162461bcd60e51b815260206004820152601560248201527f53616c653a20756e737570706f7274656420534b550000000000000000000000604482015290519081900360640190fd5b60048101600061251f84836132b2565b905061253884608001518261332290919063ffffffff16565b60c090940193909352505050565b6000612552838361329a565b61258857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611f23565b506000611f23565b3b151590565b60035460ff166110e4576040805162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b600082815260018401602052604081205480612652575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611712565b8285600001600183038154811061266557fe5b90600052602060002090600202016001018190555060009150509392505050565b816126996001600160a01b038216612590565b6126ea576040805162461bcd60e51b815260206004820152601a60248201527f4552433230577261707065723a206e6f6e2d636f6e7472616374000000000000604482015290519081900360640190fd5b600080826001600160a01b0316846040518082805190602001908083835b6020831061274557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612708565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146127a7576040519150601f19603f3d011682016040523d82523d6000602084013e6127ac565b606091505b5091509150811561282b57805115612826578080602001905160208110156127d357600080fd5b5051612826576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b612887565b805161287e576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b80518082602001fd5b5050505050565b60408101516001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156129b1578060c00151341015612910576040805162461bcd60e51b815260206004820152601660248201527f53616c653a20696e73756666696369656e742045544800000000000000000000604482015290519081900360640190fd5b60015460c08201516040516001600160a01b039092169181156108fc0291906000818181858888f1935050505015801561294e573d6000803e3d6000fd5b5060006129688260c001513461337b90919063ffffffff16565b905080156129ab5781516040516001600160a01b039091169082156108fc029083906000818181858888f193505050501580156129a9573d6000803e3d6000fd5b505b50611b22565b611b226129bc611a33565b60015460c084015160408501516001600160a01b03908116939216906133d8565b6129e681613466565b606080820151600090815260076020908152604080832081518154608094810282018501909352948501828152939493909284928491840182828015612a4b57602002820191906000526020600020905b815481526020019060010190808311612a37575b50505050508152602001600182015481526020016002820154815250509050600081602001519050600082604001519050814211612ad0576040805162461bcd60e51b815260206004820152601560248201527f53616c653a206e6f742073746172746564207965740000000000000000000000604482015290519081900360640190fd5b801580612adc57508042105b612b2d576040805162461bcd60e51b815260206004820152601360248201527f53616c653a20616c726561647920656e64656400000000000000000000000000604482015290519081900360640190fd5b8251516001811415612c06577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635cfa929786602001518660000151600081518110612b7e57fe5b602002602001015188608001516040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200182815260200180602001828103825260008152602001945050505050600060405180830381600087803b158015612be957600080fd5b505af1158015612bfd573d6000803e3d6000fd5b50505050612887565b608085015160008267ffffffffffffffff81118015612c2457600080fd5b50604051908082528060200260200182016040528015612c4e578160200160208202803683370190505b50905060005b838114612c7b5782828281518110612c6857fe5b6020908102919091010152600101612c54565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630d6a5bbb88602001518860000151846040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018060200180602001848103845286818151815260200191508051906020019060200280838360005b83811015612d1c578181015183820152602001612d04565b50505050905001848103835285818151815260200191508051906020019060200280838360005b83811015612d5b578181015183820152602001612d43565b505050509050018481038252600081526020019650505050505050600060405180830381600087803b158015612d9057600080fd5b505af1158015612da4573d6000803e3d6000fd5b5050505050505050505050565b806060015181604001516001600160a01b031682600001516001600160a01b03167f29f844483ca6b10b5c0611d039afc15ce8f6380e905307b381c3a8ee4e90e11e846020015185608001518660a001518760c001518860e001518961010001518a610120015160405160200180848051906020019060200280838360005b83811015612e48578181015183820152602001612e30565b50505050905001838051906020019060200280838360005b83811015612e78578181015183820152602001612e60565b50505050905001828051906020019060200280838360005b83811015612ea8578181015183820152602001612e90565b50505050905001935050505060405160208183030381529060405260405180866001600160a01b031681526020018581526020018060200184815260200180602001838103835286818151815260200191508051906020019080838360005b83811015612f1f578181015183820152602001612f07565b50505050905090810190601f168015612f4c5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612f7f578181015183820152602001612f67565b50505050905090810190601f168015612fac5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a460608101516000908152600660205260409020600301546001600160a01b03168015613296576361eceae860e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916816001600160a01b03166361eceae8846000015185602001518660400151876060015188608001518960a001518a60c001518b60e001518c61010001518d61012001516040518b63ffffffff1660e01b8152600401808b6001600160a01b031681526020018a6001600160a01b03168152602001896001600160a01b031681526020018881526020018781526020018060200186815260200180602001806020018060200185810385528a818151815260200191508051906020019080838360005b838110156130e55781810151838201526020016130cd565b50505050905090810190601f1680156131125780820380516001836020036101000a031916815260200191505b508581038452885181528851602091820191808b01910280838360005b8381101561314757818101518382015260200161312f565b50505050905001858103835287818151815260200191508051906020019060200280838360005b8381101561318657818101518382015260200161316e565b50505050905001858103825286818151815260200191508051906020019060200280838360005b838110156131c55781810151838201526020016131ad565b505050509050019e505050505050505050505050505050602060405180830381600087803b1580156131f657600080fd5b505af115801561320a573d6000803e3d6000fd5b505050506040513d602081101561322057600080fd5b50517fffffffff000000000000000000000000000000000000000000000000000000001614613296576040805162461bcd60e51b815260206004820152601a60248201527f53616c653a206e6f74696669636174696f6e2072656675736564000000000000604482015290519081900360640190fd5b5050565b60009081526001919091016020526040902054151590565b60408201516000906132ce9083906001600160a01b03166134b1565b905080611f23576040805162461bcd60e51b815260206004820152601f60248201527f53616c653a20756e737570706f72746564207061796d656e7420746f6b656e00604482015290519081900360640190fd5b60008261333157506000611f23565b8282028284828161333e57fe5b04146117125760405162461bcd60e51b81526004018080602001828103825260218152602001806136136021913960400191505060405180910390fd5b6000828211156133d2576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052613460908590612686565b50505050565b6060810151600090815260066020526040902080546000191461329657608082015160018201546134969161337b565b60608301516000908152600660205260409020600101555050565b600081815260018301602052604081205480613514576040805162461bcd60e51b815260206004820152601860248201527f456e756d4d61703a206e6f6e6578697374656e74206b65790000000000000000604482015290519081900360640190fd5b83600001600182038154811061352657fe5b90600052602060002090600202016001015491505092915050565b60405180610140016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600080191681526020016000815260200160608152602001600081526020016060815260200160608152602001606081525090565b8280548282559060005260206000209081019282156135ed579160200282015b828111156135ed5782518255916020019190600101906135d2565b506135f99291506135fd565b5090565b5b808211156135f957600081556001016135fe56fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220462c603976ca9030c2c33761d2e13276bf269af1edac618dcd54e34907d2944364736f6c6343000706003300000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d000000000000000000000000c0f25fb4173bcefed70ddd56ca6d223209ff068000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000032

Deployed Bytecode

0x6080604052600436106101805760003560e01c8063717838f4116100d65780639e0495451161007f578063c3666c3611610059578063c3666c3614610976578063f21f537d14610a97578063f2fde38b14610aac57610180565b80639e049545146108a5578063a963b257146108cc578063be9a65551461096157610180565b80638488bb4e116100b05780638488bb4e146108515780638be262ba146108665780638da5cb5b1461089057610180565b8063717838f4146106e557806373c8a9581461071b5780638456cb591461083c57610180565b8063474f2891116101385780635e6e9f70116101125780635e6e9f701461051257806361bd38511461064d5780636b8f9c43146106b257610180565b8063474f2891146104a35780635c4fafc7146104d45780635c975abb146104e957610180565b80632a8a45bc116101695780632a8a45bc1461031a5780632e890782146104025780633f4ba83a1461048e57610180565b80631323b06614610185578063298f53f714610282575b600080fd5b34801561019157600080fd5b50610227600480360360a08110156101a857600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156101e857600080fd5b8201836020820111156101fa57600080fd5b8035906020019184600183028401116401000000008311171561021c57600080fd5b509092509050610adf565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561026d578181015183820152602001610255565b50505050905001935050505060405180910390f35b34801561028e57600080fd5b50610318600480360360c08110156102a557600080fd5b813591602081013591604082013591908101906080810160608201356401000000008111156102d357600080fd5b8201836020820111156102e557600080fd5b8035906020019184602083028401116401000000008311171561030757600080fd5b919350915080359060200135610bd4565b005b34801561032657600080fd5b506103446004803603602081101561033d57600080fd5b5035610dda565b60405180878152602001868152602001858152602001846001600160a01b031681526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156103a9578181015183820152602001610391565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156103e85781810151838201526020016103d0565b505050509050019850505050505050505060405180910390f35b34801561040e57600080fd5b5061042c6004803603602081101561042557600080fd5b5035610f7f565b6040518080602001848152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015610478578181015183820152602001610460565b5050505090500194505050505060405180910390f35b34801561049a57600080fd5b5061031861107d565b3480156104af57600080fd5b506104b86110e6565b604080516001600160a01b039092168252519081900360200190f35b3480156104e057600080fd5b506104b861110a565b3480156104f557600080fd5b506104fe611122565b604080519115158252519081900360200190f35b34801561051e57600080fd5b506103186004803603606081101561053557600080fd5b8135919081019060408101602082013564010000000081111561055757600080fd5b82018360208201111561056957600080fd5b8035906020019184602083028401116401000000008311171561058b57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092959493602081019350359150506401000000008111156105db57600080fd5b8201836020820111156105ed57600080fd5b8035906020019184602083028401116401000000008311171561060f57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061112b945050505050565b34801561065957600080fd5b50610662611308565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561069e578181015183820152602001610686565b505050509050019250505060405180910390f35b3480156106be57600080fd5b50610318600480360360208110156106d557600080fd5b50356001600160a01b0316611363565b3480156106f157600080fd5b506103186004803603606081101561070857600080fd5b5080359060208101359060400135611430565b34801561072757600080fd5b506103186004803603606081101561073e57600080fd5b81019060208101813564010000000081111561075957600080fd5b82018360208201111561076b57600080fd5b8035906020019184602083028401116401000000008311171561078d57600080fd5b9193909290916020810190356401000000008111156107ab57600080fd5b8201836020820111156107bd57600080fd5b803590602001918460208302840111640100000000831117156107df57600080fd5b9193909290916020810190356401000000008111156107fd57600080fd5b82018360208201111561080f57600080fd5b8035906020019184602083028401116401000000008311171561083157600080fd5b5090925090506114b8565b34801561084857600080fd5b5061031861159b565b34801561085d57600080fd5b506104b8611602565b34801561087257600080fd5b506104fe6004803603602081101561088957600080fd5b5035611611565b34801561089c57600080fd5b506104b8611719565b3480156108b157600080fd5b506108ba611728565b60408051918252519081900360200190f35b610318600480360360a08110156108e257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a08101608082013564010000000081111561092257600080fd5b82018360208201111561093457600080fd5b8035906020019184600183028401116401000000008311171561095657600080fd5b50909250905061172e565b34801561096d57600080fd5b50610318611814565b34801561098257600080fd5b506103186004803603606081101561099957600080fd5b8101906020810181356401000000008111156109b457600080fd5b8201836020820111156109c657600080fd5b803590602001918460208302840111640100000000831117156109e857600080fd5b919390929091602081019035640100000000811115610a0657600080fd5b820183602082011115610a1857600080fd5b80359060200191846020830284011164010000000083111715610a3a57600080fd5b919390929091602081019035640100000000811115610a5857600080fd5b820183602082011115610a6a57600080fd5b80359060200191846020830284011164010000000083111715610a8c57600080fd5b509092509050611827565b348015610aa357600080fd5b506108ba61196f565b348015610ab857600080fd5b5061031860048036036020811015610acf57600080fd5b50356001600160a01b0316611975565b6000606060025460001415610b3b576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b610b436119db565b610b4b613541565b610b53611a33565b6001600160a01b03908116825289811660208084019190915290891660408084019190915260608301899052608083018890528051601f870183900483028101830190915285815290869086908190840183828082843760009201919091525050505060a0820152610bc481611a37565b9250925050965096945050505050565b610be4610bdf611a33565b611a5e565b8280610c37576040805162461bcd60e51b815260206004820152601260248201527f53616c653a20656d70747920746f6b656e730000000000000000000000000000604482015290519081900360640190fd5b60005b818114610d3c577f00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d6001600160a01b031663adebf6f2878784818110610c7c57fe5b905060200201356040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610cb757600080fd5b505afa158015610ccb573d6000803e3d6000fd5b505050506040513d6020811015610ce157600080fd5b5051610d34576040805162461bcd60e51b815260206004820152601a60248201527f53616c653a206e6f7420612066756e6769626c6520746f6b656e000000000000604482015290519081900360640190fd5b600101610c3a565b5060405180606001604052808686808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250938552505050602080830187905260409283018690528b825260078152919020825180519192610dac928492909101906135b2565b5060208201516001820155604090910151600290910155610dd08888886000611b25565b5050505050505050565b6000818152600660205260408120819081908190606090819083610e0060048301611d5c565b82549850905087610e58576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b60018201546002830154600384015491985096506001600160a01b031694508067ffffffffffffffff81118015610e8e57600080fd5b50604051908082528060200260200182016040528015610eb8578160200160208202803683370190505b5093508067ffffffffffffffff81118015610ed257600080fd5b50604051908082528060200260200182016040528015610efc578160200160208202803683370190505b50925060005b81811015610f7357600080610f1a6004860184611d60565b915091508160001c878481518110610f2e57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508060001c868481518110610f5e57fe5b60209081029190910101525050600101610f02565b50505091939550919395565b600081815260066020526040812054606091908190610fe5576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b6000848152600760209081526040808320815181546080948102820185019093526060810183815290939192849284919084018282801561104557602002820191906000526020600020905b815481526020019060010190808311611031575b505050918352505060018201546020808301919091526002909201546040918201528251918301519201519097919650945092505050565b6002546110d1576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b6110dc610bdf611a33565b6110e4611df1565b565b7f00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d81565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b60035460ff1681565b611136610bdf611a33565b81518151811461118d576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20696e636f6e73697374656e742061727261797300000000000000604482015290519081900360640190fd5b600084815260066020526040902080546111ee576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b600481018261123957600061120282611d5c565b905060005b8181101561123257600061121b8482611d60565b5090506112288482611e49565b5050600101611207565b5050611244565b611244818686611f29565b857fcb3fe5489e0cd43d0f4a33d1e09a4a0463a03d0d38f56165530854e5540db1438686604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156112ac578181015183820152602001611294565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156112eb5781810151838201526020016112d3565b5050505090500194505050505060405180910390a2505050505050565b6060600460000180548060200260200160405190810160405280929190818152602001828054801561135957602002820191906000526020600020905b815481526020019060010190808311611345575b5050505050905090565b61136e610bdf611a33565b6001600160a01b0381166113c9576040805162461bcd60e51b815260206004820152601460248201527f5061796f75743a207a65726f2061646472657373000000000000000000000000604482015290519081900360640190fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03838116919091179182905560408051929091168252517fdd880d24a789958a6398c99c2e54ce31bc10a638cbc42f7dd34285479ae0f855916020908290030190a150565b61143b610bdf611a33565b60008381526006602052604090205461149b576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b600092835260076020526040909220600181019190915560020155565b6114c3610bdf611a33565b8483811480156114d257508082145b611523576040805162461bcd60e51b815260206004820152601a60248201527f5265636f763a20696e636f6e73697374656e7420617272617973000000000000604482015290519081900360640190fd5b60005b818114610dd05761159388888381811061153c57fe5b905060200201356001600160a01b031685858481811061155857fe5b9050602002013588888581811061156b57fe5b905060200201356001600160a01b03166001600160a01b03166120929092919063ffffffff16565b600101611526565b6002546115ef576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b6115fa610bdf611a33565b6110e4612112565b6001546001600160a01b031681565b600081815260066020526040812054611671576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b600082815260076020908152604080832081518154608094810282018501909352606081018381529093919284928491908401828280156116d157602002820191906000526020600020905b8154815260200190600101908083116116bd575b505050505081526020016001820154815260200160028201548152505090508060200151421180156117125750604081015115806117125750806040015142105b9392505050565b6000546001600160a01b031690565b60001981565b600254611782576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b61178a6119db565b611792613541565b61179a611a33565b6001600160a01b03908116825287811660208084019190915290871660408084019190915260608301879052608083018690528051601f850183900483028101830190915283815290849084908190840183828082843760009201919091525050505060a082015261180b81612150565b50505050505050565b61181f610bdf611a33565b6110dc61217d565b611832610bdf611a33565b84838114801561184157508082145b611892576040805162461bcd60e51b815260206004820152601a60248201527f5265636f763a20696e636f6e73697374656e7420617272617973000000000000604482015290519081900360640190fd5b60005b818114610dd0578585828181106118a857fe5b905060200201356001600160a01b03166001600160a01b03166323b872dd308a8a858181106118d357fe5b905060200201356001600160a01b03168787868181106118ef57fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561194c57600080fd5b505af1158015611960573d6000803e3d6000fd5b50505050806001019050611895565b60025490565b611980610bdf611a33565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821780845560405192939116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60035460ff16156110e4576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3390565b60006060611a44836121ff565b611a4d836124a9565b505060c081015160e0909101519091565b306001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a9757600080fd5b505afa158015611aab573d6000803e3d6000fd5b505050506040513d6020811015611ac157600080fd5b50516001600160a01b03828116911614611b22576040805162461bcd60e51b815260206004820152601660248201527f4f776e61626c653a206e6f7420746865206f776e657200000000000000000000604482015290519081900360640190fd5b50565b82611b77576040805162461bcd60e51b815260206004820152601160248201527f53616c653a207a65726f20737570706c79000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000007d0611ba26004611d5c565b10611bf4576040805162461bcd60e51b815260206004820152601360248201527f53616c653a20746f6f206d616e7920736b757300000000000000000000000000604482015290519081900360640190fd5b611bff600485612546565b611c50576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20736b7520616c7265616479206372656174656400000000000000604482015290519081900360640190fd5b6001600160a01b03811615611cc257611c71816001600160a01b0316612590565b611cc2576040805162461bcd60e51b815260206004820152601b60248201527f53616c653a206e6f6e2d636f6e74726163742072656365697665720000000000604482015290519081900360640190fd5b60008481526006602090815260409182902085815560018101869055600281018590556003810180546001600160a01b03861673ffffffffffffffffffffffffffffffffffffffff1990911681179091558351888152928301879052828401869052606083015291517f38bd4aabce684540cd61351b91f2f5facf9d6963934347e25aab93d87ae7ac149181900360800190a15050505050565b5490565b815460009081908310611dba576040805162461bcd60e51b815260206004820152601c60248201527f456e756d4d61703a20696e646578206f7574206f6620626f756e647300000000604482015290519081900360640190fd5b6000846000018481548110611dcb57fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b611df9612596565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611e2c611a33565b604080516001600160a01b039092168252519081900360200190a1565b60008181526001830160205260408120548015611f1d5783546000198083019190810190600090879083908110611e7c57fe5b9060005260206000209060020201905080876000018481548110611e9c57fe5b600091825260208083208454600290930201918255600193840154918401919091558354825289830190526040902090840190558654879080611edb57fe5b6000828152602080822060026000199094019384020182815560019081018390559290935588815289820190925260408220919091559450611f239350505050565b60009150505b92915050565b60005b825181101561200f576000838281518110611f4357fe5b6020026020010151905060006001600160a01b0316816001600160a01b03161415611fb5576040805162461bcd60e51b815260206004820152601860248201527f53616c653a207a65726f206164647265737320746f6b656e0000000000000000604482015290519081900360640190fd5b6000838381518110611fc357fe5b602002602001015190508060001415611fef57611fe9866001600160a01b038416611e49565b50612005565b612003866001600160a01b038416836125ed565b505b5050600101611f2c565b507f000000000000000000000000000000000000000000000000000000000000003261203a84611d5c565b111561208d576040805162461bcd60e51b815260206004820152601560248201527f53616c653a20746f6f206d616e7920746f6b656e730000000000000000000000604482015290519081900360640190fd5b505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261208d908490612686565b61211a6119db565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611e2c611a33565b612159816121ff565b612162816124a9565b61216b8161288e565b612174816129dd565b611b2281612db1565b600254156121d2576040805162461bcd60e51b815260206004820152601260248201527f537461727461626c653a20737461727465640000000000000000000000000000604482015290519081900360640190fd5b426002557f27029695aa5f602a4ee81f4c32dfa86e562f200a17966496f3a7c3f2ec0f9417611e2c611a33565b60208101516001600160a01b031661225e576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a207a65726f206164647265737320726563697069656e7400000000604482015290519081900360640190fd5b60408101516001600160a01b03166122bd576040805162461bcd60e51b815260206004820152601860248201527f53616c653a207a65726f206164647265737320746f6b656e0000000000000000604482015290519081900360640190fd5b6080810151612313576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a207a65726f207175616e7469747920707572636861736500000000604482015290519081900360640190fd5b606081015160009081526006602052604090208054612379576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b8160800151816002015410156123d6576040805162461bcd60e51b815260206004820152601860248201527f53616c653a2061626f7665206d6178207175616e746974790000000000000000604482015290519081900360640190fd5b80546000191461243d5781608001518160010154101561243d576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20696e73756666696369656e7420737570706c7900000000000000604482015290519081900360640190fd5b60408201516001600160a01b0316612458600483018261329a565b61208d576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a206e6f6e2d6578697374656e7420736b7520746f6b656e00000000604482015290519081900360640190fd5b60608101516000908152600660205260409020805461250f576040805162461bcd60e51b815260206004820152601560248201527f53616c653a20756e737570706f7274656420534b550000000000000000000000604482015290519081900360640190fd5b60048101600061251f84836132b2565b905061253884608001518261332290919063ffffffff16565b60c090940193909352505050565b6000612552838361329a565b61258857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611f23565b506000611f23565b3b151590565b60035460ff166110e4576040805162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b600082815260018401602052604081205480612652575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611712565b8285600001600183038154811061266557fe5b90600052602060002090600202016001018190555060009150509392505050565b816126996001600160a01b038216612590565b6126ea576040805162461bcd60e51b815260206004820152601a60248201527f4552433230577261707065723a206e6f6e2d636f6e7472616374000000000000604482015290519081900360640190fd5b600080826001600160a01b0316846040518082805190602001908083835b6020831061274557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612708565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146127a7576040519150601f19603f3d011682016040523d82523d6000602084013e6127ac565b606091505b5091509150811561282b57805115612826578080602001905160208110156127d357600080fd5b5051612826576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b612887565b805161287e576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b80518082602001fd5b5050505050565b60408101516001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156129b1578060c00151341015612910576040805162461bcd60e51b815260206004820152601660248201527f53616c653a20696e73756666696369656e742045544800000000000000000000604482015290519081900360640190fd5b60015460c08201516040516001600160a01b039092169181156108fc0291906000818181858888f1935050505015801561294e573d6000803e3d6000fd5b5060006129688260c001513461337b90919063ffffffff16565b905080156129ab5781516040516001600160a01b039091169082156108fc029083906000818181858888f193505050501580156129a9573d6000803e3d6000fd5b505b50611b22565b611b226129bc611a33565b60015460c084015160408501516001600160a01b03908116939216906133d8565b6129e681613466565b606080820151600090815260076020908152604080832081518154608094810282018501909352948501828152939493909284928491840182828015612a4b57602002820191906000526020600020905b815481526020019060010190808311612a37575b50505050508152602001600182015481526020016002820154815250509050600081602001519050600082604001519050814211612ad0576040805162461bcd60e51b815260206004820152601560248201527f53616c653a206e6f742073746172746564207965740000000000000000000000604482015290519081900360640190fd5b801580612adc57508042105b612b2d576040805162461bcd60e51b815260206004820152601360248201527f53616c653a20616c726561647920656e64656400000000000000000000000000604482015290519081900360640190fd5b8251516001811415612c06577f00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d6001600160a01b0316635cfa929786602001518660000151600081518110612b7e57fe5b602002602001015188608001516040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200182815260200180602001828103825260008152602001945050505050600060405180830381600087803b158015612be957600080fd5b505af1158015612bfd573d6000803e3d6000fd5b50505050612887565b608085015160008267ffffffffffffffff81118015612c2457600080fd5b50604051908082528060200260200182016040528015612c4e578160200160208202803683370190505b50905060005b838114612c7b5782828281518110612c6857fe5b6020908102919091010152600101612c54565b507f00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d6001600160a01b0316630d6a5bbb88602001518860000151846040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018060200180602001848103845286818151815260200191508051906020019060200280838360005b83811015612d1c578181015183820152602001612d04565b50505050905001848103835285818151815260200191508051906020019060200280838360005b83811015612d5b578181015183820152602001612d43565b505050509050018481038252600081526020019650505050505050600060405180830381600087803b158015612d9057600080fd5b505af1158015612da4573d6000803e3d6000fd5b5050505050505050505050565b806060015181604001516001600160a01b031682600001516001600160a01b03167f29f844483ca6b10b5c0611d039afc15ce8f6380e905307b381c3a8ee4e90e11e846020015185608001518660a001518760c001518860e001518961010001518a610120015160405160200180848051906020019060200280838360005b83811015612e48578181015183820152602001612e30565b50505050905001838051906020019060200280838360005b83811015612e78578181015183820152602001612e60565b50505050905001828051906020019060200280838360005b83811015612ea8578181015183820152602001612e90565b50505050905001935050505060405160208183030381529060405260405180866001600160a01b031681526020018581526020018060200184815260200180602001838103835286818151815260200191508051906020019080838360005b83811015612f1f578181015183820152602001612f07565b50505050905090810190601f168015612f4c5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612f7f578181015183820152602001612f67565b50505050905090810190601f168015612fac5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a460608101516000908152600660205260409020600301546001600160a01b03168015613296576361eceae860e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916816001600160a01b03166361eceae8846000015185602001518660400151876060015188608001518960a001518a60c001518b60e001518c61010001518d61012001516040518b63ffffffff1660e01b8152600401808b6001600160a01b031681526020018a6001600160a01b03168152602001896001600160a01b031681526020018881526020018781526020018060200186815260200180602001806020018060200185810385528a818151815260200191508051906020019080838360005b838110156130e55781810151838201526020016130cd565b50505050905090810190601f1680156131125780820380516001836020036101000a031916815260200191505b508581038452885181528851602091820191808b01910280838360005b8381101561314757818101518382015260200161312f565b50505050905001858103835287818151815260200191508051906020019060200280838360005b8381101561318657818101518382015260200161316e565b50505050905001858103825286818151815260200191508051906020019060200280838360005b838110156131c55781810151838201526020016131ad565b505050509050019e505050505050505050505050505050602060405180830381600087803b1580156131f657600080fd5b505af115801561320a573d6000803e3d6000fd5b505050506040513d602081101561322057600080fd5b50517fffffffff000000000000000000000000000000000000000000000000000000001614613296576040805162461bcd60e51b815260206004820152601a60248201527f53616c653a206e6f74696669636174696f6e2072656675736564000000000000604482015290519081900360640190fd5b5050565b60009081526001919091016020526040902054151590565b60408201516000906132ce9083906001600160a01b03166134b1565b905080611f23576040805162461bcd60e51b815260206004820152601f60248201527f53616c653a20756e737570706f72746564207061796d656e7420746f6b656e00604482015290519081900360640190fd5b60008261333157506000611f23565b8282028284828161333e57fe5b04146117125760405162461bcd60e51b81526004018080602001828103825260218152602001806136136021913960400191505060405180910390fd5b6000828211156133d2576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052613460908590612686565b50505050565b6060810151600090815260066020526040902080546000191461329657608082015160018201546134969161337b565b60608301516000908152600660205260409020600101555050565b600081815260018301602052604081205480613514576040805162461bcd60e51b815260206004820152601860248201527f456e756d4d61703a206e6f6e6578697374656e74206b65790000000000000000604482015290519081900360640190fd5b83600001600182038154811061352657fe5b90600052602060002090600202016001015491505092915050565b60405180610140016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600080191681526020016000815260200160608152602001600081526020016060815260200160608152602001606081525090565b8280548282559060005260206000209081019282156135ed579160200282015b828111156135ed5782518255916020019190600101906135d2565b506135f99291506135fd565b5090565b5b808211156135f957600081556001016135fe56fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220462c603976ca9030c2c33761d2e13276bf269af1edac618dcd54e34907d2944364736f6c63430007060033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d000000000000000000000000c0f25fb4173bcefed70ddd56ca6d223209ff068000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000032

-----Decoded View---------------
Arg [0] : vouchersContract_ (address): 0x87a3747C9942d8351Cc85AaC2f94807B27A37c0D
Arg [1] : payoutWallet (address): 0xC0F25fB4173BCefeD70dDD56ca6d223209ff0680
Arg [2] : skusCapacity (uint256): 2000
Arg [3] : tokensPerSkuCapacity (uint256): 50

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d
Arg [1] : 000000000000000000000000c0f25fb4173bcefed70ddd56ca6d223209ff0680
Arg [2] : 00000000000000000000000000000000000000000000000000000000000007d0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000032


Deployed Bytecode Sourcemap

70473:5824:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52638:627;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;52638:627:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52638:627:0;;-1:-1:-1;52638:627:0;-1:-1:-1;52638:627:0;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72320:695;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72320:695:0;-1:-1:-1;72320:695:0;;;;;;;:::i;:::-;;54089:1056;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54089:1056:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;54089:1056:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74197:445;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;74197:445:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47657:117;;;;;;;;;;;;;:::i;70552:51::-;;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;70552:51:0;;;;;;;;;;;;;;45120:98;;;;;;;;;;;;;:::i;21026:18::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;48539:967;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48539:967:0;;;;;;;;-1:-1:-1;48539:967:0;;-1:-1:-1;;48539:967:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48539:967:0;;-1:-1:-1;48539:967:0;;-1:-1:-1;;;;;48539:967:0:i;55282:112::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18576:268;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;18576:268:0;-1:-1:-1;;;;;18576:268:0;;:::i;73394:415::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;73394:415:0;;;;;;;;;;;;:::i;68166:492::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;68166:492:0;;-1:-1:-1;68166:492:0;-1:-1:-1;68166:492:0;:::i;47263:113::-;;;;;;;;;;;;;:::i;18287:35::-;;;;;;;;;;;;;:::i;74914:339::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;74914:339:0;;:::i;17126:96::-;;;;;;;;;;;;;:::i;45225:69::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;50515:554;;;;;;;;;;;;;;;;-1:-1:-1;;;;;50515:554:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;50515:554:0;;-1:-1:-1;50515:554:0;-1:-1:-1;50515:554:0;:::i;46859:122::-;;;;;;;;;;;;;:::i;69484:522::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;69484:522:0;;-1:-1:-1;69484:522:0;-1:-1:-1;69484:522:0;:::i;20164:87::-;;;;;;;;;;;;;:::i;17469:201::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;17469:201:0;-1:-1:-1;;;;;17469:201:0;;:::i;52638:627::-;52866:18;52886:28;19863:10;;19877:1;19863:15;;19855:50;;;;;-1:-1:-1;;;19855:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52927:19:::1;:17;:19::i;:::-;52957:28;;:::i;:::-;53017:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;52996:33:0;;::::1;::::0;;53040:30;;::::1;:18;::::0;;::::1;:30:::0;;;;53081:22;;::::1;:14;::::0;;::::1;:22:::0;;;;53114:12:::1;::::0;::::1;:18:::0;;;53143:17:::1;::::0;::::1;:28:::0;;;53182;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;53202:8;;;;;;53182:28;::::1;53202:8:::0;;;;53182:28;::::1;;::::0;::::1;::::0;;;;-1:-1:-1;;;;53182:17:0::1;::::0;::::1;:28:::0;53230:27:::1;53182:8:::0;53230:17:::1;:27::i;:::-;53223:34;;;;;52638:627:::0;;;;;;;;;:::o;72320:695::-;72561:31;72579:12;:10;:12::i;:::-;72561:17;:31::i;:::-;72620:8;72654:11;72646:42;;;;;-1:-1:-1;;;72646:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;72704:9;72699:140;72720:6;72715:1;:11;72699:140;;72756:16;-1:-1:-1;;;;;72756:27:0;;72784:8;;72793:1;72784:11;;;;;;;;;;;;;72756:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72756:40:0;72748:79;;;;;-1:-1:-1;;;72748:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;72728:3;;72699:140;;;;72875:57;;;;;;;;72893:8;;72875:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72875:57:0;;;-1:-1:-1;;;72875:57:0;;;;;;;;;;;;;;72849:23;;;:18;:23;;;;;:83;;;;:23;;:83;;:23;;:83;;;;;:::i;:::-;-1:-1:-1;72849:83:0;;;;;;;;;;;;;;;;;;72943:64;72954:3;72959:11;72972:22;-1:-1:-1;72943:10:0;:64::i;:::-;72320:695;;;;;;;;:::o;54089:1056::-;54204:19;54480:14;;;:9;:14;;;;;54204:19;;;;;;54365:23;;;;54204:19;54522:23;:14;;;:21;:23::i;:::-;54572:19;;;-1:-1:-1;54505:40:0;-1:-1:-1;54610:16:0;54602:51;;;;;-1:-1:-1;;;54602:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;54682:23;;;;54741:30;;;;54806:29;;;;54682:23;;-1:-1:-1;54741:30:0;-1:-1:-1;;;;;;54806:29:0;;-1:-1:-1;54871:6:0;54857:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54857:21:0;;54848:30;;54912:6;54898:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54898:21:0;;54889:30;;54935:9;54930:208;54954:6;54950:1;:10;54930:208;;;54983:13;;55015:20;:14;;;55033:1;55015:17;:20::i;:::-;54982:53;;;;55078:5;55070:14;;55050:6;55057:1;55050:9;;;;;;;;;;;;;:35;-1:-1:-1;;;;;55050:35:0;;;-1:-1:-1;;;;;55050:35:0;;;;;55120:5;55112:14;;55100:6;55107:1;55100:9;;;;;;;;;;;;;;;;;:26;-1:-1:-1;;54962:3:0;;54930:208;;;;54089:1056;;;;;;;;;:::o;74197:445::-;74344:22;74437:14;;;:9;:14;;;;;:26;74304:25;;74344:22;;;74429:66;;;;;-1:-1:-1;;;74429:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;74506:29;74538:23;;;:18;:23;;;;;;;;74506:55;;;;;;;;;;;;;;;;;;;;;;;74538:23;;74506:55;;74538:23;;74506:55;;;74538:23;74506:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;74506:55:0;;;-1:-1:-1;;74506:55:0;;;;;;;;;;;;;;;;;;;;;;74580:13;;74595:19;;;;74616:17;;;74580:13;;74595:19;;-1:-1:-1;74616:17:0;-1:-1:-1;74197:445:0;-1:-1:-1;;;74197:445:0:o;47657:117::-;19863:10;;19855:50;;;;;-1:-1:-1;;;19855:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;47714:31:::1;47732:12;:10;:12::i;47714:31::-;47756:10;:8;:10::i;:::-;47657:117::o:0;70552:51::-;;;:::o;45120:98::-;45173:44;45120:98;:::o;21026:18::-;;;;;;:::o;48539:967::-;48688:31;48706:12;:10;:12::i;48688:31::-;48747:13;;48789;;48779:23;;48771:61;;;;;-1:-1:-1;;;48771:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;48843:23;48869:14;;;:9;:14;;;;;48902:19;;48894:59;;;;;-1:-1:-1;;;48894:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;49000:14;;;49029:11;49025:419;;49057:21;49081:20;:11;:18;:20::i;:::-;49057:44;;49121:9;49116:240;49140:13;49136:1;:17;49116:240;;;49260:13;49279:17;:11;49260:13;49279:14;:17::i;:::-;-1:-1:-1;49259:37:0;-1:-1:-1;49315:25:0;:11;49259:37;49315:18;:25::i;:::-;-1:-1:-1;;49155:3:0;;49116:240;;;;49025:419;;;;49388:44;49404:11;49417:6;49425;49388:15;:44::i;:::-;49478:3;49461:37;49483:6;49491;49461:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48539:967;;;;;;:::o;55282:112::-;55333:21;55374:5;:12;;55367:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55282:112;:::o;18576:268::-;18650:31;18668:12;:10;:12::i;18650:31::-;-1:-1:-1;;;;;18700:27:0;;18692:60;;;;;-1:-1:-1;;;18692:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;18763:12;:28;;-1:-1:-1;;18763:28:0;-1:-1:-1;;;;;18763:28:0;;;;;;;;;;;18807:29;;;18823:12;;;;18807:29;;;;;;;;;;;;;18576:268;:::o;73394:415::-;73536:31;73554:12;:10;:12::i;73536:31::-;73586:14;;;;:9;:14;;;;;:26;73578:66;;;;;-1:-1:-1;;;73578:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;73655:30;73688:23;;;:18;:23;;;;;;73722:19;;;:36;;;;73769:17;;:32;73394:415::o;68166:492::-;68335:31;68353:12;:10;:12::i;68335:31::-;68394:8;68428:23;;;:51;;;;-1:-1:-1;68455:24:0;;;68428:51;68420:90;;;;;-1:-1:-1;;;68420:90:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;68526:9;68521:130;68546:6;68541:1;:11;68521:130;;68574:65;68615:8;;68624:1;68615:11;;;;;;;;;;;;;-1:-1:-1;;;;;68615:11:0;68628:7;;68636:1;68628:10;;;;;;;;;;;;;68588:6;;68595:1;68588:9;;;;;;;;;;;;;-1:-1:-1;;;;;68588:9:0;-1:-1:-1;;;;;68574:40:0;;;:65;;;;;:::i;:::-;68554:3;;68521:130;;47263:113;19863:10;;19855:50;;;;;-1:-1:-1;;;19855:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;47318:31:::1;47336:12;:10;:12::i;47318:31::-;47360:8;:6;:8::i;18287:35::-:0;;;-1:-1:-1;;;;;18287:35:0;;:::o;74914:339::-;74974:4;74999:14;;;:9;:14;;;;;:26;74991:66;;;;;-1:-1:-1;;;74991:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;75068:29;75100:23;;;:18;:23;;;;;;;;75068:55;;;;;;;;;;;;;;;;;;;;;;;75100:23;;75068:55;;75100:23;;75068:55;;;75100:23;75068:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75159:4;:19;;;75141:15;:37;:104;;;;-1:-1:-1;75183:17:0;;;;:22;;:61;;;75227:4;:17;;;75209:15;:35;75183:61;75134:111;74914:339;-1:-1:-1;;;74914:339:0:o;17126:96::-;17181:7;17208:6;-1:-1:-1;;;;;17208:6:0;17126:96;:::o;45225:69::-;-1:-1:-1;;45225:69:0;:::o;50515:554::-;19863:10;;19855:50;;;;;-1:-1:-1;;;19855:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;50743:19:::1;:17;:19::i;:::-;50773:28;;:::i;:::-;50833:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;50812:33:0;;::::1;::::0;;50856:30;;::::1;:18;::::0;;::::1;:30:::0;;;;50897:22;;::::1;:14;::::0;;::::1;:22:::0;;;;50930:12:::1;::::0;::::1;:18:::0;;;50959:17:::1;::::0;::::1;:28:::0;;;50998;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;51018:8;;;;;;50998:28;::::1;51018:8:::0;;;;50998:28;::::1;;::::0;::::1;::::0;;;;-1:-1:-1;;;;50998:17:0::1;::::0;::::1;:28:::0;51039:22:::1;50998:8:::0;51039:12:::1;:22::i;:::-;19916:1;50515:554:::0;;;;;;:::o;46859:122::-;46902:31;46920:12;:10;:12::i;46902:31::-;46944:8;:6;:8::i;69484:522::-;69658:31;69676:12;:10;:12::i;69658:31::-;69717:8;69751:26;;;:55;;;;-1:-1:-1;69781:25:0;;;69751:55;69743:94;;;;;-1:-1:-1;;;69743:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;69853:9;69848:151;69873:6;69868:1;:11;69848:151;;69920:9;;69930:1;69920:12;;;;;;;;;;;;;-1:-1:-1;;;;;69920:12:0;-1:-1:-1;;;;;69901:45:0;;69955:4;69962:8;;69971:1;69962:11;;;;;;;;;;;;;-1:-1:-1;;;;;69962:11:0;69975:8;;69984:1;69975:11;;;;;;;;;;;;;69901:86;;;;;;;;;;;;;-1:-1:-1;;;;;69901:86:0;;;;;;-1:-1:-1;;;;;69901:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69881:3;;;;;69848:151;;20164:87;20233:10;;20164:87;:::o;17469:201::-;17549:31;17567:12;:10;:12::i;17549:31::-;17591:6;:17;;-1:-1:-1;;17591:17:0;-1:-1:-1;;;;;17591:17:0;;;;;;;;;17624:38;;17591:17;;17645:6;;;17624:38;;17591:6;17624:38;17469:201;:::o;21122:98::-;21185:6;;;;21184:7;21176:36;;;;;-1:-1:-1;;;21176:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;14756:106;14844:10;14756:106;:::o;41168:297::-;41256:18;41276:28;41317:21;41329:8;41317:11;:21::i;:::-;41349:18;41358:8;41349;:18::i;:::-;-1:-1:-1;;41393:19:0;;;;41437:20;;;;;41393:19;;41168:297::o;17801:138::-;17892:4;-1:-1:-1;;;;;17892:10:0;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;17892:12:0;-1:-1:-1;;;;;17881:23:0;;;;;;17873:58;;;;;-1:-1:-1;;;17873:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;17801:138;:::o;56191:895::-;56387:16;56379:46;;;;;-1:-1:-1;;;56379:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56461:13;56444:14;:5;:12;:14::i;:::-;:30;56436:62;;;;;-1:-1:-1;;;56436:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56517:14;:5;56527:3;56517:9;:14::i;:::-;56509:52;;;;;-1:-1:-1;;;56509:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;56576:35:0;;;56572:142;;56636:34;:21;-1:-1:-1;;;;;56636:32:0;;:34::i;:::-;56628:74;;;;;-1:-1:-1;;;56628:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56724:23;56750:14;;;:9;:14;;;;;;;;;56775:33;;;56819:23;;;:37;;;56867:30;;;:55;;;56933:29;;;:53;;-1:-1:-1;;;;;56933:53:0;;-1:-1:-1;;56933:53:0;;;;;;;;57002:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56191:895;;;;;:::o;8435:109::-;8518:18;;8435:109::o;8909:269::-;9013:18;;8976:7;;;;9013:26;-1:-1:-1;9005:67:0;;;;;-1:-1:-1;;;9005:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;9085:22;9110:3;:11;;9122:5;9110:18;;;;;;;;;;;;;;;;;;9085:43;;9147:5;:9;;;9158:5;:11;;;9139:31;;;;;8909:269;;;;;:::o;21744:135::-;21792:16;:14;:16::i;:::-;21819:6;:14;;-1:-1:-1;;21819:14:0;;;21849:22;21858:12;:10;:12::i;:::-;21849:22;;;-1:-1:-1;;;;;21849:22:0;;;;;;;;;;;;;;21744:135::o;6579:1553::-;6643:4;6778:16;;;:11;;;:16;;;;;;6811:13;;6807:1318;;7255:18;;-1:-1:-1;;7208:12:0;;;;7255:22;;;;7184:21;;7255:3;;:22;;7551;;;;;;;;;;;;;;;;7522:51;;7697:9;7668:3;:11;;7680:13;7668:26;;;;;;;;;;;;;;;;:38;;:26;;;;;:38;;;;;;;;;;;;;;;7786:13;;7774:26;;:11;;;:26;;;;;7803:17;;;7774:46;;7929:17;;7774:3;;7929:17;;;;;;;;;;;;;;-1:-1:-1;;7929:17:0;;;;;;;;;;;;;;;;;;;;;8024:16;;;:11;;;:16;;;;;;8017:23;;;;7929:17;-1:-1:-1;8057:11:0;;-1:-1:-1;;;;8057:11:0;6807:1318;8108:5;8101:12;;;6579:1553;;;;;:::o;57571:679::-;57746:9;57741:412;57765:6;:13;57761:1;:17;57741:412;;;57800:13;57816:6;57823:1;57816:9;;;;;;;;;;;;;;57800:25;;57865:1;-1:-1:-1;;;;;57848:19:0;:5;-1:-1:-1;;;;;57848:19:0;;;57840:56;;;;;-1:-1:-1;;;57840:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;57911:13;57927:6;57934:1;57927:9;;;;;;;;;;;;;;57911:25;;57955:5;57964:1;57955:10;57951:191;;;57986:43;:11;-1:-1:-1;;;;;58013:14:0;;57986:18;:43::i;:::-;;57951:191;;;58070:56;:11;-1:-1:-1;;;;;58094:14:0;;58119:5;58070:15;:56::i;:::-;;57951:191;-1:-1:-1;;57780:3:0;;57741:412;;;;58195:21;58171:20;:11;:18;:20::i;:::-;:45;;58163:79;;;;;-1:-1:-1;;;58163:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;57571:679;;;:::o;1919:229::-;2081:58;;;-1:-1:-1;;;;;2081:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2104:23;2081:58;;;2046:94;;2074:5;;2046:27;:94::i;21470:133::-;21516:19;:17;:19::i;:::-;21546:6;:13;;-1:-1:-1;;21546:13:0;21555:4;21546:13;;;21575:20;21582:12;:10;:12::i;41573:231::-;41653:21;41665:8;41653:11;:21::i;:::-;41685:18;41694:8;41685;:18::i;:::-;41714;41723:8;41714;:18::i;:::-;41743:19;41753:8;41743:9;:19::i;:::-;41773:23;41787:8;41773:13;:23::i;20392:134::-;19656:10;;:15;19648:46;;;;;-1:-1:-1;;;19648:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;20466:15:::1;20453:10;:28:::0;20497:21:::1;20505:12;:10;:12::i;59208:864::-:0;59309:18;;;;-1:-1:-1;;;;;59309:32:0;59301:73;;;;;-1:-1:-1;;;59301:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59393:14;;;;-1:-1:-1;;;;;59393:28:0;59385:65;;;;;-1:-1:-1;;;59385:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59469:17;;;;59461:63;;;;;-1:-1:-1;;;59461:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59571:12;;;;59535:23;59561;;;:9;:23;;;;;59603:19;;59595:59;;;;;-1:-1:-1;;;59595:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59707:8;:17;;;59673:7;:30;;;:51;;59665:88;;;;;-1:-1:-1;;;59665:88:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59768:19;;-1:-1:-1;;59768:39:0;59764:154;;59859:8;:17;;;59832:7;:23;;;:44;;59824:82;;;;;-1:-1:-1;;;59824:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59963:14;;;;-1:-1:-1;;;;;59955:23:0;59998:33;:14;;;59955:23;59998;:33::i;:::-;59990:74;;;;;-1:-1:-1;;;59990:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;64810:394;64936:12;;;;64900:23;64926;;;:9;:23;;;;;64968:19;;64960:58;;;;;-1:-1:-1;;;64960:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;65058:14;;;65029:26;65103:28;65114:8;65058:14;65103:10;:28::i;:::-;65083:48;;65164:32;65178:8;:17;;;65164:9;:13;;:32;;;;:::i;:::-;65142:19;;;;:54;;;;-1:-1:-1;;;64810:394:0:o;11229:410::-;11292:4;11314:20;11323:3;11328:5;11314:8;:20::i;:::-;11309:323;;-1:-1:-1;11351:22:0;;;;;;;;:10;:22;;;;;;;;;;;;;11532:17;;11511:18;;;:11;;;:18;;;;;;:38;;;;11564:11;;11309:323;-1:-1:-1;11615:5:0;11608:12;;1106:387;1429:20;1477:8;;;1106:387::o;21228:98::-;21287:6;;;;21279:39;;;;;-1:-1:-1;;;21279:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;5675:729;5785:4;5920:16;;;:11;;;:16;;;;;;5953:13;5949:448;;-1:-1:-1;;6050:34:0;;;;;;;;;;;;;;;;;;6033:52;;;;;;;;:11;:52;;;;;;;;;;;;;;;;;;;;;;;;6242:18;;6223:16;;;:11;;;:16;;;;;;;:37;6275:11;;5949:448;6353:5;6319:3;:11;;6342:1;6331:8;:12;6319:25;;;;;;;;;;;;;;;;;;:31;;:39;;;;6380:5;6373:12;;;5675:729;;;;;:::o;2675:892::-;2801:5;2826:19;-1:-1:-1;;;;;2826:17:0;;;:19::i;:::-;2818:58;;;;;-1:-1:-1;;;2818:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;2950:12;2964:17;2985:6;-1:-1:-1;;;;;2985:11:0;2997:8;2985:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2949:57;;;;3021:7;3017:543;;;3049:11;;:16;3045:124;;3105:4;3094:24;;;;;;;;;;;;;;;-1:-1:-1;3094:24:0;3086:67;;;;;-1:-1:-1;;;3086:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;3017:543;;;3260:11;;3256:97;;3297:40;;;-1:-1:-1;;;3297:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;3256:97;3484:4;3478:11;3529:4;3522;3518:2;3514:13;3507:27;3447:102;2675:892;;;;;:::o;65676:580::-;65765:14;;;;-1:-1:-1;;;;;65765:27:0;45173:44;65765:27;65761:488;;;65830:8;:19;;;65817:9;:32;;65809:67;;;;;-1:-1:-1;;;65809:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;65893:12;;65915:19;;;;65893:42;;-1:-1:-1;;;;;65893:12:0;;;;:42;;;;;65915:19;65893:12;:42;:12;:42;65915:19;65893:12;:42;;;;;;;;;;;;;;;;;;;;;65952:14;65969:34;65983:8;:19;;;65969:9;:13;;:34;;;;:::i;:::-;65952:51;-1:-1:-1;66024:11:0;;66020:87;;66056:18;;:35;;-1:-1:-1;;;;;66056:27:0;;;;:35;;;;;66084:6;;66056:18;:35;:18;:35;66084:6;66056:27;:35;;;;;;;;;;;;;;;;;;;;;66020:87;65761:488;;;;66139:98;66189:12;:10;:12::i;:::-;66203;;66217:19;;;;66153:14;;;;-1:-1:-1;;;;;66139:49:0;;;;:98;66203:12;;66139:49;:98::i;75287:1007::-;75365:25;75381:8;75365:15;:25::i;:::-;75452:12;;;;;75401:29;75433:32;;;:18;:32;;;;;;;;75401:64;;;;;;;;;;;;;;;;;;;;;:29;;:64;75433:32;;75401:64;;75433:32;;75401:64;;75433:32;75401:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75476:22;75501:4;:19;;;75476:44;;75531:20;75554:4;:17;;;75531:40;;75608:14;75590:15;:32;75582:66;;;;;-1:-1:-1;;;75582:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;75667:17;;;:51;;;75706:12;75688:15;:30;75667:51;75659:83;;;;;-1:-1:-1;;;75659:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;75772:13;;:20;75817:1;75807:11;;75803:484;;;75835:16;-1:-1:-1;;;;;75835:25:0;;75861:8;:18;;;75881:4;:13;;;75895:1;75881:16;;;;;;;;;;;;;;75899:8;:17;;;75835:86;;;;;;;;;;;;;-1:-1:-1;;;;;75835:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75803:484;;;75981:17;;;;75954:24;76057:6;76043:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76043:21:0;;76013:51;;76084:9;76079:101;76100:6;76095:1;:11;76079:101;;76148:16;76132:10;76143:1;76132:13;;;;;;;;;;;;;;;;;:32;76108:3;;76079:101;;;;76194:16;-1:-1:-1;;;;;76194:30:0;;76225:8;:18;;;76245:4;:13;;;76260:10;76194:81;;;;;;;;;;;;;-1:-1:-1;;;;;76194:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75803:484;;75287:1007;;;;;:::o;61778:1323::-;61991:8;:12;;;61962:8;:14;;;-1:-1:-1;;;;;61873:337:0;61896:8;:18;;;-1:-1:-1;;;;;61873:337:0;;61929:8;:18;;;62018:8;:17;;;62050:8;:17;;;62082:8;:19;;;62133:8;:20;;;62155:8;:20;;;62177:8;:21;;;62116:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61873:337;;;;-1:-1:-1;;;;;61873:337:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;61873:337:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62265:12;;;;62223:29;62255:23;;;:9;:23;;;;;:45;;;-1:-1:-1;;;;;62255:45:0;62315:35;;62311:783;;62906:82;;;62393:595;;;62424:21;-1:-1:-1;;;;;62393:84:0;;62500:8;:18;;;62541:8;:18;;;62582:8;:14;;;62619:8;:12;;;62654:8;:17;;;62694:8;:17;;;62734:8;:19;;;62776:8;:20;;;62819:8;:20;;;62862:8;:21;;;62393:509;;;;;;;;;;;;;-1:-1:-1;;;;;62393:509:0;;;;;;-1:-1:-1;;;;;62393:509:0;;;;;;-1:-1:-1;;;;;62393:509:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62393:509:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62393:509:0;:595;;;62367:715;;;;;-1:-1:-1;;;62367:715:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;61778:1323;;:::o;8216:124::-;8287:4;8311:16;;;:11;;;;;:16;;;;;;:21;;;8216:124::o;66837:281::-;67023:14;;;;66946:17;;66996:44;;:6;;-1:-1:-1;;;;;67015:23:0;66996:10;:44::i;:::-;66988:53;-1:-1:-1;67060:14:0;67052:58;;;;;-1:-1:-1;;;67052:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;25566:220;25624:7;25648:6;25644:20;;-1:-1:-1;25663:1:0;25656:8;;25644:20;25687:5;;;25691:1;25687;:5;:1;25711:5;;;;;:10;25703:56;;;;-1:-1:-1;;;25703:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25149:158;25207:7;25240:1;25235;:6;;25227:49;;;;;-1:-1:-1;;;25227:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;25294:5:0;;;25149:158::o;2156:266::-;2345:68;;;-1:-1:-1;;;;;2345:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2368:27;2345:68;;;2310:104;;2338:5;;2310:27;:104::i;:::-;2156:266;;;;:::o;60721:313::-;60843:12;;;;60807:23;60833;;;:9;:23;;;;;60871:19;;-1:-1:-1;;60871:39:0;60867:160;;60997:17;;;;60969:23;;;;:46;;:27;:46::i;:::-;60937:12;;;;60927:23;;;;:9;:23;;;;;:39;;:88;60721:313;;:::o;9339:302::-;9405:7;9444:16;;;:11;;;:16;;;;;;9479:13;9471:50;;;;;-1:-1:-1;;;9471:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;9575:3;:11;;9598:1;9587:8;:12;9575:25;;;;;;;;;;;;;;;;;;:31;;;9568:38;;;9339:302;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;

Swarm Source

ipfs://462c603976ca9030c2c33761d2e13276bf269af1edac618dcd54e34907d29443

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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