Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 493 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Purchase For | 13456163 | 1593 days ago | IN | 0 ETH | 0.00234223 | ||||
| Purchase For | 13433065 | 1597 days ago | IN | 0 ETH | 0.00172537 | ||||
| Purchase For | 13433065 | 1597 days ago | IN | 0 ETH | 0.00173065 | ||||
| Purchase For | 13432579 | 1597 days ago | IN | 0 ETH | 0.0017468 | ||||
| Purchase For | 13432579 | 1597 days ago | IN | 0 ETH | 0.00272072 | ||||
| Purchase For | 13432579 | 1597 days ago | IN | 0 ETH | 0.0017462 | ||||
| Purchase For | 13432579 | 1597 days ago | IN | 0 ETH | 0.00175711 | ||||
| Purchase For | 13409624 | 1600 days ago | IN | 0 ETH | 0.00234384 | ||||
| Purchase For | 13409624 | 1600 days ago | IN | 0 ETH | 0.00260644 | ||||
| Purchase For | 13405814 | 1601 days ago | IN | 0 ETH | 0.00177233 | ||||
| Purchase For | 13404331 | 1601 days ago | IN | 0 ETH | 0.00264781 | ||||
| Purchase For | 13404326 | 1601 days ago | IN | 0 ETH | 0.00841776 | ||||
| Purchase For | 13404322 | 1601 days ago | IN | 0 ETH | 0.00993888 | ||||
| Purchase For | 13404319 | 1601 days ago | IN | 0 ETH | 0.00643638 | ||||
| Purchase For | 13404293 | 1601 days ago | IN | 0 ETH | 0.00934163 | ||||
| Purchase For | 13404287 | 1601 days ago | IN | 0 ETH | 0.0088025 | ||||
| Purchase For | 13404270 | 1601 days ago | IN | 0 ETH | 0.0066112 | ||||
| Purchase For | 13404269 | 1601 days ago | IN | 0 ETH | 0.00339015 | ||||
| Purchase For | 13404269 | 1601 days ago | IN | 0 ETH | 0.0024299 | ||||
| Purchase For | 13404269 | 1601 days ago | IN | 0 ETH | 0.00236266 | ||||
| Purchase For | 13404269 | 1601 days ago | IN | 0 ETH | 0.00218776 | ||||
| Purchase For | 13404269 | 1601 days ago | IN | 0 ETH | 0.0020964 | ||||
| Purchase For | 13404269 | 1601 days ago | IN | 0 ETH | 0.00253187 | ||||
| Purchase For | 13404269 | 1601 days ago | IN | 0 ETH | 0.00278128 | ||||
| Purchase For | 13404269 | 1601 days ago | IN | 0 ETH | 0.00215595 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TokenLaunchpadVouchersSale
Compiler Version
v0.7.6+commit.7338295f
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-10-12
*/
// Sources flattened with hardhat v2.6.5 https://hardhat.org
// File @animoca/ethereum-contracts-core-1.1.2/contracts/utils/types/AddressIsContract.sol@v1.1.2
// 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/ERC20Wrapper.sol@v1.1.2
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/EnumMap.sol@v1.1.2
// 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/EnumSet.sol@v1.1.2
// 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/ManagedIdentity.sol@v1.1.2
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/IERC173.sol@v1.1.2
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/Ownable.sol@v1.1.2
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/PayoutWallet.sol@v1.1.2
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/Startable.sol@v1.1.2
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/Pausable.sol@v1.1.2
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/SafeMath.sol@v3.4.0
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/ISale.sol@v2.0.0
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/IPurchaseNotificationsReceiver.sol@v2.0.0
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/PurchaseLifeCycles.sol@v2.0.0
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/Sale.sol@v2.0.0
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/FixedPricesSale.sol@v2.0.0
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/Recoverable.sol@v1.1.2
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/TokenLaunchpadVouchersSale.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 TokenLaunchpadVouchersSale is FixedPricesSale, Recoverable {
IVouchersContract public immutable vouchersContract;
mapping(bytes32 => uint256) public skuTokenIds;
/**
* 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 `notificationsReceiver` is not the zero address and is not a contract address.
* @dev Reverts if the update results in too many SKUs.
* @dev Reverts if `tokenId` is zero.
* @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.
* @param tokenId The inventory contract token ID to associate with the SKU, used for purchase
* delivery.
*/
function createSku(
bytes32 sku,
uint256 totalSupply,
uint256 maxQuantityPerPurchase,
uint256 tokenId
) external {
_requireOwnership(_msgSender());
require(vouchersContract.isFungible(tokenId), "Sale: not a fungible token");
skuTokenIds[sku] = tokenId;
_createSku(sku, totalSupply, maxQuantityPerPurchase, address(0));
}
/// @inheritdoc Sale
function _delivery(PurchaseData memory purchase) internal override {
super._delivery(purchase);
vouchersContract.safeMint(purchase.recipient, skuTokenIds[purchase.sku], purchase.quantity, "");
}
}
interface IVouchersContract {
function isFungible(uint256 id) external pure returns (bool);
function safeMint(
address to,
uint256 id,
uint256 value,
bytes calldata data
) external;
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerPurchase","type":"uint256"},{"internalType":"uint256","name":"tokenId","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":"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":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"skuTokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"vouchersContract","outputs":[{"internalType":"contract IVouchersContract","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60e06040523480156200001157600080fd5b50604051620031e5380380620031e5833981810160405260808110156200003757600080fd5b5080516020820151604080840151606090940151600080546001600160a01b031916339081178255925194959394919285928592859285928592859260019290918691839182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b03811662000100576040805162461bcd60e51b815260206004820152601460248201527f5061796f75743a207a65726f2061646472657373000000000000000000000000604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fdd880d24a789958a6398c99c2e54ce31bc10a638cbc42f7dd34285479ae0f8559181900360200190a150506003805460ff1916911515919091179055608082905260a081905260408051600280825260608201835260009260208301908036833750506040805160028082526060820183529394506000939092509060208301908036833750508351919250680a89e968a9cbe8aa8960bb1b9173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee91508490600090620001e557fe5b6020026020010183600081518110620001fa57fe5b602002602001018281525082815250505060001960001b6f14d55414131657d5539312535255115160821b90836001815181106200023457fe5b60200260200101836001815181106200024957fe5b60200260200101828152508281525050507fabb92614f53337043b55dc996a83ebb09adce78ec336ca188ea02180b61d1c148282604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015620002c3578181015183820152602001620002a9565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101562000304578181015183820152602001620002ea565b5050505090500194505050505060405180910390a15050506001600160601b031960609990991b9890981660c052505050505050505060805160a05160c05160601c612e716200037460003980610cc9528061101e52806125c7525080611948525080611a1c5250612e716000f3fe60806040526004361061016a5760003560e01c80636ed51c48116100cb5780639e0495451161007f578063c3666c3611610059578063c3666c3614610844578063f21f537d14610965578063f2fde38b1461097a5761016a565b80639e04954514610785578063a963b2571461079a578063be9a65551461082f5761016a565b80638456cb59116100b05780638456cb59146107465780638488bb4e1461075b5780638da5cb5b146107705761016a565b80636ed51c48146105e957806373c8a958146106255761016a565b80635c4fafc7116101225780635e6e9f70116101075780635e6e9f701461041657806361bd3851146105515780636b8f9c43146105b65761016a565b80635c4fafc7146103d85780635c975abb146103ed5761016a565b80632a8a45bc116101535780632a8a45bc146102a85780633f4ba83a14610390578063474f2891146103a75761016a565b80631323b0661461016f5780631793494c1461026c575b600080fd5b34801561017b57600080fd5b50610211600480360360a081101561019257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156101d257600080fd5b8201836020820111156101e457600080fd5b8035906020019184600183028401116401000000008311171561020657600080fd5b5090925090506109ad565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561025757818101518382015260200161023f565b50505050905001935050505060405180910390f35b34801561027857600080fd5b506102966004803603602081101561028f57600080fd5b5035610aa2565b60408051918252519081900360200190f35b3480156102b457600080fd5b506102d2600480360360208110156102cb57600080fd5b5035610ab4565b60405180878152602001868152602001858152602001846001600160a01b031681526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561033757818101518382015260200161031f565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561037657818101518382015260200161035e565b505050509050019850505050505050505060405180910390f35b34801561039c57600080fd5b506103a5610c59565b005b3480156103b357600080fd5b506103bc610cc7565b604080516001600160a01b039092168252519081900360200190f35b3480156103e457600080fd5b506103bc610ceb565b3480156103f957600080fd5b50610402610d03565b604080519115158252519081900360200190f35b34801561042257600080fd5b506103a56004803603606081101561043957600080fd5b8135919081019060408101602082013564010000000081111561045b57600080fd5b82018360208201111561046d57600080fd5b8035906020019184602083028401116401000000008311171561048f57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092959493602081019350359150506401000000008111156104df57600080fd5b8201836020820111156104f157600080fd5b8035906020019184602083028401116401000000008311171561051357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610d0c945050505050565b34801561055d57600080fd5b50610566610ee9565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105a257818101518382015260200161058a565b505050509050019250505060405180910390f35b3480156105c257600080fd5b506103a5600480360360208110156105d957600080fd5b50356001600160a01b0316610f44565b3480156105f557600080fd5b506103a56004803603608081101561060c57600080fd5b5080359060208101359060408101359060600135611011565b34801561063157600080fd5b506103a56004803603606081101561064857600080fd5b81019060208101813564010000000081111561066357600080fd5b82018360208201111561067557600080fd5b8035906020019184602083028401116401000000008311171561069757600080fd5b9193909290916020810190356401000000008111156106b557600080fd5b8201836020820111156106c757600080fd5b803590602001918460208302840111640100000000831117156106e957600080fd5b91939092909160208101903564010000000081111561070757600080fd5b82018360208201111561071957600080fd5b8035906020019184602083028401116401000000008311171561073b57600080fd5b509092509050611123565b34801561075257600080fd5b506103a5611210565b34801561076757600080fd5b506103bc611277565b34801561077c57600080fd5b506103bc611286565b34801561079157600080fd5b50610296611295565b6103a5600480360360a08110156107b057600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156107f057600080fd5b82018360208201111561080257600080fd5b8035906020019184600183028401116401000000008311171561082457600080fd5b50909250905061129b565b34801561083b57600080fd5b506103a5611381565b34801561085057600080fd5b506103a56004803603606081101561086757600080fd5b81019060208101813564010000000081111561088257600080fd5b82018360208201111561089457600080fd5b803590602001918460208302840111640100000000831117156108b657600080fd5b9193909290916020810190356401000000008111156108d457600080fd5b8201836020820111156108e657600080fd5b8035906020019184602083028401116401000000008311171561090857600080fd5b91939092909160208101903564010000000081111561092657600080fd5b82018360208201111561093857600080fd5b8035906020019184602083028401116401000000008311171561095a57600080fd5b509092509050611394565b34801561097157600080fd5b506102966114dc565b34801561098657600080fd5b506103a56004803603602081101561099d57600080fd5b50356001600160a01b03166114e2565b6000606060025460001415610a09576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b610a11611548565b610a19612da9565b610a216115a0565b6001600160a01b03908116825289811660208084019190915290891660408084019190915260608301899052608083018890528051601f870183900483028101830190915285815290869086908190840183828082843760009201919091525050505060a0820152610a92816115a4565b9250925050965096945050505050565b60076020526000908152604090205481565b6000818152600660205260408120819081908190606090819083610ada600483016115cb565b82549850905087610b32576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b60018201546002830154600384015491985096506001600160a01b031694508067ffffffffffffffff81118015610b6857600080fd5b50604051908082528060200260200182016040528015610b92578160200160208202803683370190505b5093508067ffffffffffffffff81118015610bac57600080fd5b50604051908082528060200260200182016040528015610bd6578160200160208202803683370190505b50925060005b81811015610c4d57600080610bf460048601846115cf565b915091508160001c878481518110610c0857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508060001c868481518110610c3857fe5b60209081029190910101525050600101610bdc565b50505091939550919395565b600254610cad576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b610cbd610cb86115a0565b611660565b610cc5611727565b565b7f000000000000000000000000000000000000000000000000000000000000000081565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b60035460ff1681565b610d17610cb86115a0565b815181518114610d6e576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20696e636f6e73697374656e742061727261797300000000000000604482015290519081900360640190fd5b60008481526006602052604090208054610dcf576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b6004810182610e1a576000610de3826115cb565b905060005b81811015610e13576000610dfc84826115cf565b509050610e09848261177f565b5050600101610de8565b5050610e25565b610e2581868661185f565b857fcb3fe5489e0cd43d0f4a33d1e09a4a0463a03d0d38f56165530854e5540db1438686604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610e8d578181015183820152602001610e75565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610ecc578181015183820152602001610eb4565b5050505090500194505050505060405180910390a2505050505050565b60606004600001805480602002602001604051908101604052809291908181526020018280548015610f3a57602002820191906000526020600020905b815481526020019060010190808311610f26575b5050505050905090565b610f4f610cb86115a0565b6001600160a01b038116610faa576040805162461bcd60e51b815260206004820152601460248201527f5061796f75743a207a65726f2061646472657373000000000000000000000000604482015290519081900360640190fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03838116919091179182905560408051929091168252517fdd880d24a789958a6398c99c2e54ce31bc10a638cbc42f7dd34285479ae0f855916020908290030190a150565b61101c610cb86115a0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663adebf6f2826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561108057600080fd5b505afa158015611094573d6000803e3d6000fd5b505050506040513d60208110156110aa57600080fd5b50516110fd576040805162461bcd60e51b815260206004820152601a60248201527f53616c653a206e6f7420612066756e6769626c6520746f6b656e000000000000604482015290519081900360640190fd5b600084815260076020526040812082905561111d908590859085906119c8565b50505050565b61112e610cb86115a0565b84838114801561113d57508082145b61118e576040805162461bcd60e51b815260206004820152601a60248201527f5265636f763a20696e636f6e73697374656e7420617272617973000000000000604482015290519081900360640190fd5b60005b818114611206576111fe8888838181106111a757fe5b905060200201356001600160a01b03168585848181106111c357fe5b905060200201358888858181106111d657fe5b905060200201356001600160a01b03166001600160a01b0316611bff9092919063ffffffff16565b600101611191565b5050505050505050565b600254611264576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b61126f610cb86115a0565b610cc5611c7f565b6001546001600160a01b031681565b6000546001600160a01b031690565b60001981565b6002546112ef576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b6112f7611548565b6112ff612da9565b6113076115a0565b6001600160a01b03908116825287811660208084019190915290871660408084019190915260608301879052608083018690528051601f850183900483028101830190915283815290849084908190840183828082843760009201919091525050505060a082015261137881611cbd565b50505050505050565b61138c610cb86115a0565b610cbd611cea565b61139f610cb86115a0565b8483811480156113ae57508082145b6113ff576040805162461bcd60e51b815260206004820152601a60248201527f5265636f763a20696e636f6e73697374656e7420617272617973000000000000604482015290519081900360640190fd5b60005b8181146112065785858281811061141557fe5b905060200201356001600160a01b03166001600160a01b03166323b872dd308a8a8581811061144057fe5b905060200201356001600160a01b031687878681811061145c57fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b1580156114b957600080fd5b505af11580156114cd573d6000803e3d6000fd5b50505050806001019050611402565b60025490565b6114ed610cb86115a0565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821780845560405192939116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60035460ff1615610cc5576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3390565b600060606115b183611d6c565b6115ba83612016565b505060c081015160e0909101519091565b5490565b815460009081908310611629576040805162461bcd60e51b815260206004820152601c60248201527f456e756d4d61703a20696e646578206f7574206f6620626f756e647300000000604482015290519081900360640190fd5b600084600001848154811061163a57fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b306001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561169957600080fd5b505afa1580156116ad573d6000803e3d6000fd5b505050506040513d60208110156116c357600080fd5b50516001600160a01b03828116911614611724576040805162461bcd60e51b815260206004820152601660248201527f4f776e61626c653a206e6f7420746865206f776e657200000000000000000000604482015290519081900360640190fd5b50565b61172f6120b3565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6117626115a0565b604080516001600160a01b039092168252519081900360200190a1565b6000818152600183016020526040812054801561185357835460001980830191908101906000908790839081106117b257fe5b90600052602060002090600202019050808760000184815481106117d257fe5b60009182526020808320845460029093020191825560019384015491840191909155835482528983019052604090209084019055865487908061181157fe5b60008281526020808220600260001990940193840201828155600190810183905592909355888152898201909252604082209190915594506118599350505050565b60009150505b92915050565b60005b825181101561194557600083828151811061187957fe5b6020026020010151905060006001600160a01b0316816001600160a01b031614156118eb576040805162461bcd60e51b815260206004820152601860248201527f53616c653a207a65726f206164647265737320746f6b656e0000000000000000604482015290519081900360640190fd5b60008383815181106118f957fe5b6020026020010151905080600014156119255761191f866001600160a01b03841661177f565b5061193b565b611939866001600160a01b0384168361210a565b505b5050600101611862565b507f0000000000000000000000000000000000000000000000000000000000000000611970846115cb565b11156119c3576040805162461bcd60e51b815260206004820152601560248201527f53616c653a20746f6f206d616e7920746f6b656e730000000000000000000000604482015290519081900360640190fd5b505050565b82611a1a576040805162461bcd60e51b815260206004820152601160248201527f53616c653a207a65726f20737570706c79000000000000000000000000000000604482015290519081900360640190fd5b7f0000000000000000000000000000000000000000000000000000000000000000611a4560046115cb565b10611a97576040805162461bcd60e51b815260206004820152601360248201527f53616c653a20746f6f206d616e7920736b757300000000000000000000000000604482015290519081900360640190fd5b611aa26004856121a4565b611af3576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20736b7520616c7265616479206372656174656400000000000000604482015290519081900360640190fd5b6001600160a01b03811615611b6557611b14816001600160a01b03166121ee565b611b65576040805162461bcd60e51b815260206004820152601b60248201527f53616c653a206e6f6e2d636f6e74726163742072656365697665720000000000604482015290519081900360640190fd5b60008481526006602090815260409182902085815560018101869055600281018590556003810180546001600160a01b03861673ffffffffffffffffffffffffffffffffffffffff1990911681179091558351888152928301879052828401869052606083015291517f38bd4aabce684540cd61351b91f2f5facf9d6963934347e25aab93d87ae7ac149181900360800190a15050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526119c39084906121f4565b611c87611548565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586117626115a0565b611cc681611d6c565b611ccf81612016565b611cd8816123fc565b611ce18161254b565b6117248161261f565b60025415611d3f576040805162461bcd60e51b815260206004820152601260248201527f537461727461626c653a20737461727465640000000000000000000000000000604482015290519081900360640190fd5b426002557f27029695aa5f602a4ee81f4c32dfa86e562f200a17966496f3a7c3f2ec0f94176117626115a0565b60208101516001600160a01b0316611dcb576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a207a65726f206164647265737320726563697069656e7400000000604482015290519081900360640190fd5b60408101516001600160a01b0316611e2a576040805162461bcd60e51b815260206004820152601860248201527f53616c653a207a65726f206164647265737320746f6b656e0000000000000000604482015290519081900360640190fd5b6080810151611e80576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a207a65726f207175616e7469747920707572636861736500000000604482015290519081900360640190fd5b606081015160009081526006602052604090208054611ee6576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b816080015181600201541015611f43576040805162461bcd60e51b815260206004820152601860248201527f53616c653a2061626f7665206d6178207175616e746974790000000000000000604482015290519081900360640190fd5b805460001914611faa57816080015181600101541015611faa576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20696e73756666696369656e7420737570706c7900000000000000604482015290519081900360640190fd5b60408201516001600160a01b0316611fc56004830182612b08565b6119c3576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a206e6f6e2d6578697374656e7420736b7520746f6b656e00000000604482015290519081900360640190fd5b60608101516000908152600660205260409020805461207c576040805162461bcd60e51b815260206004820152601560248201527f53616c653a20756e737570706f7274656420534b550000000000000000000000604482015290519081900360640190fd5b60048101600061208c8483612b20565b90506120a5846080015182612b9090919063ffffffff16565b60c090940193909352505050565b60035460ff16610cc5576040805162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b60008281526001840160205260408120548061216f57505060408051808201825283815260208082018481528654600181810189556000898152848120955160029093029095019182559151908201558654868452818801909252929091205561219d565b8285600001600183038154811061218257fe5b90600052602060002090600202016001018190555060009150505b9392505050565b60006121b08383612b08565b6121e657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611859565b506000611859565b3b151590565b816122076001600160a01b0382166121ee565b612258576040805162461bcd60e51b815260206004820152601a60248201527f4552433230577261707065723a206e6f6e2d636f6e7472616374000000000000604482015290519081900360640190fd5b600080826001600160a01b0316846040518082805190602001908083835b602083106122b357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612276565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612315576040519150601f19603f3d011682016040523d82523d6000602084013e61231a565b606091505b50915091508115612399578051156123945780806020019051602081101561234157600080fd5b5051612394576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b6123f5565b80516123ec576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b80518082602001fd5b5050505050565b60408101516001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561251f578060c0015134101561247e576040805162461bcd60e51b815260206004820152601660248201527f53616c653a20696e73756666696369656e742045544800000000000000000000604482015290519081900360640190fd5b60015460c08201516040516001600160a01b039092169181156108fc0291906000818181858888f193505050501580156124bc573d6000803e3d6000fd5b5060006124d68260c0015134612be990919063ffffffff16565b905080156125195781516040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015612517573d6000803e3d6000fd5b505b50611724565b61172461252a6115a0565b60015460c084015160408501516001600160a01b0390811693921690612c46565b61255481612cce565b60208181015160608301516000908152600790925260408083205460808086015183517f5cfa92970000000000000000000000000000000000000000000000000000000081526001600160a01b0395861660048201526024810193909352604483015260648201526084810184905290517f000000000000000000000000000000000000000000000000000000000000000090921692635cfa92979260a48084019382900301818387803b15801561260b57600080fd5b505af11580156123f5573d6000803e3d6000fd5b806060015181604001516001600160a01b031682600001516001600160a01b03167f29f844483ca6b10b5c0611d039afc15ce8f6380e905307b381c3a8ee4e90e11e846020015185608001518660a001518760c001518860e001518961010001518a610120015160405160200180848051906020019060200280838360005b838110156126b657818101518382015260200161269e565b50505050905001838051906020019060200280838360005b838110156126e65781810151838201526020016126ce565b50505050905001828051906020019060200280838360005b838110156127165781810151838201526020016126fe565b50505050905001935050505060405160208183030381529060405260405180866001600160a01b031681526020018581526020018060200184815260200180602001838103835286818151815260200191508051906020019080838360005b8381101561278d578181015183820152602001612775565b50505050905090810190601f1680156127ba5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156127ed5781810151838201526020016127d5565b50505050905090810190601f16801561281a5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a460608101516000908152600660205260409020600301546001600160a01b03168015612b04576361eceae860e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916816001600160a01b03166361eceae8846000015185602001518660400151876060015188608001518960a001518a60c001518b60e001518c61010001518d61012001516040518b63ffffffff1660e01b8152600401808b6001600160a01b031681526020018a6001600160a01b03168152602001896001600160a01b031681526020018881526020018781526020018060200186815260200180602001806020018060200185810385528a818151815260200191508051906020019080838360005b8381101561295357818101518382015260200161293b565b50505050905090810190601f1680156129805780820380516001836020036101000a031916815260200191505b508581038452885181528851602091820191808b01910280838360005b838110156129b557818101518382015260200161299d565b50505050905001858103835287818151815260200191508051906020019060200280838360005b838110156129f45781810151838201526020016129dc565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015612a33578181015183820152602001612a1b565b505050509050019e505050505050505050505050505050602060405180830381600087803b158015612a6457600080fd5b505af1158015612a78573d6000803e3d6000fd5b505050506040513d6020811015612a8e57600080fd5b50517fffffffff000000000000000000000000000000000000000000000000000000001614612b04576040805162461bcd60e51b815260206004820152601a60248201527f53616c653a206e6f74696669636174696f6e2072656675736564000000000000604482015290519081900360640190fd5b5050565b60009081526001919091016020526040902054151590565b6040820151600090612b3c9083906001600160a01b0316612d19565b905080611859576040805162461bcd60e51b815260206004820152601f60248201527f53616c653a20756e737570706f72746564207061796d656e7420746f6b656e00604482015290519081900360640190fd5b600082612b9f57506000611859565b82820282848281612bac57fe5b041461219d5760405162461bcd60e51b8152600401808060200182810382526021815260200180612e1b6021913960400191505060405180910390fd5b600082821115612c40576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261111d9085906121f4565b60608101516000908152600660205260409020805460001914612b045760808201516001820154612cfe91612be9565b60608301516000908152600660205260409020600101555050565b600081815260018301602052604081205480612d7c576040805162461bcd60e51b815260206004820152601860248201527f456e756d4d61703a206e6f6e6578697374656e74206b65790000000000000000604482015290519081900360640190fd5b836000016001820381548110612d8e57fe5b90600052602060002090600202016001015491505092915050565b60405180610140016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008019168152602001600081526020016060815260200160008152602001606081526020016060815260200160608152509056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212204d8cb75b26991c2fd95de34bbfcb733e5c728a2668a653399596a37a352a4c8564736f6c6343000706003300000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d00000000000000000000000039fa29ede121b06dce3674e97970caa539afc9570000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000000a
Deployed Bytecode
0x60806040526004361061016a5760003560e01c80636ed51c48116100cb5780639e0495451161007f578063c3666c3611610059578063c3666c3614610844578063f21f537d14610965578063f2fde38b1461097a5761016a565b80639e04954514610785578063a963b2571461079a578063be9a65551461082f5761016a565b80638456cb59116100b05780638456cb59146107465780638488bb4e1461075b5780638da5cb5b146107705761016a565b80636ed51c48146105e957806373c8a958146106255761016a565b80635c4fafc7116101225780635e6e9f70116101075780635e6e9f701461041657806361bd3851146105515780636b8f9c43146105b65761016a565b80635c4fafc7146103d85780635c975abb146103ed5761016a565b80632a8a45bc116101535780632a8a45bc146102a85780633f4ba83a14610390578063474f2891146103a75761016a565b80631323b0661461016f5780631793494c1461026c575b600080fd5b34801561017b57600080fd5b50610211600480360360a081101561019257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156101d257600080fd5b8201836020820111156101e457600080fd5b8035906020019184600183028401116401000000008311171561020657600080fd5b5090925090506109ad565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561025757818101518382015260200161023f565b50505050905001935050505060405180910390f35b34801561027857600080fd5b506102966004803603602081101561028f57600080fd5b5035610aa2565b60408051918252519081900360200190f35b3480156102b457600080fd5b506102d2600480360360208110156102cb57600080fd5b5035610ab4565b60405180878152602001868152602001858152602001846001600160a01b031681526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561033757818101518382015260200161031f565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561037657818101518382015260200161035e565b505050509050019850505050505050505060405180910390f35b34801561039c57600080fd5b506103a5610c59565b005b3480156103b357600080fd5b506103bc610cc7565b604080516001600160a01b039092168252519081900360200190f35b3480156103e457600080fd5b506103bc610ceb565b3480156103f957600080fd5b50610402610d03565b604080519115158252519081900360200190f35b34801561042257600080fd5b506103a56004803603606081101561043957600080fd5b8135919081019060408101602082013564010000000081111561045b57600080fd5b82018360208201111561046d57600080fd5b8035906020019184602083028401116401000000008311171561048f57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092959493602081019350359150506401000000008111156104df57600080fd5b8201836020820111156104f157600080fd5b8035906020019184602083028401116401000000008311171561051357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610d0c945050505050565b34801561055d57600080fd5b50610566610ee9565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105a257818101518382015260200161058a565b505050509050019250505060405180910390f35b3480156105c257600080fd5b506103a5600480360360208110156105d957600080fd5b50356001600160a01b0316610f44565b3480156105f557600080fd5b506103a56004803603608081101561060c57600080fd5b5080359060208101359060408101359060600135611011565b34801561063157600080fd5b506103a56004803603606081101561064857600080fd5b81019060208101813564010000000081111561066357600080fd5b82018360208201111561067557600080fd5b8035906020019184602083028401116401000000008311171561069757600080fd5b9193909290916020810190356401000000008111156106b557600080fd5b8201836020820111156106c757600080fd5b803590602001918460208302840111640100000000831117156106e957600080fd5b91939092909160208101903564010000000081111561070757600080fd5b82018360208201111561071957600080fd5b8035906020019184602083028401116401000000008311171561073b57600080fd5b509092509050611123565b34801561075257600080fd5b506103a5611210565b34801561076757600080fd5b506103bc611277565b34801561077c57600080fd5b506103bc611286565b34801561079157600080fd5b50610296611295565b6103a5600480360360a08110156107b057600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156107f057600080fd5b82018360208201111561080257600080fd5b8035906020019184600183028401116401000000008311171561082457600080fd5b50909250905061129b565b34801561083b57600080fd5b506103a5611381565b34801561085057600080fd5b506103a56004803603606081101561086757600080fd5b81019060208101813564010000000081111561088257600080fd5b82018360208201111561089457600080fd5b803590602001918460208302840111640100000000831117156108b657600080fd5b9193909290916020810190356401000000008111156108d457600080fd5b8201836020820111156108e657600080fd5b8035906020019184602083028401116401000000008311171561090857600080fd5b91939092909160208101903564010000000081111561092657600080fd5b82018360208201111561093857600080fd5b8035906020019184602083028401116401000000008311171561095a57600080fd5b509092509050611394565b34801561097157600080fd5b506102966114dc565b34801561098657600080fd5b506103a56004803603602081101561099d57600080fd5b50356001600160a01b03166114e2565b6000606060025460001415610a09576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b610a11611548565b610a19612da9565b610a216115a0565b6001600160a01b03908116825289811660208084019190915290891660408084019190915260608301899052608083018890528051601f870183900483028101830190915285815290869086908190840183828082843760009201919091525050505060a0820152610a92816115a4565b9250925050965096945050505050565b60076020526000908152604090205481565b6000818152600660205260408120819081908190606090819083610ada600483016115cb565b82549850905087610b32576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b60018201546002830154600384015491985096506001600160a01b031694508067ffffffffffffffff81118015610b6857600080fd5b50604051908082528060200260200182016040528015610b92578160200160208202803683370190505b5093508067ffffffffffffffff81118015610bac57600080fd5b50604051908082528060200260200182016040528015610bd6578160200160208202803683370190505b50925060005b81811015610c4d57600080610bf460048601846115cf565b915091508160001c878481518110610c0857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508060001c868481518110610c3857fe5b60209081029190910101525050600101610bdc565b50505091939550919395565b600254610cad576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b610cbd610cb86115a0565b611660565b610cc5611727565b565b7f00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d81565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b60035460ff1681565b610d17610cb86115a0565b815181518114610d6e576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20696e636f6e73697374656e742061727261797300000000000000604482015290519081900360640190fd5b60008481526006602052604090208054610dcf576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b6004810182610e1a576000610de3826115cb565b905060005b81811015610e13576000610dfc84826115cf565b509050610e09848261177f565b5050600101610de8565b5050610e25565b610e2581868661185f565b857fcb3fe5489e0cd43d0f4a33d1e09a4a0463a03d0d38f56165530854e5540db1438686604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610e8d578181015183820152602001610e75565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610ecc578181015183820152602001610eb4565b5050505090500194505050505060405180910390a2505050505050565b60606004600001805480602002602001604051908101604052809291908181526020018280548015610f3a57602002820191906000526020600020905b815481526020019060010190808311610f26575b5050505050905090565b610f4f610cb86115a0565b6001600160a01b038116610faa576040805162461bcd60e51b815260206004820152601460248201527f5061796f75743a207a65726f2061646472657373000000000000000000000000604482015290519081900360640190fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03838116919091179182905560408051929091168252517fdd880d24a789958a6398c99c2e54ce31bc10a638cbc42f7dd34285479ae0f855916020908290030190a150565b61101c610cb86115a0565b7f00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d6001600160a01b031663adebf6f2826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561108057600080fd5b505afa158015611094573d6000803e3d6000fd5b505050506040513d60208110156110aa57600080fd5b50516110fd576040805162461bcd60e51b815260206004820152601a60248201527f53616c653a206e6f7420612066756e6769626c6520746f6b656e000000000000604482015290519081900360640190fd5b600084815260076020526040812082905561111d908590859085906119c8565b50505050565b61112e610cb86115a0565b84838114801561113d57508082145b61118e576040805162461bcd60e51b815260206004820152601a60248201527f5265636f763a20696e636f6e73697374656e7420617272617973000000000000604482015290519081900360640190fd5b60005b818114611206576111fe8888838181106111a757fe5b905060200201356001600160a01b03168585848181106111c357fe5b905060200201358888858181106111d657fe5b905060200201356001600160a01b03166001600160a01b0316611bff9092919063ffffffff16565b600101611191565b5050505050505050565b600254611264576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b61126f610cb86115a0565b610cc5611c7f565b6001546001600160a01b031681565b6000546001600160a01b031690565b60001981565b6002546112ef576040805162461bcd60e51b815260206004820152601660248201527f537461727461626c653a206e6f74207374617274656400000000000000000000604482015290519081900360640190fd5b6112f7611548565b6112ff612da9565b6113076115a0565b6001600160a01b03908116825287811660208084019190915290871660408084019190915260608301879052608083018690528051601f850183900483028101830190915283815290849084908190840183828082843760009201919091525050505060a082015261137881611cbd565b50505050505050565b61138c610cb86115a0565b610cbd611cea565b61139f610cb86115a0565b8483811480156113ae57508082145b6113ff576040805162461bcd60e51b815260206004820152601a60248201527f5265636f763a20696e636f6e73697374656e7420617272617973000000000000604482015290519081900360640190fd5b60005b8181146112065785858281811061141557fe5b905060200201356001600160a01b03166001600160a01b03166323b872dd308a8a8581811061144057fe5b905060200201356001600160a01b031687878681811061145c57fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b1580156114b957600080fd5b505af11580156114cd573d6000803e3d6000fd5b50505050806001019050611402565b60025490565b6114ed610cb86115a0565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821780845560405192939116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60035460ff1615610cc5576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3390565b600060606115b183611d6c565b6115ba83612016565b505060c081015160e0909101519091565b5490565b815460009081908310611629576040805162461bcd60e51b815260206004820152601c60248201527f456e756d4d61703a20696e646578206f7574206f6620626f756e647300000000604482015290519081900360640190fd5b600084600001848154811061163a57fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b306001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561169957600080fd5b505afa1580156116ad573d6000803e3d6000fd5b505050506040513d60208110156116c357600080fd5b50516001600160a01b03828116911614611724576040805162461bcd60e51b815260206004820152601660248201527f4f776e61626c653a206e6f7420746865206f776e657200000000000000000000604482015290519081900360640190fd5b50565b61172f6120b3565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6117626115a0565b604080516001600160a01b039092168252519081900360200190a1565b6000818152600183016020526040812054801561185357835460001980830191908101906000908790839081106117b257fe5b90600052602060002090600202019050808760000184815481106117d257fe5b60009182526020808320845460029093020191825560019384015491840191909155835482528983019052604090209084019055865487908061181157fe5b60008281526020808220600260001990940193840201828155600190810183905592909355888152898201909252604082209190915594506118599350505050565b60009150505b92915050565b60005b825181101561194557600083828151811061187957fe5b6020026020010151905060006001600160a01b0316816001600160a01b031614156118eb576040805162461bcd60e51b815260206004820152601860248201527f53616c653a207a65726f206164647265737320746f6b656e0000000000000000604482015290519081900360640190fd5b60008383815181106118f957fe5b6020026020010151905080600014156119255761191f866001600160a01b03841661177f565b5061193b565b611939866001600160a01b0384168361210a565b505b5050600101611862565b507f000000000000000000000000000000000000000000000000000000000000000a611970846115cb565b11156119c3576040805162461bcd60e51b815260206004820152601560248201527f53616c653a20746f6f206d616e7920746f6b656e730000000000000000000000604482015290519081900360640190fd5b505050565b82611a1a576040805162461bcd60e51b815260206004820152601160248201527f53616c653a207a65726f20737570706c79000000000000000000000000000000604482015290519081900360640190fd5b7f0000000000000000000000000000000000000000000000000000000000000019611a4560046115cb565b10611a97576040805162461bcd60e51b815260206004820152601360248201527f53616c653a20746f6f206d616e7920736b757300000000000000000000000000604482015290519081900360640190fd5b611aa26004856121a4565b611af3576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20736b7520616c7265616479206372656174656400000000000000604482015290519081900360640190fd5b6001600160a01b03811615611b6557611b14816001600160a01b03166121ee565b611b65576040805162461bcd60e51b815260206004820152601b60248201527f53616c653a206e6f6e2d636f6e74726163742072656365697665720000000000604482015290519081900360640190fd5b60008481526006602090815260409182902085815560018101869055600281018590556003810180546001600160a01b03861673ffffffffffffffffffffffffffffffffffffffff1990911681179091558351888152928301879052828401869052606083015291517f38bd4aabce684540cd61351b91f2f5facf9d6963934347e25aab93d87ae7ac149181900360800190a15050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526119c39084906121f4565b611c87611548565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586117626115a0565b611cc681611d6c565b611ccf81612016565b611cd8816123fc565b611ce18161254b565b6117248161261f565b60025415611d3f576040805162461bcd60e51b815260206004820152601260248201527f537461727461626c653a20737461727465640000000000000000000000000000604482015290519081900360640190fd5b426002557f27029695aa5f602a4ee81f4c32dfa86e562f200a17966496f3a7c3f2ec0f94176117626115a0565b60208101516001600160a01b0316611dcb576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a207a65726f206164647265737320726563697069656e7400000000604482015290519081900360640190fd5b60408101516001600160a01b0316611e2a576040805162461bcd60e51b815260206004820152601860248201527f53616c653a207a65726f206164647265737320746f6b656e0000000000000000604482015290519081900360640190fd5b6080810151611e80576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a207a65726f207175616e7469747920707572636861736500000000604482015290519081900360640190fd5b606081015160009081526006602052604090208054611ee6576040805162461bcd60e51b815260206004820152601660248201527f53616c653a206e6f6e2d6578697374656e7420736b7500000000000000000000604482015290519081900360640190fd5b816080015181600201541015611f43576040805162461bcd60e51b815260206004820152601860248201527f53616c653a2061626f7665206d6178207175616e746974790000000000000000604482015290519081900360640190fd5b805460001914611faa57816080015181600101541015611faa576040805162461bcd60e51b815260206004820152601960248201527f53616c653a20696e73756666696369656e7420737570706c7900000000000000604482015290519081900360640190fd5b60408201516001600160a01b0316611fc56004830182612b08565b6119c3576040805162461bcd60e51b815260206004820152601c60248201527f53616c653a206e6f6e2d6578697374656e7420736b7520746f6b656e00000000604482015290519081900360640190fd5b60608101516000908152600660205260409020805461207c576040805162461bcd60e51b815260206004820152601560248201527f53616c653a20756e737570706f7274656420534b550000000000000000000000604482015290519081900360640190fd5b60048101600061208c8483612b20565b90506120a5846080015182612b9090919063ffffffff16565b60c090940193909352505050565b60035460ff16610cc5576040805162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b60008281526001840160205260408120548061216f57505060408051808201825283815260208082018481528654600181810189556000898152848120955160029093029095019182559151908201558654868452818801909252929091205561219d565b8285600001600183038154811061218257fe5b90600052602060002090600202016001018190555060009150505b9392505050565b60006121b08383612b08565b6121e657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611859565b506000611859565b3b151590565b816122076001600160a01b0382166121ee565b612258576040805162461bcd60e51b815260206004820152601a60248201527f4552433230577261707065723a206e6f6e2d636f6e7472616374000000000000604482015290519081900360640190fd5b600080826001600160a01b0316846040518082805190602001908083835b602083106122b357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612276565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612315576040519150601f19603f3d011682016040523d82523d6000602084013e61231a565b606091505b50915091508115612399578051156123945780806020019051602081101561234157600080fd5b5051612394576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b6123f5565b80516123ec576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b80518082602001fd5b5050505050565b60408101516001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561251f578060c0015134101561247e576040805162461bcd60e51b815260206004820152601660248201527f53616c653a20696e73756666696369656e742045544800000000000000000000604482015290519081900360640190fd5b60015460c08201516040516001600160a01b039092169181156108fc0291906000818181858888f193505050501580156124bc573d6000803e3d6000fd5b5060006124d68260c0015134612be990919063ffffffff16565b905080156125195781516040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015612517573d6000803e3d6000fd5b505b50611724565b61172461252a6115a0565b60015460c084015160408501516001600160a01b0390811693921690612c46565b61255481612cce565b60208181015160608301516000908152600790925260408083205460808086015183517f5cfa92970000000000000000000000000000000000000000000000000000000081526001600160a01b0395861660048201526024810193909352604483015260648201526084810184905290517f00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d90921692635cfa92979260a48084019382900301818387803b15801561260b57600080fd5b505af11580156123f5573d6000803e3d6000fd5b806060015181604001516001600160a01b031682600001516001600160a01b03167f29f844483ca6b10b5c0611d039afc15ce8f6380e905307b381c3a8ee4e90e11e846020015185608001518660a001518760c001518860e001518961010001518a610120015160405160200180848051906020019060200280838360005b838110156126b657818101518382015260200161269e565b50505050905001838051906020019060200280838360005b838110156126e65781810151838201526020016126ce565b50505050905001828051906020019060200280838360005b838110156127165781810151838201526020016126fe565b50505050905001935050505060405160208183030381529060405260405180866001600160a01b031681526020018581526020018060200184815260200180602001838103835286818151815260200191508051906020019080838360005b8381101561278d578181015183820152602001612775565b50505050905090810190601f1680156127ba5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156127ed5781810151838201526020016127d5565b50505050905090810190601f16801561281a5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a460608101516000908152600660205260409020600301546001600160a01b03168015612b04576361eceae860e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916816001600160a01b03166361eceae8846000015185602001518660400151876060015188608001518960a001518a60c001518b60e001518c61010001518d61012001516040518b63ffffffff1660e01b8152600401808b6001600160a01b031681526020018a6001600160a01b03168152602001896001600160a01b031681526020018881526020018781526020018060200186815260200180602001806020018060200185810385528a818151815260200191508051906020019080838360005b8381101561295357818101518382015260200161293b565b50505050905090810190601f1680156129805780820380516001836020036101000a031916815260200191505b508581038452885181528851602091820191808b01910280838360005b838110156129b557818101518382015260200161299d565b50505050905001858103835287818151815260200191508051906020019060200280838360005b838110156129f45781810151838201526020016129dc565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015612a33578181015183820152602001612a1b565b505050509050019e505050505050505050505050505050602060405180830381600087803b158015612a6457600080fd5b505af1158015612a78573d6000803e3d6000fd5b505050506040513d6020811015612a8e57600080fd5b50517fffffffff000000000000000000000000000000000000000000000000000000001614612b04576040805162461bcd60e51b815260206004820152601a60248201527f53616c653a206e6f74696669636174696f6e2072656675736564000000000000604482015290519081900360640190fd5b5050565b60009081526001919091016020526040902054151590565b6040820151600090612b3c9083906001600160a01b0316612d19565b905080611859576040805162461bcd60e51b815260206004820152601f60248201527f53616c653a20756e737570706f72746564207061796d656e7420746f6b656e00604482015290519081900360640190fd5b600082612b9f57506000611859565b82820282848281612bac57fe5b041461219d5760405162461bcd60e51b8152600401808060200182810382526021815260200180612e1b6021913960400191505060405180910390fd5b600082821115612c40576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261111d9085906121f4565b60608101516000908152600660205260409020805460001914612b045760808201516001820154612cfe91612be9565b60608301516000908152600660205260409020600101555050565b600081815260018301602052604081205480612d7c576040805162461bcd60e51b815260206004820152601860248201527f456e756d4d61703a206e6f6e6578697374656e74206b65790000000000000000604482015290519081900360640190fd5b836000016001820381548110612d8e57fe5b90600052602060002090600202016001015491505092915050565b60405180610140016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008019168152602001600081526020016060815260200160008152602001606081526020016060815260200160608152509056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212204d8cb75b26991c2fd95de34bbfcb733e5c728a2668a653399596a37a352a4c8564736f6c63430007060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d00000000000000000000000039fa29ede121b06dce3674e97970caa539afc9570000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000000a
-----Decoded View---------------
Arg [0] : vouchersContract_ (address): 0x87a3747C9942d8351Cc85AaC2f94807B27A37c0D
Arg [1] : payoutWallet (address): 0x39FA29EdE121b06dCe3674E97970caa539AFc957
Arg [2] : skusCapacity (uint256): 25
Arg [3] : tokensPerSkuCapacity (uint256): 10
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000087a3747c9942d8351cc85aac2f94807b27a37c0d
Arg [1] : 00000000000000000000000039fa29ede121b06dce3674e97970caa539afc957
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000019
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000a
Deployed Bytecode Sourcemap
70469:2422: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;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70604:46;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;70604:46:0;;:::i;:::-;;;;;;;;;;;;;;;;54089:1056;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54089:1056:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;54089:1056:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47657:117;;;;;;;;;;;;;:::i;:::-;;70544:51;;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;70544: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;72235:402::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72235:402: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;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;70604:46::-;;;;;;;;;;;;;:::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;47657:117::-;19863:10;;19855:50;;;;;-1:-1:-1;;;19855:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;47714:31:::1;47732:12;:10;:12::i;:::-;47714:17;:31::i;:::-;47756:10;:8;:10::i;:::-;47657:117::o:0;70544: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;72235:402::-;72400:31;72418:12;:10;:12::i;72400:31::-;72450:16;-1:-1:-1;;;;;72450:27:0;;72478:7;72450:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72450:36:0;72442:75;;;;;-1:-1:-1;;;72442:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;72528:16;;;;:11;:16;;;;;:26;;;72565:64;;72540:3;;72581:11;;72594:22;;72565:10;:64::i;:::-;72235:402;;;;:::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;;;;68166:492;;;;;;;:::o;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;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;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;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;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;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;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;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;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;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;72671:217::-;72749:25;72765:8;72749:15;:25::i;:::-;72811:18;;;;;72843:12;;;;72831:25;;;;:11;:25;;;;;;;;72858:17;;;;;72785:95;;;;;-1:-1:-1;;;;;72785:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:16;:25;;;;;;:95;;;;;;;;;;72831:25;72785;:95;;;;;;;;;;;;;;;;;;;;;;;;;;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;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
Swarm Source
ipfs://4d8cb75b26991c2fd95de34bbfcb733e5c728a2668a653399596a37a352a4c85
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.