Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
ETHWasabiPool
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-04-24 */ // File: contracts/IWasabiPoolFactory.sol // SPDX-License-Identifier: MIT pragma solidity 0.8.19; /** * @dev Required interface of an WasabiPoolFactory compliant contract. */ interface IWasabiPoolFactory { /** * @dev The States of Pools */ enum PoolState { INVALID, ACTIVE, DISABLED } /** * @dev Emitted when there is a new pool created */ event NewPool(address poolAddress, address indexed nftAddress, address indexed owner); /** * @dev INVALID/ACTIVE/DISABLE the specified pool. */ function togglePool(address _poolAddress, PoolState _poolState) external; /** * @dev Checks if the pool for the given address is enabled. */ function isValidPool(address _poolAddress) external view returns(bool); /** * @dev Returns the PoolState */ function getPoolState(address _poolAddress) external view returns(PoolState); /** * @dev Returns IWasabiConduit Contract Address. */ function getConduitAddress() external view returns(address); /** * @dev Returns IWasabiFeeManager Contract Address. */ function getFeeManager() external view returns(address); } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: contracts/fees/IWasabiFeeManager.sol /** * @dev Required interface of an Wasabi Fee Manager compliant contract. */ interface IWasabiFeeManager { /** * @dev Returns the fee data for the given pool and amount * @param _pool the pool address * @param _amount the amount being paid * @return receiver the receiver of the fee * @return amount the fee amount */ function getFeeData(address _pool, uint256 _amount) external view returns (address receiver, uint256 amount); /** * @dev Returns the fee data for the given option and amount * @param _optionId the option id * @param _amount the amount being paid * @return receiver the receiver of the fee * @return amount the fee amount */ function getFeeDataForOption(uint256 _optionId, uint256 _amount) external view returns (address receiver, uint256 amount); } // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } // File: @openzeppelin/contracts/utils/introspection/IERC165.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: @openzeppelin/contracts/token/ERC721/IERC721.sol // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); } // File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) /** * @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 EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. * ==== */ library EnumerableSet { // 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. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // 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) private 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) private 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; if (lastIndex != toDeleteIndex) { 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] = valueIndex; // Replace lastValue's index to valueIndex } // 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) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private 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) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @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(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @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(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @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(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @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(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @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(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @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(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @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(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @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(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @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(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } } // File: @openzeppelin/contracts/security/ReentrancyGuard.sol // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File: contracts/lib/WasabiStructs.sol library WasabiStructs { enum OptionType { CALL, PUT } struct OptionData { bool active; OptionType optionType; uint256 strikePrice; uint256 expiry; uint256 tokenId; // Locked token for CALL options } struct PoolAsk { uint256 id; address poolAddress; OptionType optionType; uint256 strikePrice; uint256 premium; uint256 expiry; uint256 tokenId; // Token to lock for CALL options uint256 orderExpiry; } struct PoolBid { uint256 id; uint256 price; address tokenAddress; uint256 orderExpiry; uint256 optionId; } struct Bid { uint256 id; uint256 price; address tokenAddress; address collection; uint256 orderExpiry; address buyer; OptionType optionType; uint256 strikePrice; uint256 expiry; uint256 expiryAllowance; address optionTokenAddress; } struct Ask { uint256 id; uint256 price; address tokenAddress; uint256 orderExpiry; address seller; uint256 optionId; } struct EIP712Domain { string name; string version; uint256 chainId; address verifyingContract; } struct ExecutionInfo { address module; bytes data; uint256 value; } } // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); } // File: @openzeppelin/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } } // File: @openzeppelin/contracts/utils/introspection/ERC165.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: @openzeppelin/contracts/token/ERC721/ERC721.sol // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol) /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} } // File: @openzeppelin/contracts/interfaces/IERC2981.sol // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); } // File: contracts/IWasabiPool.sol /** * @dev Required interface of an WasabiPool compliant contract. */ interface IWasabiPool is IERC165, IERC721Receiver { /** * @dev Emitted when `admin` is changed. */ event AdminChanged(address admin); /** * @dev Emitted when an order is cancelled. */ event OrderCancelled(uint256 id); /** * @dev Emitted when a pool bid is taken */ event PoolBidTaken(uint256 id); /** * @dev Emitted when an ERC721 is received */ event ERC721Received(uint256 tokenId); /** * @dev Emitted when ETH is received */ event ETHReceived(uint amount); /** * @dev Emitted when ERC20 is received */ event ERC20Received(uint amount); /** * @dev Emitted when an ERC721 is withdrawn */ event ERC721Withdrawn(uint256 tokenId); /** * @dev Emitted when ERC20 is withdrawn */ event ERC20Withdrawn(uint amount); /** * @dev Emitted when ETH is withdrawn */ event ETHWithdrawn(uint amount); /** * @dev Emitted when an option is executed. */ event OptionExecuted(uint256 optionId); /** * @dev Emitted when an option is issued */ event OptionIssued(uint256 optionId, uint256 price); /** * @dev Emitted when an option is issued */ event OptionIssued(uint256 optionId, uint256 price, uint256 poolAskId); /** * @dev Emitted when the pool settings are edited */ event PoolSettingsChanged(); /** * @dev Returns the address of the nft */ function getNftAddress() external view returns(address); /** * @dev Returns the address of the nft */ function getLiquidityAddress() external view returns(address); /** * @dev Writes an option for the given ask. */ function writeOption( WasabiStructs.PoolAsk calldata _request, bytes calldata _signature ) external payable returns (uint256); /** * @dev Writes an option for the given rule and buyer. */ function writeOptionTo( WasabiStructs.PoolAsk calldata _request, bytes calldata _signature, address _receiver ) external payable returns (uint256); /** * @dev Executes the option for the given id. */ function executeOption(uint256 _optionId) external payable; /** * @dev Executes the option for the given id. */ function executeOptionWithSell(uint256 _optionId, uint256 _tokenId) external payable; /** * @dev Cancels the order for the given _orderId. */ function cancelOrder(uint256 _orderId) external; /** * @dev Withdraws ERC721 tokens from the pool. */ function withdrawERC721(IERC721 _nft, uint256[] calldata _tokenIds) external; /** * @dev Deposits ERC721 tokens to the pool. */ function depositERC721(IERC721 _nft, uint256[] calldata _tokenIds) external; /** * @dev Withdraws ETH from this pool */ function withdrawETH(uint256 _amount) external payable; /** * @dev Withdraws ERC20 tokens from this pool */ function withdrawERC20(IERC20 _token, uint256 _amount) external; /** * @dev Sets the admin of this pool. */ function setAdmin(address _admin) external; /** * @dev Removes the admin from this pool. */ function removeAdmin() external; /** * @dev Returns the address of the current admin. */ function getAdmin() external view returns (address); /** * @dev Returns the address of the factory managing this pool */ function getFactory() external view returns (address); /** * @dev Returns the available balance this pool contains that can be withdrawn or collateralized */ function availableBalance() view external returns(uint256); /** * @dev Returns an array of ids of all outstanding (issued or expired) options */ function getOptionIds() external view returns(uint256[] memory); /** * @dev Returns the id of the option that locked the given token id, reverts if there is none */ function getOptionIdForToken(uint256 _tokenId) external view returns(uint256); /** * @dev Returns the option data for the given option id */ function getOptionData(uint256 _optionId) external view returns(WasabiStructs.OptionData memory); /** * @dev Returns 'true' if the option for the given id is valid and active, 'false' otherwise */ function isValid(uint256 _optionId) view external returns(bool); /** * @dev Checks if _tokenId unlocked */ function isAvailableTokenId(uint256 _tokenId) external view returns(bool); /** * @dev Clears the expired options from the pool */ function clearExpiredOptions(uint256[] memory _optionIds) external; /** * @dev accepts the bid for LPs with _tokenId. If its a put option, _tokenId can be 0 */ function acceptBid(WasabiStructs.Bid calldata _bid, bytes calldata _signature, uint256 _tokenId) external returns(uint256); /** * @dev accepts the ask for LPs */ function acceptAsk(WasabiStructs.Ask calldata _ask, bytes calldata _signature) external; /** * @dev accepts a bid created for this pool */ function acceptPoolBid(WasabiStructs.PoolBid calldata _poolBid, bytes calldata _signature) external payable; } // File: contracts/WasabiOption.sol /** * @dev An ERC721 which tracks Wasabi Option positions of accounts */ contract WasabiOption is ERC721, IERC2981, Ownable { address private lastFactory; mapping(address => bool) private factoryAddresses; mapping(uint256 => address) private optionPools; uint256 private _currentId = 1; string private _baseURIextended; /** * @dev Constructs WasabiOption */ constructor() ERC721("Wasabi Option NFTs", "WASAB") {} /** * @dev Toggles the owning factory */ function toggleFactory(address _factory, bool _enabled) external onlyOwner { factoryAddresses[_factory] = _enabled; if (_enabled) { lastFactory = _factory; } } /** * @dev Mints a new WasabiOption */ function mint(address _to, address _factory) external returns (uint256 mintedId) { require(factoryAddresses[_factory] == true, "Invalid Factory"); require(IWasabiPoolFactory(_factory).isValidPool(_msgSender()), "Only valid pools can mint"); _safeMint(_to, _currentId); mintedId = _currentId; optionPools[mintedId] = _msgSender(); _currentId++; } /** * @dev Burns the specified option */ function burn(uint256 _optionId) external { require(optionPools[_optionId] == _msgSender(), "Caller can't burn option"); _burn(_optionId); } /** * @dev Sets the base URI */ function setBaseURI(string memory baseURI_) external onlyOwner { _baseURIextended = baseURI_; } /** * @dev Returns the address of the pool which created the given option */ function getPool(uint256 _optionId) external view returns (address) { return optionPools[_optionId]; } /// @inheritdoc ERC721 function _baseURI() internal view virtual override returns (string memory) { return _baseURIextended; } /// @inheritdoc IERC2981 function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view returns (address, uint256) { IWasabiPool pool = IWasabiPool(optionPools[_tokenId]); IWasabiPoolFactory factory = IWasabiPoolFactory(pool.getFactory()); IWasabiFeeManager feeManager = IWasabiFeeManager(factory.getFeeManager()); return feeManager.getFeeDataForOption(_tokenId, _salePrice); } /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) public view override(ERC721, IERC165) returns (bool) { return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } } // File: contracts/IWasabiConduit.sol /** * @dev Required interface of an WasabiConduit compliant contract. */ interface IWasabiConduit { /** * @dev Buys multiple options */ function buyOptions( WasabiStructs.PoolAsk[] calldata _requests, WasabiStructs.Ask[] calldata _asks, bytes[] calldata _signatures ) external payable returns (uint256[] memory); /** * @dev Buys an option */ function buyOption( WasabiStructs.PoolAsk calldata _request, bytes calldata _signature ) external payable returns (uint256); /** * @dev Transfers a NFT to _target * * @param _nft the address of NFT * @param _tokenId the tokenId to transfer * @param _target the target to transfer the NFT */ function transferToken( address _nft, uint256 _tokenId, address _target ) external; /** * @dev Sets Option information */ function setOption(WasabiOption _option) external; /** * @dev Sets maximum number of option to buy */ function setMaxOptionsToBuy(uint256 _maxOptionsToBuy) external; /** * @dev Sets pool factory address */ function setPoolFactoryAddress(address _factory) external; /** * @dev Accpets the Ask */ function acceptAsk( WasabiStructs.Ask calldata _ask, bytes calldata _signature ) external payable returns (uint256); /** * @dev Accpets the Bid */ function acceptBid( uint256 _optionId, address _poolAddress, WasabiStructs.Bid calldata _bid, bytes calldata _signature ) external payable; /** * @dev Pool Accepts the _bid */ function poolAcceptBid(WasabiStructs.Bid calldata _bid, bytes calldata _signature, uint256 _optionId) external; /** * @dev Cancel the _ask */ function cancelAsk( WasabiStructs.Ask calldata _ask, bytes calldata _signature ) external; /** * @dev Cancel the _bid */ function cancelBid( WasabiStructs.Bid calldata _bid, bytes calldata _signature ) external; } // File: contracts/IWasabiErrors.sol /** * @dev Required interface for defining all the errors */ interface IWasabiErrors { /** * @dev Thrown when an order that has been filled or cancelled is being acted upon */ error OrderFilledOrCancelled(); /** * @dev Thrown when someone tries to make an unauthorized request */ error Unauthorized(); /** * @dev Thrown when a signature is invalid */ error InvalidSignature(); /** * @dev Thrown when there is no sufficient available liquidity left in the pool for issuing a PUT option */ error InsufficientAvailableLiquidity(); /** * @dev Thrown when the requested NFT for a CALL is already locked for another option */ error RequestNftIsLocked(); /** * @dev Thrown when the NFT is not in the pool or invalid */ error NftIsInvalid(); /** * @dev Thrown when the expiry of an ask is invalid for the pool */ error InvalidExpiry(); /** * @dev Thrown when the strike price of an ask is invalid for the pool */ error InvalidStrike(); /** * @dev Thrown when an expired order or option is being exercised */ error HasExpired(); /** * @dev Thrown when sending ETH failed */ error FailedToSend(); } // File: contracts/lib/Signing.sol /** * @dev Signature Verification */ library Signing { /** * @dev Returns the message hash for the given request */ function getMessageHash(WasabiStructs.PoolAsk calldata _request) public pure returns (bytes32) { return keccak256( abi.encode( _request.id, _request.poolAddress, _request.optionType, _request.strikePrice, _request.premium, _request.expiry, _request.tokenId, _request.orderExpiry)); } /** * @dev Returns the message hash for the given request */ function getAskHash(WasabiStructs.Ask calldata _ask) public pure returns (bytes32) { return keccak256( abi.encode( _ask.id, _ask.price, _ask.tokenAddress, _ask.orderExpiry, _ask.seller, _ask.optionId)); } function getBidHash(WasabiStructs.Bid calldata _bid) public pure returns (bytes32) { return keccak256( abi.encode( _bid.id, _bid.price, _bid.tokenAddress, _bid.collection, _bid.orderExpiry, _bid.buyer, _bid.optionType, _bid.strikePrice, _bid.expiry, _bid.expiryAllowance)); } /** * @dev creates an ETH signed message hash */ function getEthSignedMessageHash(bytes32 _messageHash) public pure returns (bytes32) { /* Signature is produced by signing a keccak256 hash with the following format: "\x19Ethereum Signed Message\n" + len(msg) + msg */ return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash)); } function getSigner( WasabiStructs.PoolAsk calldata _request, bytes memory signature ) public pure returns (address) { bytes32 messageHash = getMessageHash(_request); bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash); return recoverSigner(ethSignedMessageHash, signature); } function getAskSigner( WasabiStructs.Ask calldata _ask, bytes memory signature ) public pure returns (address) { bytes32 messageHash = getAskHash(_ask); bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash); return recoverSigner(ethSignedMessageHash, signature); } function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature) public pure returns (address) { (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature); return ecrecover(_ethSignedMessageHash, v, r, s); } function splitSignature(bytes memory sig) public pure returns ( bytes32 r, bytes32 s, uint8 v ) { require(sig.length == 65, "invalid signature length"); assembly { /* First 32 bytes stores the length of the signature add(sig, 32) = pointer of sig + 32 effectively, skips first 32 bytes of signature mload(p) loads next 32 bytes starting at the memory address p into memory */ // first 32 bytes, after the length prefix r := mload(add(sig, 32)) // second 32 bytes s := mload(add(sig, 64)) // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } // implicitly return (r, s, v) } } // File: contracts/lib/PoolAskVerifier.sol /** * @dev Signature Verification for PoolAsk */ library PoolAskVerifier { bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); bytes32 constant POOLASK_TYPEHASH = keccak256( "PoolAsk(uint256 id,address poolAddress,uint8 optionType,uint256 strikePrice,uint256 premium,uint256 expiry,uint256 tokenId,uint256 orderExpiry)" ); /** * @dev Creates the hash of the EIP712 domain for this validator * * @param _eip712Domain the domain to hash * @return the hashed domain */ function hashDomain( WasabiStructs.EIP712Domain memory _eip712Domain ) internal pure returns (bytes32) { return keccak256( abi.encode( EIP712DOMAIN_TYPEHASH, keccak256(bytes(_eip712Domain.name)), keccak256(bytes(_eip712Domain.version)), _eip712Domain.chainId, _eip712Domain.verifyingContract ) ); } /** * @dev Creates the hash of the PoolAsk for this validator * * @param _poolAsk to hash * @return the poolAsk domain */ function hashForPoolAsk( WasabiStructs.PoolAsk memory _poolAsk ) public pure returns (bytes32) { return keccak256( abi.encode( POOLASK_TYPEHASH, _poolAsk.id, _poolAsk.poolAddress, _poolAsk.optionType, _poolAsk.strikePrice, _poolAsk.premium, _poolAsk.expiry, _poolAsk.tokenId, _poolAsk.orderExpiry ) ); } /** * @dev Gets the signer of the given signature for the given _poolAsk * * @param _poolAsk the ask to validate * @param _signature the signature to validate * @return address who signed the signature */ function getSignerForPoolAsk( WasabiStructs.PoolAsk memory _poolAsk, bytes memory _signature ) public view returns (address) { bytes32 domainSeparator = hashDomain( WasabiStructs.EIP712Domain({ name: "PoolAskSignature", version: "1", chainId: getChainID(), verifyingContract: address(this) }) ); bytes32 digest = keccak256( abi.encodePacked("\x19\x01", domainSeparator, hashForPoolAsk(_poolAsk)) ); return Signing.recoverSigner(digest, _signature); } /** * @dev Checks the signer of the given signature for the given poolAsk is the given signer * * @param _poolAsk the _poolAsk to validate * @param _signature the signature to validate * @param _signer the signer to validate * @return true if the signature belongs to the signer, false otherwise */ function verifyPoolAsk( WasabiStructs.PoolAsk memory _poolAsk, bytes memory _signature, address _signer ) internal view returns (bool) { return getSignerForPoolAsk(_poolAsk, _signature) == _signer; } /** * @return the current chain id */ function getChainID() internal view returns (uint256) { uint256 id; assembly { id := chainid() } return id; } } // File: contracts/lib/PoolBidVerifier.sol /** * @dev Signature Verification for PoolBid */ library PoolBidVerifier { bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); bytes32 constant POOLBID_TYPEHASH = keccak256( "PoolBid(uint256 id,uint256 price,address tokenAddress,uint256 orderExpiry,uint256 optionId)" ); /** * @dev Creates the hash of the EIP712 domain for this validator * * @param _eip712Domain the domain to hash * @return the hashed domain */ function hashDomain( WasabiStructs.EIP712Domain memory _eip712Domain ) internal pure returns (bytes32) { return keccak256( abi.encode( EIP712DOMAIN_TYPEHASH, keccak256(bytes(_eip712Domain.name)), keccak256(bytes(_eip712Domain.version)), _eip712Domain.chainId, _eip712Domain.verifyingContract ) ); } /** * @dev Creates the hash of the PoolBid for this validator * * @param _poolBid to hash * @return the poolBid hash */ function hashForPoolBid( WasabiStructs.PoolBid memory _poolBid ) public pure returns (bytes32) { return keccak256( abi.encode( POOLBID_TYPEHASH, _poolBid.id, _poolBid.price, _poolBid.tokenAddress, _poolBid.orderExpiry, _poolBid.optionId ) ); } /** * @dev Gets the signer of the given signature for the given _poolBid * * @param _poolBid the bid to validate * @param _signature the signature to validate * @return address who signed the signature */ function getSignerForPoolBid( WasabiStructs.PoolBid memory _poolBid, bytes memory _signature ) public view returns (address) { bytes32 domainSeparator = hashDomain( WasabiStructs.EIP712Domain({ name: "PoolBidVerifier", version: "1", chainId: getChainID(), verifyingContract: address(this) }) ); bytes32 digest = keccak256( abi.encodePacked("\x19\x01", domainSeparator, hashForPoolBid(_poolBid)) ); return Signing.recoverSigner(digest, _signature); } /** * @dev Checks the signer of the given signature for the given _poolBid is the given signer * * @param _poolBid the bid to validate * @param _signature the signature to validate * @param _signer the signer to validate * @return true if the signature belongs to the signer, false otherwise */ function verifyPoolBid( WasabiStructs.PoolBid memory _poolBid, bytes memory _signature, address _signer ) internal view returns (bool) { return getSignerForPoolBid(_poolBid, _signature) == _signer; } /** * @return the current chain id */ function getChainID() internal view returns (uint256) { uint256 id; assembly { id := chainid() } return id; } } // File: contracts/AbstractWasabiPool.sol /** * An base abstract implementation of the IWasabiPool which handles issuing and exercising options alond with state management. */ abstract contract AbstractWasabiPool is IERC721Receiver, Ownable, IWasabiPool, ReentrancyGuard { using EnumerableSet for EnumerableSet.UintSet; // Pool metadata IWasabiPoolFactory public factory; WasabiOption private optionNFT; IERC721 private nft; address private admin; // Option state EnumerableSet.UintSet private optionIds; mapping(uint256 => uint256) private tokenIdToOptionId; mapping(uint256 => WasabiStructs.OptionData) private options; mapping(uint256 => bool) public idToFilledOrCancelled; receive() external payable virtual {} fallback() external payable { require(false, "No fallback"); } /** * @dev Initializes this pool */ function baseInitialize( IWasabiPoolFactory _factory, IERC721 _nft, address _optionNFT, address _owner, address _admin ) internal { require(owner() == address(0), "Already initialized"); factory = _factory; _transferOwnership(_owner); nft = _nft; optionNFT = WasabiOption(_optionNFT); if (_admin != address(0)) { admin = _admin; emit AdminChanged(_admin); } } /// @inheritdoc IWasabiPool function getNftAddress() external view returns(address) { return address(nft); } /// @inheritdoc IWasabiPool function getLiquidityAddress() public view virtual returns(address) { return address(0); } /// @inheritdoc IWasabiPool function setAdmin(address _admin) external onlyOwner { admin = _admin; emit AdminChanged(_admin); } /// @inheritdoc IWasabiPool function removeAdmin() external onlyOwner { admin = address(0); emit AdminChanged(address(0)); } /// @inheritdoc IWasabiPool function getAdmin() public view virtual returns (address) { return admin; } /// @inheritdoc IWasabiPool function getFactory() external view returns (address) { return address(factory); } /** * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address /* operator */, address /* from */, uint256 tokenId, bytes memory /* data */) public virtual override returns (bytes4) { if (_msgSender() == address(optionNFT)) { if (!optionIds.contains(tokenId)) { revert IWasabiErrors.NftIsInvalid(); } clearOption(tokenId, 0, false); } else if (_msgSender() != address(nft)) { revert IWasabiErrors.NftIsInvalid(); } return this.onERC721Received.selector; } /// @inheritdoc IWasabiPool function writeOptionTo( WasabiStructs.PoolAsk calldata _request, bytes calldata _signature, address _receiver ) public payable nonReentrant returns (uint256) { if (idToFilledOrCancelled[_request.id]) { revert IWasabiErrors.OrderFilledOrCancelled(); } validate(_request, _signature); uint256 optionId = optionNFT.mint(_receiver, address(factory)); WasabiStructs.OptionData memory optionData = WasabiStructs.OptionData( true, _request.optionType, _request.strikePrice, _request.expiry, _request.tokenId ); options[optionId] = optionData; // Lock NFT / Token into a vault if (_request.optionType == WasabiStructs.OptionType.CALL) { tokenIdToOptionId[_request.tokenId] = optionId; } optionIds.add(optionId); idToFilledOrCancelled[_request.id] = true; emit OptionIssued(optionId, _request.premium, _request.id); return optionId; } /// @inheritdoc IWasabiPool function writeOption( WasabiStructs.PoolAsk calldata _request, bytes calldata _signature ) external payable returns (uint256) { return writeOptionTo(_request, _signature, _msgSender()); } /** * @dev Validates the given PoolAsk in order to issue an option */ function validate(WasabiStructs.PoolAsk calldata _request, bytes calldata _signature) internal { // 1. Validate Signature address signer = PoolAskVerifier.getSignerForPoolAsk(_request, _signature); if (signer == address(0) || (signer != admin && signer != owner())) { revert IWasabiErrors.InvalidSignature(); } // 2. Validate Meta if (_request.orderExpiry < block.timestamp) { revert IWasabiErrors.HasExpired(); } require(_request.poolAddress == address(this), "WasabiPool: Signature doesn't belong to this pool"); validateAndWithdrawPayment(_request.premium, "WasabiPool: Not enough premium is supplied"); // 3. Request Validation if (_request.strikePrice == 0) { revert IWasabiErrors.InvalidStrike(); } if (_request.expiry == 0) { revert IWasabiErrors.InvalidExpiry(); } // 4. Type specific validation if (_request.optionType == WasabiStructs.OptionType.CALL) { if (nft.ownerOf(_request.tokenId) != address(this)) { revert IWasabiErrors.NftIsInvalid(); } // Check that the token is free uint256 optionId = tokenIdToOptionId[_request.tokenId]; if (isValid(optionId)) { revert IWasabiErrors.RequestNftIsLocked(); } } else if (_request.optionType == WasabiStructs.OptionType.PUT) { if (availableBalance() < _request.strikePrice) { revert IWasabiErrors.InsufficientAvailableLiquidity(); } } } /// @inheritdoc IWasabiPool function executeOption(uint256 _optionId) external payable nonReentrant { validateOptionForExecution(_optionId, 0); clearOption(_optionId, 0, true); emit OptionExecuted(_optionId); } /// @inheritdoc IWasabiPool function executeOptionWithSell(uint256 _optionId, uint256 _tokenId) external payable nonReentrant { validateOptionForExecution(_optionId, _tokenId); clearOption(_optionId, _tokenId, true); emit OptionExecuted(_optionId); } /** * @dev Validates the option if its available for execution */ function validateOptionForExecution(uint256 _optionId, uint256 _tokenId) private { require(optionIds.contains(_optionId), "WasabiPool: Option NFT doesn't belong to this pool"); require(_msgSender() == optionNFT.ownerOf(_optionId), "WasabiPool: Only the token owner can execute the option"); WasabiStructs.OptionData memory optionData = options[_optionId]; if (optionData.expiry < block.timestamp) { revert IWasabiErrors.HasExpired(); } if (optionData.optionType == WasabiStructs.OptionType.CALL) { validateAndWithdrawPayment(optionData.strikePrice, "WasabiPool: Strike price needs to be supplied to execute a CALL option"); } else if (optionData.optionType == WasabiStructs.OptionType.PUT) { require(_msgSender() == nft.ownerOf(_tokenId), "WasabiPool: Need to own the token to sell in order to execute a PUT option"); } } /// @inheritdoc IWasabiPool function acceptBid( WasabiStructs.Bid calldata _bid, bytes calldata _signature, uint256 _tokenId ) public onlyOwner returns(uint256) { // Other validations are done in WasabiConduit if (_bid.optionType == WasabiStructs.OptionType.CALL) { if (!isAvailableTokenId(_tokenId)) { revert IWasabiErrors.NftIsInvalid(); } } else { if (availableBalance() < _bid.strikePrice) { revert IWasabiErrors.InsufficientAvailableLiquidity(); } _tokenId = 0; } // Lock NFT / Token into a vault uint256 _optionId = optionNFT.mint(_bid.buyer, address(factory)); if (_bid.optionType == WasabiStructs.OptionType.CALL) { tokenIdToOptionId[_tokenId] = _optionId; } WasabiStructs.OptionData memory optionData = WasabiStructs.OptionData( true, _bid.optionType, _bid.strikePrice, _bid.expiry, _tokenId ); options[_optionId] = optionData; optionIds.add(_optionId); emit OptionIssued(_optionId, _bid.price); IWasabiConduit(factory.getConduitAddress()).poolAcceptBid(_bid, _signature, _optionId); return _optionId; } /// @inheritdoc IWasabiPool function acceptAsk ( WasabiStructs.Ask calldata _ask, bytes calldata _signature ) external onlyOwner { if (_ask.tokenAddress == getLiquidityAddress() && availableBalance() < _ask.price) { revert IWasabiErrors.InsufficientAvailableLiquidity(); } if (_ask.tokenAddress == address(0)) { IWasabiConduit(factory.getConduitAddress()).acceptAsk{value: _ask.price}(_ask, _signature); } else { IERC20 erc20 = IERC20(_ask.tokenAddress); erc20.approve(factory.getConduitAddress(), _ask.price); IWasabiConduit(factory.getConduitAddress()).acceptAsk(_ask, _signature); } } /// @inheritdoc IWasabiPool function acceptPoolBid(WasabiStructs.PoolBid calldata _poolBid, bytes calldata _signature) external payable nonReentrant { // 1. Validate address signer = PoolBidVerifier.getSignerForPoolBid(_poolBid, _signature); if (signer != owner()) { revert IWasabiErrors.InvalidSignature(); } if (!isValid(_poolBid.optionId)) { revert IWasabiErrors.HasExpired(); } if (idToFilledOrCancelled[_poolBid.id]) { revert IWasabiErrors.OrderFilledOrCancelled(); } if (_poolBid.orderExpiry < block.timestamp) { revert IWasabiErrors.HasExpired(); } // 2. Only owner of option can accept bid if (_msgSender() != optionNFT.ownerOf(_poolBid.optionId)) { revert IWasabiErrors.Unauthorized(); } if (_poolBid.tokenAddress == getLiquidityAddress()) { WasabiStructs.OptionData memory optionData = getOptionData(_poolBid.optionId); if (optionData.optionType == WasabiStructs.OptionType.CALL && availableBalance() < _poolBid.price) { revert IWasabiErrors.InsufficientAvailableLiquidity(); } else if (optionData.optionType == WasabiStructs.OptionType.PUT && // The strike price of the option can be used to payout the bid price (availableBalance() + optionData.strikePrice) < _poolBid.price ) { revert IWasabiErrors.InsufficientAvailableLiquidity(); } clearOption(_poolBid.optionId, 0, false); payAddress(_msgSender(), _poolBid.price); } else { IWasabiFeeManager feeManager = IWasabiFeeManager(factory.getFeeManager()); (address feeReceiver, uint256 feeAmount) = feeManager.getFeeData(address(this), _poolBid.price); uint256 maxFee = _maxFee(_poolBid.price); if (feeAmount > maxFee) { feeAmount = maxFee; } if (_poolBid.tokenAddress == address(0)) { if (address(this).balance < _poolBid.price) { revert IWasabiErrors.InsufficientAvailableLiquidity(); } (bool sent, ) = payable(_msgSender()).call{value: _poolBid.price - feeAmount}(""); if (!sent) { revert IWasabiErrors.FailedToSend(); } if (feeAmount > 0) { (bool _sent, ) = payable(feeReceiver).call{value: feeAmount}(""); if (!_sent) { revert IWasabiErrors.FailedToSend(); } } } else { IERC20 erc20 = IERC20(_poolBid.tokenAddress); if (erc20.balanceOf(address(this)) < _poolBid.price) { revert IWasabiErrors.InsufficientAvailableLiquidity(); } if (!erc20.transfer(_msgSender(), _poolBid.price - feeAmount)) { revert IWasabiErrors.FailedToSend(); } if (feeAmount > 0) { if (!erc20.transfer(feeReceiver, feeAmount)) { revert IWasabiErrors.FailedToSend(); } } } clearOption(_poolBid.optionId, 0, false); } idToFilledOrCancelled[_poolBid.id] = true; emit PoolBidTaken(_poolBid.id); } /** * @dev An abstract function to check available balance in this pool. */ function availableBalance() view public virtual returns(uint256); /** * @dev An abstract function to send payment for any function */ function payAddress(address _seller, uint256 _amount) internal virtual; /** * @dev An abstract function to validate and withdraw payment for any function */ function validateAndWithdrawPayment(uint256 _premium, string memory _message) internal virtual; /// @inheritdoc IWasabiPool function clearExpiredOptions(uint256[] memory _optionIds) public { if (_optionIds.length > 0) { for (uint256 i = 0; i < _optionIds.length; i++) { uint256 _optionId = _optionIds[i]; if (!isValid(_optionId)) { optionIds.remove(_optionId); } } } else { for (uint256 i = 0; i < optionIds.length();) { uint256 _optionId = optionIds.at(i); if (!isValid(_optionId)) { optionIds.remove(_optionId); } else { i ++; } } } } /** * @dev Clears the option from the existing state and optionally exercises it. */ function clearOption(uint256 _optionId, uint256 _tokenId, bool _exercised) internal { WasabiStructs.OptionData memory optionData = options[_optionId]; if (optionData.optionType == WasabiStructs.OptionType.CALL) { if (_exercised) { // Sell to executor, the validateOptionForExecution already checked if strike is paid nft.safeTransferFrom(address(this), _msgSender(), optionData.tokenId); } if (tokenIdToOptionId[optionData.tokenId] == _optionId) { delete tokenIdToOptionId[optionData.tokenId]; } } else if (optionData.optionType == WasabiStructs.OptionType.PUT) { if (_exercised) { // Buy from executor nft.safeTransferFrom(_msgSender(), address(this), _tokenId); payAddress(_msgSender(), optionData.strikePrice); } } options[_optionId].active = false; optionIds.remove(_optionId); optionNFT.burn(_optionId); } /// @inheritdoc IWasabiPool function withdrawERC721(IERC721 _nft, uint256[] calldata _tokenIds) external onlyOwner nonReentrant { bool isPoolAsset = _nft == nft; uint256 numNFTs = _tokenIds.length; for (uint256 i; i < numNFTs; ) { if (isPoolAsset) { if (nft.ownerOf(_tokenIds[i]) != address(this)) { revert IWasabiErrors.NftIsInvalid(); } uint256 optionId = tokenIdToOptionId[_tokenIds[i]]; if (isValid(optionId)) { revert IWasabiErrors.RequestNftIsLocked(); } delete tokenIdToOptionId[_tokenIds[i]]; } _nft.safeTransferFrom(address(this), owner(), _tokenIds[i]); unchecked { ++i; } } } /// @inheritdoc IWasabiPool function depositERC721(IERC721 _nft, uint256[] calldata _tokenIds) external onlyOwner nonReentrant { require(_nft == nft, 'Invalid Collection'); uint256 numNFTs = _tokenIds.length; for (uint256 i; i < numNFTs; ) { _nft.safeTransferFrom(_msgSender(), address(this), _tokenIds[i]); unchecked { ++i; } } } /// @inheritdoc IWasabiPool function cancelOrder(uint256 _orderId) external { if (_msgSender() != admin && _msgSender() != owner()) { revert IWasabiErrors.Unauthorized(); } if (idToFilledOrCancelled[_orderId]) { revert IWasabiErrors.OrderFilledOrCancelled(); } idToFilledOrCancelled[_orderId] = true; emit OrderCancelled(_orderId); } /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) external pure returns (bool) { return interfaceId == type(IWasabiPool).interfaceId || interfaceId == type(IERC721Receiver).interfaceId; } /// @inheritdoc IWasabiPool function isValid(uint256 _optionId) view public returns(bool) { return options[_optionId].active && options[_optionId].expiry >= block.timestamp; } /// @inheritdoc IWasabiPool function getOptionData(uint256 _optionId) public view returns(WasabiStructs.OptionData memory) { return options[_optionId]; } /// @inheritdoc IWasabiPool function getOptionIdForToken(uint256 _tokenId) external view returns(uint256) { if (nft.ownerOf(_tokenId) != address(this)) { revert IWasabiErrors.NftIsInvalid(); } return tokenIdToOptionId[_tokenId]; } /// @inheritdoc IWasabiPool function getOptionIds() public view returns(uint256[] memory) { return optionIds.values(); } /// @inheritdoc IWasabiPool function isAvailableTokenId(uint256 _tokenId) public view returns(bool) { if (nft.ownerOf(_tokenId) != address(this)) { return false; } uint256 optionId = tokenIdToOptionId[_tokenId]; return !isValid(optionId); } /** * @dev returns the maximum fee that the protocol can take for the given amount */ function _maxFee(uint256 _amount) internal pure returns(uint256) { return _amount / 10; } } // File: contracts/pools/ETHWasabiPool.sol /** * An ETH backed implementation of the IWasabiErrors. */ contract ETHWasabiPool is AbstractWasabiPool { receive() external payable override { emit ETHReceived(msg.value); } /** * @dev Initializes this pool with the given parameters. */ function initialize( IWasabiPoolFactory _factory, IERC721 _nft, address _optionNFT, address _owner, address _admin ) external payable { baseInitialize(_factory, _nft, _optionNFT, _owner, _admin); } /// @inheritdoc AbstractWasabiPool function validateAndWithdrawPayment(uint256 _premium, string memory _message) internal override { IWasabiFeeManager feeManager = IWasabiFeeManager(factory.getFeeManager()); (address feeReceiver, uint256 feeAmount) = feeManager.getFeeData(address(this), _premium); if (feeAmount > 0) { uint256 maxFee = _maxFee(_premium); if (feeAmount > maxFee) { feeAmount = maxFee; } (bool _sent, ) = payable(feeReceiver).call{value: feeAmount}(""); if (!_sent) { revert IWasabiErrors.FailedToSend(); } } require(msg.value >= (_premium + feeAmount) && _premium > 0, _message); } /// @inheritdoc AbstractWasabiPool function payAddress(address _seller, uint256 _amount) internal override { IWasabiFeeManager feeManager = IWasabiFeeManager(factory.getFeeManager()); (address feeReceiver, uint256 feeAmount) = feeManager.getFeeData(address(this), _amount); if (feeAmount > 0) { uint256 maxFee = _maxFee(_amount); if (feeAmount > maxFee) { feeAmount = maxFee; } (bool _sent, ) = payable(feeReceiver).call{value: feeAmount}(""); if (!_sent) { revert IWasabiErrors.FailedToSend(); } } (bool sent, ) = payable(_seller).call{value: _amount - feeAmount}(""); if (!sent) { revert IWasabiErrors.FailedToSend(); } } /// @inheritdoc IWasabiPool function withdrawETH(uint256 _amount) external payable onlyOwner { if (availableBalance() < _amount) { revert IWasabiErrors.InsufficientAvailableLiquidity(); } address payable to = payable(_msgSender()); (bool sent, ) = to.call{value: _amount}(""); if (!sent) { revert IWasabiErrors.FailedToSend(); } emit ETHWithdrawn(_amount); } /// @inheritdoc IWasabiPool function withdrawERC20(IERC20 _token, uint256 _amount) external onlyOwner { if (!_token.transfer(msg.sender, _amount)) { revert IWasabiErrors.FailedToSend(); } } /// @inheritdoc IWasabiPool function availableBalance() view public override returns(uint256) { uint256 balance = address(this).balance; uint256[] memory optionIds = getOptionIds(); for (uint256 i = 0; i < optionIds.length; i++) { WasabiStructs.OptionData memory optionData = getOptionData(optionIds[i]); if (optionData.optionType == WasabiStructs.OptionType.PUT && isValid(optionIds[i])) { balance -= optionData.strikePrice; } } return balance; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"FailedToSend","type":"error"},{"inputs":[],"name":"HasExpired","type":"error"},{"inputs":[],"name":"InsufficientAvailableLiquidity","type":"error"},{"inputs":[],"name":"InvalidExpiry","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidStrike","type":"error"},{"inputs":[],"name":"NftIsInvalid","type":"error"},{"inputs":[],"name":"OrderFilledOrCancelled","type":"error"},{"inputs":[],"name":"RequestNftIsLocked","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"optionId","type":"uint256"}],"name":"OptionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"optionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"OptionIssued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"optionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"poolAskId","type":"uint256"}],"name":"OptionIssued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"OrderCancelled","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":"uint256","name":"id","type":"uint256"}],"name":"PoolBidTaken","type":"event"},{"anonymous":false,"inputs":[],"name":"PoolSettingsChanged","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"optionId","type":"uint256"}],"internalType":"struct WasabiStructs.Ask","name":"_ask","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"acceptAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"expiryAllowance","type":"uint256"},{"internalType":"address","name":"optionTokenAddress","type":"address"}],"internalType":"struct WasabiStructs.Bid","name":"_bid","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"acceptBid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"uint256","name":"optionId","type":"uint256"}],"internalType":"struct WasabiStructs.PoolBid","name":"_poolBid","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"acceptPoolBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"availableBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_orderId","type":"uint256"}],"name":"cancelOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_optionIds","type":"uint256[]"}],"name":"clearExpiredOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_nft","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"depositERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_optionId","type":"uint256"}],"name":"executeOption","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_optionId","type":"uint256"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"executeOptionWithSell","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IWasabiPoolFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLiquidityAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNftAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_optionId","type":"uint256"}],"name":"getOptionData","outputs":[{"components":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct WasabiStructs.OptionData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getOptionIdForToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOptionIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"idToFilledOrCancelled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IWasabiPoolFactory","name":"_factory","type":"address"},{"internalType":"contract IERC721","name":"_nft","type":"address"},{"internalType":"address","name":"_optionNFT","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_admin","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"isAvailableTokenId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_optionId","type":"uint256"}],"name":"isValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_nft","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"withdrawERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"premium","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"}],"internalType":"struct WasabiStructs.PoolAsk","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"writeOption","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"premium","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"}],"internalType":"struct WasabiStructs.PoolAsk","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"writeOptionTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001d3362000027565b6001805562000077565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61424a80620000876000396000f3fe6080604052600436106102025760003560e01c80636e9960c31161011d578063ab2f0e51116100b0578063daf73d1b1161007f578063f14210a611610064578063f14210a614610637578063f2fde38b1461064a578063f577a5001461066a5761023c565b8063daf73d1b146105ea578063e2213a4b1461060a5761023c565b8063ab2f0e5114610584578063be9a71bd14610599578063c45a0155146105b7578063c644e6a2146105d75761023c565b806388cc58e4116100ec57806388cc58e4146105135780638da5cb5b146105315780639a202d471461054f578063a1db9782146105645761023c565b80636e9960c3146104a0578063704b6c02146104be578063715018a6146104de5780637aca566f146104f35761023c565b806324f78688116101955780635223f2d4116101645780635223f2d41461043a578063522dd3df1461044d5780635ef0a6f91461046d57806362f51dcb1461048d5761023c565b806324f78688146103b757806331ee918d146103e757806337fb409c14610407578063514fcac71461041a5761023c565b806313edab81116101d157806313edab81146103295780631459457a14610349578063150b7a021461035c57806322649613146103955761023c565b806301ffc9a71461028b57806303f97a5c146102c057806309dd2928146102e057806312384c88146103015761023c565b3661023c576040513481527f27f12abfe35860a9a927b465bb3d4a9c23c8428174b83f278fe45ed7b4da26629060200160405180910390a1005b60405162461bcd60e51b815260206004820152600b60248201527f4e6f2066616c6c6261636b00000000000000000000000000000000000000000060448201526064015b60405180910390fd5b005b34801561029757600080fd5b506102ab6102a636600461374f565b61068a565b60405190151581526020015b60405180910390f35b3480156102cc57600080fd5b506102896102db36600461378e565b6106da565b6102f36102ee366004613878565b61084a565b6040519081526020016102b7565b34801561030d57600080fd5b5060005b6040516001600160a01b0390911681526020016102b7565b34801561033557600080fd5b5061028961034436600461378e565b610860565b6102896103573660046138de565b610ad6565b34801561036857600080fd5b5061037c610377366004613996565b610aea565b6040516001600160e01b031990911681526020016102b7565b3480156103a157600080fd5b506103aa610b7d565b6040516102b79190613a5a565b3480156103c357600080fd5b506102ab6103d2366004613a9e565b600a6020526000908152604090205460ff1681565b3480156103f357600080fd5b50610289610402366004613ab7565b610b8e565b610289610415366004613a9e565b610c48565b34801561042657600080fd5b50610289610435366004613a9e565b610cf1565b610289610448366004613b5d565b610dc3565b34801561045957600080fd5b506102ab610468366004613a9e565b6115ca565b34801561047957600080fd5b50610289610488366004613b9f565b611670565b61028961049b366004613be1565b6119d9565b3480156104ac57600080fd5b506005546001600160a01b0316610311565b3480156104ca57600080fd5b506102896104d9366004613c03565b611a81565b3480156104ea57600080fd5b50610289611ae4565b3480156104ff57600080fd5b506102f361050e366004613a9e565b611af8565b34801561051f57600080fd5b506002546001600160a01b0316610311565b34801561053d57600080fd5b506000546001600160a01b0316610311565b34801561055b57600080fd5b50610289611ba2565b34801561057057600080fd5b5061028961057f366004613c20565b611bfd565b34801561059057600080fd5b506102f3611c93565b3480156105a557600080fd5b506004546001600160a01b0316610311565b3480156105c357600080fd5b50600254610311906001600160a01b031681565b6102f36105e5366004613c4c565b611d47565b3480156105f657600080fd5b506102f3610605366004613cb6565b612013565b34801561061657600080fd5b5061062a610625366004613a9e565b61237c565b6040516102b79190613d53565b610289610645366004613a9e565b61242b565b34801561065657600080fd5b50610289610665366004613c03565b6124fe565b34801561067657600080fd5b506102ab610685366004613a9e565b61258b565b60006001600160e01b031982167f7af930b60000000000000000000000000000000000000000000000000000000014806106d457506001600160e01b03198216630a85bd0160e11b145b92915050565b6106e26125bd565b6002600154036107345760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b60026001556004546001600160a01b038481169116146107965760405162461bcd60e51b815260206004820152601260248201527f496e76616c696420436f6c6c656374696f6e00000000000000000000000000006044820152606401610280565b8060005b8181101561083f576001600160a01b0385166342842e0e33308787868181106107c5576107c5613d95565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561081c57600080fd5b505af1158015610830573d6000803e3d6000fd5b5050505080600101905061079a565b505060018055505050565b600061085884848433611d47565b949350505050565b6108686125bd565b6002600154036108ba5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b60026001556004546001600160a01b038481169116148160005b81811015610aca578215610a1c5760045430906001600160a01b0316636352211e87878581811061090757610907613d95565b905060200201356040518263ffffffff1660e01b815260040161092c91815260200190565b602060405180830381865afa158015610949573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096d9190613dab565b6001600160a01b031614610994576040516363f03bed60e11b815260040160405180910390fd5b6000600860008787858181106109ac576109ac613d95565b9050602002013581526020019081526020016000205490506109cd8161258b565b156109eb57604051637aac9f5d60e01b815260040160405180910390fd5b60086000878785818110610a0157610a01613d95565b90506020020135815260200190815260200160002060009055505b856001600160a01b03166342842e0e30610a3e6000546001600160a01b031690565b888886818110610a5057610a50613d95565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b158015610aa757600080fd5b505af1158015610abb573d6000803e3d6000fd5b505050508060010190506108d4565b50506001805550505050565b610ae38585858585612617565b5050505050565b6003546000906001600160a01b03163303610b3857610b0a600684612748565b610b27576040516363f03bed60e11b815260040160405180910390fd5b610b3383600080612763565b610b6c565b6004546001600160a01b0316336001600160a01b031614610b6c576040516363f03bed60e11b815260040160405180910390fd5b50630a85bd0160e11b949350505050565b6060610b896006612a03565b905090565b805115610bf05760005b8151811015610bec576000828281518110610bb557610bb5613d95565b60200260200101519050610bc88161258b565b610bd957610bd7600682612a10565b505b5080610be481613dde565b915050610b98565b5050565b60005b610bfd6006612a1c565b811015610bec576000610c11600683612a26565b9050610c1c8161258b565b610c3157610c2b600682612a10565b50610c3f565b81610c3b81613dde565b9250505b50610bf3565b50565b600260015403610c9a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b6002600155610caa816000612a32565b610cb78160006001612763565b6040518181527f71bef4a8469a3b83c64a11128d95ac7253a399544da7d5f50e8ef4a32f3fac329060200160405180910390a15060018055565b6005546001600160a01b0316336001600160a01b031614158015610d2057506000546001600160a01b03163314155b15610d3d576040516282b42960e81b815260040160405180910390fd5b6000818152600a602052604090205460ff1615610d6d57604051633d9c5bb760e11b815260040160405180910390fd5b6000818152600a602052604090819020805460ff19166001179055517f61b9399f2f0f32ca39ce8d7be32caed5ec22fe07a6daba3a467ed479ec60658290610db89083815260200190565b60405180910390a150565b600260015403610e155760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b60026001556040517ffd68c4dd0000000000000000000000000000000000000000000000000000000081526000907366873693e8b125dbea46274173b0d6dcd1933cca9063fd68c4dd90610e7190879087908790600401613e20565b602060405180830381865af4158015610e8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb29190613dab565b9050610ec66000546001600160a01b031690565b6001600160a01b0316816001600160a01b031614610ef757604051638baa579f60e01b815260040160405180910390fd5b610f04846080013561258b565b610f2157604051633d36c2e560e01b815260040160405180910390fd5b83356000908152600a602052604090205460ff1615610f5357604051633d9c5bb760e11b815260040160405180910390fd5b4284606001351015610f7857604051633d36c2e560e01b815260040160405180910390fd5b6003546040516331a9108f60e11b8152608086013560048201526001600160a01b0390911690636352211e90602401602060405180830381865afa158015610fc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe89190613dab565b6001600160a01b0316336001600160a01b031614611018576040516282b42960e81b815260040160405180910390fd5b600061102a6060860160408701613c03565b6001600160a01b031603611116576000611047856080013561237c565b905060008160200151600181111561106157611061613d1b565b14801561107857508460200135611076611c93565b105b156110965760405163e926a90f60e01b815260040160405180910390fd5b6001816020015160018111156110ae576110ae613d1b565b1480156110d45750846020013581604001516110c8611c93565b6110d29190613e80565b105b156110f25760405163e926a90f60e01b815260040160405180910390fd5b6111028560800135600080612763565b611110338660200135612db8565b5061156b565b6002546040805163796b1c1360e11b815290516000926001600160a01b03169163f2d638269160048083019260209291908290030181865afa158015611160573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111849190613dab565b604051635424042960e01b81523060048201526020870135602482015290915060009081906001600160a01b038416906354240429906044016040805180830381865afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd9190613e93565b9150915060006112108860200135612fb8565b90508082111561121e578091505b600061123060608a0160408b01613c03565b6001600160a01b0316036113595787602001354710156112635760405163e926a90f60e01b815260040160405180910390fd5b6000336112748460208c0135613ec1565b604051600081818185875af1925050503d80600081146112b0576040519150601f19603f3d011682016040523d82523d6000602084013e6112b5565b606091505b50509050806112d75760405163467d86d160e01b815260040160405180910390fd5b8215611353576000846001600160a01b03168460405160006040518083038185875af1925050503d806000811461132a576040519150601f19603f3d011682016040523d82523d6000602084013e61132f565b606091505b50509050806113515760405163467d86d160e01b815260040160405180910390fd5b505b50611556565b600061136b60608a0160408b01613c03565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060208a0135906001600160a01b038316906370a0823190602401602060405180830381865afa1580156113d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f59190613ed4565b10156114145760405163e926a90f60e01b815260040160405180910390fd5b6001600160a01b03811663a9059cbb336114328660208e0135613ec1565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af115801561147d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a19190613eed565b6114be5760405163467d86d160e01b815260040160405180910390fd5b82156115545760405163a9059cbb60e01b81526001600160a01b0385811660048301526024820185905282169063a9059cbb906044016020604051808303816000875af1158015611513573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115379190613eed565b6115545760405163467d86d160e01b815260040160405180910390fd5b505b6115668860800135600080612763565b505050505b83356000818152600a602052604090819020805460ff19166001179055517fd77013b27e07d15bcec97cad88a301ffe3d12b999b47d155c610e4cb4de1dc64916115b89190815260200190565b60405180910390a15050600180555050565b600480546040516331a9108f60e11b815291820183905260009130916001600160a01b031690636352211e90602401602060405180830381865afa158015611616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163a9190613dab565b6001600160a01b03161461165057506000919050565b6000828152600860205260409020546116688161258b565b159392505050565b6116786125bd565b600061168a6060850160408601613c03565b6001600160a01b03161480156116aa575082602001356116a8611c93565b105b156116c85760405163e926a90f60e01b815260040160405180910390fd5b60006116da6060850160408601613c03565b6001600160a01b0316036117dc57600260009054906101000a90046001600160a01b03166001600160a01b031663f27d5f466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561173b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175f9190613dab565b6001600160a01b0316635ef0a6f984602001358585856040518563ffffffff1660e01b815260040161179393929190613f0f565b60206040518083038185885af11580156117b1573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906117d69190613ed4565b50505050565b60006117ee6060850160408601613c03565b9050806001600160a01b031663095ea7b3600260009054906101000a90046001600160a01b03166001600160a01b031663f27d5f466040518163ffffffff1660e01b8152600401602060405180830381865afa158015611852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118769190613dab565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602087013560248201526044016020604051808303816000875af11580156118c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ea9190613eed565b50600260009054906101000a90046001600160a01b03166001600160a01b031663f27d5f466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561193e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119629190613dab565b6001600160a01b0316635ef0a6f98585856040518463ffffffff1660e01b815260040161199193929190613f0f565b6020604051808303816000875af11580156119b0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae39190613ed4565b505050565b600260015403611a2b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b6002600155611a3a8282612a32565b611a4682826001612763565b6040518281527f71bef4a8469a3b83c64a11128d95ac7253a399544da7d5f50e8ef4a32f3fac329060200160405180910390a1505060018055565b611a896125bd565b6005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c90602001610db8565b611aec6125bd565b611af66000612fc5565b565b600480546040516331a9108f60e11b815291820183905260009130916001600160a01b031690636352211e90602401602060405180830381865afa158015611b44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b689190613dab565b6001600160a01b031614611b8f576040516363f03bed60e11b815260040160405180910390fd5b5060009081526008602052604090205490565b611baa6125bd565b6005805473ffffffffffffffffffffffffffffffffffffffff19169055604051600081527f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c9060200160405180910390a1565b611c056125bd565b60405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0383169063a9059cbb906044016020604051808303816000875af1158015611c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c769190613eed565b610bec5760405163467d86d160e01b815260040160405180910390fd5b60004781611c9f610b7d565b905060005b8151811015611d3f576000611cd1838381518110611cc457611cc4613d95565b602002602001015161237c565b9050600181602001516001811115611ceb57611ceb613d1b565b148015611d155750611d15838381518110611d0857611d08613d95565b602002602001015161258b565b15611d2c576040810151611d299085613ec1565b93505b5080611d3781613dde565b915050611ca4565b509092915050565b6000600260015403611d9b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b600260015584356000908152600a602052604090205460ff1615611dd257604051633d9c5bb760e11b815260040160405180910390fd5b611ddd858585613022565b6003546002546040517fee1fe2ad0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301529182166024820152600092919091169063ee1fe2ad906044016020604051808303816000875af1158015611e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e759190613ed4565b905060006040518060a00160405280600115158152602001886040016020810190611ea09190613f8c565b6001811115611eb157611eb1613d1b565b81526060808a013560208084019190915260a08b013560408085019190915260c08c01359290930191909152600085815260098252919091208251815490151560ff198216811783559284015193945084939192839161ff001990911661ffff1990911617610100836001811115611f2b57611f2b613d1b565b021790555060408201516001820155606082015160028201556080909101516003909101556000611f626060890160408a01613f8c565b6001811115611f7357611f73613d1b565b03611f8f5760c087013560009081526008602052604090208290555b611f9a6006836133c4565b5086356000818152600a602052604090819020805460ff19166001179055517f6bb1c0efefbf73ea6121a1bc64a18154976add0ae92fb1434d5731f157e0a3fb91611ffd91859160808c0135919283526020830191909152604082015260600190565b60405180910390a1506001805595945050505050565b600061201d6125bd565b600061202f60e0870160c08801613f8c565b600181111561204057612040613d1b565b036120705761204e826115ca565b61206b576040516363f03bed60e11b815260040160405180910390fd5b6120a1565b8460e0013561207d611c93565b101561209c5760405163e926a90f60e01b815260040160405180910390fd5b600091505b6003546000906001600160a01b031663ee1fe2ad6120c560c0890160a08a01613c03565b60025460405160e084901b6001600160e01b03191681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af1158015612115573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121399190613ed4565b9050600061214d60e0880160c08901613f8c565b600181111561215e5761215e613d1b565b036121755760008381526008602052604090208190555b6040805160a08101909152600181526000906020810161219b60e08a0160c08b01613f8c565b60018111156121ac576121ac613d1b565b81526020018860e0013581526020018861010001358152602001858152509050806009600084815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff0219169083600181111561222a5761222a613d1b565b0217905550604082015160018201556060820151600282015560809091015160039091015561225a6006836133c4565b50604080518381526020808a0135908201527fbef1c9f7171f2ce944e29c1be0951badd44e40459d6e541791baf896f3db1845910160405180910390a1600260009054906101000a90046001600160a01b03166001600160a01b031663f27d5f466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230e9190613dab565b6001600160a01b03166375031dc8888888866040518563ffffffff1660e01b815260040161233f9493929190613fa7565b600060405180830381600087803b15801561235957600080fd5b505af115801561236d573d6000803e3d6000fd5b50939998505050505050505050565b6123af6040805160a081019091526000808252602082019081526020016000815260200160008152602001600081525090565b600082815260096020908152604091829020825160a08101909352805460ff8082161515855291928401916101009091041660018111156123f2576123f2613d1b565b600181111561240357612403613d1b565b8152600182015460208201526002820154604082015260039091015460609091015292915050565b6124336125bd565b8061243c611c93565b101561245b5760405163e926a90f60e01b815260040160405180910390fd5b6040513390600090829084908381818185875af1925050503d806000811461249f576040519150601f19603f3d011682016040523d82523d6000602084013e6124a4565b606091505b50509050806124c65760405163467d86d160e01b815260040160405180910390fd5b6040518381527f043f607a14d3b4f0a11a0b2e192bbfcd894298ba5abf22553be6081406db28aa9060200160405180910390a1505050565b6125066125bd565b6001600160a01b0381166125825760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610280565b610c4581612fc5565b60008181526009602052604081205460ff1680156106d457505060009081526009602052604090206002015442111590565b6000546001600160a01b03163314611af65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610280565b6000546001600160a01b0316156126705760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a6564000000000000000000000000006044820152606401610280565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0387161790556126a182612fc5565b600480546001600160a01b0380871673ffffffffffffffffffffffffffffffffffffffff1992831617909255600380548684169216919091179055811615610ae3576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c9060200160405180910390a15050505050565b600081815260018301602052604081205415155b9392505050565b6000838152600960209081526040808320815160a08101909252805460ff8082161515845292939192918401916101009091041660018111156127a8576127a8613d1b565b60018111156127b9576127b9613d1b565b8152600182015460208201526002820154604082015260039091015460609091015290506000816020015160018111156127f5576127f5613d1b565b036128b5578115612880576004546001600160a01b03166342842e0e303360808501516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561286757600080fd5b505af115801561287b573d6000803e3d6000fd5b505050505b60808101516000908152600860205260409020548490036128b05760808101516000908152600860205260408120555b612964565b6001816020015160018111156128cd576128cd613d1b565b03612964578115612964576004546001600160a01b03166342842e0e336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015230602482015260448101869052606401600060405180830381600087803b15801561293857600080fd5b505af115801561294c573d6000803e3d6000fd5b5050505061296461295a3390565b8260400151612db8565b6000848152600960205260409020805460ff19169055612985600685612a10565b506003546040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b03909116906342966c6890602401600060405180830381600087803b1580156129e557600080fd5b505af11580156129f9573d6000803e3d6000fd5b5050505050505050565b6060600061275c836133d0565b600061275c838361342c565b60006106d4825490565b600061275c838361351f565b612a3d600683612748565b612aaf5760405162461bcd60e51b815260206004820152603260248201527f576173616269506f6f6c3a204f7074696f6e204e465420646f65736e2774206260448201527f656c6f6e6720746f207468697320706f6f6c00000000000000000000000000006064820152608401610280565b6003546040516331a9108f60e11b8152600481018490526001600160a01b0390911690636352211e90602401602060405180830381865afa158015612af8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b1c9190613dab565b6001600160a01b0316336001600160a01b031614612ba25760405162461bcd60e51b815260206004820152603760248201527f576173616269506f6f6c3a204f6e6c792074686520746f6b656e206f776e657260448201527f2063616e206578656375746520746865206f7074696f6e0000000000000000006064820152608401610280565b6000828152600960209081526040808320815160a08101909252805460ff808216151584529293919291840191610100909104166001811115612be757612be7613d1b565b6001811115612bf857612bf8613d1b565b8152602001600182015481526020016002820154815260200160038201548152505090504281606001511015612c4157604051633d36c2e560e01b815260040160405180910390fd5b600081602001516001811115612c5957612c59613d1b565b03612c84576119d481604001516040518060800160405280604681526020016141cf60469139613549565b600181602001516001811115612c9c57612c9c613d1b565b036119d457600480546040516331a9108f60e11b81529182018490526001600160a01b031690636352211e90602401602060405180830381865afa158015612ce8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0c9190613dab565b6001600160a01b0316336001600160a01b0316146119d45760405162461bcd60e51b815260206004820152604a60248201527f576173616269506f6f6c3a204e65656420746f206f776e2074686520746f6b6560448201527f6e20746f2073656c6c20696e206f7264657220746f206578656375746520612060648201527f505554206f7074696f6e00000000000000000000000000000000000000000000608482015260a401610280565b6002546040805163796b1c1360e11b815290516000926001600160a01b03169163f2d638269160048083019260209291908290030181865afa158015612e02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e269190613dab565b604051635424042960e01b81523060048201526024810184905290915060009081906001600160a01b038416906354240429906044016040805180830381865afa158015612e78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e9c9190613e93565b90925090508015612f37576000612eb285612fb8565b905080821115612ec0578091505b6000836001600160a01b03168360405160006040518083038185875af1925050503d8060008114612f0d576040519150601f19603f3d011682016040523d82523d6000602084013e612f12565b606091505b5050905080612f345760405163467d86d160e01b815260040160405180910390fd5b50505b60006001600160a01b038616612f4d8387613ec1565b604051600081818185875af1925050503d8060008114612f89576040519150601f19603f3d011682016040523d82523d6000602084013e612f8e565b606091505b5050905080612fb05760405163467d86d160e01b815260040160405180910390fd5b505050505050565b60006106d4600a8361408f565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040517f827f3b6e00000000000000000000000000000000000000000000000000000000815260009073e3f3dca2bd68cbd34b58cfc3bcd109998fcce0ac9063827f3b6e90613079908790879087906004016140b1565b602060405180830381865af4158015613096573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130ba9190613dab565b90506001600160a01b03811615806130f957506005546001600160a01b038281169116148015906130f957506000546001600160a01b03828116911614155b1561311757604051638baa579f60e01b815260040160405180910390fd5b428460e00135101561313c57604051633d36c2e560e01b815260040160405180910390fd5b3061314d6040860160208701613c03565b6001600160a01b0316146131c95760405162461bcd60e51b815260206004820152603160248201527f576173616269506f6f6c3a205369676e617475726520646f65736e277420626560448201527f6c6f6e6720746f207468697320706f6f6c0000000000000000000000000000006064820152608401610280565b6131ef84608001356040518060600160405280602a81526020016141a5602a9139613549565b836060013560000361322d576040517f9a5818d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360a0013560000361326b576040517fd36c850000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061327d6060860160408701613f8c565b600181111561328e5761328e613d1b565b0361337057600480546040516331a9108f60e11b815260c08701359281019290925230916001600160a01b0390911690636352211e90602401602060405180830381865afa1580156132e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133089190613dab565b6001600160a01b03161461332f576040516363f03bed60e11b815260040160405180910390fd5b60c084013560009081526008602052604090205461334c8161258b565b1561336a57604051637aac9f5d60e01b815260040160405180910390fd5b506117d6565b60016133826060860160408701613f8c565b600181111561339357613393613d1b565b036117d65783606001356133a5611c93565b10156117d65760405163e926a90f60e01b815260040160405180910390fd5b600061275c8383613700565b60608160000180548060200260200160405190810160405280929190818152602001828054801561342057602002820191906000526020600020905b81548152602001906001019080831161340c575b50505050509050919050565b60008181526001830160205260408120548015613515576000613450600183613ec1565b855490915060009061346490600190613ec1565b90508181146134c957600086600001828154811061348457613484613d95565b90600052602060002001549050808760000184815481106134a7576134a7613d95565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806134da576134da614140565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106d4565b60009150506106d4565b600082600001828154811061353657613536613d95565b9060005260206000200154905092915050565b6002546040805163796b1c1360e11b815290516000926001600160a01b03169163f2d638269160048083019260209291908290030181865afa158015613593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b79190613dab565b604051635424042960e01b81523060048201526024810185905290915060009081906001600160a01b038416906354240429906044016040805180830381865afa158015613609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061362d9190613e93565b909250905080156136c857600061364386612fb8565b905080821115613651578091505b6000836001600160a01b03168360405160006040518083038185875af1925050503d806000811461369e576040519150601f19603f3d011682016040523d82523d6000602084013e6136a3565b606091505b50509050806136c55760405163467d86d160e01b815260040160405180910390fd5b50505b6136d28186613e80565b34101580156136e15750600085115b8490612fb05760405162461bcd60e51b81526004016102809190614156565b6000818152600183016020526040812054613747575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106d4565b5060006106d4565b60006020828403121561376157600080fd5b81356001600160e01b03198116811461275c57600080fd5b6001600160a01b0381168114610c4557600080fd5b6000806000604084860312156137a357600080fd5b83356137ae81613779565b9250602084013567ffffffffffffffff808211156137cb57600080fd5b818601915086601f8301126137df57600080fd5b8135818111156137ee57600080fd5b8760208260051b850101111561380357600080fd5b6020830194508093505050509250925092565b6000610100828403121561382957600080fd5b50919050565b60008083601f84011261384157600080fd5b50813567ffffffffffffffff81111561385957600080fd5b60208301915083602082850101111561387157600080fd5b9250929050565b6000806000610120848603121561388e57600080fd5b6138988585613816565b925061010084013567ffffffffffffffff8111156138b557600080fd5b6138c18682870161382f565b9497909650939450505050565b80356138d981613779565b919050565b600080600080600060a086880312156138f657600080fd5b853561390181613779565b9450602086013561391181613779565b9350604086013561392181613779565b9250606086013561393181613779565b9150608086013561394181613779565b809150509295509295909350565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561398e5761398e61394f565b604052919050565b600080600080608085870312156139ac57600080fd5b84356139b781613779565b93506020858101356139c881613779565b935060408601359250606086013567ffffffffffffffff808211156139ec57600080fd5b818801915088601f830112613a0057600080fd5b813581811115613a1257613a1261394f565b613a24601f8201601f19168501613965565b91508082528984828501011115613a3a57600080fd5b808484018584013760008482840101525080935050505092959194509250565b6020808252825182820181905260009190848201906040850190845b81811015613a9257835183529284019291840191600101613a76565b50909695505050505050565b600060208284031215613ab057600080fd5b5035919050565b60006020808385031215613aca57600080fd5b823567ffffffffffffffff80821115613ae257600080fd5b818501915085601f830112613af657600080fd5b813581811115613b0857613b0861394f565b8060051b9150613b19848301613965565b8181529183018401918481019088841115613b3357600080fd5b938501935b83851015613b5157843582529385019390850190613b38565b98975050505050505050565b600080600083850360c0811215613b7357600080fd5b60a0811215613b8157600080fd5b5083925060a084013567ffffffffffffffff8111156138b557600080fd5b600080600083850360e0811215613bb557600080fd5b60c0811215613bc357600080fd5b5083925060c084013567ffffffffffffffff8111156138b557600080fd5b60008060408385031215613bf457600080fd5b50508035926020909101359150565b600060208284031215613c1557600080fd5b813561275c81613779565b60008060408385031215613c3357600080fd5b8235613c3e81613779565b946020939093013593505050565b6000806000806101408587031215613c6357600080fd5b613c6d8686613816565b935061010085013567ffffffffffffffff811115613c8a57600080fd5b613c968782880161382f565b909450925050610120850135613cab81613779565b939692955090935050565b6000806000808486036101a0811215613cce57600080fd5b61016080821215613cde57600080fd5b869550850135905067ffffffffffffffff811115613cfb57600080fd5b613d078782880161382f565b959890975094956101800135949350505050565b634e487b7160e01b600052602160045260246000fd5b60028110613d4f57634e487b7160e01b600052602160045260246000fd5b9052565b81511515815260208083015160a0830191613d7090840182613d31565b5060408301516040830152606083015160608301526080830151608083015292915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613dbd57600080fd5b815161275c81613779565b634e487b7160e01b600052601160045260246000fd5b600060018201613df057613df0613dc8565b5060010190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b833581526020840135602082015260006040850135613e3e81613779565b6001600160a01b038116604084015250606085013560608301526080850135608083015260c060a0830152613e7760c083018486613df7565b95945050505050565b808201808211156106d4576106d4613dc8565b60008060408385031215613ea657600080fd5b8251613eb181613779565b6020939093015192949293505050565b818103818111156106d4576106d4613dc8565b600060208284031215613ee657600080fd5b5051919050565b600060208284031215613eff57600080fd5b8151801515811461275c57600080fd5b833581526020840135602082015260006040850135613f2d81613779565b6001600160a01b0380821660408501526060870135606085015260808701359150613f5782613779565b16608083015260a0858101359083015260e060c08301819052613e779083018486613df7565b8035600281106138d957600080fd5b600060208284031215613f9e57600080fd5b61275c82613f7d565b60006101a08635835260208701356020840152613fc6604088016138ce565b6001600160a01b03166040840152613fe0606088016138ce565b6001600160a01b031660608401526080878101359084015261400460a088016138ce565b6001600160a01b031660a084015261401e60c08801613f7d565b61402b60c0850182613d31565b5060e087810135908401526101008088013590840152610120808801359084015261014061405a8189016138ce565b6001600160a01b031690840152610160830181905261407c8184018688613df7565b9150508261018083015295945050505050565b6000826140ac57634e487b7160e01b600052601260045260246000fd5b500490565b60006101208535835260208601356140c881613779565b6001600160a01b031660208401526140e260408701613f7d565b6140ef6040850182613d31565b50606086013560608401526080860135608084015260a086013560a084015260c086013560c084015260e086013560e0840152806101008401526141368184018587613df7565b9695505050505050565b634e487b7160e01b600052603160045260246000fd5b600060208083528351808285015260005b8181101561418357858101830151858201604001528201614167565b506000604082860101526040601f19601f830116850101925050509291505056fe576173616269506f6f6c3a204e6f7420656e6f756768207072656d69756d20697320737570706c696564576173616269506f6f6c3a20537472696b65207072696365206e6565647320746f20626520737570706c69656420746f206578656375746520612043414c4c206f7074696f6ea2646970667358221220d68b729683b67aac1630260e8e40dc473eb072dbb23d3524a04f9071c71e327664736f6c63430008130033
Deployed Bytecode
0x6080604052600436106102025760003560e01c80636e9960c31161011d578063ab2f0e51116100b0578063daf73d1b1161007f578063f14210a611610064578063f14210a614610637578063f2fde38b1461064a578063f577a5001461066a5761023c565b8063daf73d1b146105ea578063e2213a4b1461060a5761023c565b8063ab2f0e5114610584578063be9a71bd14610599578063c45a0155146105b7578063c644e6a2146105d75761023c565b806388cc58e4116100ec57806388cc58e4146105135780638da5cb5b146105315780639a202d471461054f578063a1db9782146105645761023c565b80636e9960c3146104a0578063704b6c02146104be578063715018a6146104de5780637aca566f146104f35761023c565b806324f78688116101955780635223f2d4116101645780635223f2d41461043a578063522dd3df1461044d5780635ef0a6f91461046d57806362f51dcb1461048d5761023c565b806324f78688146103b757806331ee918d146103e757806337fb409c14610407578063514fcac71461041a5761023c565b806313edab81116101d157806313edab81146103295780631459457a14610349578063150b7a021461035c57806322649613146103955761023c565b806301ffc9a71461028b57806303f97a5c146102c057806309dd2928146102e057806312384c88146103015761023c565b3661023c576040513481527f27f12abfe35860a9a927b465bb3d4a9c23c8428174b83f278fe45ed7b4da26629060200160405180910390a1005b60405162461bcd60e51b815260206004820152600b60248201527f4e6f2066616c6c6261636b00000000000000000000000000000000000000000060448201526064015b60405180910390fd5b005b34801561029757600080fd5b506102ab6102a636600461374f565b61068a565b60405190151581526020015b60405180910390f35b3480156102cc57600080fd5b506102896102db36600461378e565b6106da565b6102f36102ee366004613878565b61084a565b6040519081526020016102b7565b34801561030d57600080fd5b5060005b6040516001600160a01b0390911681526020016102b7565b34801561033557600080fd5b5061028961034436600461378e565b610860565b6102896103573660046138de565b610ad6565b34801561036857600080fd5b5061037c610377366004613996565b610aea565b6040516001600160e01b031990911681526020016102b7565b3480156103a157600080fd5b506103aa610b7d565b6040516102b79190613a5a565b3480156103c357600080fd5b506102ab6103d2366004613a9e565b600a6020526000908152604090205460ff1681565b3480156103f357600080fd5b50610289610402366004613ab7565b610b8e565b610289610415366004613a9e565b610c48565b34801561042657600080fd5b50610289610435366004613a9e565b610cf1565b610289610448366004613b5d565b610dc3565b34801561045957600080fd5b506102ab610468366004613a9e565b6115ca565b34801561047957600080fd5b50610289610488366004613b9f565b611670565b61028961049b366004613be1565b6119d9565b3480156104ac57600080fd5b506005546001600160a01b0316610311565b3480156104ca57600080fd5b506102896104d9366004613c03565b611a81565b3480156104ea57600080fd5b50610289611ae4565b3480156104ff57600080fd5b506102f361050e366004613a9e565b611af8565b34801561051f57600080fd5b506002546001600160a01b0316610311565b34801561053d57600080fd5b506000546001600160a01b0316610311565b34801561055b57600080fd5b50610289611ba2565b34801561057057600080fd5b5061028961057f366004613c20565b611bfd565b34801561059057600080fd5b506102f3611c93565b3480156105a557600080fd5b506004546001600160a01b0316610311565b3480156105c357600080fd5b50600254610311906001600160a01b031681565b6102f36105e5366004613c4c565b611d47565b3480156105f657600080fd5b506102f3610605366004613cb6565b612013565b34801561061657600080fd5b5061062a610625366004613a9e565b61237c565b6040516102b79190613d53565b610289610645366004613a9e565b61242b565b34801561065657600080fd5b50610289610665366004613c03565b6124fe565b34801561067657600080fd5b506102ab610685366004613a9e565b61258b565b60006001600160e01b031982167f7af930b60000000000000000000000000000000000000000000000000000000014806106d457506001600160e01b03198216630a85bd0160e11b145b92915050565b6106e26125bd565b6002600154036107345760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b60026001556004546001600160a01b038481169116146107965760405162461bcd60e51b815260206004820152601260248201527f496e76616c696420436f6c6c656374696f6e00000000000000000000000000006044820152606401610280565b8060005b8181101561083f576001600160a01b0385166342842e0e33308787868181106107c5576107c5613d95565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561081c57600080fd5b505af1158015610830573d6000803e3d6000fd5b5050505080600101905061079a565b505060018055505050565b600061085884848433611d47565b949350505050565b6108686125bd565b6002600154036108ba5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b60026001556004546001600160a01b038481169116148160005b81811015610aca578215610a1c5760045430906001600160a01b0316636352211e87878581811061090757610907613d95565b905060200201356040518263ffffffff1660e01b815260040161092c91815260200190565b602060405180830381865afa158015610949573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096d9190613dab565b6001600160a01b031614610994576040516363f03bed60e11b815260040160405180910390fd5b6000600860008787858181106109ac576109ac613d95565b9050602002013581526020019081526020016000205490506109cd8161258b565b156109eb57604051637aac9f5d60e01b815260040160405180910390fd5b60086000878785818110610a0157610a01613d95565b90506020020135815260200190815260200160002060009055505b856001600160a01b03166342842e0e30610a3e6000546001600160a01b031690565b888886818110610a5057610a50613d95565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b158015610aa757600080fd5b505af1158015610abb573d6000803e3d6000fd5b505050508060010190506108d4565b50506001805550505050565b610ae38585858585612617565b5050505050565b6003546000906001600160a01b03163303610b3857610b0a600684612748565b610b27576040516363f03bed60e11b815260040160405180910390fd5b610b3383600080612763565b610b6c565b6004546001600160a01b0316336001600160a01b031614610b6c576040516363f03bed60e11b815260040160405180910390fd5b50630a85bd0160e11b949350505050565b6060610b896006612a03565b905090565b805115610bf05760005b8151811015610bec576000828281518110610bb557610bb5613d95565b60200260200101519050610bc88161258b565b610bd957610bd7600682612a10565b505b5080610be481613dde565b915050610b98565b5050565b60005b610bfd6006612a1c565b811015610bec576000610c11600683612a26565b9050610c1c8161258b565b610c3157610c2b600682612a10565b50610c3f565b81610c3b81613dde565b9250505b50610bf3565b50565b600260015403610c9a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b6002600155610caa816000612a32565b610cb78160006001612763565b6040518181527f71bef4a8469a3b83c64a11128d95ac7253a399544da7d5f50e8ef4a32f3fac329060200160405180910390a15060018055565b6005546001600160a01b0316336001600160a01b031614158015610d2057506000546001600160a01b03163314155b15610d3d576040516282b42960e81b815260040160405180910390fd5b6000818152600a602052604090205460ff1615610d6d57604051633d9c5bb760e11b815260040160405180910390fd5b6000818152600a602052604090819020805460ff19166001179055517f61b9399f2f0f32ca39ce8d7be32caed5ec22fe07a6daba3a467ed479ec60658290610db89083815260200190565b60405180910390a150565b600260015403610e155760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b60026001556040517ffd68c4dd0000000000000000000000000000000000000000000000000000000081526000907366873693e8b125dbea46274173b0d6dcd1933cca9063fd68c4dd90610e7190879087908790600401613e20565b602060405180830381865af4158015610e8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb29190613dab565b9050610ec66000546001600160a01b031690565b6001600160a01b0316816001600160a01b031614610ef757604051638baa579f60e01b815260040160405180910390fd5b610f04846080013561258b565b610f2157604051633d36c2e560e01b815260040160405180910390fd5b83356000908152600a602052604090205460ff1615610f5357604051633d9c5bb760e11b815260040160405180910390fd5b4284606001351015610f7857604051633d36c2e560e01b815260040160405180910390fd5b6003546040516331a9108f60e11b8152608086013560048201526001600160a01b0390911690636352211e90602401602060405180830381865afa158015610fc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe89190613dab565b6001600160a01b0316336001600160a01b031614611018576040516282b42960e81b815260040160405180910390fd5b600061102a6060860160408701613c03565b6001600160a01b031603611116576000611047856080013561237c565b905060008160200151600181111561106157611061613d1b565b14801561107857508460200135611076611c93565b105b156110965760405163e926a90f60e01b815260040160405180910390fd5b6001816020015160018111156110ae576110ae613d1b565b1480156110d45750846020013581604001516110c8611c93565b6110d29190613e80565b105b156110f25760405163e926a90f60e01b815260040160405180910390fd5b6111028560800135600080612763565b611110338660200135612db8565b5061156b565b6002546040805163796b1c1360e11b815290516000926001600160a01b03169163f2d638269160048083019260209291908290030181865afa158015611160573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111849190613dab565b604051635424042960e01b81523060048201526020870135602482015290915060009081906001600160a01b038416906354240429906044016040805180830381865afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd9190613e93565b9150915060006112108860200135612fb8565b90508082111561121e578091505b600061123060608a0160408b01613c03565b6001600160a01b0316036113595787602001354710156112635760405163e926a90f60e01b815260040160405180910390fd5b6000336112748460208c0135613ec1565b604051600081818185875af1925050503d80600081146112b0576040519150601f19603f3d011682016040523d82523d6000602084013e6112b5565b606091505b50509050806112d75760405163467d86d160e01b815260040160405180910390fd5b8215611353576000846001600160a01b03168460405160006040518083038185875af1925050503d806000811461132a576040519150601f19603f3d011682016040523d82523d6000602084013e61132f565b606091505b50509050806113515760405163467d86d160e01b815260040160405180910390fd5b505b50611556565b600061136b60608a0160408b01613c03565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060208a0135906001600160a01b038316906370a0823190602401602060405180830381865afa1580156113d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f59190613ed4565b10156114145760405163e926a90f60e01b815260040160405180910390fd5b6001600160a01b03811663a9059cbb336114328660208e0135613ec1565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af115801561147d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a19190613eed565b6114be5760405163467d86d160e01b815260040160405180910390fd5b82156115545760405163a9059cbb60e01b81526001600160a01b0385811660048301526024820185905282169063a9059cbb906044016020604051808303816000875af1158015611513573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115379190613eed565b6115545760405163467d86d160e01b815260040160405180910390fd5b505b6115668860800135600080612763565b505050505b83356000818152600a602052604090819020805460ff19166001179055517fd77013b27e07d15bcec97cad88a301ffe3d12b999b47d155c610e4cb4de1dc64916115b89190815260200190565b60405180910390a15050600180555050565b600480546040516331a9108f60e11b815291820183905260009130916001600160a01b031690636352211e90602401602060405180830381865afa158015611616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163a9190613dab565b6001600160a01b03161461165057506000919050565b6000828152600860205260409020546116688161258b565b159392505050565b6116786125bd565b600061168a6060850160408601613c03565b6001600160a01b03161480156116aa575082602001356116a8611c93565b105b156116c85760405163e926a90f60e01b815260040160405180910390fd5b60006116da6060850160408601613c03565b6001600160a01b0316036117dc57600260009054906101000a90046001600160a01b03166001600160a01b031663f27d5f466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561173b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175f9190613dab565b6001600160a01b0316635ef0a6f984602001358585856040518563ffffffff1660e01b815260040161179393929190613f0f565b60206040518083038185885af11580156117b1573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906117d69190613ed4565b50505050565b60006117ee6060850160408601613c03565b9050806001600160a01b031663095ea7b3600260009054906101000a90046001600160a01b03166001600160a01b031663f27d5f466040518163ffffffff1660e01b8152600401602060405180830381865afa158015611852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118769190613dab565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602087013560248201526044016020604051808303816000875af11580156118c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ea9190613eed565b50600260009054906101000a90046001600160a01b03166001600160a01b031663f27d5f466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561193e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119629190613dab565b6001600160a01b0316635ef0a6f98585856040518463ffffffff1660e01b815260040161199193929190613f0f565b6020604051808303816000875af11580156119b0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae39190613ed4565b505050565b600260015403611a2b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b6002600155611a3a8282612a32565b611a4682826001612763565b6040518281527f71bef4a8469a3b83c64a11128d95ac7253a399544da7d5f50e8ef4a32f3fac329060200160405180910390a1505060018055565b611a896125bd565b6005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c90602001610db8565b611aec6125bd565b611af66000612fc5565b565b600480546040516331a9108f60e11b815291820183905260009130916001600160a01b031690636352211e90602401602060405180830381865afa158015611b44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b689190613dab565b6001600160a01b031614611b8f576040516363f03bed60e11b815260040160405180910390fd5b5060009081526008602052604090205490565b611baa6125bd565b6005805473ffffffffffffffffffffffffffffffffffffffff19169055604051600081527f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c9060200160405180910390a1565b611c056125bd565b60405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0383169063a9059cbb906044016020604051808303816000875af1158015611c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c769190613eed565b610bec5760405163467d86d160e01b815260040160405180910390fd5b60004781611c9f610b7d565b905060005b8151811015611d3f576000611cd1838381518110611cc457611cc4613d95565b602002602001015161237c565b9050600181602001516001811115611ceb57611ceb613d1b565b148015611d155750611d15838381518110611d0857611d08613d95565b602002602001015161258b565b15611d2c576040810151611d299085613ec1565b93505b5080611d3781613dde565b915050611ca4565b509092915050565b6000600260015403611d9b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610280565b600260015584356000908152600a602052604090205460ff1615611dd257604051633d9c5bb760e11b815260040160405180910390fd5b611ddd858585613022565b6003546002546040517fee1fe2ad0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301529182166024820152600092919091169063ee1fe2ad906044016020604051808303816000875af1158015611e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e759190613ed4565b905060006040518060a00160405280600115158152602001886040016020810190611ea09190613f8c565b6001811115611eb157611eb1613d1b565b81526060808a013560208084019190915260a08b013560408085019190915260c08c01359290930191909152600085815260098252919091208251815490151560ff198216811783559284015193945084939192839161ff001990911661ffff1990911617610100836001811115611f2b57611f2b613d1b565b021790555060408201516001820155606082015160028201556080909101516003909101556000611f626060890160408a01613f8c565b6001811115611f7357611f73613d1b565b03611f8f5760c087013560009081526008602052604090208290555b611f9a6006836133c4565b5086356000818152600a602052604090819020805460ff19166001179055517f6bb1c0efefbf73ea6121a1bc64a18154976add0ae92fb1434d5731f157e0a3fb91611ffd91859160808c0135919283526020830191909152604082015260600190565b60405180910390a1506001805595945050505050565b600061201d6125bd565b600061202f60e0870160c08801613f8c565b600181111561204057612040613d1b565b036120705761204e826115ca565b61206b576040516363f03bed60e11b815260040160405180910390fd5b6120a1565b8460e0013561207d611c93565b101561209c5760405163e926a90f60e01b815260040160405180910390fd5b600091505b6003546000906001600160a01b031663ee1fe2ad6120c560c0890160a08a01613c03565b60025460405160e084901b6001600160e01b03191681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af1158015612115573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121399190613ed4565b9050600061214d60e0880160c08901613f8c565b600181111561215e5761215e613d1b565b036121755760008381526008602052604090208190555b6040805160a08101909152600181526000906020810161219b60e08a0160c08b01613f8c565b60018111156121ac576121ac613d1b565b81526020018860e0013581526020018861010001358152602001858152509050806009600084815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff0219169083600181111561222a5761222a613d1b565b0217905550604082015160018201556060820151600282015560809091015160039091015561225a6006836133c4565b50604080518381526020808a0135908201527fbef1c9f7171f2ce944e29c1be0951badd44e40459d6e541791baf896f3db1845910160405180910390a1600260009054906101000a90046001600160a01b03166001600160a01b031663f27d5f466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230e9190613dab565b6001600160a01b03166375031dc8888888866040518563ffffffff1660e01b815260040161233f9493929190613fa7565b600060405180830381600087803b15801561235957600080fd5b505af115801561236d573d6000803e3d6000fd5b50939998505050505050505050565b6123af6040805160a081019091526000808252602082019081526020016000815260200160008152602001600081525090565b600082815260096020908152604091829020825160a08101909352805460ff8082161515855291928401916101009091041660018111156123f2576123f2613d1b565b600181111561240357612403613d1b565b8152600182015460208201526002820154604082015260039091015460609091015292915050565b6124336125bd565b8061243c611c93565b101561245b5760405163e926a90f60e01b815260040160405180910390fd5b6040513390600090829084908381818185875af1925050503d806000811461249f576040519150601f19603f3d011682016040523d82523d6000602084013e6124a4565b606091505b50509050806124c65760405163467d86d160e01b815260040160405180910390fd5b6040518381527f043f607a14d3b4f0a11a0b2e192bbfcd894298ba5abf22553be6081406db28aa9060200160405180910390a1505050565b6125066125bd565b6001600160a01b0381166125825760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610280565b610c4581612fc5565b60008181526009602052604081205460ff1680156106d457505060009081526009602052604090206002015442111590565b6000546001600160a01b03163314611af65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610280565b6000546001600160a01b0316156126705760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a6564000000000000000000000000006044820152606401610280565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0387161790556126a182612fc5565b600480546001600160a01b0380871673ffffffffffffffffffffffffffffffffffffffff1992831617909255600380548684169216919091179055811615610ae3576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c9060200160405180910390a15050505050565b600081815260018301602052604081205415155b9392505050565b6000838152600960209081526040808320815160a08101909252805460ff8082161515845292939192918401916101009091041660018111156127a8576127a8613d1b565b60018111156127b9576127b9613d1b565b8152600182015460208201526002820154604082015260039091015460609091015290506000816020015160018111156127f5576127f5613d1b565b036128b5578115612880576004546001600160a01b03166342842e0e303360808501516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561286757600080fd5b505af115801561287b573d6000803e3d6000fd5b505050505b60808101516000908152600860205260409020548490036128b05760808101516000908152600860205260408120555b612964565b6001816020015160018111156128cd576128cd613d1b565b03612964578115612964576004546001600160a01b03166342842e0e336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015230602482015260448101869052606401600060405180830381600087803b15801561293857600080fd5b505af115801561294c573d6000803e3d6000fd5b5050505061296461295a3390565b8260400151612db8565b6000848152600960205260409020805460ff19169055612985600685612a10565b506003546040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b03909116906342966c6890602401600060405180830381600087803b1580156129e557600080fd5b505af11580156129f9573d6000803e3d6000fd5b5050505050505050565b6060600061275c836133d0565b600061275c838361342c565b60006106d4825490565b600061275c838361351f565b612a3d600683612748565b612aaf5760405162461bcd60e51b815260206004820152603260248201527f576173616269506f6f6c3a204f7074696f6e204e465420646f65736e2774206260448201527f656c6f6e6720746f207468697320706f6f6c00000000000000000000000000006064820152608401610280565b6003546040516331a9108f60e11b8152600481018490526001600160a01b0390911690636352211e90602401602060405180830381865afa158015612af8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b1c9190613dab565b6001600160a01b0316336001600160a01b031614612ba25760405162461bcd60e51b815260206004820152603760248201527f576173616269506f6f6c3a204f6e6c792074686520746f6b656e206f776e657260448201527f2063616e206578656375746520746865206f7074696f6e0000000000000000006064820152608401610280565b6000828152600960209081526040808320815160a08101909252805460ff808216151584529293919291840191610100909104166001811115612be757612be7613d1b565b6001811115612bf857612bf8613d1b565b8152602001600182015481526020016002820154815260200160038201548152505090504281606001511015612c4157604051633d36c2e560e01b815260040160405180910390fd5b600081602001516001811115612c5957612c59613d1b565b03612c84576119d481604001516040518060800160405280604681526020016141cf60469139613549565b600181602001516001811115612c9c57612c9c613d1b565b036119d457600480546040516331a9108f60e11b81529182018490526001600160a01b031690636352211e90602401602060405180830381865afa158015612ce8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0c9190613dab565b6001600160a01b0316336001600160a01b0316146119d45760405162461bcd60e51b815260206004820152604a60248201527f576173616269506f6f6c3a204e65656420746f206f776e2074686520746f6b6560448201527f6e20746f2073656c6c20696e206f7264657220746f206578656375746520612060648201527f505554206f7074696f6e00000000000000000000000000000000000000000000608482015260a401610280565b6002546040805163796b1c1360e11b815290516000926001600160a01b03169163f2d638269160048083019260209291908290030181865afa158015612e02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e269190613dab565b604051635424042960e01b81523060048201526024810184905290915060009081906001600160a01b038416906354240429906044016040805180830381865afa158015612e78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e9c9190613e93565b90925090508015612f37576000612eb285612fb8565b905080821115612ec0578091505b6000836001600160a01b03168360405160006040518083038185875af1925050503d8060008114612f0d576040519150601f19603f3d011682016040523d82523d6000602084013e612f12565b606091505b5050905080612f345760405163467d86d160e01b815260040160405180910390fd5b50505b60006001600160a01b038616612f4d8387613ec1565b604051600081818185875af1925050503d8060008114612f89576040519150601f19603f3d011682016040523d82523d6000602084013e612f8e565b606091505b5050905080612fb05760405163467d86d160e01b815260040160405180910390fd5b505050505050565b60006106d4600a8361408f565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040517f827f3b6e00000000000000000000000000000000000000000000000000000000815260009073e3f3dca2bd68cbd34b58cfc3bcd109998fcce0ac9063827f3b6e90613079908790879087906004016140b1565b602060405180830381865af4158015613096573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130ba9190613dab565b90506001600160a01b03811615806130f957506005546001600160a01b038281169116148015906130f957506000546001600160a01b03828116911614155b1561311757604051638baa579f60e01b815260040160405180910390fd5b428460e00135101561313c57604051633d36c2e560e01b815260040160405180910390fd5b3061314d6040860160208701613c03565b6001600160a01b0316146131c95760405162461bcd60e51b815260206004820152603160248201527f576173616269506f6f6c3a205369676e617475726520646f65736e277420626560448201527f6c6f6e6720746f207468697320706f6f6c0000000000000000000000000000006064820152608401610280565b6131ef84608001356040518060600160405280602a81526020016141a5602a9139613549565b836060013560000361322d576040517f9a5818d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360a0013560000361326b576040517fd36c850000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061327d6060860160408701613f8c565b600181111561328e5761328e613d1b565b0361337057600480546040516331a9108f60e11b815260c08701359281019290925230916001600160a01b0390911690636352211e90602401602060405180830381865afa1580156132e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133089190613dab565b6001600160a01b03161461332f576040516363f03bed60e11b815260040160405180910390fd5b60c084013560009081526008602052604090205461334c8161258b565b1561336a57604051637aac9f5d60e01b815260040160405180910390fd5b506117d6565b60016133826060860160408701613f8c565b600181111561339357613393613d1b565b036117d65783606001356133a5611c93565b10156117d65760405163e926a90f60e01b815260040160405180910390fd5b600061275c8383613700565b60608160000180548060200260200160405190810160405280929190818152602001828054801561342057602002820191906000526020600020905b81548152602001906001019080831161340c575b50505050509050919050565b60008181526001830160205260408120548015613515576000613450600183613ec1565b855490915060009061346490600190613ec1565b90508181146134c957600086600001828154811061348457613484613d95565b90600052602060002001549050808760000184815481106134a7576134a7613d95565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806134da576134da614140565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106d4565b60009150506106d4565b600082600001828154811061353657613536613d95565b9060005260206000200154905092915050565b6002546040805163796b1c1360e11b815290516000926001600160a01b03169163f2d638269160048083019260209291908290030181865afa158015613593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b79190613dab565b604051635424042960e01b81523060048201526024810185905290915060009081906001600160a01b038416906354240429906044016040805180830381865afa158015613609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061362d9190613e93565b909250905080156136c857600061364386612fb8565b905080821115613651578091505b6000836001600160a01b03168360405160006040518083038185875af1925050503d806000811461369e576040519150601f19603f3d011682016040523d82523d6000602084013e6136a3565b606091505b50509050806136c55760405163467d86d160e01b815260040160405180910390fd5b50505b6136d28186613e80565b34101580156136e15750600085115b8490612fb05760405162461bcd60e51b81526004016102809190614156565b6000818152600183016020526040812054613747575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106d4565b5060006106d4565b60006020828403121561376157600080fd5b81356001600160e01b03198116811461275c57600080fd5b6001600160a01b0381168114610c4557600080fd5b6000806000604084860312156137a357600080fd5b83356137ae81613779565b9250602084013567ffffffffffffffff808211156137cb57600080fd5b818601915086601f8301126137df57600080fd5b8135818111156137ee57600080fd5b8760208260051b850101111561380357600080fd5b6020830194508093505050509250925092565b6000610100828403121561382957600080fd5b50919050565b60008083601f84011261384157600080fd5b50813567ffffffffffffffff81111561385957600080fd5b60208301915083602082850101111561387157600080fd5b9250929050565b6000806000610120848603121561388e57600080fd5b6138988585613816565b925061010084013567ffffffffffffffff8111156138b557600080fd5b6138c18682870161382f565b9497909650939450505050565b80356138d981613779565b919050565b600080600080600060a086880312156138f657600080fd5b853561390181613779565b9450602086013561391181613779565b9350604086013561392181613779565b9250606086013561393181613779565b9150608086013561394181613779565b809150509295509295909350565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561398e5761398e61394f565b604052919050565b600080600080608085870312156139ac57600080fd5b84356139b781613779565b93506020858101356139c881613779565b935060408601359250606086013567ffffffffffffffff808211156139ec57600080fd5b818801915088601f830112613a0057600080fd5b813581811115613a1257613a1261394f565b613a24601f8201601f19168501613965565b91508082528984828501011115613a3a57600080fd5b808484018584013760008482840101525080935050505092959194509250565b6020808252825182820181905260009190848201906040850190845b81811015613a9257835183529284019291840191600101613a76565b50909695505050505050565b600060208284031215613ab057600080fd5b5035919050565b60006020808385031215613aca57600080fd5b823567ffffffffffffffff80821115613ae257600080fd5b818501915085601f830112613af657600080fd5b813581811115613b0857613b0861394f565b8060051b9150613b19848301613965565b8181529183018401918481019088841115613b3357600080fd5b938501935b83851015613b5157843582529385019390850190613b38565b98975050505050505050565b600080600083850360c0811215613b7357600080fd5b60a0811215613b8157600080fd5b5083925060a084013567ffffffffffffffff8111156138b557600080fd5b600080600083850360e0811215613bb557600080fd5b60c0811215613bc357600080fd5b5083925060c084013567ffffffffffffffff8111156138b557600080fd5b60008060408385031215613bf457600080fd5b50508035926020909101359150565b600060208284031215613c1557600080fd5b813561275c81613779565b60008060408385031215613c3357600080fd5b8235613c3e81613779565b946020939093013593505050565b6000806000806101408587031215613c6357600080fd5b613c6d8686613816565b935061010085013567ffffffffffffffff811115613c8a57600080fd5b613c968782880161382f565b909450925050610120850135613cab81613779565b939692955090935050565b6000806000808486036101a0811215613cce57600080fd5b61016080821215613cde57600080fd5b869550850135905067ffffffffffffffff811115613cfb57600080fd5b613d078782880161382f565b959890975094956101800135949350505050565b634e487b7160e01b600052602160045260246000fd5b60028110613d4f57634e487b7160e01b600052602160045260246000fd5b9052565b81511515815260208083015160a0830191613d7090840182613d31565b5060408301516040830152606083015160608301526080830151608083015292915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613dbd57600080fd5b815161275c81613779565b634e487b7160e01b600052601160045260246000fd5b600060018201613df057613df0613dc8565b5060010190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b833581526020840135602082015260006040850135613e3e81613779565b6001600160a01b038116604084015250606085013560608301526080850135608083015260c060a0830152613e7760c083018486613df7565b95945050505050565b808201808211156106d4576106d4613dc8565b60008060408385031215613ea657600080fd5b8251613eb181613779565b6020939093015192949293505050565b818103818111156106d4576106d4613dc8565b600060208284031215613ee657600080fd5b5051919050565b600060208284031215613eff57600080fd5b8151801515811461275c57600080fd5b833581526020840135602082015260006040850135613f2d81613779565b6001600160a01b0380821660408501526060870135606085015260808701359150613f5782613779565b16608083015260a0858101359083015260e060c08301819052613e779083018486613df7565b8035600281106138d957600080fd5b600060208284031215613f9e57600080fd5b61275c82613f7d565b60006101a08635835260208701356020840152613fc6604088016138ce565b6001600160a01b03166040840152613fe0606088016138ce565b6001600160a01b031660608401526080878101359084015261400460a088016138ce565b6001600160a01b031660a084015261401e60c08801613f7d565b61402b60c0850182613d31565b5060e087810135908401526101008088013590840152610120808801359084015261014061405a8189016138ce565b6001600160a01b031690840152610160830181905261407c8184018688613df7565b9150508261018083015295945050505050565b6000826140ac57634e487b7160e01b600052601260045260246000fd5b500490565b60006101208535835260208601356140c881613779565b6001600160a01b031660208401526140e260408701613f7d565b6140ef6040850182613d31565b50606086013560608401526080860135608084015260a086013560a084015260c086013560c084015260e086013560e0840152806101008401526141368184018587613df7565b9695505050505050565b634e487b7160e01b600052603160045260246000fd5b600060208083528351808285015260005b8181101561418357858101830151858201604001528201614167565b506000604082860101526040601f19601f830116850101925050509291505056fe576173616269506f6f6c3a204e6f7420656e6f756768207072656d69756d20697320737570706c696564576173616269506f6f6c3a20537472696b65207072696365206e6565647320746f20626520737570706c69656420746f206578656375746520612043414c4c206f7074696f6ea2646970667358221220d68b729683b67aac1630260e8e40dc473eb072dbb23d3524a04f9071c71e327664736f6c63430008130033
Libraries Used
PoolAskVerifier : 0xe3f3dca2bd68cbd34b58cfc3bcd109998fcce0acPoolBidVerifier : 0x66873693e8b125dbea46274173b0d6dcd1933cca
Deployed Bytecode Sourcemap
103318:3377:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103422:22;;103434:9;160:25:1;;103422:22:0;;148:2:1;133:18;103422:22:0;;;;;;;103318:3377;;84902:29;;-1:-1:-1;;;84902:29:0;;398:2:1;84902:29:0;;;380:21:1;437:2;417:18;;;410:30;476:13;456:18;;;449:41;507:18;;84902:29:0;;;;;;;;;103318:3377;101641:211;;;;;;;;;;-1:-1:-1;101641:211:0;;;;;:::i;:::-;;:::i;:::-;;;1038:14:1;;1031:22;1013:41;;1001:2;986:18;101641:211:0;;;;;;;;100774:399;;;;;;;;;;-1:-1:-1;100774:399:0;;;;;:::i;:::-;;:::i;88198:215::-;;;;;;:::i;:::-;;:::i;:::-;;;160:25:1;;;148:2;133:18;88198:215:0;14:177:1;85683:104:0;;;;;;;;;;-1:-1:-1;85742:7:0;85683:104;;;-1:-1:-1;;;;;3363:55:1;;;3345:74;;3333:2;3318:18;85683:104:0;3199:226:1;99904:829:0;;;;;;;;;;-1:-1:-1;99904:829:0;;;;;:::i;:::-;;:::i;103540:261::-;;;;;;:::i;:::-;;:::i;86471:578::-;;;;;;;;;;-1:-1:-1;86471:578:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;;6243:79:1;;;6225:98;;6213:2;6198:18;86471:578:0;6081:248:1;102563:106:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;84756:53::-;;;;;;;;;;-1:-1:-1;84756:53:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;98017:678;;;;;;;;;;-1:-1:-1;98017:678:0;;;;;:::i;:::-;;:::i;90229:214::-;;;;;;:::i;:::-;;:::i;101214:390::-;;;;;;;;;;-1:-1:-1;101214:390:0;;;;;:::i;:::-;;:::i;93933:3508::-;;;;;;:::i;:::-;;:::i;102710:266::-;;;;;;;;;;-1:-1:-1;102710:266:0;;;;;:::i;:::-;;:::i;93191:701::-;;;;;;;;;;-1:-1:-1;93191:701:0;;;;;:::i;:::-;;:::i;90484:254::-;;;;;;:::i;:::-;;:::i;86151:89::-;;;;;;;;;;-1:-1:-1;86227:5:0;;-1:-1:-1;;;;;86227:5:0;86151:89;;85828:122;;;;;;;;;;-1:-1:-1;85828:122:0;;;;;:::i;:::-;;:::i;3988:103::-;;;;;;;;;;;;;:::i;102275:247::-;;;;;;;;;;-1:-1:-1;102275:247:0;;;;;:::i;:::-;;:::i;86281:96::-;;;;;;;;;;-1:-1:-1;86361:7:0;;-1:-1:-1;;;;;86361:7:0;86281:96;;3340:87;;;;;;;;;;-1:-1:-1;3386:7:0;3413:6;-1:-1:-1;;;;;3413:6:0;3340:87;;85991:119;;;;;;;;;;;;;:::i;105929:197::-;;;;;;;;;;-1:-1:-1;105929:197:0;;;;;:::i;:::-;;:::i;106167:525::-;;;;;;;;;;;;;:::i;85548:94::-;;;;;;;;;;-1:-1:-1;85630:3:0;;-1:-1:-1;;;;;85630:3:0;85548:94;;84429:33;;;;;;;;;;-1:-1:-1;84429:33:0;;;;-1:-1:-1;;;;;84429:33:0;;;87090:1067;;;;;;:::i;:::-;;:::i;91811:1339::-;;;;;;;;;;-1:-1:-1;91811:1339:0;;;;;:::i;:::-;;:::i;102095:139::-;;;;;;;;;;-1:-1:-1;102095:139:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;105462:426::-;;;;;;:::i;:::-;;:::i;4246:201::-;;;;;;;;;;-1:-1:-1;4246:201:0;;;;;:::i;:::-;;:::i;101893:161::-;;;;;;;;;;-1:-1:-1;101893:161:0;;;;;:::i;:::-;;:::i;101641:211::-;101711:4;-1:-1:-1;;;;;;101735:44:0;;101750:29;101735:44;;:109;;-1:-1:-1;;;;;;;101796:48:0;;-1:-1:-1;;;101796:48:0;101735:109;101728:116;101641:211;-1:-1:-1;;101641:211:0:o;100774:399::-;3226:13;:11;:13::i;:::-;27358:1:::1;27956:7;;:19:::0;27948:63:::1;;;::::0;-1:-1:-1;;;27948:63:0;;12930:2:1;27948:63:0::1;::::0;::::1;12912:21:1::0;12969:2;12949:18;;;12942:30;13008:33;12988:18;;;12981:61;13059:18;;27948:63:0::1;12728:355:1::0;27948:63:0::1;27358:1;28089:7;:18:::0;100900:3:::2;::::0;-1:-1:-1;;;;;100892:11:0;;::::2;100900:3:::0;::::2;100892:11;100884:42;;;::::0;-1:-1:-1;;;100884:42:0;;13290:2:1;100884:42:0::2;::::0;::::2;13272:21:1::0;13329:2;13309:18;;;13302:30;13368:20;13348:18;;;13341:48;13406:18;;100884:42:0::2;13088:342:1::0;100884:42:0::2;100955:9:::0;100937:15:::2;100982:184;101002:7;100998:1;:11;100982:184;;;-1:-1:-1::0;;;;;101028:21:0;::::2;;1996:10:::0;101072:4:::2;101079:9;;101089:1;101079:12;;;;;;;:::i;:::-;101028:64;::::0;-1:-1:-1;;;;;;101028:64:0::2;::::0;;;;;;-1:-1:-1;;;;;13905:15:1;;;101028:64:0::2;::::0;::::2;13887:34:1::0;13957:15;;;;13937:18;;;13930:43;-1:-1:-1;101079:12:0::2;::::0;;::::2;;;13989:18:1::0;;;13982:34;13799:18;;101028:64:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;101136:3;;;;;100982:184;;;-1:-1:-1::0;;27314:1:0::1;28268:22:::0;;-1:-1:-1;;;100774:399:0:o;88198:215::-;88329:7;88356:49;88370:8;88380:10;;1996;87090:1067;:::i;88356:49::-;88349:56;88198:215;-1:-1:-1;;;;88198:215:0:o;99904:829::-;3226:13;:11;:13::i;:::-;27358:1:::1;27956:7;;:19:::0;27948:63:::1;;;::::0;-1:-1:-1;;;27948:63:0;;12930:2:1;27948:63:0::1;::::0;::::1;12912:21:1::0;12969:2;12949:18;;;12942:30;13008:33;12988:18;;;12981:61;13059:18;;27948:63:0::1;12728:355:1::0;27948:63:0::1;27358:1;28089:7;:18:::0;100042:3:::2;::::0;-1:-1:-1;;;;;100034:11:0;;::::2;100042:3:::0;::::2;100034:11;100076:9:::0;100015:16:::2;100103:623;100123:7;100119:1;:11;100103:623;;;100153:11;100149:430;;;100189:3;::::0;100226:4:::2;::::0;-1:-1:-1;;;;;100189:3:0::2;:11;100201:9:::0;;100211:1;100201:12;;::::2;;;;;:::i;:::-;;;;;;;100189:25;;;;;;;;;;;;;160::1::0;;148:2;133:18;;14:177;100189:25:0::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;100189:42:0::2;;100185:126;;100263:28;;-1:-1:-1::0;;;100263:28:0::2;;;;;;;;;;;100185:126;100329:16;100348:17;:31;100366:9;;100376:1;100366:12;;;;;;;:::i;:::-;;;;;;;100348:31;;;;;;;;;;;;100329:50;;100402:17;100410:8;100402:7;:17::i;:::-;100398:107;;;100451:34;;-1:-1:-1::0;;;100451:34:0::2;;;;;;;;;;;100398:107;100532:17;:31;100550:9;;100560:1;100550:12;;;;;;;:::i;:::-;;;;;;;100532:31;;;;;;;;;;;100525:38;;;100166:413;100149:430;100593:4;-1:-1:-1::0;;;;;100593:21:0::2;;100623:4;100630:7;3386::::0;3413:6;-1:-1:-1;;;;;3413:6:0;;3340:87;100630:7:::2;100639:9;;100649:1;100639:12;;;;;;;:::i;:::-;100593:59;::::0;-1:-1:-1;;;;;;100593:59:0::2;::::0;;;;;;-1:-1:-1;;;;;13905:15:1;;;100593:59:0::2;::::0;::::2;13887:34:1::0;13957:15;;;;13937:18;;;13930:43;-1:-1:-1;100639:12:0::2;::::0;;::::2;;;13989:18:1::0;;;13982:34;13799:18;;100593:59:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;100696:3;;;;;100103:623;;;-1:-1:-1::0;;27314:1:0::1;28268:22:::0;;-1:-1:-1;;;;99904:829:0:o;103540:261::-;103735:58;103750:8;103760:4;103766:10;103778:6;103786;103735:14;:58::i;:::-;103540:261;;;;;:::o;86471:578::-;86705:9;;86658:6;;-1:-1:-1;;;;;86705:9:0;1996:10;86681:34;86677:317;;86737:27;:9;86756:7;86737:18;:27::i;:::-;86732:104;;86792:28;;-1:-1:-1;;;86792:28:0;;;;;;;;;;;86732:104;86850:30;86862:7;86871:1;86874:5;86850:11;:30::i;:::-;86677:317;;;86926:3;;-1:-1:-1;;;;;86926:3:0;1996:10;-1:-1:-1;;;;;86902:28:0;;86898:96;;86954:28;;-1:-1:-1;;;86954:28:0;;;;;;;;;;;86898:96;-1:-1:-1;;;;86471:578:0;;;;;;:::o;102563:106::-;102607:16;102643:18;:9;:16;:18::i;:::-;102636:25;;102563:106;:::o;98017:678::-;98097:17;;:21;98093:595;;98140:9;98135:229;98159:10;:17;98155:1;:21;98135:229;;;98202:17;98222:10;98233:1;98222:13;;;;;;;;:::i;:::-;;;;;;;98202:33;;98259:18;98267:9;98259:7;:18::i;:::-;98254:95;;98302:27;:9;98319;98302:16;:27::i;:::-;;98254:95;-1:-1:-1;98178:3:0;;;;:::i;:::-;;;;98135:229;;;;98017:678;:::o;98093:595::-;98401:9;98396:281;98420:18;:9;:16;:18::i;:::-;98416:1;:22;98396:281;;;98460:17;98480:15;:9;98493:1;98480:12;:15::i;:::-;98460:35;;98519:18;98527:9;98519:7;:18::i;:::-;98514:148;;98562:27;:9;98579;98562:16;:27::i;:::-;;98514:148;;;98638:4;;;;:::i;:::-;;;;98514:148;98441:236;98396:281;;98093:595;98017:678;:::o;90229:214::-;27358:1;27956:7;;:19;27948:63;;;;-1:-1:-1;;;27948:63:0;;12930:2:1;27948:63:0;;;12912:21:1;12969:2;12949:18;;;12942:30;13008:33;12988:18;;;12981:61;13059:18;;27948:63:0;12728:355:1;27948:63:0;27358:1;28089:7;:18;90312:40:::1;90339:9:::0;90350:1:::1;90312:26;:40::i;:::-;90363:31;90375:9;90386:1;90389:4;90363:11;:31::i;:::-;90410:25;::::0;160::1;;;90410::0::1;::::0;148:2:1;133:18;90410:25:0::1;;;;;;;-1:-1:-1::0;27314:1:0;28268:22;;90229:214::o;101214:390::-;101293:5;;-1:-1:-1;;;;;101293:5:0;1996:10;-1:-1:-1;;;;;101277:21:0;;;:48;;;;-1:-1:-1;3386:7:0;3413:6;-1:-1:-1;;;;;3413:6:0;1996:10;101302:23;;101277:48;101273:116;;;101349:28;;-1:-1:-1;;;101349:28:0;;;;;;;;;;;101273:116;101403:31;;;;:21;:31;;;;;;;;101399:109;;;101458:38;;-1:-1:-1;;;101458:38:0;;;;;;;;;;;101399:109;101518:31;;;;:21;:31;;;;;;;:38;;-1:-1:-1;;101518:38:0;101552:4;101518:38;;;101572:24;;;;;101540:8;160:25:1;;148:2;133:18;;14:177;101572:24:0;;;;;;;;101214:390;:::o;93933:3508::-;27358:1;27956:7;;:19;27948:63;;;;-1:-1:-1;;;27948:63:0;;12930:2:1;27948:63:0;;;12912:21:1;12969:2;12949:18;;;12942:30;13008:33;12988:18;;;12981:61;13059:18;;27948:63:0;12728:355:1;27948:63:0;27358:1;28089:7;:18;94106:57:::1;::::0;;;;94089:14:::1;::::0;94106:15:::1;::::0;:35:::1;::::0;:57:::1;::::0;94142:8;;94152:10;;;;94106:57:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94089:74;;94188:7;3386::::0;3413:6;-1:-1:-1;;;;;3413:6:0;;3340:87;94188:7:::1;-1:-1:-1::0;;;;;94178:17:0::1;:6;-1:-1:-1::0;;;;;94178:17:0::1;;94174:89;;94219:32;;-1:-1:-1::0;;;94219:32:0::1;;;;;;;;;;;94174:89;94278:26;94286:8;:17;;;94278:7;:26::i;:::-;94273:93;;94328:26;;-1:-1:-1::0;;;94328:26:0::1;;;;;;;;;;;94273:93;94402:11:::0;::::1;94380:34;::::0;;;:21:::1;:34;::::0;;;;;::::1;;94376:112;;;94438:38;;-1:-1:-1::0;;;94438:38:0::1;;;;;;;;;;;94376:112;94525:15;94502:8;:20;;;:38;94498:104;;;94564:26;;-1:-1:-1::0;;;94564:26:0::1;;;;;;;;;;;94498:104;94685:9;::::0;:36:::1;::::0;-1:-1:-1;;;94685:36:0;;94703:17:::1;::::0;::::1;;94685:36;::::0;::::1;160:25:1::0;-1:-1:-1;;;;;94685:9:0;;::::1;::::0;:17:::1;::::0;133:18:1;;94685:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;94669:52:0::1;1996:10:::0;-1:-1:-1;;;;;94669:52:0::1;;94665:120;;94745:28;;-1:-1:-1::0;;;94745:28:0::1;;;;;;;;;;;94665:120;85742:7:::0;94801:21:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;94801:46:0::1;::::0;94797:2544:::1;;94864:42;94909:32;94923:8;:17;;;94909:13;:32::i;:::-;94864:77:::0;-1:-1:-1;94985:29:0::1;94960:10;:21;;;:54;;;;;;;;:::i;:::-;;:93;;;;;95039:8;:14;;;95018:18;:16;:18::i;:::-;:35;94960:93;94956:524;;;95081:46;;-1:-1:-1::0;;;95081:46:0::1;;;;;;;;;;;94956:524;95178:28;95153:10;:21;;;:53;;;;;;;;:::i;:::-;;:223;;;;;95362:8;:14;;;95336:10;:22;;;95315:18;:16;:18::i;:::-;:43;;;;:::i;:::-;95314:62;95153:223;95149:331;;;95418:46;;-1:-1:-1::0;;;95418:46:0::1;;;;;;;;;;;95149:331;95494:40;95506:8;:17;;;95525:1;95528:5:::0;95494:11:::1;:40::i;:::-;95549;1996:10:::0;95574:8:::1;:14;;;95549:10;:40::i;:::-;94849:752;94797:2544;;;95671:7;::::0;:23:::1;::::0;;-1:-1:-1;;;95671:23:0;;;;95622:28:::1;::::0;-1:-1:-1;;;;;95671:7:0::1;::::0;:21:::1;::::0;:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:7;:23:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95753:52;::::0;-1:-1:-1;;;95753:52:0;;95783:4:::1;95753:52;::::0;::::1;15998:74:1::0;95790:14:0::1;::::0;::::1;;16088:18:1::0;;;16081:34;95622:73:0;;-1:-1:-1;95711:19:0::1;::::0;;;-1:-1:-1;;;;;95753:21:0;::::1;::::0;::::1;::::0;15971:18:1;;95753:52:0::1;::::0;::::1;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95710:95;;;;95820:14;95837:23;95845:8;:14;;;95837:7;:23::i;:::-;95820:40;;95891:6;95879:9;:18;95875:77;;;95930:6;95918:18;;95875:77;96005:1;95972:21;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;95972:35:0::1;::::0;95968:1307:::1;;96056:8;:14;;;96032:21;:38;96028:140;;;96102:46;;-1:-1:-1::0;;;96102:46:0::1;;;;;;;;;;;96028:140;96187:9;1996:10:::0;96236:26:::1;96253:9:::0;96236:14:::1;::::0;::::1;;:26;:::i;:::-;96202:65;::::0;::::1;::::0;;;;;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96186:81;;;96291:4;96286:89;;96327:28;;-1:-1:-1::0;;;96327:28:0::1;;;;;;;;;;;96286:89;96397:13:::0;;96393:246:::1;;96436:10;96460:11;-1:-1:-1::0;;;;;96452:25:0::1;96485:9;96452:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96435:64;;;96527:5;96522:98;;96568:28;;-1:-1:-1::0;;;96568:28:0::1;;;;;;;;;;;96522:98;96412:227;96393:246;96009:645;95968:1307;;;96679:12;96701:21;::::0;;;::::1;::::0;::::1;;:::i;:::-;96746:30;::::0;;;;96770:4:::1;96746:30;::::0;::::1;3345:74:1::0;96679:44:0;;-1:-1:-1;96779:14:0::1;::::0;::::1;;::::0;-1:-1:-1;;;;;96746:15:0;::::1;::::0;::::1;::::0;3318:18:1;;96746:30:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;96742:149;;;96825:46;;-1:-1:-1::0;;;96825:46:0::1;;;;;;;;;;;96742:149;-1:-1:-1::0;;;;;96914:14:0;::::1;;1996:10:::0;96943:26:::1;96960:9:::0;96943:14:::1;::::0;::::1;;:26;:::i;:::-;96914:56;::::0;-1:-1:-1;;;;;;96914:56:0::1;::::0;;;;;;-1:-1:-1;;;;;16016:55:1;;;96914:56:0::1;::::0;::::1;15998:74:1::0;16088:18;;;16081:34;15971:18;;96914:56:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96909:141;;97002:28;;-1:-1:-1::0;;;97002:28:0::1;;;;;;;;;;;96909:141;97072:13:::0;;97068:192:::1;;97115:38;::::0;-1:-1:-1;;;97115:38:0;;-1:-1:-1;;;;;16016:55:1;;;97115:38:0::1;::::0;::::1;15998:74:1::0;16088:18;;;16081:34;;;97115:14:0;::::1;::::0;::::1;::::0;15971:18:1;;97115:38:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97110:131;;97189:28;;-1:-1:-1::0;;;97189:28:0::1;;;;;;;;;;;97110:131;96660:615;95968:1307;97289:40;97301:8;:17;;;97320:1;97323:5:::0;97289:11:::1;:40::i;:::-;95607:1734;;;;94797:2544;97373:11:::0;::::1;97351:34;::::0;;;:21:::1;:34;::::0;;;;;;:41;;-1:-1:-1;;97351:41:0::1;97388:4;97351:41;::::0;;97408:25;::::1;::::0;::::1;::::0;160::1;;;148:2;133:18;;14:177;97408:25:0::1;;;;;;;;-1:-1:-1::0;;27314:1:0;28268:22;;-1:-1:-1;;93933:3508:0:o;102710:266::-;102797:3;;;:21;;-1:-1:-1;;;102797:21:0;;;;;160:25:1;;;102776:4:0;;102830;;-1:-1:-1;;;;;102797:3:0;;:11;;133:18:1;;102797:21:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;102797:38:0;;102793:83;;-1:-1:-1;102859:5:0;;102710:266;-1:-1:-1;102710:266:0:o;102793:83::-;102886:16;102905:27;;;:17;:27;;;;;;102951:17;102905:27;102951:7;:17::i;:::-;102950:18;;102710:266;-1:-1:-1;;;102710:266:0:o;93191:701::-;3226:13;:11;:13::i;:::-;85742:7;93332:17:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;93332:42:0::1;;:77;;;;;93399:4;:10;;;93378:18;:16;:18::i;:::-;:31;93332:77;93328:163;;;93433:46;;-1:-1:-1::0;;;93433:46:0::1;;;;;;;;;;;93328:163;93536:1;93507:17;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;93507:31:0::1;::::0;93503:382:::1;;93570:7;;;;;;;;;-1:-1:-1::0;;;;;93570:7:0::1;-1:-1:-1::0;;;;;93570:25:0::1;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;93555:53:0::1;;93616:4;:10;;;93628:4;93634:10;;93555:90;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;93191:701:::0;;;:::o;93503:382::-:1;93678:12;93700:17;::::0;;;::::1;::::0;::::1;;:::i;:::-;93678:40;;93733:5;-1:-1:-1::0;;;;;93733:13:0::1;;93747:7;;;;;;;;;-1:-1:-1::0;;;;;93747:7:0::1;-1:-1:-1::0;;;;;93747:25:0::1;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93733:54;::::0;-1:-1:-1;;;;;;93733:54:0::1;::::0;;;;;;-1:-1:-1;;;;;16016:55:1;;;93733:54:0::1;::::0;::::1;15998:74:1::0;93776:10:0::1;::::0;::::1;;16088:18:1::0;;;16081:34;15971:18;;93733:54:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;93817:7;;;;;;;;;-1:-1:-1::0;;;;;93817:7:0::1;-1:-1:-1::0;;;;;93817:25:0::1;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;93802:53:0::1;;93856:4;93862:10;;93802:71;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;93503:382::-;93191:701:::0;;;:::o;90484:254::-;27358:1;27956:7;;:19;27948:63;;;;-1:-1:-1;;;27948:63:0;;12930:2:1;27948:63:0;;;12912:21:1;12969:2;12949:18;;;12942:30;13008:33;12988:18;;;12981:61;13059:18;;27948:63:0;12728:355:1;27948:63:0;27358:1;28089:7;:18;90593:47:::1;90620:9:::0;90631:8;90593:26:::1;:47::i;:::-;90651:38;90663:9;90674:8;90684:4;90651:11;:38::i;:::-;90705:25;::::0;160::1;;;90705::0::1;::::0;148:2:1;133:18;90705:25:0::1;;;;;;;-1:-1:-1::0;;27314:1:0;28268:22;;90484:254::o;85828:122::-;3226:13;:11;:13::i;:::-;85892:5:::1;:14:::0;;-1:-1:-1;;85892:14:0::1;-1:-1:-1::0;;;;;85892:14:0;::::1;::::0;;::::1;::::0;;;85922:20:::1;::::0;3345:74:1;;;85922:20:0::1;::::0;3333:2:1;3318:18;85922:20:0::1;3199:226:1::0;3988:103:0;3226:13;:11;:13::i;:::-;4053:30:::1;4080:1;4053:18;:30::i;:::-;3988:103::o:0;102275:247::-;102368:3;;;:21;;-1:-1:-1;;;102368:21:0;;;;;160:25:1;;;102344:7:0;;102401:4;;-1:-1:-1;;;;;102368:3:0;;:11;;133:18:1;;102368:21:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;102368:38:0;;102364:106;;102430:28;;-1:-1:-1;;;102430:28:0;;;;;;;;;;;102364:106;-1:-1:-1;102487:27:0;;;;:17;:27;;;;;;;102275:247::o;85991:119::-;3226:13;:11;:13::i;:::-;86044:5:::1;:18:::0;;-1:-1:-1;;86044:18:0::1;::::0;;86078:24:::1;::::0;-1:-1:-1;3345:74:1;;86078:24:0::1;::::0;3333:2:1;3318:18;86078:24:0::1;;;;;;;85991:119::o:0;105929:197::-;3226:13;:11;:13::i;:::-;106019:36:::1;::::0;-1:-1:-1;;;106019:36:0;;106035:10:::1;106019:36;::::0;::::1;15998:74:1::0;16088:18;;;16081:34;;;-1:-1:-1;;;;;106019:15:0;::::1;::::0;::::1;::::0;15971:18:1;;106019:36:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;106014:105;;106079:28;;-1:-1:-1::0;;;106079:28:0::1;;;;;;;;;;;106167:525:::0;106224:7;106262:21;106224:7;106323:14;:12;:14::i;:::-;106294:43;;106353:9;106348:312;106372:9;:16;106368:1;:20;106348:312;;;106410:42;106455:27;106469:9;106479:1;106469:12;;;;;;;;:::i;:::-;;;;;;;106455:13;:27::i;:::-;106410:72;-1:-1:-1;106526:28:0;106501:10;:21;;;:53;;;;;;;;:::i;:::-;;:78;;;;;106558:21;106566:9;106576:1;106566:12;;;;;;;;:::i;:::-;;;;;;;106558:7;:21::i;:::-;106497:152;;;106611:22;;;;106600:33;;;;:::i;:::-;;;106497:152;-1:-1:-1;106390:3:0;;;;:::i;:::-;;;;106348:312;;;-1:-1:-1;106677:7:0;;106167:525;-1:-1:-1;;106167:525:0:o;87090:1067::-;87253:7;27358:1;27956:7;;:19;27948:63;;;;-1:-1:-1;;;27948:63:0;;12930:2:1;27948:63:0;;;12912:21:1;12969:2;12949:18;;;12942:30;13008:33;12988:18;;;12981:61;13059:18;;27948:63:0;12728:355:1;27948:63:0;27358:1;28089:7;:18;87299:11;::::1;87277:34;::::0;;;:21:::1;:34;::::0;;;;;::::1;;87273:112;;;87335:38;;-1:-1:-1::0;;;87335:38:0::1;;;;;;;;;;;87273:112;87395:30;87404:8;87414:10;;87395:8;:30::i;:::-;87457:9;::::0;87491:7:::1;::::0;87457:43:::1;::::0;;;;-1:-1:-1;;;;;18487:15:1;;;87457:43:0::1;::::0;::::1;18469:34:1::0;87491:7:0;;::::1;18519:18:1::0;;;18512:43;87438:16:0::1;::::0;87457:9;;;::::1;::::0;:14:::1;::::0;18381:18:1;;87457:43:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87438:62;;87511:42;87556:184;;;;;;;;87595:4;87556:184;;;;;;87614:8;:19;;;;;;;;;;:::i;:::-;87556:184;;;;;;;;:::i;:::-;::::0;;87648:20:::1;::::0;;::::1;;87556:184;::::0;;::::1;::::0;;;;87683:15:::1;::::0;::::1;;87556:184:::0;;;;;;;;87713:16:::1;::::0;::::1;;87556:184:::0;;;;;;;;-1:-1:-1;87751:17:0;;;:7:::1;:17:::0;;;;;;:30;;;;;::::1;;-1:-1:-1::0;;87751:30:0;::::1;::::0;::::1;::::0;;;;::::1;::::0;87511:229;;-1:-1:-1;87511:229:0;;87751:17;;;;-1:-1:-1;;87751:30:0;;;-1:-1:-1;;87751:30:0;;;;::::1;::::0;;;::::1;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;87751:30:0::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;-1:-1:-1;87840:19:0::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;:52;;;;;;;;:::i;:::-;::::0;87836:131:::1;;87927:16;::::0;::::1;;87909:35;::::0;;;:17:::1;:35;::::0;;;;:46;;;87836:131:::1;87977:23;:9;87991:8:::0;87977:13:::1;:23::i;:::-;-1:-1:-1::0;88033:11:0;::::1;88011:34;::::0;;;:21:::1;:34;::::0;;;;;;:41;;-1:-1:-1;;88011:41:0::1;88048:4;88011:41;::::0;;88070:53;::::1;::::0;::::1;::::0;88083:8;;88093:16:::1;::::0;::::1;;::::0;19137:25:1;;;19193:2;19178:18;;19171:34;;;;19236:2;19221:18;;19214:34;19125:2;19110:18;;18935:319;88070:53:0::1;;;;;;;;-1:-1:-1::0;27314:1:0;28268:22;;88141:8;87090:1067;-1:-1:-1;;;;;87090:1067:0:o;91811:1339::-;91967:7;3226:13;:11;:13::i;:::-;92066:29:::1;92047:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;:48;;;;;;;;:::i;:::-;::::0;92043:375:::1;;92117:28;92136:8;92117:18;:28::i;:::-;92112:105;;92173:28;;-1:-1:-1::0;;;92173:28:0::1;;;;;;;;;;;92112:105;92043:375;;;92274:4;:16;;;92253:18;:16;:18::i;:::-;:37;92249:131;;;92318:46;;-1:-1:-1::0;;;92318:46:0::1;;;;;;;;;;;92249:131;92405:1;92394:12;;92043:375;92492:9;::::0;92472:17:::1;::::0;-1:-1:-1;;;;;92492:9:0::1;:14;92507:10;::::0;;;::::1;::::0;::::1;;:::i;:::-;92527:7;::::0;92492:44:::1;::::0;::::1;::::0;;;-1:-1:-1;;;;;;92492:44:0;;;-1:-1:-1;;;;;18487:15:1;;;92492:44:0::1;::::0;::::1;18469:34:1::0;92527:7:0;::::1;18519:18:1::0;;;18512:43;18381:18;;92492:44:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92472:64:::0;-1:-1:-1;92570:29:0::1;92551:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;:48;;;;;;;;:::i;:::-;::::0;92547:120:::1;;92616:27;::::0;;;:17:::1;:27;::::0;;;;:39;;;92547:120:::1;92724:164;::::0;;::::1;::::0;::::1;::::0;;;92763:4:::1;92724:164:::0;;92679:42:::1;::::0;92724:164:::1;::::0;::::1;92782:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;92724:164;;;;;;;;:::i;:::-;;;;;92812:4;:16;;;92724:164;;;;92843:4;:11;;;92724:164;;;;92869:8;92724:164;;::::0;92679:209:::1;;92920:10;92899:7;:18;92907:9;92899:18;;;;;;;;;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;92899:31:0::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;92941:24:::1;:9;92955::::0;92941:13:::1;:24::i;:::-;-1:-1:-1::0;92983:35:0::1;::::0;;19433:25:1;;;93007:10:0::1;::::0;;::::1;;19474:18:1::0;;;19467:34;92983:35:0::1;::::0;19406:18:1;92983:35:0::1;;;;;;;93044:7;;;;;;;;;-1:-1:-1::0;;;;;93044:7:0::1;-1:-1:-1::0;;;;;93044:25:0::1;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;93029:57:0::1;;93087:4;93093:10;;93105:9;93029:86;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;93133:9:0;;91811:1339;-1:-1:-1;;;;;;;;;91811:1339:0:o;102095:139::-;102157:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102157:31:0;102208:18;;;;:7;:18;;;;;;;;;102201:25;;;;;;;;;;;;;;;;;;102208:18;;102201:25;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102095:139;-1:-1:-1;;102095:139:0:o;105462:426::-;3226:13;:11;:13::i;:::-;105563:7:::1;105542:18;:16;:18::i;:::-;:28;105538:114;;;105594:46;;-1:-1:-1::0;;;105594:46:0::1;;;;;;;;;;;105538:114;105731:27;::::0;1996:10;;105662:18:::1;::::0;1996:10;;105746:7;;105662:18;105731:27;105662:18;105731:27;105746:7;1996:10;105731:27:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105715:43;;;105774:4;105769:73;;105802:28;;-1:-1:-1::0;;;105802:28:0::1;;;;;;;;;;;105769:73;105859:21;::::0;160:25:1;;;105859:21:0::1;::::0;148:2:1;133:18;105859:21:0::1;;;;;;;105527:361;;105462:426:::0;:::o;4246:201::-;3226:13;:11;:13::i;:::-;-1:-1:-1;;;;;4335:22:0;::::1;4327:73;;;::::0;-1:-1:-1;;;4327:73:0;;21277:2:1;4327:73:0::1;::::0;::::1;21259:21:1::0;21316:2;21296:18;;;21289:30;21355:34;21335:18;;;21328:62;21426:8;21406:18;;;21399:36;21452:19;;4327:73:0::1;21075:402:1::0;4327:73:0::1;4411:28;4430:8;4411:18;:28::i;101893:161::-:0;101949:4;101973:18;;;:7;:18;;;;;:25;;;:73;;;;-1:-1:-1;;102002:18:0;;;;:7;:18;;;;;:25;;;102031:15;-1:-1:-1;102002:44:0;;101893:161::o;3505:132::-;3386:7;3413:6;-1:-1:-1;;;;;3413:6:0;1996:10;3569:23;3561:68;;;;-1:-1:-1;;;3561:68:0;;21684:2:1;3561:68:0;;;21666:21:1;;;21703:18;;;21696:30;21762:34;21742:18;;;21735:62;21814:18;;3561:68:0;21482:356:1;85000:507:0;85218:1;3413:6;-1:-1:-1;;;;;3413:6:0;85199:21;85191:53;;;;-1:-1:-1;;;85191:53:0;;22045:2:1;85191:53:0;;;22027:21:1;22084:2;22064:18;;;22057:30;22123:21;22103:18;;;22096:49;22162:18;;85191:53:0;21843:343:1;85191:53:0;85255:7;:18;;-1:-1:-1;;85255:18:0;-1:-1:-1;;;;;85255:18:0;;;;;85284:26;85303:6;85284:18;:26::i;:::-;85323:3;:10;;-1:-1:-1;;;;;85323:10:0;;;-1:-1:-1;;85323:10:0;;;;;;;85344:9;:36;;;;;;;;;;;;;85397:20;;;85393:107;;85434:5;:14;;-1:-1:-1;;85434:14:0;-1:-1:-1;;;;;85434:14:0;;;;;;;;85468:20;;3345:74:1;;;85468:20:0;;3333:2:1;3318:18;85468:20:0;;;;;;;85000:507;;;;;:::o;23868:146::-;23945:4;16884:19;;;:12;;;:19;;;;;;:24;;23969:37;23962:44;23868:146;-1:-1:-1;;;23868:146:0:o;98805:1058::-;98900:42;98945:18;;;:7;:18;;;;;;;;98900:63;;;;;;;;;;;;;;;;;;;;98945:18;;98900:63;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;98978:10:0;:21;;;:54;;;;;;;;:::i;:::-;;98974:764;;99053:10;99049:223;;;99187:3;;-1:-1:-1;;;;;99187:3:0;:20;99216:4;1996:10;99237:18;;;;99187:69;;-1:-1:-1;;;;;;99187:69:0;;;;;;;-1:-1:-1;;;;;13905:15:1;;;99187:69:0;;;13887:34:1;13957:15;;;;13937:18;;;13930:43;13989:18;;;13982:34;13799:18;;99187:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99049:223;99308:18;;;;99290:37;;;;:17;:37;;;;;;:50;;;99286:135;;99386:18;;;;99368:37;;;;:17;:37;;;;;99361:44;99286:135;98974:764;;;99467:28;99442:10;:21;;;:53;;;;;;;;:::i;:::-;;99438:300;;99516:10;99512:215;;;99585:3;;-1:-1:-1;;;;;99585:3:0;:20;1996:10;99585:59;;-1:-1:-1;;;;;;99585:59:0;;;;;;;-1:-1:-1;;;;;13905:15:1;;;99585:59:0;;;13887:34:1;99628:4:0;13937:18:1;;;13930:43;13989:18;;;13982:34;;;13799:18;;99585:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99663:48;99674:12;1996:10;;1916:98;99674:12;99688:10;:22;;;99663:10;:48::i;:::-;99776:5;99748:18;;;:7;:18;;;;;:33;;-1:-1:-1;;99748:33:0;;;99792:27;:9;99756;99792:16;:27::i;:::-;-1:-1:-1;99830:9:0;;:25;;;;;;;;160::1;;;-1:-1:-1;;;;;99830:9:0;;;;:14;;133:18:1;;99830:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98889:974;98805:1058;;;:::o;25255:307::-;25315:16;25344:22;25369:19;25377:3;25369:7;:19::i;23645:137::-;23715:4;23739:35;23747:3;23767:5;23739:7;:35::i;24100:114::-;24160:7;24187:19;24195:3;17085:18;;17002:109;24568:137;24639:7;24674:22;24678:3;24690:5;24674:3;:22::i;90829:941::-;90929:29;:9;90948;90929:18;:29::i;:::-;90921:92;;;;-1:-1:-1;;;90921:92:0;;22393:2:1;90921:92:0;;;22375:21:1;22432:2;22412:18;;;22405:30;22471:34;22451:18;;;22444:62;22542:20;22522:18;;;22515:48;22580:19;;90921:92:0;22191:414:1;90921:92:0;91048:9;;:28;;-1:-1:-1;;;91048:28:0;;;;;160:25:1;;;-1:-1:-1;;;;;91048:9:0;;;;:17;;133:18:1;;91048:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;91032:44:0;1996:10;-1:-1:-1;;;;;91032:44:0;;91024:112;;;;-1:-1:-1;;;91024:112:0;;22812:2:1;91024:112:0;;;22794:21:1;22851:2;22831:18;;;22824:30;22890:34;22870:18;;;22863:62;22961:25;22941:18;;;22934:53;23004:19;;91024:112:0;22610:419:1;91024:112:0;91149:42;91194:18;;;:7;:18;;;;;;;;91149:63;;;;;;;;;;;;;;;;;;;;91194:18;;91149:63;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91247:15;91227:10;:17;;;:35;91223:101;;;91286:26;;-1:-1:-1;;;91286:26:0;;;;;;;;;;;91223:101;91365:29;91340:10;:21;;;:54;;;;;;;;:::i;:::-;;91336:427;;91411:124;91438:10;:22;;;91411:124;;;;;;;;;;;;;;;;;:26;:124::i;91336:427::-;91582:28;91557:10;:21;;;:53;;;;;;;;:::i;:::-;;91553:210;;91651:3;;;:21;;-1:-1:-1;;;91651:21:0;;;;;160:25:1;;;-1:-1:-1;;;;;91651:3:0;;:11;;133:18:1;;91651:21:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;91635:37:0;1996:10;-1:-1:-1;;;;;91635:37:0;;91627:124;;;;-1:-1:-1;;;91627:124:0;;23236:2:1;91627:124:0;;;23218:21:1;23275:2;23255:18;;;23248:30;23314:34;23294:18;;;23287:62;23385:34;23365:18;;;23358:62;23457:12;23436:19;;;23429:41;23487:19;;91627:124:0;23034:478:1;104636:785:0;104768:7;;:23;;;-1:-1:-1;;;104768:23:0;;;;104719:28;;-1:-1:-1;;;;;104768:7:0;;:21;;:23;;;;;;;;;;;;;;:7;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104846:45;;-1:-1:-1;;;104846:45:0;;104876:4;104846:45;;;15998:74:1;16088:18;;;16081:34;;;104719:73:0;;-1:-1:-1;104804:19:0;;;;-1:-1:-1;;;;;104846:21:0;;;;;15971:18:1;;104846:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104803:88;;-1:-1:-1;104803:88:0;-1:-1:-1;104908:13:0;;104904:345;;104938:14;104955:16;104963:7;104955;:16::i;:::-;104938:33;;105002:6;104990:9;:18;104986:77;;;105041:6;105029:18;;104986:77;105078:10;105102:11;-1:-1:-1;;;;;105094:25:0;105127:9;105094:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105077:64;;;105161:5;105156:82;;105194:28;;-1:-1:-1;;;105194:28:0;;;;;;;;;;;105156:82;104923:326;;104904:345;105262:9;-1:-1:-1;;;;;105277:21:0;;105306:19;105316:9;105306:7;:19;:::i;:::-;105277:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105261:69;;;105346:4;105341:73;;105374:28;;-1:-1:-1;;;105374:28:0;;;;;;;;;;;105341:73;104708:713;;;;104636:785;;:::o;103087:103::-;103143:7;103170:12;103180:2;103170:7;:12;:::i;4607:191::-;4681:16;4700:6;;-1:-1:-1;;;;;4717:17:0;;;-1:-1:-1;;4717:17:0;;;;;;4750:40;;4700:6;;;;;;;4750:40;;4681:16;4750:40;4670:128;4607:191;:::o;88508:1680::-;88665:57;;;;;88648:14;;88665:15;;:35;;:57;;88701:8;;88711:10;;;;88665:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;88648:74;-1:-1:-1;;;;;;88737:20:0;;;;:62;;-1:-1:-1;88772:5:0;;-1:-1:-1;;;;;88762:15:0;;;88772:5;;88762:15;;;;:36;;-1:-1:-1;3386:7:0;3413:6;-1:-1:-1;;;;;88781:17:0;;;3413:6;;88781:17;;88762:36;88733:134;;;88823:32;;-1:-1:-1;;;88823:32:0;;;;;;;;;;;88733:134;88935:15;88912:8;:20;;;:38;88908:104;;;88974:26;;-1:-1:-1;;;88974:26:0;;;;;;;;;;;88908:104;89072:4;89040:20;;;;;;;;:::i;:::-;-1:-1:-1;;;;;89040:37:0;;89032:99;;;;-1:-1:-1;;;89032:99:0;;25105:2:1;89032:99:0;;;25087:21:1;25144:2;25124:18;;;25117:30;25183:34;25163:18;;;25156:62;25254:19;25234:18;;;25227:47;25291:19;;89032:99:0;24903:413:1;89032:99:0;89142:90;89169:8;:16;;;89142:90;;;;;;;;;;;;;;;;;:26;:90::i;:::-;89283:8;:20;;;89307:1;89283:25;89279:94;;89332:29;;;;;;;;;;;;;;89279:94;89387:8;:15;;;89406:1;89387:20;89383:89;;89431:29;;;;;;;;;;;;;;89383:89;89551:29;89528:19;;;;;;;;:::i;:::-;:52;;;;;;;;:::i;:::-;;89524:657;;89601:3;;;:29;;-1:-1:-1;;;89601:29:0;;89613:16;;;;89601:29;;;160:25:1;;;;89642:4:0;;-1:-1:-1;;;;;89601:3:0;;;;:11;;133:18:1;;89601:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;89601:46:0;;89597:122;;89675:28;;-1:-1:-1;;;89675:28:0;;;;;;;;;;;89597:122;89815:16;;;;89778;89797:35;;;:17;:35;;;;;;89851:17;89797:35;89851:7;:17::i;:::-;89847:99;;;89896:34;;-1:-1:-1;;;89896:34:0;;;;;;;;;;;89847:99;89582:375;89524:657;;;89990:28;89967:19;;;;;;;;:::i;:::-;:51;;;;;;;;:::i;:::-;;89963:218;;90060:8;:20;;;90039:18;:16;:18::i;:::-;:41;90035:135;;;90108:46;;-1:-1:-1;;;90108:46:0;;;;;;;;;;;23338:131;23405:4;23429:32;23434:3;23454:5;23429:4;:32::i;18135:111::-;18191:16;18227:3;:11;;18220:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18135:111;;;:::o;15281:1420::-;15347:4;15486:19;;;:12;;;:19;;;;;;15522:15;;15518:1176;;15897:21;15921:14;15934:1;15921:10;:14;:::i;:::-;15970:18;;15897:38;;-1:-1:-1;15950:17:0;;15970:22;;15991:1;;15970:22;:::i;:::-;15950:42;;16026:13;16013:9;:26;16009:405;;16060:17;16080:3;:11;;16092:9;16080:22;;;;;;;;:::i;:::-;;;;;;;;;16060:42;;16234:9;16205:3;:11;;16217:13;16205:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;16319:23;;;:12;;;:23;;;;;:36;;;16009:405;16495:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;16590:3;:12;;:19;16603:5;16590:19;;;;;;;;;;;16583:26;;;16633:4;16626:11;;;;;;;15518:1176;16677:5;16670:12;;;;;17465:120;17532:7;17559:3;:11;;17571:5;17559:18;;;;;;;;:::i;:::-;;;;;;;;;17552:25;;17465:120;;;;:::o;103849:739::-;104013:7;;:23;;;-1:-1:-1;;;104013:23:0;;;;103964:28;;-1:-1:-1;;;;;104013:7:0;;:21;;:23;;;;;;;;;;;;;;:7;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104091:46;;-1:-1:-1;;;104091:46:0;;104121:4;104091:46;;;15998:74:1;16088:18;;;16081:34;;;103964:73:0;;-1:-1:-1;104049:19:0;;;;-1:-1:-1;;;;;104091:21:0;;;;;15971:18:1;;104091:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104048:89;;-1:-1:-1;104048:89:0;-1:-1:-1;104154:13:0;;104150:348;;104184:14;104201:17;104209:8;104201:7;:17::i;:::-;104184:34;;104249:6;104237:9;:18;104233:77;;;104288:6;104276:18;;104233:77;104327:10;104351:11;-1:-1:-1;;;;;104343:25:0;104376:9;104343:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104326:64;;;104410:5;104405:82;;104443:28;;-1:-1:-1;;;104443:28:0;;;;;;;;;;;104405:82;104169:329;;104150:348;104532:20;104543:9;104532:8;:20;:::i;:::-;104518:9;:35;;:51;;;;;104568:1;104557:8;:12;104518:51;104571:8;104510:70;;;;;-1:-1:-1;;;104510:70:0;;;;;;;;:::i;14691:414::-;14754:4;16884:19;;;:12;;;:19;;;;;;14771:327;;-1:-1:-1;14814:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;14997:18;;14975:19;;;:12;;;:19;;;;;;:40;;;;15030:11;;14771:327;-1:-1:-1;15081:5:0;15074:12;;536:332:1;594:6;647:2;635:9;626:7;622:23;618:32;615:52;;;663:1;660;653:12;615:52;702:9;689:23;-1:-1:-1;;;;;;745:5:1;741:78;734:5;731:89;721:117;;834:1;831;824:12;1065:163;-1:-1:-1;;;;;1153:5:1;1149:54;1142:5;1139:65;1129:93;;1218:1;1215;1208:12;1233:774;1343:6;1351;1359;1412:2;1400:9;1391:7;1387:23;1383:32;1380:52;;;1428:1;1425;1418:12;1380:52;1467:9;1454:23;1486:40;1520:5;1486:40;:::i;:::-;1545:5;-1:-1:-1;1601:2:1;1586:18;;1573:32;1624:18;1654:14;;;1651:34;;;1681:1;1678;1671:12;1651:34;1719:6;1708:9;1704:22;1694:32;;1764:7;1757:4;1753:2;1749:13;1745:27;1735:55;;1786:1;1783;1776:12;1735:55;1826:2;1813:16;1852:2;1844:6;1841:14;1838:34;;;1868:1;1865;1858:12;1838:34;1921:7;1916:2;1906:6;1903:1;1899:14;1895:2;1891:23;1887:32;1884:45;1881:65;;;1942:1;1939;1932:12;1881:65;1973:2;1969;1965:11;1955:21;;1995:6;1985:16;;;;;1233:774;;;;;:::o;2012:156::-;2072:5;2117:3;2108:6;2103:3;2099:16;2095:26;2092:46;;;2134:1;2131;2124:12;2092:46;-1:-1:-1;2156:6:1;2012:156;-1:-1:-1;2012:156:1:o;2173:347::-;2224:8;2234:6;2288:3;2281:4;2273:6;2269:17;2265:27;2255:55;;2306:1;2303;2296:12;2255:55;-1:-1:-1;2329:20:1;;2372:18;2361:30;;2358:50;;;2404:1;2401;2394:12;2358:50;2441:4;2433:6;2429:17;2417:29;;2493:3;2486:4;2477:6;2469;2465:19;2461:30;2458:39;2455:59;;;2510:1;2507;2500:12;2455:59;2173:347;;;;;:::o;2525:537::-;2631:6;2639;2647;2700:3;2688:9;2679:7;2675:23;2671:33;2668:53;;;2717:1;2714;2707:12;2668:53;2740:54;2786:7;2775:9;2740:54;:::i;:::-;2730:64;;2845:3;2834:9;2830:19;2817:33;2873:18;2865:6;2862:30;2859:50;;;2905:1;2902;2895:12;2859:50;2944:58;2994:7;2985:6;2974:9;2970:22;2944:58;:::i;:::-;2525:537;;3021:8;;-1:-1:-1;2918:84:1;;-1:-1:-1;;;;2525:537:1:o;3430:143::-;3498:20;;3527:40;3498:20;3527:40;:::i;:::-;3430:143;;;:::o;3578:898::-;3713:6;3721;3729;3737;3745;3798:3;3786:9;3777:7;3773:23;3769:33;3766:53;;;3815:1;3812;3805:12;3766:53;3854:9;3841:23;3873:40;3907:5;3873:40;:::i;:::-;3932:5;-1:-1:-1;3989:2:1;3974:18;;3961:32;4002:42;3961:32;4002:42;:::i;:::-;4063:7;-1:-1:-1;4122:2:1;4107:18;;4094:32;4135:42;4094:32;4135:42;:::i;:::-;4196:7;-1:-1:-1;4255:2:1;4240:18;;4227:32;4268:42;4227:32;4268:42;:::i;:::-;4329:7;-1:-1:-1;4388:3:1;4373:19;;4360:33;4402:42;4360:33;4402:42;:::i;:::-;4463:7;4453:17;;;3578:898;;;;;;;;:::o;4481:184::-;-1:-1:-1;;;4530:1:1;4523:88;4630:4;4627:1;4620:15;4654:4;4651:1;4644:15;4670:275;4741:2;4735:9;4806:2;4787:13;;-1:-1:-1;;4783:27:1;4771:40;;4841:18;4826:34;;4862:22;;;4823:62;4820:88;;;4888:18;;:::i;:::-;4924:2;4917:22;4670:275;;-1:-1:-1;4670:275:1:o;4950:1126::-;5045:6;5053;5061;5069;5122:3;5110:9;5101:7;5097:23;5093:33;5090:53;;;5139:1;5136;5129:12;5090:53;5178:9;5165:23;5197:40;5231:5;5197:40;:::i;:::-;5256:5;-1:-1:-1;5280:2:1;5319:18;;;5306:32;5347:42;5306:32;5347:42;:::i;:::-;5408:7;-1:-1:-1;5462:2:1;5447:18;;5434:32;;-1:-1:-1;5517:2:1;5502:18;;5489:32;5540:18;5570:14;;;5567:34;;;5597:1;5594;5587:12;5567:34;5635:6;5624:9;5620:22;5610:32;;5680:7;5673:4;5669:2;5665:13;5661:27;5651:55;;5702:1;5699;5692:12;5651:55;5738:2;5725:16;5760:2;5756;5753:10;5750:36;;;5766:18;;:::i;:::-;5808:53;5851:2;5832:13;;-1:-1:-1;;5828:27:1;5824:36;;5808:53;:::i;:::-;5795:66;;5884:2;5877:5;5870:17;5924:7;5919:2;5914;5910;5906:11;5902:20;5899:33;5896:53;;;5945:1;5942;5935:12;5896:53;6000:2;5995;5991;5987:11;5982:2;5975:5;5971:14;5958:45;6044:1;6039:2;6034;6027:5;6023:14;6019:23;6012:34;;6065:5;6055:15;;;;;4950:1126;;;;;;;:::o;6334:632::-;6505:2;6557:21;;;6627:13;;6530:18;;;6649:22;;;6476:4;;6505:2;6728:15;;;;6702:2;6687:18;;;6476:4;6771:169;6785:6;6782:1;6779:13;6771:169;;;6846:13;;6834:26;;6915:15;;;;6880:12;;;;6807:1;6800:9;6771:169;;;-1:-1:-1;6957:3:1;;6334:632;-1:-1:-1;;;;;;6334:632:1:o;6971:180::-;7030:6;7083:2;7071:9;7062:7;7058:23;7054:32;7051:52;;;7099:1;7096;7089:12;7051:52;-1:-1:-1;7122:23:1;;6971:180;-1:-1:-1;6971:180:1:o;7156:946::-;7240:6;7271:2;7314;7302:9;7293:7;7289:23;7285:32;7282:52;;;7330:1;7327;7320:12;7282:52;7370:9;7357:23;7399:18;7440:2;7432:6;7429:14;7426:34;;;7456:1;7453;7446:12;7426:34;7494:6;7483:9;7479:22;7469:32;;7539:7;7532:4;7528:2;7524:13;7520:27;7510:55;;7561:1;7558;7551:12;7510:55;7597:2;7584:16;7619:2;7615;7612:10;7609:36;;;7625:18;;:::i;:::-;7671:2;7668:1;7664:10;7654:20;;7694:28;7718:2;7714;7710:11;7694:28;:::i;:::-;7756:15;;;7826:11;;;7822:20;;;7787:12;;;;7854:19;;;7851:39;;;7886:1;7883;7876:12;7851:39;7910:11;;;;7930:142;7946:6;7941:3;7938:15;7930:142;;;8012:17;;8000:30;;7963:12;;;;8050;;;;7930:142;;;8091:5;7156:946;-1:-1:-1;;;;;;;;7156:946:1:o;8107:554::-;8213:6;8221;8229;8273:9;8264:7;8260:23;8303:3;8299:2;8295:12;8292:32;;;8320:1;8317;8310:12;8292:32;8344:3;8340:2;8336:12;8333:32;;;8361:1;8358;8351:12;8333:32;;8384:9;8374:19;;8444:3;8433:9;8429:19;8416:33;8472:18;8464:6;8461:30;8458:50;;;8504:1;8501;8494:12;8666:550;8768:6;8776;8784;8828:9;8819:7;8815:23;8858:3;8854:2;8850:12;8847:32;;;8875:1;8872;8865:12;8847:32;8899:3;8895:2;8891:12;8888:32;;;8916:1;8913;8906:12;8888:32;;8939:9;8929:19;;8999:3;8988:9;8984:19;8971:33;9027:18;9019:6;9016:30;9013:50;;;9059:1;9056;9049:12;9221:248;9289:6;9297;9350:2;9338:9;9329:7;9325:23;9321:32;9318:52;;;9366:1;9363;9356:12;9318:52;-1:-1:-1;;9389:23:1;;;9459:2;9444:18;;;9431:32;;-1:-1:-1;9221:248:1:o;9474:256::-;9533:6;9586:2;9574:9;9565:7;9561:23;9557:32;9554:52;;;9602:1;9599;9592:12;9554:52;9641:9;9628:23;9660:40;9694:5;9660:40;:::i;9735:339::-;9818:6;9826;9879:2;9867:9;9858:7;9854:23;9850:32;9847:52;;;9895:1;9892;9885:12;9847:52;9934:9;9921:23;9953:40;9987:5;9953:40;:::i;:::-;10012:5;10064:2;10049:18;;;;10036:32;;-1:-1:-1;;;9735:339:1:o;10335:682::-;10450:6;10458;10466;10474;10527:3;10515:9;10506:7;10502:23;10498:33;10495:53;;;10544:1;10541;10534:12;10495:53;10567:54;10613:7;10602:9;10567:54;:::i;:::-;10557:64;;10672:3;10661:9;10657:19;10644:33;10700:18;10692:6;10689:30;10686:50;;;10732:1;10729;10722:12;10686:50;10771:58;10821:7;10812:6;10801:9;10797:22;10771:58;:::i;:::-;10848:8;;-1:-1:-1;10745:84:1;-1:-1:-1;;10933:3:1;10918:19;;10905:33;10947:40;10905:33;10947:40;:::i;:::-;10335:682;;;;-1:-1:-1;10335:682:1;;-1:-1:-1;;10335:682:1:o;11022:639::-;11133:6;11141;11149;11157;11201:9;11192:7;11188:23;11231:3;11227:2;11223:12;11220:32;;;11248:1;11245;11238:12;11220:32;11271:3;11294:2;11290;11286:11;11283:31;;;11310:1;11307;11300:12;11283:31;11333:9;;-1:-1:-1;11378:18:1;;11365:32;;-1:-1:-1;11420:18:1;11409:30;;11406:50;;;11452:1;11449;11442:12;11406:50;11491:58;11541:7;11532:6;11521:9;11517:22;11491:58;:::i;:::-;11022:639;;11568:8;;-1:-1:-1;11465:84:1;;11650:3;11635:19;11622:33;;11022:639;-1:-1:-1;;;;11022:639:1:o;11666:184::-;-1:-1:-1;;;11715:1:1;11708:88;11815:4;11812:1;11805:15;11839:4;11836:1;11829:15;11855:295;11937:1;11930:5;11927:12;11917:200;;-1:-1:-1;;;11970:1:1;11963:88;12074:4;12071:1;12064:15;12102:4;12099:1;12092:15;11917:200;12126:18;;11855:295::o;12155:568::-;12388:13;;12381:21;12374:29;12356:48;;12451:4;12439:17;;;12433:24;12343:3;12328:19;;;12466:62;;12507:20;;12433:24;12466:62;:::i;:::-;;12584:4;12576:6;12572:17;12566:24;12559:4;12548:9;12544:20;12537:54;12647:4;12639:6;12635:17;12629:24;12622:4;12611:9;12607:20;12600:54;12710:4;12702:6;12698:17;12692:24;12685:4;12674:9;12670:20;12663:54;12155:568;;;;:::o;13435:184::-;-1:-1:-1;;;13484:1:1;13477:88;13584:4;13581:1;13574:15;13608:4;13605:1;13598:15;14027:260;14097:6;14150:2;14138:9;14129:7;14125:23;14121:32;14118:52;;;14166:1;14163;14156:12;14118:52;14198:9;14192:16;14217:40;14251:5;14217:40;:::i;14292:184::-;-1:-1:-1;;;14341:1:1;14334:88;14441:4;14438:1;14431:15;14465:4;14462:1;14455:15;14481:135;14520:3;14541:17;;;14538:43;;14561:18;;:::i;:::-;-1:-1:-1;14608:1:1;14597:13;;14481:135::o;14621:266::-;14709:6;14704:3;14697:19;14761:6;14754:5;14747:4;14742:3;14738:14;14725:43;-1:-1:-1;14813:1:1;14788:16;;;14806:4;14784:27;;;14777:38;;;;14869:2;14848:15;;;-1:-1:-1;;14844:29:1;14835:39;;;14831:50;;14621:266::o;14892:797::-;15150:6;15137:20;15126:9;15119:39;15221:4;15213:6;15209:17;15196:31;15189:4;15178:9;15174:20;15167:61;15100:4;15275;15267:6;15263:17;15250:31;15290:40;15324:5;15290:40;:::i;:::-;-1:-1:-1;;;;;15372:5:1;15368:54;15361:4;15350:9;15346:20;15339:84;;15486:4;15478:6;15474:17;15461:31;15454:4;15443:9;15439:20;15432:61;15556:4;15548:6;15544:17;15531:31;15524:4;15513:9;15509:20;15502:61;15600:3;15594;15583:9;15579:19;15572:32;15621:62;15678:3;15667:9;15663:19;15655:6;15647;15621:62;:::i;:::-;15613:70;14892:797;-1:-1:-1;;;;;14892:797:1:o;15694:125::-;15759:9;;;15780:10;;;15777:36;;;15793:18;;:::i;16126:321::-;16205:6;16213;16266:2;16254:9;16245:7;16241:23;16237:32;16234:52;;;16282:1;16279;16272:12;16234:52;16314:9;16308:16;16333:40;16367:5;16333:40;:::i;:::-;16437:2;16422:18;;;;16416:25;16392:5;;16416:25;;-1:-1:-1;;;16126:321:1:o;16452:128::-;16519:9;;;16540:11;;;16537:37;;;16554:18;;:::i;16795:184::-;16865:6;16918:2;16906:9;16897:7;16893:23;16889:32;16886:52;;;16934:1;16931;16924:12;16886:52;-1:-1:-1;16957:16:1;;16795:184;-1:-1:-1;16795:184:1:o;16984:277::-;17051:6;17104:2;17092:9;17083:7;17079:23;17075:32;17072:52;;;17120:1;17117;17110:12;17072:52;17152:9;17146:16;17205:5;17198:13;17191:21;17184:5;17181:32;17171:60;;17227:1;17224;17217:12;17266:963;17508:6;17495:20;17484:9;17477:39;17579:4;17571:6;17567:17;17554:31;17547:4;17536:9;17532:20;17525:61;17458:4;17633;17625:6;17621:17;17608:31;17648:40;17682:5;17648:40;:::i;:::-;-1:-1:-1;;;;;17798:2:1;17791:5;17787:14;17780:4;17769:9;17765:20;17758:44;17865:4;17857:6;17853:17;17840:31;17833:4;17822:9;17818:20;17811:61;17921:4;17913:6;17909:17;17896:31;17881:46;;17936:42;17970:7;17936:42;:::i;:::-;18016:16;18009:4;17994:20;;17987:46;18096:4;18084:17;;;18071:31;18049:20;;;18042:61;18140:3;18134;18119:19;;18112:32;;;18161:62;;18203:19;;18195:6;18187;18161:62;:::i;18566:151::-;18642:20;;18691:1;18681:12;;18671:40;;18707:1;18704;18697:12;18722:208;18795:6;18848:2;18836:9;18827:7;18823:23;18819:32;18816:52;;;18864:1;18861;18854:12;18816:52;18887:37;18914:9;18887:37;:::i;19512:1558::-;19732:4;19761:3;19804:6;19791:20;19780:9;19773:39;19875:4;19867:6;19863:17;19850:31;19843:4;19832:9;19828:20;19821:61;19911:37;19942:4;19934:6;19930:17;19911:37;:::i;:::-;-1:-1:-1;;;;;3133:54:1;20005:4;19990:20;;3121:67;20042:37;20073:4;20061:17;;20042:37;:::i;:::-;-1:-1:-1;;;;;3133:54:1;20138:4;20123:20;;3121:67;20207:4;20195:17;;;20182:31;20160:20;;;20153:61;20245:37;20276:4;20264:17;;20245:37;:::i;:::-;-1:-1:-1;;;;;3133:54:1;20341:4;20326:20;;3121:67;20378:45;20417:4;20405:17;;20378:45;:::i;:::-;20432:64;20490:4;20479:9;20475:20;20459:14;20432:64;:::i;:::-;-1:-1:-1;20559:4:1;20547:17;;;20534:31;20512:20;;;20505:61;20585:6;20640:15;;;20627:29;20607:18;;;20600:57;20676:6;20731:15;;;20718:29;20698:18;;;20691:57;20767:6;20804:35;20823:15;;;20804:35;:::i;:::-;-1:-1:-1;;;;;3133:54:1;20883:18;;;3121:67;20933:3;20918:19;;20911:31;;;20959:61;21001:18;;;20993:6;20985;20959:61;:::i;:::-;20951:69;;;21057:6;21051:3;21040:9;21036:19;21029:35;19512:1558;;;;;;;:::o;23517:274::-;23557:1;23583;23573:189;;-1:-1:-1;;;23615:1:1;23608:88;23719:4;23716:1;23709:15;23747:4;23744:1;23737:15;23573:189;-1:-1:-1;23776:9:1;;23517:274::o;23796:1102::-;24004:4;24033:3;24076:6;24063:20;24052:9;24045:39;24131:4;24123:6;24119:17;24106:31;24146:40;24180:5;24146:40;:::i;:::-;-1:-1:-1;;;;;24224:54:1;24217:4;24202:20;;24195:84;24308:45;24347:4;24335:17;;24308:45;:::i;:::-;24362:62;24418:4;24407:9;24403:20;24389:12;24362:62;:::i;:::-;;24487:4;24479:6;24475:17;24462:31;24455:4;24444:9;24440:20;24433:61;24557:4;24549:6;24545:17;24532:31;24525:4;24514:9;24510:20;24503:61;24627:4;24619:6;24615:17;24602:31;24595:4;24584:9;24580:20;24573:61;24697:4;24689:6;24685:17;24672:31;24665:4;24654:9;24650:20;24643:61;24767:4;24759:6;24755:17;24742:31;24735:4;24724:9;24720:20;24713:61;24811:2;24805:3;24794:9;24790:19;24783:31;24831:61;24888:2;24877:9;24873:18;24865:6;24857;24831:61;:::i;:::-;24823:69;23796:1102;-1:-1:-1;;;;;;23796:1102:1:o;25321:184::-;-1:-1:-1;;;25370:1:1;25363:88;25470:4;25467:1;25460:15;25494:4;25491:1;25484:15;25510:548;25622:4;25651:2;25680;25669:9;25662:21;25712:6;25706:13;25755:6;25750:2;25739:9;25735:18;25728:34;25780:1;25790:140;25804:6;25801:1;25798:13;25790:140;;;25899:14;;;25895:23;;25889:30;25865:17;;;25884:2;25861:26;25854:66;25819:10;;25790:140;;;25794:3;25979:1;25974:2;25965:6;25954:9;25950:22;25946:31;25939:42;26049:2;26042;26038:7;26033:2;26025:6;26021:15;26017:29;26006:9;26002:45;25998:54;25990:62;;;;25510:548;;;;:::o
Swarm Source
ipfs://d68b729683b67aac1630260e8e40dc473eb072dbb23d3524a04f9071c71e3276
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BLAST | 66.58% | $0.008755 | 19,607,969.4248 | $171,661.69 | |
BLAST | 9.69% | $3,233.64 | 7.7228 | $24,972.81 | |
BLAST | 9.27% | $0.000732 | 32,654,605.5763 | $23,900.89 | |
BLAST | 6.61% | $97,214 | 0.1753 | $17,045.96 | |
BLAST | 5.60% | $0.023986 | 601,748.7286 | $14,433.68 | |
BLAST | 2.23% | $0.994508 | 5,771.7785 | $5,740.08 | |
BLAST | <0.01% | $0.007865 | 828.6897 | $6.52 | |
ARB | 0.01% | $3,235.12 | 0.01 | $32.35 | |
SCROLL | 0.01% | $3,233.79 | 0.01 | $32.34 |
Loading...
Loading
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.