Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 2,266 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Purchase For | 14119045 | 1117 days ago | IN | 0 ETH | 0.00439035 | ||||
Purchase For | 14106095 | 1119 days ago | IN | 0 ETH | 0.00424998 | ||||
Purchase For | 14098377 | 1120 days ago | IN | 0 ETH | 0.01540745 | ||||
Purchase For | 14098365 | 1120 days ago | IN | 0 ETH | 0.01974174 | ||||
Purchase For | 14098358 | 1120 days ago | IN | 0 ETH | 0.02051382 | ||||
Purchase For | 14098350 | 1120 days ago | IN | 0 ETH | 0.02322119 | ||||
Purchase For | 14098338 | 1120 days ago | IN | 0 ETH | 0.01850163 | ||||
Purchase For | 14098331 | 1120 days ago | IN | 0 ETH | 0.014753 | ||||
Purchase For | 14098322 | 1120 days ago | IN | 0 ETH | 0.01808852 | ||||
Purchase For | 14098309 | 1120 days ago | IN | 0 ETH | 0.01530137 | ||||
Purchase For | 14098289 | 1120 days ago | IN | 0 ETH | 0.01102139 | ||||
Purchase For | 14098287 | 1120 days ago | IN | 0 ETH | 0.01032474 | ||||
Purchase For | 14098286 | 1120 days ago | IN | 0 ETH | 0.0105451 | ||||
Purchase For | 14098285 | 1120 days ago | IN | 0 ETH | 0.00952862 | ||||
Purchase For | 14098284 | 1120 days ago | IN | 0 ETH | 0.00999311 | ||||
Purchase For | 14098280 | 1120 days ago | IN | 0 ETH | 0.01176712 | ||||
Purchase For | 14098277 | 1120 days ago | IN | 0 ETH | 0.00941823 | ||||
Purchase For | 14098272 | 1120 days ago | IN | 0 ETH | 0.01132242 | ||||
Purchase For | 14098270 | 1120 days ago | IN | 0 ETH | 0.01355402 | ||||
Purchase For | 14098268 | 1120 days ago | IN | 0 ETH | 0.01418577 | ||||
Purchase For | 14098181 | 1120 days ago | IN | 0 ETH | 0.01299511 | ||||
Purchase For | 14098178 | 1120 days ago | IN | 0 ETH | 0.01376055 | ||||
Purchase For | 14098176 | 1120 days ago | IN | 0 ETH | 0.01480082 | ||||
Purchase For | 14098175 | 1120 days ago | IN | 0 ETH | 0.0142832 | ||||
Purchase For | 14098173 | 1120 days ago | IN | 0 ETH | 0.01247285 |
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
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.