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:
SodiumCore
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-10-16 */ // Sources flattened with hardhat v2.10.1 https://hardhat.org // File @openzeppelin/contracts-upgradeable/utils/introspection/[email protected] // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @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-upgradeable/token/ERC721/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721Upgradeable is IERC165Upgradeable { /** * @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-upgradeable/token/ERC1155/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value ); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll( address indexed account, address indexed operator, bool approved ); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; } // File @openzeppelin/contracts-upgradeable/token/ERC20/[email protected] // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval( address indexed owner, address indexed spender, uint256 value ); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); } // File @openzeppelin/contracts-upgradeable/token/ERC20/extensions/[email protected] // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20PermitUpgradeable { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // File @openzeppelin/contracts-upgradeable/utils/[email protected] // 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 AddressUpgradeable { /** * @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 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-upgradeable/token/ERC20/utils/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20Upgradeable { using AddressUpgradeable for address; function safeTransfer( IERC20Upgradeable token, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transfer.selector, to, value) ); } function safeTransferFrom( IERC20Upgradeable token, address from, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value) ); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20Upgradeable token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, value) ); } function safeIncreaseAllowance( IERC20Upgradeable token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } function safeDecreaseAllowance( IERC20Upgradeable token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require( oldAllowance >= value, "SafeERC20: decreased allowance below zero" ); uint256 newAllowance = oldAllowance - value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } } function safePermit( IERC20PermitUpgradeable token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require( nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed" ); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall( data, "SafeERC20: low-level call failed" ); if (returndata.length > 0) { // Return data is optional require( abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed" ); } } } // File @openzeppelin/contracts-upgradeable/utils/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { 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-upgradeable/utils/cryptography/[email protected] // OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSAUpgradeable { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32( 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if ( uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 ) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256( abi.encodePacked("\x19Ethereum Signed Message:\n32", hash) ); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256( abi.encodePacked( "\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s ) ); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256( abi.encodePacked("\x19\x01", domainSeparator, structHash) ); } } // File @openzeppelin/contracts-upgradeable/proxy/utils/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { require( !_initializing && _initialized < version, "Initializable: contract is already initialized" ); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } } // File @openzeppelin/contracts-upgradeable/utils/cryptography/[email protected] // OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol) pragma solidity ^0.8.0; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ * * @custom:storage-size 52 */ abstract contract EIP712Upgradeable is Initializable { /* solhint-disable var-name-mixedcase */ bytes32 private _HASHED_NAME; bytes32 private _HASHED_VERSION; bytes32 private constant _TYPE_HASH = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP712_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init_unchained(name, version); } function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator( _TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash() ); } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256( abi.encode( typeHash, nameHash, versionHash, block.chainid, address(this) ) ); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev The hash of the name parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712NameHash() internal view virtual returns (bytes32) { return _HASHED_NAME; } /** * @dev The hash of the version parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712VersionHash() internal view virtual returns (bytes32) { return _HASHED_VERSION; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } // File @openzeppelin/contracts-upgradeable/security/[email protected] // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // 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; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _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; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } // File @openzeppelin/contracts-upgradeable/utils/[email protected] // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing {} function __Context_init_unchained() internal onlyInitializing {} function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } // File @openzeppelin/contracts-upgradeable/access/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _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); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } // File @openzeppelin/contracts-upgradeable/interfaces/[email protected] // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822ProxiableUpgradeable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); } // File @openzeppelin/contracts-upgradeable/proxy/beacon/[email protected] // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); } // File @openzeppelin/contracts-upgradeable/utils/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } } // File @openzeppelin/contracts-upgradeable/proxy/ERC1967/[email protected] // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable { function __ERC1967Upgrade_init() internal onlyInitializing {} function __ERC1967Upgrade_init_unchained() internal onlyInitializing {} // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require( AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract" ); StorageSlotUpgradeable .getAddressSlot(_IMPLEMENTATION_SLOT) .value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require( slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID" ); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require( newAdmin != address(0), "ERC1967: new admin is the zero address" ); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require( AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract" ); require( AddressUpgradeable.isContract( IBeaconUpgradeable(newBeacon).implementation() ), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { _functionDelegateCall( IBeaconUpgradeable(newBeacon).implementation(), data ); } } /** * @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) private returns (bytes memory) { require( AddressUpgradeable.isContract(target), "Address: delegate call to non-contract" ); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult( success, returndata, "Address: low-level delegate call failed" ); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } // File @openzeppelin/contracts-upgradeable/proxy/utils/[email protected] // OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing {} function __UUPSUpgradeable_init_unchained() internal onlyInitializing {} /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require( address(this) != __self, "Function must be called through delegatecall" ); require( _getImplementation() == __self, "Function must be called through active proxy" ); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require( address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall" ); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate that the this implementation remains valid after an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } // File contracts/interfaces/ISodiumWalletFactory.sol pragma solidity ^0.8.0; interface ISodiumWalletFactory { /* ===== EVENTS ===== */ // Emitted when a Sodium Wallet is created for a user event WalletCreated(address indexed owner, address wallet); /* ===== METHODS ===== */ function createWallet(address borrower) external returns (address); } // File contracts/libraries/Types.sol pragma solidity ^0.8.0; // A library containing structs and enums used on the Sodium Protocol library Types { // Indicates type of collateral enum Collateral { ERC721, ERC1155 } // Represents an ongoing loan struct Loan { // Requested loan length uint256 length; // End of loan uint256 end; // End of potential loan auction uint256 auctionEnd; // ID of collateral uint256 tokenId; // Total funds added to the loan uint256 liquidity; // Loan lenders in lending queue order address[] lenders; // In-order principals of lenders in `lenders` uint256[] principals; // In-order APRs of said prinicpals uint256[] APRs; // Timestamps at which contributions of lenders in `lenders` were added uint256[] timestamps; // Address of collateral's contract address tokenAddress; // The currency the loan is made in address currency; // The loan's borrower address borrower; // Address holding loan collateral address wallet; // Debt repaid by borrower uint256 repayment; // Indicates type of collateral Collateral collateralType; } // Encapsulates information required for a lender's meta-transaction struct MetaContribution { // Signature - used to infer meta-lender's address bytes32 r; bytes32 s; uint8 v; // Total funds the meta-lender has offered uint256 available; // The APR the meta-lender has offered said funds at uint256 APR; // The limit up to which the funds can be used to increase loan liquidity uint256 liquidityLimit; // Lender's loan-specific meta-contribution nonce uint256 nonce; } // Encapsulates a collateral auction's state struct Auction { // Address of current highest bidder address bidder; // Their non-boosted bid => equal to the actual funds they sent uint256 rawBid; // Their boosted bid uint256 effectiveBid; } // Parameters for a loan request via Sodium Core struct RequestParams { // The requested amount uint256 amount; // Their starting APR uint256 APR; // Requested length of the loan uint256 length; // Loan currency - zero address used for an ETH loan address currency; } // Contains information needed to validate that a set of meta-contributions have not been withdrawn struct NoWithdrawalSignature { // The deadline up to which the signature is valid uint256 deadline; // Signature uint8 v; bytes32 r; bytes32 s; } // Used to identify a token (ERC721) or type of token struct Token { // Address of the token's contract address tokenAddress; // ID of the token uint256 tokenId; } } // File contracts/interfaces/ISodiumWallet.sol pragma solidity ^0.8.0; interface ISodiumWallet { function initialize( address _owner, address _core, address _registry ) external; function execute( address[] calldata contractAddresses, bytes[] memory calldatas, uint256[] calldata values ) external payable; function transferERC721( address recipient, address tokenAddress, uint256 tokenId ) external; function transferERC1155( address recipient, address tokenAddress, uint256 tokenId ) external; function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4); } // File contracts/interfaces/ISodiumCore.sol pragma solidity ^0.8.0; interface ISodiumCore { /* ===== EVENTS ===== */ // Emitted when a user requests a loan by sending collateral to the Core event RequestMade( uint256 indexed id, address indexed requester, address tokenAddress, uint256 tokenId, uint256 amount, uint256 APR, uint256 length, address currency ); // Emitted when a borrower cancels their request before adding any funds and converting it to an active loan event RequestWithdrawn(uint256 indexed requestId); // Emitted when a meta-lenders funds are added to a loan // One emitted each meta-contribution => can be multiple in a single call event FundsAdded( uint256 indexed loanId, address lender, uint256 amount, uint256 APR ); // Emitted when a borrower repays an amount of loan debt to a lender event RepaymentMade( uint256 indexed loanId, address indexed lender, uint256 principal, uint256 interest, uint256 fee ); // Emitted when a bid is made on an auction for liquidated collateral event BidMade( uint256 indexed id, address indexed bidder, uint256 bid, uint256 index ); // Emitted when a user instant-purchases auctioned collateral event PurchaseMade(uint256 indexed id); // Emitted when auction proceeds reimburse a lender // Seperate event to `RepaymentMade` as no fees are collected in auction event AuctionRepaymentMade( uint256 indexed auctionId, address indexed lender, uint256 amount ); // Emitted when a collateral auction is resolved. event AuctionConcluded(uint256 indexed id, address indexed winner); // Emitted when protocol parameter setters are called by Core owner event FeeUpdated(uint256 feeNumerator, uint256 feeDenominator); event AuctionLengthUpdated(uint256 auctionLength); event WalletFactoryUpdated(address walletFactory); event TreasuryUpdated(address treasury); event MetaContributionValidatorUpdated(address validator); /* ===== METHODS ===== */ function initialize( string calldata name, string calldata version, uint256 numerator, uint256 denominator, uint256 length, address factory, address payable treasury, address validator ) external; function onERC721Received( address requester, address, uint256 tokenId, bytes calldata data ) external returns (bytes4); function onERC1155Received( address requester, address, uint256 tokenId, uint256 value, bytes calldata data ) external returns (bytes4); function withdraw(uint256 requestId) external; function borrowETH( uint256 loanId, Types.MetaContribution[] calldata metaContributions, uint256[] calldata amounts, Types.NoWithdrawalSignature calldata noWithdrawalSignature ) external; function borrowERC20( uint256 loanId, Types.MetaContribution[] calldata metaContributions, uint256[] calldata amounts, Types.NoWithdrawalSignature calldata noWithdrawalSignature ) external; function repayETH(uint256 loanId) external payable; function repayERC20(uint256 loanId, uint256 amount) external; function bidETH(uint256 auctionId, uint256 index) external payable; function bidERC20( uint256 auctionId, uint256 amount, uint256 index ) external; function purchaseETH(uint256 auctionId) external payable; function purchaseERC20(uint256 auctionId) external; function resolveAuctionETH(uint256 auctionId) external; function resolveAuctionERC20(uint256 auctionId) external; // function getLoan(uint256 loanId) external view returns (Types.Loan memory); // function getWallet(address borrower) external view returns (address); // function getAuction(uint256 auctionId) // external // view // returns (Types.Auction memory); function setFee(uint256 numerator, uint256 denominator) external; function setAuctionLength(uint256 length) external; function setWalletFactory(address factory) external; function setTreasury(address payable treasury) external; function setValidator(address validator) external; } // File contracts/interfaces/IWETH.sol pragma solidity ^0.8.0; interface IWETH is IERC20Upgradeable { function deposit() external payable; function withdraw(uint256 wad) external; } // File contracts/libraries/Maths.sol pragma solidity ^0.8.0; // A library for performing calculations used by the Sodium Protocol // Units: // - Loan durations are in seconds // - APRs are in basis points // Interest // - Meta-lenders earn interest on the bigger of the following: // - the loan's duration // - half the borrowers requested loan length // - Interest increases discretely every hour // Fees: // - There are two components to protocol fees: // - The borrower pays a fee, equal to a fraction of the interest earned, on top of that interest // - This amount is also taken from the interest itself // - Fraction is feeNumerator / feeDenominator library Maths { // Calculate the interest and fee required for a given APR, principal, and duration function calculateInterestAndFee( uint256 principal, uint256 APR, uint256 duration, uint256 feeNumerator, uint256 feeDenominator ) internal pure returns (uint256, uint256) { // Interest increases every hour duration = (duration / 3600) * 3600; uint256 baseInterest = (principal * APR * duration) / 3650000 days; uint256 baseFee = (baseInterest * feeNumerator) / feeDenominator; return (baseInterest - baseFee, baseFee * 2); } function principalPlusInterest( uint256 principal, uint256 APR, uint256 duration ) internal pure returns (uint256) { // Interest increases every hour duration = (duration / 3600) * 3600; uint256 interest = (principal * APR * duration) / 3650000 days; return principal + interest; } // Calculates the maximum principal reduction for an input amount of available funds function partialPaymentParameters( uint256 available, uint256 APR, uint256 duration, uint256 feeNumerator, uint256 feeDenominator ) internal pure returns ( uint256, uint256, uint256 ) { // Obtain max principal reduction via => available funds = max reduction + corresponding interest + corresponding fee uint256 reductionNumerator = available * feeDenominator * 3650000 days; uint256 reductionDenominator = (feeDenominator * 3650000 days) + (duration * APR * (feeNumerator + feeDenominator)); uint256 reduction = reductionNumerator / reductionDenominator; // Interest increases every hour duration = (duration / 3600) * 3600; uint256 baseInterest = (reduction * APR * duration) / 3650000 days; uint256 baseFee = (baseInterest * feeNumerator) / feeDenominator; return (reduction, baseInterest - baseFee, baseFee * 2); } } // File contracts/SodiumCore.sol pragma solidity ^0.8.0; /// @title Sodium Core Contract /// @notice Manages loans and collateral auctions on the Sodium Protocol /// @dev WARNING! This contract is vulnerable to ERC20-transfer reentrancy => this is to save gas contract SodiumCore is ISodiumCore, Initializable, EIP712Upgradeable, ReentrancyGuardUpgradeable, OwnableUpgradeable, UUPSUpgradeable { /* ===== LIBRARIES ===== */ using SafeERC20Upgradeable for IERC20Upgradeable; /* ==================== STATE ==================== */ /* ===== ADDRESSES ===== */ // Used to deploy new Sodium Wallets ISodiumWalletFactory public sodiumWalletFactory; // The WETH contract used during ETH-loan-related functionality // See https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 IWETH private constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); // The address to which fees collected by the protocol are sent address payable public sodiumTreasury; // Validates meta-contributions as not having been withdrawn by meta-lenders address public metaContributionValidator; /* ===== PROTOCOL PARAMETERS ===== */ // The protocol's fee is stored as a fraction uint256 public feeNumerator; uint256 public feeDenominator; // The length of the protocol's collateral auction in seconds uint256 public auctionLength; /* ===== PROTOCOL STATE ===== */ // Maps a user to their Sodium Wallet mapping(address => address) private wallets; // Maps a loan's ID to its state-encapsulating `Loan` struct mapping(uint256 => Types.Loan) private loans; // Maps an auction's ID to its state-encapsulating `Auction` struct mapping(uint256 => Types.Auction) private auctions; /* ===== NONCES ===== */ /// @notice Get a meta-lender's meta-contibution nonce mapping(uint256 => mapping(address => uint256)) public nonces; // Used to create distinct IDs for same-collateral ERC1155 loans uint256 private ERC1155Nonce; // EIP-712 type hash for meta-contributions bytes32 private constant META_CONTRIBUTION_TYPE_HASH = keccak256( "MetaContribution(uint256 id,uint256 available,uint256 APR,uint256 liquidityLimit,uint256 nonce)" ); /* ===== MODIFIERS ===== */ // Reverts unless in-auction modifier duringAuctionOnly(uint256 auctionId) { require( block.timestamp > loans[auctionId].end && block.timestamp < loans[auctionId].auctionEnd, "19" ); _; } /* ===== INITIALIZER ===== */ /// @notice Proxy initializer function /// @param name The contract name used to verify EIP-712 meta-contribution signatures /// @param version The contract version used to verify EIP-712 meta-contribution signatures function initialize( string calldata name, string calldata version, uint256 numerator, uint256 denominator, uint256 length, address factory, address payable treasury, address validator ) public override initializer { __EIP712_init(name, version); __Ownable_init(); feeNumerator = numerator; feeDenominator = denominator; auctionLength = length; sodiumWalletFactory = ISodiumWalletFactory(factory); sodiumTreasury = treasury; metaContributionValidator = validator; } /* ===== RECEIVE ===== */ // Allows core to unwrap WETH receive() external payable {} /* ==================== LOANS ==================== */ /* ===== MAKE REQUESTS ===== */ /// @notice Initiates a loan request when called by an ERC721 contract during a `safeTransferFrom` call /// @param data Request parameters ABI-encoded into a `RequestParams` struct function onERC721Received( address requester, address, uint256 tokenId, bytes calldata data ) external override returns (bytes4) { // Block timestamp included in ID hash to ensure subsequent same-collateral loans have distinct IDs uint256 requestId = uint256( keccak256(abi.encode(tokenId, msg.sender, block.timestamp)) ); // Decode request information and execute request logic address wallet = _executeRequest( abi.decode(data, (Types.RequestParams)), requestId, tokenId, requester, msg.sender, Types.Collateral.ERC721 ); // Transfer collateral to wallet IERC721Upgradeable(msg.sender).transferFrom( address(this), wallet, tokenId ); return this.onERC721Received.selector; } /// @notice Initiates a loan request when called by an ERC1155 contract during a `safeTransferFrom` call /// @param data Request parameters ABI-encoded into a `RequestParams` struct function onERC1155Received( address requester, address, uint256 tokenId, uint256 value, bytes calldata data ) external override returns (bytes4) { require(value == 1, "2"); // Nonce included in hash to allow distinct IDs for same-collateral loans uint256 requestId = uint256( keccak256(abi.encode(tokenId, msg.sender, ERC1155Nonce)) ); // Increment nonce ERC1155Nonce++; // Decode request information and execute request logic address wallet = _executeRequest( abi.decode(data, (Types.RequestParams)), requestId, tokenId, requester, msg.sender, Types.Collateral.ERC1155 ); // Transfer collateral to wallet IERC1155Upgradeable(msg.sender).safeTransferFrom( address(this), wallet, tokenId, 1, "" ); return this.onERC1155Received.selector; } /* ===== CANCEL REQUESTS ===== */ /// @notice Used by borrower to withdraw collateral from loan requests that have not been converted into active loans /// @param requestId The ID of the target request function withdraw(uint256 requestId) external override { // Check no unpaid lenders require(loans[requestId].lenders.length == 0, "5"); // Ensure borrower calling address borrower = loans[requestId].borrower; require(msg.sender == borrower, "6"); // Transfer collateral to borrower _transferCollateral( loans[requestId].tokenAddress, loans[requestId].tokenId, loans[requestId].wallet, borrower, loans[requestId].collateralType ); delete loans[requestId]; emit RequestWithdrawn(requestId); } /* ===== ADD META-CONTRIBUTIONS ===== */ /// @notice Used by borrower to add funds to an ETH request/loan /// @dev Unwraps meta-lender WETH then sends resulting ETH to borrower /// @param id The ID of the target request/loan to which the meta-contributions are to be added /// @param metaContributions One or more signed lender meta-contributions /// @param amounts The amount of each meta-contribution's available funds that are to be added to the loan /// @param noWithdrawalSignature A signature of the meta-contributions that indicates they have not been withdrawn function borrowETH( uint256 id, Types.MetaContribution[] calldata metaContributions, uint256[] calldata amounts, Types.NoWithdrawalSignature calldata noWithdrawalSignature ) external override { Types.Loan storage loan = loans[id]; require(loan.currency == address(0), "3"); address borrower = _preAdditionLogic( loan, metaContributions, noWithdrawalSignature ); // Keep track of liquidity using stack => initialise as current value uint256 liquidity = loan.liquidity; // Track total ETH added (sum of amounts) uint256 total = 0; // Iterate over meta-contributions in order for (uint256 i = 0; i < metaContributions.length; i++) { address lender = _processMetaContribution( id, amounts[i], liquidity, metaContributions[i] ); // Transfer WETH to contract WETH.transferFrom(lender, address(this), amounts[i]); // Update tracked quantities total += amounts[i]; liquidity += amounts[i]; } // Convert all lender WETH into ETH WETH.withdraw(total); // Save loan's final liquidity loan.liquidity = liquidity; // Send ETH after state changes to avoid reentrancy payable(borrower).transfer(total); } /// @notice Used by borrower to add funds to an ERC20 loan /// @dev Transfers core-approved meta-lender tokens to the borrower /// @param id The ID of the target request/loan to which the meta-contributions are to be added /// @param metaContributions One or more signed lender meta-contributions /// @param amounts The amount of each meta-contribution's available funds that are to be added to the loan /// @param noWithdrawalSignature A signature of the meta-contributions that indicates they have not been withdrawn function borrowERC20( uint256 id, Types.MetaContribution[] calldata metaContributions, uint256[] calldata amounts, Types.NoWithdrawalSignature calldata noWithdrawalSignature ) external override { Types.Loan storage loan = loans[id]; require(loan.currency != address(0), "4"); address borrower = _preAdditionLogic( loan, metaContributions, noWithdrawalSignature ); // Keep track of liquidity using stack uint256 liquidity = loan.liquidity; address currency = loan.currency; // Iterate over meta-contributions in order for (uint256 i = 0; i < metaContributions.length; i++) { address lender = _processMetaContribution( id, amounts[i], liquidity, metaContributions[i] ); // Transfer funds to borrower IERC20Upgradeable(currency).safeTransferFrom( lender, borrower, amounts[i] ); liquidity += amounts[i]; } // Save new loan liquidity into storage loan.liquidity = liquidity; } /* ===== REPAY DEBT ===== */ /// @notice Used to repay an ETH loan /// @dev No auth required as no gain to be made from repaying someone else's loan /// @dev Sent ETH (msg.value) is used for the repayment /// @param loanId The ID of the target loan function repayETH(uint256 loanId) external payable override { // Ensure ETH loan being repaid require(loans[loanId].currency == address(0), "3"); // Wrap sent ETH to use for repayment WETH.deposit{value: msg.value}(); // Set `from` to this contract as it owns the WETH _executeRepayment(loanId, msg.value, address(WETH), address(this)); } /// @notice Used to repay an ERC20 loan /// @dev No auth required as no gain to be made from repaying someone else's loan /// @dev The Core must be granted approval over the tokens used for repayment /// @param loanId The ID of the target loan /// @param amount The amount of tokens to repay function repayERC20(uint256 loanId, uint256 amount) external override { _executeRepayment(loanId, amount, loans[loanId].currency, msg.sender); } /* ==================== AUCTION ==================== */ /* ===== BID ===== */ /// @notice Make an ETH bid in a collateral auction /// @dev WARNING: Do not bid higher than purchase amount => purchase instead /// @dev Set index parameter to the length of the lending queue if no boost available /// @param auctionId The ID of the target auction /// @param index The index of the caller in the lending queue => requests a boost function bidETH(uint256 auctionId, uint256 index) external payable override duringAuctionOnly(auctionId) { require(loans[auctionId].currency == address(0), "3"); address previousBidder = auctions[auctionId].bidder; uint256 previousRawBid = auctions[auctionId].rawBid; _executeBid(auctionId, msg.value, index); // Repay previous bidder if needed if (previousBidder != address(0)) { _nonBlockingTransfer(previousBidder, previousRawBid); } } /// @notice Make an bid of some ERC20 tokens for some auctioned collateral /// @dev WARNING! Do not bid higher than purchase amount => purchase instead /// @dev Set index parameter to the length of the lending queue if no boost available /// @param auctionId The ID of the target auction /// @param index The index of the caller in the lending queue => requests a boost /// @param amount The amount of tokens to bid /// @param index The index of the caller in the lending queue => requests a boost function bidERC20( uint256 auctionId, uint256 amount, uint256 index ) external override duringAuctionOnly(auctionId) { address currency = loans[auctionId].currency; address bidder = auctions[auctionId].bidder; // Repay previous bidder if needed if (bidder != address(0)) { IERC20Upgradeable(currency).safeTransfer( bidder, auctions[auctionId].rawBid ); } // Transfer bid to the Core // Call will fail if to zero address (cant't be used on ETH loans) IERC20Upgradeable(currency).safeTransferFrom( msg.sender, address(this), amount ); _executeBid(auctionId, amount, index); } /* ===== PURCHASE ===== */ /// @notice Purchase in-auction collateral instantly with ETH /// @dev Requires settling all unpaid lender debts plus any repayments the borrower has made /// @dev If the caller is an unpaid lender, a borrower who has repaid, or the most recent bidder, a purchase discount will be applied accordingly /// @param auctionId The ID of the collateral's auction function purchaseETH(uint256 auctionId) external payable override duringAuctionOnly(auctionId) nonReentrant { Types.Loan storage loan = loans[auctionId]; Types.Auction memory auction = auctions[auctionId]; require(loan.currency == address(0), "3"); // Track funds remaing to carry out payments required for purchase uint256 remainingFunds = msg.value; if (msg.sender == auction.bidder) { // Add raw bid to purchase funds if bidder is the caller remainingFunds += auction.rawBid; } else { // Otherwise pay back bidder _nonBlockingTransfer(auction.bidder, auction.rawBid); } address borrower = loan.borrower; uint256 repayment = loan.repayment; if (borrower != msg.sender && repayment != 0) { // Pay back borrower's repayment _nonBlockingTransfer(borrower, repayment); // Update remaining funds remainingFunds -= repayment; } // Wrap remaining funds to pay meta-lenders back in WETH WETH.deposit{value: remainingFunds}(); uint256 numberOfLenders = loan.lenders.length; for (uint256 i = 0; i < numberOfLenders; i++) { address lender = loan.lenders[i]; // Repay lender if they are not the caller if (lender != msg.sender) { // Calculate total owed to lender uint256 owed = Maths.principalPlusInterest( loan.principals[i], loan.APRs[i], loan.end - loan.timestamps[i] ); // This will revert if insufficient funds sent to repay lenders remainingFunds -= owed; // Pay lender fully WETH.transfer(lender, owed); emit AuctionRepaymentMade(auctionId, lender, owed); } } _auctionCleanup(auctionId, msg.sender); emit PurchaseMade(auctionId); } /// @notice Purchase in-auction collateral instantly with ERC20 /// @dev Requires settling all unpaid lender debts plus any repayments the borrower has made /// @dev If the caller is an unpaid lender, a borrower who has repaid, or the most recent bidder, a purchase discount will be applied accordingly /// @dev Tokens used for purchase must be approved to the core before calling /// @param auctionId The ID of the collateral's auction function purchaseERC20(uint256 auctionId) external override duringAuctionOnly(auctionId) { Types.Auction memory auction = auctions[auctionId]; Types.Loan storage loan = loans[auctionId]; address currency = loan.currency; require(currency != address(0), "4"); if (auction.bidder != address(0)) { // Pay back bidder // Funds are returned before paying other debt if bidder is the caller IERC20Upgradeable(currency).safeTransfer( auction.bidder, auction.rawBid ); } address borrower = loan.borrower; uint256 repayment = loan.repayment; if (borrower != msg.sender && repayment != 0) { // Pay back borrower if not the caller => will fail if to zero address IERC20Upgradeable(currency).safeTransferFrom( msg.sender, borrower, repayment ); } uint256 numberOfLenders = loan.lenders.length; for (uint256 i = 0; i < numberOfLenders; i++) { address lender = loan.lenders[i]; // Repay lender if they are not the caller if (lender != msg.sender) { // Calculate total owed to lender uint256 owed = Maths.principalPlusInterest( loan.principals[i], loan.APRs[i], loan.end - loan.timestamps[i] ); // Pay lender fully IERC20Upgradeable(currency).safeTransferFrom( msg.sender, lender, owed ); emit AuctionRepaymentMade(auctionId, lender, owed); } } _auctionCleanup(auctionId, msg.sender); emit PurchaseMade(auctionId); } /* ===== RESOLVE AUCTION ===== */ /// @notice Resolve an ETH-auction after it has finished /// @dev Pays back debts using WETH and sends collateral to the auction winner /// @param auctionId The ID of the finished auction function resolveAuctionETH(uint256 auctionId) external override { require(loans[auctionId].currency == address(0), "3"); WETH.deposit{value: auctions[auctionId].rawBid}(); _resolveAuction(auctionId, address(WETH)); } /// @notice Resolve an ERC20-auction after it has finished /// @dev Pays back debts using WETH and sends collateral to the auction winner /// @param auctionId The ID of the finished auction function resolveAuctionERC20(uint256 auctionId) external override { address currency = loans[auctionId].currency; require(currency != address(0), "4"); _resolveAuction(auctionId, currency); } // /* ==================== GETTERS ==================== */ // These are used for testing, but are not required for deployment // function getLoan(uint256 loanId) public view returns (Types.Loan memory) { // return loans[loanId]; // } // function getWallet(address borrower) public view returns (address) { // return wallets[borrower]; // } // function getAuction(uint256 auctionId) // public // view // returns (Types.Auction memory) // { // return auctions[auctionId]; // } /* ==================== ADMIN ==================== */ function setFee(uint256 numerator, uint256 denominator) external override onlyOwner { feeNumerator = numerator; feeDenominator = denominator; emit FeeUpdated(numerator, denominator); } function setAuctionLength(uint256 length) external override onlyOwner { auctionLength = length; emit AuctionLengthUpdated(length); } function setWalletFactory(address factory) external override onlyOwner { sodiumWalletFactory = ISodiumWalletFactory(factory); emit WalletFactoryUpdated(factory); } function setTreasury(address payable treasury) external override onlyOwner { sodiumTreasury = treasury; emit TreasuryUpdated(treasury); } function setValidator(address validator) external override onlyOwner { metaContributionValidator = validator; emit MetaContributionValidatorUpdated(validator); } /* ==================== INTERNAL ==================== */ // Performs shared request logic: // - creates a new Sodium Wallet for the requester if they do not have one already // - saves request information in a `Loan` struct function _executeRequest( Types.RequestParams memory requestParams, uint256 requestId, uint256 tokenId, address requester, address tokenAddress, Types.Collateral collateralType ) internal returns (address) { address wallet = wallets[requester]; // If user's wallet is zero address => their first loan => create a new wallet if (wallet == address(0)) { // Deploy wallet = sodiumWalletFactory.createWallet(requester); // Register wallets[requester] = wallet; } // Save request details loans[requestId] = Types.Loan( requestParams.length, 0, 0, tokenId, 0, new address[](0), new uint256[](0), new uint256[](0), new uint256[](0), tokenAddress, requestParams.currency, requester, wallet, 0, collateralType ); // Log request details emit RequestMade( requestId, requester, tokenAddress, tokenId, requestParams.amount, requestParams.APR, requestParams.length, requestParams.currency ); return wallet; } // Performs shared pre-fund addition logic: // - checks caller is borrower // - sets loan end if first time funds are added // - ensures auction has not started // - checks meta-contributions have not been recinded using `noWithdrawalSignature` function _preAdditionLogic( Types.Loan storage loan, Types.MetaContribution[] calldata metaContributions, Types.NoWithdrawalSignature calldata noWithdrawalSignature ) internal returns (address) { address borrower = loan.borrower; require(msg.sender == borrower, "6"); if (loan.lenders.length == 0) { // Set end of loan if it is the first addition uint256 end = loan.length + block.timestamp; loan.end = end; // Fix loan's auction length at time of loan start loan.auctionEnd = end + auctionLength; } else { // Check that loan is not over (in auction) require(block.timestamp < loan.end, "14"); } // Nonce in metaContributions ensures no replayability of signature bytes32 hash = keccak256( abi.encode(noWithdrawalSignature.deadline, metaContributions) ); // Load signed message bytes32 signed = ECDSAUpgradeable.toEthSignedMessageHash(hash); // Determine signer address signer = ECDSAUpgradeable.recover( signed, noWithdrawalSignature.v, noWithdrawalSignature.r, noWithdrawalSignature.s ); // Get assurance from validator that meta-contributions are non-withdrawn require(signer == metaContributionValidator, "7"); require(block.timestamp <= noWithdrawalSignature.deadline, "8"); return borrower; } // Verifies and executes a meta-contribution: // - checks meta-lender has offered sufficient funds // - checks meta-lender's liquidity limit is not surpassed // - derives lender from signature function _processMetaContribution( uint256 id, uint256 amount, uint256 currentLiquidity, Types.MetaContribution calldata contribution ) internal returns (address) { require(amount <= contribution.available, "9"); require(amount + currentLiquidity <= contribution.liquidityLimit, "10"); // Calculate lender's signed EIP712 message bytes32 hashStruct = keccak256( abi.encode( META_CONTRIBUTION_TYPE_HASH, id, contribution.available, contribution.APR, contribution.liquidityLimit, contribution.nonce ) ); bytes32 digest = _hashTypedDataV4(hashStruct); // Assume signer is lender address lender = ECDSAUpgradeable.recover( digest, contribution.v, contribution.r, contribution.s ); // Avoid meta-contribution replay via lender nonce require(contribution.nonce == nonces[id][lender], "11"); nonces[id][lender]++; // Update loan state loans[id].principals.push(amount); loans[id].lenders.push(lender); loans[id].APRs.push(contribution.APR); loans[id].timestamps.push(block.timestamp); emit FundsAdded(id, lender, amount, contribution.APR); return lender; } // Performs shared repayment logic: // - checks loan is ongoing // - pays back lenders from the top of the lending queue (loan.lenders) // - returns collateral if full repayment function _executeRepayment( uint256 loanId, uint256 amount, address currency, address from ) internal { Types.Loan storage loan = loans[loanId]; // For front end convenience require(loan.borrower != address(0), "13"); // Can only repay an active loan require(block.timestamp < loan.end, "14"); // Track funds remaining for repayment uint256 remainingFunds = amount; // Borrowers must pay interest on at least half the requested loan length uint256 minimumDuration = loan.length / 2; // Iterate through lenders from top of lending queue and pay them back for (uint256 i = loan.lenders.length; 0 < i; i--) { uint256 principal = loan.principals[i - 1]; // // Borrowers must pay interest on at least half the requested loan length // uint256 minimumDuration = loan.length / 2; uint256 timePassed = block.timestamp - loan.timestamps[i - 1]; uint256 effectiveLoanDuration = timePassed > minimumDuration ? timePassed : minimumDuration; // Calculate outstanding interest and fee (uint256 interest, uint256 fee) = Maths.calculateInterestAndFee( principal, loan.APRs[i - 1], effectiveLoanDuration, feeNumerator, feeDenominator ); address lender = loan.lenders[i - 1]; // Partial vs complete lender repayment if (remainingFunds < principal + interest + fee) { // Get partial payment parameters (principal, interest, fee) = Maths.partialPaymentParameters( remainingFunds, loan.APRs[i - 1], effectiveLoanDuration, feeNumerator, feeDenominator ); // Update the outstanding principal of the debt owed to the lender loan.principals[i - 1] -= principal; // Ensure loop termination i = 1; } else if (remainingFunds == principal + interest + fee) { // Complete repayment of lender using all remaining funds loan.lenders.pop(); // Ensure loop termination i = 1; } else { // Complete repayment with funds left over loan.lenders.pop(); } // Repay lender IERC20Upgradeable(currency).safeTransferFrom( from, lender, principal + interest ); // Send fee IERC20Upgradeable(currency).safeTransferFrom( from, sodiumTreasury, fee ); // Decreasing funds available for further repayment remainingFunds -= principal + interest + fee; emit RepaymentMade(loanId, lender, principal, interest, fee); } if (loan.lenders.length == 0) { // If no lender debts => return collateral _transferCollateral( loan.tokenAddress, loan.tokenId, loan.wallet, loan.borrower, loan.collateralType ); delete loans[loanId]; } else { // Increase overall borrower repayment by repaid amount loan.repayment += amount; } } // Performs shared bid logic: // - attempts to apply boost if lender index passed // - checks effective bid is greater than previous function _executeBid( uint256 auctionId, uint256 amount, uint256 index ) internal { Types.Loan storage loan = loans[auctionId]; Types.Auction storage auction = auctions[auctionId]; // Save raw bid pre-boost auction.rawBid = amount; // Boost bid if lender index entered if (index != loan.lenders.length) { // Check caller is lender at index require(msg.sender == loan.lenders[index], "15"); // Calculate starting boundary of lender liquidity uint256 lenderLiquidityStart = 0; for (uint256 i = 0; i < index; i++) { lenderLiquidityStart += Maths.principalPlusInterest( loan.principals[i], loan.APRs[i], loan.end - loan.timestamps[i] ); } // Boost bid with loaned lender liqudity if (amount >= lenderLiquidityStart) { amount += Maths.principalPlusInterest( loan.principals[index], loan.APRs[index], loan.end - loan.timestamps[index] ); } } // Check post-boost bid is greater than previous require(auction.effectiveBid < amount, "16"); auction.effectiveBid = amount; auction.bidder = msg.sender; emit BidMade(auctionId, msg.sender, amount, index); } // Performs shared auction-resolution functionality: // - ensures loan's auction is over // - pays lenders from the bottom of the lending queue (loan.lenders) // - repays any borrower repayment with any funds remaining after lender repayment // - transfers collateral to winner (via _auctionCleanup) function _resolveAuction(uint256 auctionId, address currency) internal { Types.Loan storage loan = loans[auctionId]; uint256 numberOfLenders = loan.lenders.length; // Check loan has lender debts => ensures loan.end is non-zero require(numberOfLenders != 0, "17"); // Check auction has finished require(loan.auctionEnd < block.timestamp, "18"); Types.Auction memory auction = auctions[auctionId]; // Pay off all possible lenders with bid => start at bottom of lending queue for (uint256 i = 0; i < numberOfLenders; i++) { address lender = loan.lenders[i]; // Repay lender if they are not the caller if (lender != msg.sender) { // Calculate total owed to lender uint256 owed = Maths.principalPlusInterest( loan.principals[i], loan.APRs[i], loan.end - loan.timestamps[i] ); if (auction.rawBid <= owed) { // Pay lender with remaining IERC20Upgradeable(currency).safeTransfer( lender, auction.rawBid ); auction.rawBid = 0; emit AuctionRepaymentMade( auctionId, lender, auction.rawBid ); // Stop payment iteration as no more available funds break; } else { // Pay lender fully IERC20Upgradeable(currency).safeTransfer(lender, owed); // Update remaining funds auction.rawBid -= owed; emit AuctionRepaymentMade(auctionId, lender, owed); } } } // Send remaining funds to borrower to compensate for any loan repayment they have made if (auction.rawBid != 0) { IERC20Upgradeable(currency).safeTransfer( loan.borrower, auction.rawBid ); } // Set winner to first lender if no bids made address winner = auction.bidder == address(0) ? loan.lenders[0] : auction.bidder; _auctionCleanup(auctionId, winner); emit AuctionConcluded(auctionId, winner); } // Performs end-of-purchase logic that is shared between ETH & ERC20 purchases function _auctionCleanup(uint256 auctionId, address winner) internal { // Send collateral to purchaser _transferCollateral( loans[auctionId].tokenAddress, loans[auctionId].tokenId, loans[auctionId].wallet, winner, loans[auctionId].collateralType ); delete auctions[auctionId]; delete loans[auctionId]; } // Transfers collateral from a sodium wallet to a recipient function _transferCollateral( address tokenAddress, uint256 tokenId, address from, address to, Types.Collateral collateralType ) internal { if (collateralType == Types.Collateral.ERC721) { ISodiumWallet(from).transferERC721(to, tokenAddress, tokenId); } else { ISodiumWallet(from).transferERC1155(to, tokenAddress, tokenId); } } // Avoids DOS resulting from from Core ETH transfers made to contracts that don't accept ETH function _nonBlockingTransfer(address recipient, uint256 amount) internal { // Attempt to send ETH to recipient (bool success, ) = recipient.call{value: amount}(""); // If repayment fails => avoid blocking and send funds to treasury if (!success) { sodiumTreasury.transfer(amount); } } // Contract owner is authorized to perform upgrades (Open Zep UUPS) function _authorizeUpgrade(address) internal view override onlyOwner {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"winner","type":"address"}],"name":"AuctionConcluded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"auctionLength","type":"uint256"}],"name":"AuctionLengthUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AuctionRepaymentMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"bidder","type":"address"},{"indexed":false,"internalType":"uint256","name":"bid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"BidMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"feeNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeDenominator","type":"uint256"}],"name":"FeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"loanId","type":"uint256"},{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"APR","type":"uint256"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"validator","type":"address"}],"name":"MetaContributionValidatorUpdated","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":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"PurchaseMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"loanId","type":"uint256"},{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"principal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"RepaymentMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"APR","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"length","type":"uint256"},{"indexed":false,"internalType":"address","name":"currency","type":"address"}],"name":"RequestMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"RequestWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"treasury","type":"address"}],"name":"TreasuryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"walletFactory","type":"address"}],"name":"WalletFactoryUpdated","type":"event"},{"inputs":[],"name":"auctionLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"bidERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"bidETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"APR","type":"uint256"},{"internalType":"uint256","name":"liquidityLimit","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct Types.MetaContribution[]","name":"metaContributions","type":"tuple[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Types.NoWithdrawalSignature","name":"noWithdrawalSignature","type":"tuple"}],"name":"borrowERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"APR","type":"uint256"},{"internalType":"uint256","name":"liquidityLimit","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct Types.MetaContribution[]","name":"metaContributions","type":"tuple[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Types.NoWithdrawalSignature","name":"noWithdrawalSignature","type":"tuple"}],"name":"borrowETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"},{"internalType":"address","name":"factory","type":"address"},{"internalType":"address payable","name":"treasury","type":"address"},{"internalType":"address","name":"validator","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"metaContributionValidator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","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":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"purchaseERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"purchaseETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"repayETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"resolveAuctionERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"resolveAuctionETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"setAuctionLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"validator","type":"address"}],"name":"setValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"factory","type":"address"}],"name":"setWalletFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sodiumTreasury","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sodiumWalletFactory","outputs":[{"internalType":"contract ISodiumWalletFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523060601b60805234801561001757600080fd5b5060805160601c615dcf6200005360003960008181610cdd01528181610d7301528181610eac01528181610f42015261122a0152615dcf6000f3fe6080604052600436106101e75760003560e01c8063715018a611610102578063bdf1a30d11610095578063e86dea4a11610064578063e86dea4a146105d0578063f0f44260146105e7578063f23a6e6114610607578063f2fde38b1461062757600080fd5b8063bdf1a30d14610541578063c5d891c614610554578063d309c9d214610574578063e2f60afc146105a257600080fd5b80639c224b00116100d15780639c224b00146104c1578063a1f094d4146104e1578063a4357b5814610501578063b579605b1461052157600080fd5b8063715018a6146104415780637ebf879c14610456578063802cec01146104765780638da5cb5b1461049657600080fd5b8063325c25a21161017a5780635232bdfd116101495780635232bdfd146103d957806352d1902d146103f957806352f7c9881461040e5780636bd131a01461042e57600080fd5b8063325c25a21461033c5780633659cfe6146103535780634971a5e4146103735780634f1ef286146103c657600080fd5b8063180b0d7e116101b6578063180b0d7e146102ab5780632247463e146102d05780632a81d49d146102e35780632e1a7d4d1461031c57600080fd5b80630439ae86146101f35780630c7df6f3146102155780631327d3d814610235578063150b7a021461025557600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061021361020e366004615953565b610647565b005b34801561022157600080fd5b50610213610230366004615953565b6106d0565b34801561024157600080fd5b5061021361025036600461560a565b6107f3565b34801561026157600080fd5b50610275610270366004615642565b610876565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020015b60405180910390f35b3480156102b757600080fd5b506102c26101335481565b6040519081526020016102a2565b6102136102de366004615953565b610982565b3480156102ef57600080fd5b506102c26102fe36600461596b565b61013860209081526000928352604080842090915290825290205481565b34801561032857600080fd5b50610213610337366004615953565b610a8d565b34801561034857600080fd5b506102c26101345481565b34801561035f57600080fd5b5061021361036e36600461560a565b610cc5565b34801561037f57600080fd5b50610131546103a19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102a2565b6102136103d436600461572d565b610e94565b3480156103e557600080fd5b506102136103f436600461599a565b611053565b34801561040557600080fd5b506102c2611210565b34801561041a57600080fd5b50610213610429366004615a4f565b6112e2565b61021361043c366004615a4f565b611333565b34801561044d57600080fd5b50610213611491565b34801561046257600080fd5b5061021361047136600461560a565b6114a5565b34801561048257600080fd5b50610213610491366004615a4f565b611521565b3480156104a257600080fd5b5060995473ffffffffffffffffffffffffffffffffffffffff166103a1565b3480156104cd57600080fd5b506102136104dc366004615825565b611558565b3480156104ed57600080fd5b506102136104fc366004615a70565b6117c4565b34801561050d57600080fd5b5061021361051c36600461599a565b6118ef565b34801561052d57600080fd5b5061021361053c366004615953565b611be6565b61021361054f366004615953565b611c24565b34801561056057600080fd5b5061021361056f366004615953565b61212b565b34801561058057600080fd5b50610130546103a19073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105ae57600080fd5b5061012f546103a19073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105dc57600080fd5b506102c26101325481565b3480156105f357600080fd5b5061021361060236600461560a565b6124bc565b34801561061357600080fd5b506102756106223660046156b3565b612538565b34801561063357600080fd5b5061021361064236600461560a565b6126bf565b600081815261013660205260409020600a015473ffffffffffffffffffffffffffffffffffffffff16806106c25760405162461bcd60e51b815260206004820152600160248201527f340000000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6106cc8282612759565b5050565b600081815261013660205260409020600a015473ffffffffffffffffffffffffffffffffffffffff16156107465760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600081815261013760205260408082206001015481517fd0e30db0000000000000000000000000000000000000000000000000000000008152915173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29363d0e30db0936004808201939182900301818588803b1580156107b957600080fd5b505af11580156107cd573d6000803e3d6000fd5b50505050506107f08173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2612759565b50565b6107fb612b75565b61013180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f0e846f611977d6990509259e30a2da1e38921350a7eb798ab12a79fd4fa18221906020015b60405180910390a150565b6040805160208082018690523382840152426060808401919091528351808403909101815260809092019092528051910120600090816108c66108bb868601876158e8565b83888b336000612bdc565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff821660248201526044810188905290915033906323b872dd90606401600060405180830381600087803b15801561093d57600080fd5b505af1158015610951573d6000803e3d6000fd5b507f150b7a02000000000000000000000000000000000000000000000000000000009b9a5050505050505050505050565b600081815261013660205260409020600a015473ffffffffffffffffffffffffffffffffffffffff16156109f85760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a5457600080fd5b505af1158015610a68573d6000803e3d6000fd5b50505050506107f0813473c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2306130eb565b6000818152610136602052604090206005015415610aed5760405162461bcd60e51b815260206004820152600160248201527f350000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600081815261013660205260409020600b015473ffffffffffffffffffffffffffffffffffffffff16338114610b655760405162461bcd60e51b815260206004820152600160248201527f360000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60008281526101366020526040902060098101546003820154600c830154600e90930154610bb29373ffffffffffffffffffffffffffffffffffffffff938416931690859060ff16613739565b6000828152610136602052604081208181556001810182905560028101829055600381018290556004810182905590610bee600583018261545b565b610bfc60068301600061545b565b610c0a60078301600061545b565b610c1860088301600061545b565b506009810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600a8201805482169055600b8201805482169055600c8201805490911690556000600d8201819055600e90910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560405183917fa96b5d0d7f26bd7262aefaa969b62e7b98f59439bca50822d598df9c16a20d6791a25050565b3073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161415610d715760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084016106b9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610de67f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610e6f5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f7879000000000000000000000000000000000000000060648201526084016106b9565b610e788161388d565b604080516000808252602082019092526107f091839190613895565b3073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161415610f405760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084016106b9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610fb57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161461103e5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f7879000000000000000000000000000000000000000060648201526084016106b9565b6110478261388d565b6106cc82826001613895565b600086815261013660205260409020600a81015473ffffffffffffffffffffffffffffffffffffffff166110c95760405162461bcd60e51b815260206004820152600160248201527f340000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60006110d782888886613a74565b6004830154600a8401549192509073ffffffffffffffffffffffffffffffffffffffff1660005b888110156111fc57600061115f8c8a8a8581811061112c57634e487b7160e01b600052603260045260246000fd5b90506020020135868e8e8781811061115457634e487b7160e01b600052603260045260246000fd5b905060e00201613ced565b90506111b481868b8b8681811061118657634e487b7160e01b600052603260045260246000fd5b905060200201358673ffffffffffffffffffffffffffffffffffffffff16614001909392919063ffffffff16565b8888838181106111d457634e487b7160e01b600052603260045260246000fd5b90506020020135846111e69190615bfe565b93505080806111f490615ceb565b9150506110fe565b505060049092019190915550505050505050565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146112bd5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016106b9565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b6112ea612b75565b61013282905561013381905560408051838152602081018390527f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df61302910160405180910390a15050565b6000828152610136602052604090206001015482904211801561136757506000818152610136602052604090206002015442105b6113b35760405162461bcd60e51b815260206004820152600260248201527f313900000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600083815261013660205260409020600a015473ffffffffffffffffffffffffffffffffffffffff16156114295760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600083815261013760205260409020805460019091015473ffffffffffffffffffffffffffffffffffffffff909116906114648534866140e3565b73ffffffffffffffffffffffffffffffffffffffff82161561148a5761148a82826143e2565b5050505050565b611499612b75565b6114a36000614492565b565b6114ad612b75565b61012f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f276bc6b7f3a3bf51ef77c951554906c71c845188820b58292b7bbca5b010a9d19060200161086b565b600082815261013660205260409020600a01546106cc908390839073ffffffffffffffffffffffffffffffffffffffff16336130eb565b600054610100900460ff16158080156115785750600054600160ff909116105b806115925750303b158015611592575060005460ff166001145b6116045760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106b9565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561166257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6116d58b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c908190840183828082843760009201919091525061450992505050565b6116dd614590565b61013287905561013386905561013485905561012f805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255610130805486841690831617905561013180549285169290911691909117905580156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b600083815261013660205260409020600101548390421180156117f857506000818152610136602052604090206002015442105b6118445760405162461bcd60e51b815260206004820152600260248201527f313900000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600084815261013660209081526040808320600a01546101379092529091205473ffffffffffffffffffffffffffffffffffffffff918216911680156118ba57600086815261013760205260409020600101546118ba9073ffffffffffffffffffffffffffffffffffffffff8416908390614615565b6118dc73ffffffffffffffffffffffffffffffffffffffff8316333088614001565b6118e78686866140e3565b505050505050565b600086815261013660205260409020600a81015473ffffffffffffffffffffffffffffffffffffffff16156119665760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600061197482888886613a74565b60048301549091506000805b88811015611b1d5760006119ae8c8a8a8581811061112c57634e487b7160e01b600052603260045260246000fd5b905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26323b872dd82308c8c878181106119ec57634e487b7160e01b600052603260045260246000fd5b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b16815273ffffffffffffffffffffffffffffffffffffffff958616600482015294909316602485015250602090910201356044820152606401602060405180830381600087803b158015611a6857600080fd5b505af1158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa091906157ed565b50888883818110611ac157634e487b7160e01b600052603260045260246000fd5b9050602002013583611ad39190615bfe565b9250888883818110611af557634e487b7160e01b600052603260045260246000fd5b9050602002013584611b079190615bfe565b9350508080611b1590615ceb565b915050611980565b506040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810182905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b158015611b8457600080fd5b505af1158015611b98573d6000803e3d6000fd5b505050506004840182905560405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083906000818181858888f193505050501580156117b7573d6000803e3d6000fd5b611bee612b75565b6101348190556040518181527f26d6292d6fb0e786778ddcd15ee4e4ee219a7b892d1bf667e1c497c85bbcddcb9060200161086b565b60008181526101366020526040902060010154819042118015611c5857506000818152610136602052604090206002015442105b611ca45760405162461bcd60e51b815260206004820152600260248201527f313900000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60026035541415611cf75760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106b9565b600260358190556000838152610136602090815260408083206101378352928190208151606081018352815473ffffffffffffffffffffffffffffffffffffffff908116825260018301549482019490945294015490840152600a8201549192911615611da65760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b8051349073ffffffffffffffffffffffffffffffffffffffff16331415611ddd576020820151611dd69082615bfe565b9050611def565b611def826000015183602001516143e2565b600b830154600d84015473ffffffffffffffffffffffffffffffffffffffff90911690338214801590611e2157508015155b15611e3d57611e3082826143e2565b611e3a8184615c73565b92505b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e9957600080fd5b505af1158015611ead573d6000803e3d6000fd5b505050506005860154905060005b818110156120e6576000876005018281548110611ee857634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690503381146120d3576000611fb6896006018481548110611f3b57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548a6007018581548110611f6957634e487b7160e01b600052603260045260246000fd5b90600052602060002001548b6008018681548110611f9757634e487b7160e01b600052603260045260246000fd5b90600052602060002001548c60010154611fb19190615c73565b61466b565b9050611fc28188615c73565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905290975073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29063a9059cbb90604401602060405180830381600087803b15801561204757600080fd5b505af115801561205b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207f91906157ed565b508173ffffffffffffffffffffffffffffffffffffffff168b7f8443e4accb3d433827f4c371ddc39a1d28200f88dc619d5c54214cd5a3678e35836040516120c991815260200190565b60405180910390a3505b50806120de81615ceb565b915050611ebb565b506120f188336146c5565b60405188907ffdbd78280a858f138c490eae641a1da4e1e20547975de5d7c93d9be654d5194c90600090a250506001603555505050505050565b6000818152610136602052604090206001015481904211801561215f57506000818152610136602052604090206002015442105b6121ab5760405162461bcd60e51b815260206004820152600260248201527f313900000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6000828152610137602090815260408083208151606081018352815473ffffffffffffffffffffffffffffffffffffffff9081168252600183015482860152600290920154818401528685526101369093529220600a8101549192909116806122565760405162461bcd60e51b815260206004820152600160248201527f340000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b825173ffffffffffffffffffffffffffffffffffffffff161561229b578251602084015161229b9173ffffffffffffffffffffffffffffffffffffffff841691614615565b600b820154600d83015473ffffffffffffffffffffffffffffffffffffffff909116903382148015906122cd57508015155b156122f4576122f473ffffffffffffffffffffffffffffffffffffffff8416338484614001565b600584015460005b8181101561247c57600086600501828154811061232957634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690503381146124695760006123f288600601848154811061237c57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548960070185815481106123aa57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548a60080186815481106123d857634e487b7160e01b600052603260045260246000fd5b90600052602060002001548b60010154611fb19190615c73565b905061241673ffffffffffffffffffffffffffffffffffffffff8816338484614001565b8173ffffffffffffffffffffffffffffffffffffffff168b7f8443e4accb3d433827f4c371ddc39a1d28200f88dc619d5c54214cd5a3678e358360405161245f91815260200190565b60405180910390a3505b508061247481615ceb565b9150506122fc565b5061248788336146c5565b60405188907ffdbd78280a858f138c490eae641a1da4e1e20547975de5d7c93d9be654d5194c90600090a25050505050505050565b6124c4612b75565b61013080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d19060200161086b565b60008360011461258a5760405162461bcd60e51b815260206004820152600160248201527f320000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b61013980546040805160208082018a90523382840152606080830185905283518084039091018152608090920190925280519101209160006125cb83615ceb565b90915550600090506125ed6125e2858701876158e8565b83898c336001612bdc565b6040517ff242432a00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152604481018990526001606482015260a06084820152600060a4820152909150339063f242432a9060c401600060405180830381600087803b15801561267957600080fd5b505af115801561268d573d6000803e3d6000fd5b507ff23a6e61000000000000000000000000000000000000000000000000000000009c9b505050505050505050505050565b6126c7612b75565b73ffffffffffffffffffffffffffffffffffffffff81166127505760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106b9565b6107f081614492565b6000828152610136602052604090206005810154806127ba5760405162461bcd60e51b815260206004820152600260248201527f313700000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b4282600201541061280d5760405162461bcd60e51b815260206004820152600260248201527f313800000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6000848152610137602090815260408083208151606081018352815473ffffffffffffffffffffffffffffffffffffffff1681526001820154938101939093526002015490820152905b82811015612a7657600084600501828154811061288457634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050338114612a6357600061294d8660060184815481106128d757634e487b7160e01b600052603260045260246000fd5b906000526020600020015487600701858154811061290557634e487b7160e01b600052603260045260246000fd5b906000526020600020015488600801868154811061293357634e487b7160e01b600052603260045260246000fd5b90600052602060002001548960010154611fb19190615c73565b9050808460200151116129de5760208401516129829073ffffffffffffffffffffffffffffffffffffffff8916908490614615565b6000602085810182905260405191825273ffffffffffffffffffffffffffffffffffffffff8416918a917f8443e4accb3d433827f4c371ddc39a1d28200f88dc619d5c54214cd5a3678e35910160405180910390a35050612a76565b6129ff73ffffffffffffffffffffffffffffffffffffffff88168383614615565b8084602001818151612a119190615c73565b90525060405181815273ffffffffffffffffffffffffffffffffffffffff83169089907f8443e4accb3d433827f4c371ddc39a1d28200f88dc619d5c54214cd5a3678e359060200160405180910390a3505b5080612a6e81615ceb565b915050612857565b50602081015115612ab057600b8301546020820151612ab09173ffffffffffffffffffffffffffffffffffffffff87811692911690614615565b805160009073ffffffffffffffffffffffffffffffffffffffff1615612ad7578151612b1e565b83600501600081548110612afb57634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff165b9050612b2a86826146c5565b60405173ffffffffffffffffffffffffffffffffffffffff82169087907f14ddbb54b023fe50b4afefb9dd4d86d569714bede3c600ce529266a57321fbf290600090a3505050505050565b60995473ffffffffffffffffffffffffffffffffffffffff1633146114a35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106b9565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152610135602052604081205490911680612d095761012f546040517fb054a9e800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301529091169063b054a9e890602401602060405180830381600087803b158015612c7a57600080fd5b505af1158015612c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb29190615626565b73ffffffffffffffffffffffffffffffffffffffff86811660009081526101356020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691831691909117905590505b604051806101e0016040528089604001518152602001600081526020016000815260200187815260200160008152602001600067ffffffffffffffff811115612d6257634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612d8b578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612dbc578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612ded578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612e1e578160200160208202803683370190505b5081526020018573ffffffffffffffffffffffffffffffffffffffff168152602001896060015173ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001846001811115612ebf57634e487b7160e01b600052602160045260246000fd5b90526000888152610136602090815260409182902083518155838201516001820155918301516002830155606083015160038301556080830151600483015560a08301518051612f159260058501920190615479565b5060c08201518051612f31916006840191602090910190615503565b5060e08201518051612f4d916007840191602090910190615503565b506101008201518051612f6a916008840191602090910190615503565b5061012082015160098201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617909155610140840151600a84018054918416918316919091179055610160840151600b84018054918416918316919091179055610180840151600c840180549190931691161790556101a0820151600d8201556101c0820151600e820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001838181111561305657634e487b7160e01b600052602160045260246000fd5b02179055505088516020808b01516040808d01516060808f0151835173ffffffffffffffffffffffffffffffffffffffff8d811682529681018f90528085019790975290860193909352608085015290821660a084015251908816925089917f244a0d71f327a5b72e6d2f41c1359e43a93410edf36b3812ed72dfffff9f2285919081900360c00190a3979650505050505050565b600084815261013660205260409020600b81015473ffffffffffffffffffffffffffffffffffffffff166131615760405162461bcd60e51b815260206004820152600260248201527f313300000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b806001015442106131b45760405162461bcd60e51b815260206004820152600260248201527f313400000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b805484906000906131c790600290615c16565b60058401549091505b80156135e0576000600685016131e7600184615c73565b8154811061320557634e487b7160e01b600052603260045260246000fd5b6000918252602082200154915060088601613221600185615c73565b8154811061323f57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154426132559190615c73565b905060008482116132665784613268565b815b90506000806132b78560078b0161328060018a615c73565b8154811061329e57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154856101325461013354614838565b9092509050600060058a016132cd600189615c73565b815481106132eb57634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508161331a8488615bfe565b6133249190615bfe565b8910156133d2576133758960078c0161333e60018b615c73565b8154811061335c57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548661013254610133546148bc565b919750935091508560068b0161338c60018a615c73565b815481106133aa57634e487b7160e01b600052603260045260246000fd5b9060005260206000200160008282546133c39190615c73565b90915550600197506134ea9050565b816133dd8488615bfe565b6133e79190615bfe565b891415613470578960050180548061340f57634e487b7160e01b600052603160045260246000fd5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055600196506134ea565b8960050180548061349157634e487b7160e01b600052603160045260246000fd5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555b6135208b826134f9868a615bfe565b8f73ffffffffffffffffffffffffffffffffffffffff16614001909392919063ffffffff16565b6101305461354a9073ffffffffffffffffffffffffffffffffffffffff8e8116918e911685614001565b816135558488615bfe565b61355f9190615bfe565b613569908a615c73565b604080518881526020810186905290810184905290995073ffffffffffffffffffffffffffffffffffffffff8216908f907f1925feae58cf7aa6a70574859aab697cc68351d62dc2d3583f9c12c69453497d9060600160405180910390a350505050505080806135d890615cb6565b9150506131d0565b5060058301546137165760098301546003840154600c850154600b860154600e87015461362e9473ffffffffffffffffffffffffffffffffffffffff9081169493811692169060ff16613739565b600087815261013660205260408120818155600181018290556002810182905560038101829055600481018290559061366a600583018261545b565b61367860068301600061545b565b61368660078301600061545b565b61369460088301600061545b565b506009810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600a8201805482169055600b8201805482169055600c8201805490911690556000600d820155600e0180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055613730565b8583600d01600082825461372a9190615bfe565b90915550505b50505050505050565b600081600181111561375b57634e487b7160e01b600052602160045260246000fd5b14156137f6576040517f1aca637600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152868116602483015260448201869052841690631aca637690606401600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b5050505061148a565b6040517fb686fdba00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015286811660248301526044820186905284169063b686fdba90606401600060405180830381600087803b15801561386e57600080fd5b505af1158015613882573d6000803e3d6000fd5b505050505050505050565b6107f0612b75565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156138cd576138c8836149ad565b505050565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561391357600080fd5b505afa925050508015613961575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261395e9181019061580d565b60015b6139d35760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f74205555505300000000000000000000000000000000000060648201526084016106b9565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114613a685760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c6555554944000000000000000000000000000000000000000000000060648201526084016106b9565b506138c8838383614a9d565b600b84015460009073ffffffffffffffffffffffffffffffffffffffff16338114613ae15760405162461bcd60e51b815260206004820152600160248201527f360000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6005860154613b1d578554600090613afa904290615bfe565b6001880181905561013454909150613b129082615bfe565b600288015550613b70565b85600101544210613b705760405162461bcd60e51b815260206004820152600260248201527f313400000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b604051600090613b899085359088908890602001615b22565b6040516020818303038152906040528051906020012090506000613bfa826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b90506000613c2182613c126040890160208a01615a9b565b88604001358960600135614ac2565b6101315490915073ffffffffffffffffffffffffffffffffffffffff808316911614613c8f5760405162461bcd60e51b815260206004820152600160248201527f370000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b8535421115613ce05760405162461bcd60e51b815260206004820152600160248201527f380000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b5091979650505050505050565b60008160600135841115613d435760405162461bcd60e51b815260206004820152600160248201527f390000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60a0820135613d528486615bfe565b1115613da05760405162461bcd60e51b815260206004820152600260248201527f313000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b604080517fefe3f0a82f9122f279a2f7e34b471ab3d790d96e2e32cce338bff6c94cad82726020820152908101869052606080840135908201526080808401359082015260a0808401359082015260c0808401359082015260009060e0016040516020818303038152906040528051906020012090506000613e2182614aea565b90506000613e4582613e396060880160408901615a9b565b87356020890135614ac2565b60008981526101386020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205490915060c086013514613ecb5760405162461bcd60e51b815260206004820152600260248201527f313100000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60008881526101386020908152604080832073ffffffffffffffffffffffffffffffffffffffff851684529091528120805491613f0783615ceb565b909155505060008881526101366020908152604080832060068101805460018082018355918652848620018c905560058201805480830182559086528486200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8816908117909155600783018054808401825590875285872060808d013591018190556008909301805492830181558652948490204291015581519384529183018a905282015288907f337ac6ceecf7ab68028cc68df243cdc6988d3583aafdf19844cb526c4316a2799060600160405180910390a2979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526140dd9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614b59565b50505050565b600083815261013660209081526040808320610137909252909120600181018490556005820154831461431c5781600501838154811061413357634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633146141a35760405162461bcd60e51b815260206004820152600260248201527f313500000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6000805b848110156142695761424b8460060182815481106141d557634e487b7160e01b600052603260045260246000fd5b906000526020600020015485600701838154811061420357634e487b7160e01b600052603260045260246000fd5b906000526020600020015486600801848154811061423157634e487b7160e01b600052603260045260246000fd5b90600052602060002001548760010154611fb19190615c73565b6142559083615bfe565b91508061426181615ceb565b9150506141a7565b5080851061431a5761430d83600601858154811061429757634e487b7160e01b600052603260045260246000fd5b90600052602060002001548460070186815481106142c557634e487b7160e01b600052603260045260246000fd5b90600052602060002001548560080187815481106142f357634e487b7160e01b600052603260045260246000fd5b90600052602060002001548660010154611fb19190615c73565b6143179086615bfe565b94505b505b8381600201541061436f5760405162461bcd60e51b815260206004820152600260248201527f313600000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6002810184905580547fffffffffffffffffffffffff000000000000000000000000000000000000000016339081178255604080518681526020810186905287917f476bd0783cc4e83d617258e2b86038c40cb0dba0cca615fcc28e7ccb3d66cbed910160405180910390a35050505050565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461443c576040519150601f19603f3d011682016040523d82523d6000602084013e614441565b606091505b50509050806138c8576101305460405173ffffffffffffffffffffffffffffffffffffffff9091169083156108fc029084906000818181858888f193505050501580156140dd573d6000803e3d6000fd5b6099805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166145865760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106b9565b6106cc8282614c4b565b600054610100900460ff1661460d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106b9565b6114a3614ce2565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526138c89084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161405b565b6000614679610e1083615c16565b61468590610e10615c36565b9150600064496cebb8008361469a8688615c36565b6146a49190615c36565b6146ae9190615c16565b90506146ba8186615bfe565b9150505b9392505050565b60008281526101366020526040902060098101546003820154600c830154600e909301546147129373ffffffffffffffffffffffffffffffffffffffff938416931690859060ff16613739565b60008281526101376020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018082018590556002918201859055610136909352908320838155918201839055810182905560038101829055600481018290559061478d600583018261545b565b61479b60068301600061545b565b6147a960078301600061545b565b6147b760088301600061545b565b506009810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600a8201805482169055600b8201805482169055600c8201805490911690556000600d820155600e0180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555050565b600080614847610e1086615c16565b61485390610e10615c36565b9450600064496cebb80086614868898b615c36565b6148729190615c36565b61487c9190615c16565b905060008461488b8784615c36565b6148959190615c16565b90506148a18183615c73565b6148ac826002615c36565b9350935050509550959350505050565b60008080806148cb858a615c36565b6148da9064496cebb800615c36565b905060006148e88688615bfe565b6148f28a8a615c36565b6148fc9190615c36565b61490b8764496cebb800615c36565b6149159190615bfe565b905060006149238284615c16565b9050614931610e108a615c16565b61493d90610e10615c36565b9850600064496cebb8008a6149528d85615c36565b61495c9190615c36565b6149669190615c16565b90506000886149758b84615c36565b61497f9190615c16565b90508261498c8284615c73565b614997836002615c36565b9750975097505050505050955095509592505050565b73ffffffffffffffffffffffffffffffffffffffff81163b614a375760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e74726163740000000000000000000000000000000000000060648201526084016106b9565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b614aa683614d68565b600082511180614ab35750805b156138c8576140dd8383614db5565b6000806000614ad387878787614eda565b91509150614ae081614ff2565b5095945050505050565b6000614b53614af7615229565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b92915050565b6000614bbb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166152a99092919063ffffffff16565b8051909150156138c85780806020019051810190614bd991906157ed565b6138c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106b9565b600054610100900460ff16614cc85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106b9565b815160209283012081519190920120600191909155600255565b600054610100900460ff16614d5f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106b9565b6114a333614492565b614d71816149ad565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606073ffffffffffffffffffffffffffffffffffffffff83163b614e415760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084016106b9565b6000808473ffffffffffffffffffffffffffffffffffffffff1684604051614e699190615ab5565b600060405180830381855af49150503d8060008114614ea4576040519150601f19603f3d011682016040523d82523d6000602084013e614ea9565b606091505b5091509150614ed18282604051806060016040528060278152602001615d73602791396152c0565b95945050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115614f115750600090506003614fe9565b8460ff16601b14158015614f2957508460ff16601c14155b15614f3a5750600090506004614fe9565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614f8e573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116614fe257600060019250925050614fe9565b9150600090505b94509492505050565b600081600481111561501457634e487b7160e01b600052602160045260246000fd5b141561501d5750565b600181600481111561503f57634e487b7160e01b600052602160045260246000fd5b141561508d5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016106b9565b60028160048111156150af57634e487b7160e01b600052602160045260246000fd5b14156150fd5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016106b9565b600381600481111561511f57634e487b7160e01b600052602160045260246000fd5b14156151935760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016106b9565b60048160048111156151b557634e487b7160e01b600052602160045260246000fd5b14156107f05760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016106b9565b60006152a47f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61525860015490565b6002546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b905090565b60606152b884846000856152f9565b949350505050565b606083156152cf5750816146be565b8251156152df5782518084602001fd5b8160405162461bcd60e51b81526004016106b99190615ad1565b6060824710156153715760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016106b9565b73ffffffffffffffffffffffffffffffffffffffff85163b6153d55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106b9565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516153fe9190615ab5565b60006040518083038185875af1925050503d806000811461543b576040519150601f19603f3d011682016040523d82523d6000602084013e615440565b606091505b50915091506154508282866152c0565b979650505050505050565b50805460008255906000526020600020908101906107f0919061553e565b8280548282559060005260206000209081019282156154f3579160200282015b828111156154f357825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190615499565b506154ff92915061553e565b5090565b8280548282559060005260206000209081019282156154f3579160200282015b828111156154f3578251825591602001919060010190615523565b5b808211156154ff576000815560010161553f565b60008083601f840112615564578182fd5b50813567ffffffffffffffff81111561557b578182fd5b6020830191508360208260051b850101111561559657600080fd5b9250929050565b60008083601f8401126155ae578182fd5b50813567ffffffffffffffff8111156155c5578182fd5b60208301915083602082850101111561559657600080fd5b6000608082840312156155ee578081fd5b50919050565b803560ff8116811461560557600080fd5b919050565b60006020828403121561561b578081fd5b81356146be81615d50565b600060208284031215615637578081fd5b81516146be81615d50565b600080600080600060808688031215615659578081fd5b853561566481615d50565b9450602086013561567481615d50565b935060408601359250606086013567ffffffffffffffff811115615696578182fd5b6156a28882890161559d565b969995985093965092949392505050565b60008060008060008060a087890312156156cb578081fd5b86356156d681615d50565b955060208701356156e681615d50565b94506040870135935060608701359250608087013567ffffffffffffffff81111561570f578182fd5b61571b89828a0161559d565b979a9699509497509295939492505050565b6000806040838503121561573f578182fd5b823561574a81615d50565b915060208381013567ffffffffffffffff80821115615767578384fd5b818601915086601f83011261577a578384fd5b81358181111561578c5761578c615d3a565b6157bc847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601615baf565b915080825287848285010111156157d1578485fd5b8084840185840137810190920192909252919491935090915050565b6000602082840312156157fe578081fd5b815180151581146146be578182fd5b60006020828403121561581e578081fd5b5051919050565b6000806000806000806000806000806101008b8d031215615844578384fd5b8a3567ffffffffffffffff8082111561585b578586fd5b6158678e838f0161559d565b909c509a5060208d013591508082111561587f578586fd5b5061588c8d828e0161559d565b90995097505060408b0135955060608b0135945060808b0135935060a08b01356158b581615d50565b925060c08b01356158c581615d50565b915060e08b01356158d581615d50565b809150509295989b9194979a5092959850565b6000608082840312156158f9578081fd5b6040516080810181811067ffffffffffffffff8211171561591c5761591c615d3a565b8060405250823581526020830135602082015260408301356040820152606083013561594781615d50565b60608201529392505050565b600060208284031215615964578081fd5b5035919050565b6000806040838503121561597d578182fd5b82359150602083013561598f81615d50565b809150509250929050565b60008060008060008060e087890312156159b2578384fd5b86359550602087013567ffffffffffffffff808211156159d0578586fd5b818901915089601f8301126159e3578586fd5b8135818111156159f1578687fd5b8a602060e083028501011115615a05578687fd5b602083019750809650506040890135915080821115615a22578384fd5b50615a2f89828a01615553565b9094509250615a43905088606089016155dd565b90509295509295509295565b60008060408385031215615a61578182fd5b50508035926020909101359150565b600080600060608486031215615a84578081fd5b505081359360208301359350604090920135919050565b600060208284031215615aac578081fd5b6146be826155f4565b60008251615ac7818460208701615c8a565b9190910192915050565b6020815260008251806020840152615af0816040850160208701615c8a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b838152604060208083018290528282018490526000919060609081850187855b88811015615ba05781358352838201358484015260ff615b638784016155f4565b168387015281850135858401526080808301359084015260a0808301359084015260c0808301359084015260e09283019290910190600101615b42565b50909998505050505050505050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715615bf657615bf6615d3a565b604052919050565b60008219821115615c1157615c11615d24565b500190565b600082615c3157634e487b7160e01b81526012600452602481fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c6e57615c6e615d24565b500290565b600082821015615c8557615c85615d24565b500390565b60005b83811015615ca5578181015183820152602001615c8d565b838111156140dd5750506000910152565b600081615cc557615cc5615d24565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615d1d57615d1d615d24565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff811681146107f057600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c37cf1022cf4b804ed17a3503023d847e2bff0eceebfaac19ad104fc255be7db64736f6c63430008040033
Deployed Bytecode
0x6080604052600436106101e75760003560e01c8063715018a611610102578063bdf1a30d11610095578063e86dea4a11610064578063e86dea4a146105d0578063f0f44260146105e7578063f23a6e6114610607578063f2fde38b1461062757600080fd5b8063bdf1a30d14610541578063c5d891c614610554578063d309c9d214610574578063e2f60afc146105a257600080fd5b80639c224b00116100d15780639c224b00146104c1578063a1f094d4146104e1578063a4357b5814610501578063b579605b1461052157600080fd5b8063715018a6146104415780637ebf879c14610456578063802cec01146104765780638da5cb5b1461049657600080fd5b8063325c25a21161017a5780635232bdfd116101495780635232bdfd146103d957806352d1902d146103f957806352f7c9881461040e5780636bd131a01461042e57600080fd5b8063325c25a21461033c5780633659cfe6146103535780634971a5e4146103735780634f1ef286146103c657600080fd5b8063180b0d7e116101b6578063180b0d7e146102ab5780632247463e146102d05780632a81d49d146102e35780632e1a7d4d1461031c57600080fd5b80630439ae86146101f35780630c7df6f3146102155780631327d3d814610235578063150b7a021461025557600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061021361020e366004615953565b610647565b005b34801561022157600080fd5b50610213610230366004615953565b6106d0565b34801561024157600080fd5b5061021361025036600461560a565b6107f3565b34801561026157600080fd5b50610275610270366004615642565b610876565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020015b60405180910390f35b3480156102b757600080fd5b506102c26101335481565b6040519081526020016102a2565b6102136102de366004615953565b610982565b3480156102ef57600080fd5b506102c26102fe36600461596b565b61013860209081526000928352604080842090915290825290205481565b34801561032857600080fd5b50610213610337366004615953565b610a8d565b34801561034857600080fd5b506102c26101345481565b34801561035f57600080fd5b5061021361036e36600461560a565b610cc5565b34801561037f57600080fd5b50610131546103a19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102a2565b6102136103d436600461572d565b610e94565b3480156103e557600080fd5b506102136103f436600461599a565b611053565b34801561040557600080fd5b506102c2611210565b34801561041a57600080fd5b50610213610429366004615a4f565b6112e2565b61021361043c366004615a4f565b611333565b34801561044d57600080fd5b50610213611491565b34801561046257600080fd5b5061021361047136600461560a565b6114a5565b34801561048257600080fd5b50610213610491366004615a4f565b611521565b3480156104a257600080fd5b5060995473ffffffffffffffffffffffffffffffffffffffff166103a1565b3480156104cd57600080fd5b506102136104dc366004615825565b611558565b3480156104ed57600080fd5b506102136104fc366004615a70565b6117c4565b34801561050d57600080fd5b5061021361051c36600461599a565b6118ef565b34801561052d57600080fd5b5061021361053c366004615953565b611be6565b61021361054f366004615953565b611c24565b34801561056057600080fd5b5061021361056f366004615953565b61212b565b34801561058057600080fd5b50610130546103a19073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105ae57600080fd5b5061012f546103a19073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105dc57600080fd5b506102c26101325481565b3480156105f357600080fd5b5061021361060236600461560a565b6124bc565b34801561061357600080fd5b506102756106223660046156b3565b612538565b34801561063357600080fd5b5061021361064236600461560a565b6126bf565b600081815261013660205260409020600a015473ffffffffffffffffffffffffffffffffffffffff16806106c25760405162461bcd60e51b815260206004820152600160248201527f340000000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6106cc8282612759565b5050565b600081815261013660205260409020600a015473ffffffffffffffffffffffffffffffffffffffff16156107465760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600081815261013760205260408082206001015481517fd0e30db0000000000000000000000000000000000000000000000000000000008152915173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29363d0e30db0936004808201939182900301818588803b1580156107b957600080fd5b505af11580156107cd573d6000803e3d6000fd5b50505050506107f08173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2612759565b50565b6107fb612b75565b61013180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f0e846f611977d6990509259e30a2da1e38921350a7eb798ab12a79fd4fa18221906020015b60405180910390a150565b6040805160208082018690523382840152426060808401919091528351808403909101815260809092019092528051910120600090816108c66108bb868601876158e8565b83888b336000612bdc565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff821660248201526044810188905290915033906323b872dd90606401600060405180830381600087803b15801561093d57600080fd5b505af1158015610951573d6000803e3d6000fd5b507f150b7a02000000000000000000000000000000000000000000000000000000009b9a5050505050505050505050565b600081815261013660205260409020600a015473ffffffffffffffffffffffffffffffffffffffff16156109f85760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a5457600080fd5b505af1158015610a68573d6000803e3d6000fd5b50505050506107f0813473c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2306130eb565b6000818152610136602052604090206005015415610aed5760405162461bcd60e51b815260206004820152600160248201527f350000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600081815261013660205260409020600b015473ffffffffffffffffffffffffffffffffffffffff16338114610b655760405162461bcd60e51b815260206004820152600160248201527f360000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60008281526101366020526040902060098101546003820154600c830154600e90930154610bb29373ffffffffffffffffffffffffffffffffffffffff938416931690859060ff16613739565b6000828152610136602052604081208181556001810182905560028101829055600381018290556004810182905590610bee600583018261545b565b610bfc60068301600061545b565b610c0a60078301600061545b565b610c1860088301600061545b565b506009810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600a8201805482169055600b8201805482169055600c8201805490911690556000600d8201819055600e90910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560405183917fa96b5d0d7f26bd7262aefaa969b62e7b98f59439bca50822d598df9c16a20d6791a25050565b3073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000bf6c2eb9dfd0f90577d5ffa51759e9d878114411161415610d715760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084016106b9565b7f000000000000000000000000bf6c2eb9dfd0f90577d5ffa51759e9d87811441173ffffffffffffffffffffffffffffffffffffffff16610de67f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610e6f5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f7879000000000000000000000000000000000000000060648201526084016106b9565b610e788161388d565b604080516000808252602082019092526107f091839190613895565b3073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000bf6c2eb9dfd0f90577d5ffa51759e9d878114411161415610f405760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084016106b9565b7f000000000000000000000000bf6c2eb9dfd0f90577d5ffa51759e9d87811441173ffffffffffffffffffffffffffffffffffffffff16610fb57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161461103e5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f7879000000000000000000000000000000000000000060648201526084016106b9565b6110478261388d565b6106cc82826001613895565b600086815261013660205260409020600a81015473ffffffffffffffffffffffffffffffffffffffff166110c95760405162461bcd60e51b815260206004820152600160248201527f340000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60006110d782888886613a74565b6004830154600a8401549192509073ffffffffffffffffffffffffffffffffffffffff1660005b888110156111fc57600061115f8c8a8a8581811061112c57634e487b7160e01b600052603260045260246000fd5b90506020020135868e8e8781811061115457634e487b7160e01b600052603260045260246000fd5b905060e00201613ced565b90506111b481868b8b8681811061118657634e487b7160e01b600052603260045260246000fd5b905060200201358673ffffffffffffffffffffffffffffffffffffffff16614001909392919063ffffffff16565b8888838181106111d457634e487b7160e01b600052603260045260246000fd5b90506020020135846111e69190615bfe565b93505080806111f490615ceb565b9150506110fe565b505060049092019190915550505050505050565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000bf6c2eb9dfd0f90577d5ffa51759e9d87811441116146112bd5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016106b9565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b6112ea612b75565b61013282905561013381905560408051838152602081018390527f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df61302910160405180910390a15050565b6000828152610136602052604090206001015482904211801561136757506000818152610136602052604090206002015442105b6113b35760405162461bcd60e51b815260206004820152600260248201527f313900000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600083815261013660205260409020600a015473ffffffffffffffffffffffffffffffffffffffff16156114295760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600083815261013760205260409020805460019091015473ffffffffffffffffffffffffffffffffffffffff909116906114648534866140e3565b73ffffffffffffffffffffffffffffffffffffffff82161561148a5761148a82826143e2565b5050505050565b611499612b75565b6114a36000614492565b565b6114ad612b75565b61012f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f276bc6b7f3a3bf51ef77c951554906c71c845188820b58292b7bbca5b010a9d19060200161086b565b600082815261013660205260409020600a01546106cc908390839073ffffffffffffffffffffffffffffffffffffffff16336130eb565b600054610100900460ff16158080156115785750600054600160ff909116105b806115925750303b158015611592575060005460ff166001145b6116045760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106b9565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561166257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6116d58b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c908190840183828082843760009201919091525061450992505050565b6116dd614590565b61013287905561013386905561013485905561012f805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255610130805486841690831617905561013180549285169290911691909117905580156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b600083815261013660205260409020600101548390421180156117f857506000818152610136602052604090206002015442105b6118445760405162461bcd60e51b815260206004820152600260248201527f313900000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600084815261013660209081526040808320600a01546101379092529091205473ffffffffffffffffffffffffffffffffffffffff918216911680156118ba57600086815261013760205260409020600101546118ba9073ffffffffffffffffffffffffffffffffffffffff8416908390614615565b6118dc73ffffffffffffffffffffffffffffffffffffffff8316333088614001565b6118e78686866140e3565b505050505050565b600086815261013660205260409020600a81015473ffffffffffffffffffffffffffffffffffffffff16156119665760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b600061197482888886613a74565b60048301549091506000805b88811015611b1d5760006119ae8c8a8a8581811061112c57634e487b7160e01b600052603260045260246000fd5b905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26323b872dd82308c8c878181106119ec57634e487b7160e01b600052603260045260246000fd5b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b16815273ffffffffffffffffffffffffffffffffffffffff958616600482015294909316602485015250602090910201356044820152606401602060405180830381600087803b158015611a6857600080fd5b505af1158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa091906157ed565b50888883818110611ac157634e487b7160e01b600052603260045260246000fd5b9050602002013583611ad39190615bfe565b9250888883818110611af557634e487b7160e01b600052603260045260246000fd5b9050602002013584611b079190615bfe565b9350508080611b1590615ceb565b915050611980565b506040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810182905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b158015611b8457600080fd5b505af1158015611b98573d6000803e3d6000fd5b505050506004840182905560405173ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083906000818181858888f193505050501580156117b7573d6000803e3d6000fd5b611bee612b75565b6101348190556040518181527f26d6292d6fb0e786778ddcd15ee4e4ee219a7b892d1bf667e1c497c85bbcddcb9060200161086b565b60008181526101366020526040902060010154819042118015611c5857506000818152610136602052604090206002015442105b611ca45760405162461bcd60e51b815260206004820152600260248201527f313900000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60026035541415611cf75760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106b9565b600260358190556000838152610136602090815260408083206101378352928190208151606081018352815473ffffffffffffffffffffffffffffffffffffffff908116825260018301549482019490945294015490840152600a8201549192911615611da65760405162461bcd60e51b815260206004820152600160248201527f330000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b8051349073ffffffffffffffffffffffffffffffffffffffff16331415611ddd576020820151611dd69082615bfe565b9050611def565b611def826000015183602001516143e2565b600b830154600d84015473ffffffffffffffffffffffffffffffffffffffff90911690338214801590611e2157508015155b15611e3d57611e3082826143e2565b611e3a8184615c73565b92505b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e9957600080fd5b505af1158015611ead573d6000803e3d6000fd5b505050506005860154905060005b818110156120e6576000876005018281548110611ee857634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690503381146120d3576000611fb6896006018481548110611f3b57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548a6007018581548110611f6957634e487b7160e01b600052603260045260246000fd5b90600052602060002001548b6008018681548110611f9757634e487b7160e01b600052603260045260246000fd5b90600052602060002001548c60010154611fb19190615c73565b61466b565b9050611fc28188615c73565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905290975073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29063a9059cbb90604401602060405180830381600087803b15801561204757600080fd5b505af115801561205b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207f91906157ed565b508173ffffffffffffffffffffffffffffffffffffffff168b7f8443e4accb3d433827f4c371ddc39a1d28200f88dc619d5c54214cd5a3678e35836040516120c991815260200190565b60405180910390a3505b50806120de81615ceb565b915050611ebb565b506120f188336146c5565b60405188907ffdbd78280a858f138c490eae641a1da4e1e20547975de5d7c93d9be654d5194c90600090a250506001603555505050505050565b6000818152610136602052604090206001015481904211801561215f57506000818152610136602052604090206002015442105b6121ab5760405162461bcd60e51b815260206004820152600260248201527f313900000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6000828152610137602090815260408083208151606081018352815473ffffffffffffffffffffffffffffffffffffffff9081168252600183015482860152600290920154818401528685526101369093529220600a8101549192909116806122565760405162461bcd60e51b815260206004820152600160248201527f340000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b825173ffffffffffffffffffffffffffffffffffffffff161561229b578251602084015161229b9173ffffffffffffffffffffffffffffffffffffffff841691614615565b600b820154600d83015473ffffffffffffffffffffffffffffffffffffffff909116903382148015906122cd57508015155b156122f4576122f473ffffffffffffffffffffffffffffffffffffffff8416338484614001565b600584015460005b8181101561247c57600086600501828154811061232957634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690503381146124695760006123f288600601848154811061237c57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548960070185815481106123aa57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548a60080186815481106123d857634e487b7160e01b600052603260045260246000fd5b90600052602060002001548b60010154611fb19190615c73565b905061241673ffffffffffffffffffffffffffffffffffffffff8816338484614001565b8173ffffffffffffffffffffffffffffffffffffffff168b7f8443e4accb3d433827f4c371ddc39a1d28200f88dc619d5c54214cd5a3678e358360405161245f91815260200190565b60405180910390a3505b508061247481615ceb565b9150506122fc565b5061248788336146c5565b60405188907ffdbd78280a858f138c490eae641a1da4e1e20547975de5d7c93d9be654d5194c90600090a25050505050505050565b6124c4612b75565b61013080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d19060200161086b565b60008360011461258a5760405162461bcd60e51b815260206004820152600160248201527f320000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b61013980546040805160208082018a90523382840152606080830185905283518084039091018152608090920190925280519101209160006125cb83615ceb565b90915550600090506125ed6125e2858701876158e8565b83898c336001612bdc565b6040517ff242432a00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152604481018990526001606482015260a06084820152600060a4820152909150339063f242432a9060c401600060405180830381600087803b15801561267957600080fd5b505af115801561268d573d6000803e3d6000fd5b507ff23a6e61000000000000000000000000000000000000000000000000000000009c9b505050505050505050505050565b6126c7612b75565b73ffffffffffffffffffffffffffffffffffffffff81166127505760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106b9565b6107f081614492565b6000828152610136602052604090206005810154806127ba5760405162461bcd60e51b815260206004820152600260248201527f313700000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b4282600201541061280d5760405162461bcd60e51b815260206004820152600260248201527f313800000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6000848152610137602090815260408083208151606081018352815473ffffffffffffffffffffffffffffffffffffffff1681526001820154938101939093526002015490820152905b82811015612a7657600084600501828154811061288457634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169050338114612a6357600061294d8660060184815481106128d757634e487b7160e01b600052603260045260246000fd5b906000526020600020015487600701858154811061290557634e487b7160e01b600052603260045260246000fd5b906000526020600020015488600801868154811061293357634e487b7160e01b600052603260045260246000fd5b90600052602060002001548960010154611fb19190615c73565b9050808460200151116129de5760208401516129829073ffffffffffffffffffffffffffffffffffffffff8916908490614615565b6000602085810182905260405191825273ffffffffffffffffffffffffffffffffffffffff8416918a917f8443e4accb3d433827f4c371ddc39a1d28200f88dc619d5c54214cd5a3678e35910160405180910390a35050612a76565b6129ff73ffffffffffffffffffffffffffffffffffffffff88168383614615565b8084602001818151612a119190615c73565b90525060405181815273ffffffffffffffffffffffffffffffffffffffff83169089907f8443e4accb3d433827f4c371ddc39a1d28200f88dc619d5c54214cd5a3678e359060200160405180910390a3505b5080612a6e81615ceb565b915050612857565b50602081015115612ab057600b8301546020820151612ab09173ffffffffffffffffffffffffffffffffffffffff87811692911690614615565b805160009073ffffffffffffffffffffffffffffffffffffffff1615612ad7578151612b1e565b83600501600081548110612afb57634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff165b9050612b2a86826146c5565b60405173ffffffffffffffffffffffffffffffffffffffff82169087907f14ddbb54b023fe50b4afefb9dd4d86d569714bede3c600ce529266a57321fbf290600090a3505050505050565b60995473ffffffffffffffffffffffffffffffffffffffff1633146114a35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106b9565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152610135602052604081205490911680612d095761012f546040517fb054a9e800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301529091169063b054a9e890602401602060405180830381600087803b158015612c7a57600080fd5b505af1158015612c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb29190615626565b73ffffffffffffffffffffffffffffffffffffffff86811660009081526101356020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691831691909117905590505b604051806101e0016040528089604001518152602001600081526020016000815260200187815260200160008152602001600067ffffffffffffffff811115612d6257634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612d8b578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612dbc578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612ded578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612e1e578160200160208202803683370190505b5081526020018573ffffffffffffffffffffffffffffffffffffffff168152602001896060015173ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001846001811115612ebf57634e487b7160e01b600052602160045260246000fd5b90526000888152610136602090815260409182902083518155838201516001820155918301516002830155606083015160038301556080830151600483015560a08301518051612f159260058501920190615479565b5060c08201518051612f31916006840191602090910190615503565b5060e08201518051612f4d916007840191602090910190615503565b506101008201518051612f6a916008840191602090910190615503565b5061012082015160098201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617909155610140840151600a84018054918416918316919091179055610160840151600b84018054918416918316919091179055610180840151600c840180549190931691161790556101a0820151600d8201556101c0820151600e820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001838181111561305657634e487b7160e01b600052602160045260246000fd5b02179055505088516020808b01516040808d01516060808f0151835173ffffffffffffffffffffffffffffffffffffffff8d811682529681018f90528085019790975290860193909352608085015290821660a084015251908816925089917f244a0d71f327a5b72e6d2f41c1359e43a93410edf36b3812ed72dfffff9f2285919081900360c00190a3979650505050505050565b600084815261013660205260409020600b81015473ffffffffffffffffffffffffffffffffffffffff166131615760405162461bcd60e51b815260206004820152600260248201527f313300000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b806001015442106131b45760405162461bcd60e51b815260206004820152600260248201527f313400000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b805484906000906131c790600290615c16565b60058401549091505b80156135e0576000600685016131e7600184615c73565b8154811061320557634e487b7160e01b600052603260045260246000fd5b6000918252602082200154915060088601613221600185615c73565b8154811061323f57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154426132559190615c73565b905060008482116132665784613268565b815b90506000806132b78560078b0161328060018a615c73565b8154811061329e57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154856101325461013354614838565b9092509050600060058a016132cd600189615c73565b815481106132eb57634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690508161331a8488615bfe565b6133249190615bfe565b8910156133d2576133758960078c0161333e60018b615c73565b8154811061335c57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548661013254610133546148bc565b919750935091508560068b0161338c60018a615c73565b815481106133aa57634e487b7160e01b600052603260045260246000fd5b9060005260206000200160008282546133c39190615c73565b90915550600197506134ea9050565b816133dd8488615bfe565b6133e79190615bfe565b891415613470578960050180548061340f57634e487b7160e01b600052603160045260246000fd5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055600196506134ea565b8960050180548061349157634e487b7160e01b600052603160045260246000fd5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555b6135208b826134f9868a615bfe565b8f73ffffffffffffffffffffffffffffffffffffffff16614001909392919063ffffffff16565b6101305461354a9073ffffffffffffffffffffffffffffffffffffffff8e8116918e911685614001565b816135558488615bfe565b61355f9190615bfe565b613569908a615c73565b604080518881526020810186905290810184905290995073ffffffffffffffffffffffffffffffffffffffff8216908f907f1925feae58cf7aa6a70574859aab697cc68351d62dc2d3583f9c12c69453497d9060600160405180910390a350505050505080806135d890615cb6565b9150506131d0565b5060058301546137165760098301546003840154600c850154600b860154600e87015461362e9473ffffffffffffffffffffffffffffffffffffffff9081169493811692169060ff16613739565b600087815261013660205260408120818155600181018290556002810182905560038101829055600481018290559061366a600583018261545b565b61367860068301600061545b565b61368660078301600061545b565b61369460088301600061545b565b506009810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600a8201805482169055600b8201805482169055600c8201805490911690556000600d820155600e0180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055613730565b8583600d01600082825461372a9190615bfe565b90915550505b50505050505050565b600081600181111561375b57634e487b7160e01b600052602160045260246000fd5b14156137f6576040517f1aca637600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152868116602483015260448201869052841690631aca637690606401600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b5050505061148a565b6040517fb686fdba00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015286811660248301526044820186905284169063b686fdba90606401600060405180830381600087803b15801561386e57600080fd5b505af1158015613882573d6000803e3d6000fd5b505050505050505050565b6107f0612b75565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156138cd576138c8836149ad565b505050565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561391357600080fd5b505afa925050508015613961575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261395e9181019061580d565b60015b6139d35760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f74205555505300000000000000000000000000000000000060648201526084016106b9565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114613a685760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c6555554944000000000000000000000000000000000000000000000060648201526084016106b9565b506138c8838383614a9d565b600b84015460009073ffffffffffffffffffffffffffffffffffffffff16338114613ae15760405162461bcd60e51b815260206004820152600160248201527f360000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6005860154613b1d578554600090613afa904290615bfe565b6001880181905561013454909150613b129082615bfe565b600288015550613b70565b85600101544210613b705760405162461bcd60e51b815260206004820152600260248201527f313400000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b604051600090613b899085359088908890602001615b22565b6040516020818303038152906040528051906020012090506000613bfa826040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b90506000613c2182613c126040890160208a01615a9b565b88604001358960600135614ac2565b6101315490915073ffffffffffffffffffffffffffffffffffffffff808316911614613c8f5760405162461bcd60e51b815260206004820152600160248201527f370000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b8535421115613ce05760405162461bcd60e51b815260206004820152600160248201527f380000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b5091979650505050505050565b60008160600135841115613d435760405162461bcd60e51b815260206004820152600160248201527f390000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60a0820135613d528486615bfe565b1115613da05760405162461bcd60e51b815260206004820152600260248201527f313000000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b604080517fefe3f0a82f9122f279a2f7e34b471ab3d790d96e2e32cce338bff6c94cad82726020820152908101869052606080840135908201526080808401359082015260a0808401359082015260c0808401359082015260009060e0016040516020818303038152906040528051906020012090506000613e2182614aea565b90506000613e4582613e396060880160408901615a9b565b87356020890135614ac2565b60008981526101386020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205490915060c086013514613ecb5760405162461bcd60e51b815260206004820152600260248201527f313100000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b60008881526101386020908152604080832073ffffffffffffffffffffffffffffffffffffffff851684529091528120805491613f0783615ceb565b909155505060008881526101366020908152604080832060068101805460018082018355918652848620018c905560058201805480830182559086528486200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8816908117909155600783018054808401825590875285872060808d013591018190556008909301805492830181558652948490204291015581519384529183018a905282015288907f337ac6ceecf7ab68028cc68df243cdc6988d3583aafdf19844cb526c4316a2799060600160405180910390a2979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526140dd9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614b59565b50505050565b600083815261013660209081526040808320610137909252909120600181018490556005820154831461431c5781600501838154811061413357634e487b7160e01b600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633146141a35760405162461bcd60e51b815260206004820152600260248201527f313500000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6000805b848110156142695761424b8460060182815481106141d557634e487b7160e01b600052603260045260246000fd5b906000526020600020015485600701838154811061420357634e487b7160e01b600052603260045260246000fd5b906000526020600020015486600801848154811061423157634e487b7160e01b600052603260045260246000fd5b90600052602060002001548760010154611fb19190615c73565b6142559083615bfe565b91508061426181615ceb565b9150506141a7565b5080851061431a5761430d83600601858154811061429757634e487b7160e01b600052603260045260246000fd5b90600052602060002001548460070186815481106142c557634e487b7160e01b600052603260045260246000fd5b90600052602060002001548560080187815481106142f357634e487b7160e01b600052603260045260246000fd5b90600052602060002001548660010154611fb19190615c73565b6143179086615bfe565b94505b505b8381600201541061436f5760405162461bcd60e51b815260206004820152600260248201527f313600000000000000000000000000000000000000000000000000000000000060448201526064016106b9565b6002810184905580547fffffffffffffffffffffffff000000000000000000000000000000000000000016339081178255604080518681526020810186905287917f476bd0783cc4e83d617258e2b86038c40cb0dba0cca615fcc28e7ccb3d66cbed910160405180910390a35050505050565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461443c576040519150601f19603f3d011682016040523d82523d6000602084013e614441565b606091505b50509050806138c8576101305460405173ffffffffffffffffffffffffffffffffffffffff9091169083156108fc029084906000818181858888f193505050501580156140dd573d6000803e3d6000fd5b6099805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166145865760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106b9565b6106cc8282614c4b565b600054610100900460ff1661460d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106b9565b6114a3614ce2565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526138c89084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161405b565b6000614679610e1083615c16565b61468590610e10615c36565b9150600064496cebb8008361469a8688615c36565b6146a49190615c36565b6146ae9190615c16565b90506146ba8186615bfe565b9150505b9392505050565b60008281526101366020526040902060098101546003820154600c830154600e909301546147129373ffffffffffffffffffffffffffffffffffffffff938416931690859060ff16613739565b60008281526101376020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018082018590556002918201859055610136909352908320838155918201839055810182905560038101829055600481018290559061478d600583018261545b565b61479b60068301600061545b565b6147a960078301600061545b565b6147b760088301600061545b565b506009810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600a8201805482169055600b8201805482169055600c8201805490911690556000600d820155600e0180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555050565b600080614847610e1086615c16565b61485390610e10615c36565b9450600064496cebb80086614868898b615c36565b6148729190615c36565b61487c9190615c16565b905060008461488b8784615c36565b6148959190615c16565b90506148a18183615c73565b6148ac826002615c36565b9350935050509550959350505050565b60008080806148cb858a615c36565b6148da9064496cebb800615c36565b905060006148e88688615bfe565b6148f28a8a615c36565b6148fc9190615c36565b61490b8764496cebb800615c36565b6149159190615bfe565b905060006149238284615c16565b9050614931610e108a615c16565b61493d90610e10615c36565b9850600064496cebb8008a6149528d85615c36565b61495c9190615c36565b6149669190615c16565b90506000886149758b84615c36565b61497f9190615c16565b90508261498c8284615c73565b614997836002615c36565b9750975097505050505050955095509592505050565b73ffffffffffffffffffffffffffffffffffffffff81163b614a375760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e74726163740000000000000000000000000000000000000060648201526084016106b9565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b614aa683614d68565b600082511180614ab35750805b156138c8576140dd8383614db5565b6000806000614ad387878787614eda565b91509150614ae081614ff2565b5095945050505050565b6000614b53614af7615229565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b92915050565b6000614bbb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166152a99092919063ffffffff16565b8051909150156138c85780806020019051810190614bd991906157ed565b6138c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106b9565b600054610100900460ff16614cc85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106b9565b815160209283012081519190920120600191909155600255565b600054610100900460ff16614d5f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106b9565b6114a333614492565b614d71816149ad565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606073ffffffffffffffffffffffffffffffffffffffff83163b614e415760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084016106b9565b6000808473ffffffffffffffffffffffffffffffffffffffff1684604051614e699190615ab5565b600060405180830381855af49150503d8060008114614ea4576040519150601f19603f3d011682016040523d82523d6000602084013e614ea9565b606091505b5091509150614ed18282604051806060016040528060278152602001615d73602791396152c0565b95945050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115614f115750600090506003614fe9565b8460ff16601b14158015614f2957508460ff16601c14155b15614f3a5750600090506004614fe9565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614f8e573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116614fe257600060019250925050614fe9565b9150600090505b94509492505050565b600081600481111561501457634e487b7160e01b600052602160045260246000fd5b141561501d5750565b600181600481111561503f57634e487b7160e01b600052602160045260246000fd5b141561508d5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016106b9565b60028160048111156150af57634e487b7160e01b600052602160045260246000fd5b14156150fd5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016106b9565b600381600481111561511f57634e487b7160e01b600052602160045260246000fd5b14156151935760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016106b9565b60048160048111156151b557634e487b7160e01b600052602160045260246000fd5b14156107f05760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016106b9565b60006152a47f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61525860015490565b6002546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b905090565b60606152b884846000856152f9565b949350505050565b606083156152cf5750816146be565b8251156152df5782518084602001fd5b8160405162461bcd60e51b81526004016106b99190615ad1565b6060824710156153715760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016106b9565b73ffffffffffffffffffffffffffffffffffffffff85163b6153d55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106b9565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516153fe9190615ab5565b60006040518083038185875af1925050503d806000811461543b576040519150601f19603f3d011682016040523d82523d6000602084013e615440565b606091505b50915091506154508282866152c0565b979650505050505050565b50805460008255906000526020600020908101906107f0919061553e565b8280548282559060005260206000209081019282156154f3579160200282015b828111156154f357825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190615499565b506154ff92915061553e565b5090565b8280548282559060005260206000209081019282156154f3579160200282015b828111156154f3578251825591602001919060010190615523565b5b808211156154ff576000815560010161553f565b60008083601f840112615564578182fd5b50813567ffffffffffffffff81111561557b578182fd5b6020830191508360208260051b850101111561559657600080fd5b9250929050565b60008083601f8401126155ae578182fd5b50813567ffffffffffffffff8111156155c5578182fd5b60208301915083602082850101111561559657600080fd5b6000608082840312156155ee578081fd5b50919050565b803560ff8116811461560557600080fd5b919050565b60006020828403121561561b578081fd5b81356146be81615d50565b600060208284031215615637578081fd5b81516146be81615d50565b600080600080600060808688031215615659578081fd5b853561566481615d50565b9450602086013561567481615d50565b935060408601359250606086013567ffffffffffffffff811115615696578182fd5b6156a28882890161559d565b969995985093965092949392505050565b60008060008060008060a087890312156156cb578081fd5b86356156d681615d50565b955060208701356156e681615d50565b94506040870135935060608701359250608087013567ffffffffffffffff81111561570f578182fd5b61571b89828a0161559d565b979a9699509497509295939492505050565b6000806040838503121561573f578182fd5b823561574a81615d50565b915060208381013567ffffffffffffffff80821115615767578384fd5b818601915086601f83011261577a578384fd5b81358181111561578c5761578c615d3a565b6157bc847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601615baf565b915080825287848285010111156157d1578485fd5b8084840185840137810190920192909252919491935090915050565b6000602082840312156157fe578081fd5b815180151581146146be578182fd5b60006020828403121561581e578081fd5b5051919050565b6000806000806000806000806000806101008b8d031215615844578384fd5b8a3567ffffffffffffffff8082111561585b578586fd5b6158678e838f0161559d565b909c509a5060208d013591508082111561587f578586fd5b5061588c8d828e0161559d565b90995097505060408b0135955060608b0135945060808b0135935060a08b01356158b581615d50565b925060c08b01356158c581615d50565b915060e08b01356158d581615d50565b809150509295989b9194979a5092959850565b6000608082840312156158f9578081fd5b6040516080810181811067ffffffffffffffff8211171561591c5761591c615d3a565b8060405250823581526020830135602082015260408301356040820152606083013561594781615d50565b60608201529392505050565b600060208284031215615964578081fd5b5035919050565b6000806040838503121561597d578182fd5b82359150602083013561598f81615d50565b809150509250929050565b60008060008060008060e087890312156159b2578384fd5b86359550602087013567ffffffffffffffff808211156159d0578586fd5b818901915089601f8301126159e3578586fd5b8135818111156159f1578687fd5b8a602060e083028501011115615a05578687fd5b602083019750809650506040890135915080821115615a22578384fd5b50615a2f89828a01615553565b9094509250615a43905088606089016155dd565b90509295509295509295565b60008060408385031215615a61578182fd5b50508035926020909101359150565b600080600060608486031215615a84578081fd5b505081359360208301359350604090920135919050565b600060208284031215615aac578081fd5b6146be826155f4565b60008251615ac7818460208701615c8a565b9190910192915050565b6020815260008251806020840152615af0816040850160208701615c8a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b838152604060208083018290528282018490526000919060609081850187855b88811015615ba05781358352838201358484015260ff615b638784016155f4565b168387015281850135858401526080808301359084015260a0808301359084015260c0808301359084015260e09283019290910190600101615b42565b50909998505050505050505050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715615bf657615bf6615d3a565b604052919050565b60008219821115615c1157615c11615d24565b500190565b600082615c3157634e487b7160e01b81526012600452602481fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c6e57615c6e615d24565b500290565b600082821015615c8557615c85615d24565b500390565b60005b83811015615ca5578181015183820152602001615c8d565b838111156140dd5750506000910152565b600081615cc557615cc5615d24565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615d1d57615d1d615d24565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff811681146107f057600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c37cf1022cf4b804ed17a3503023d847e2bff0eceebfaac19ad104fc255be7db64736f6c63430008040033
Deployed Bytecode Sourcemap
90611:37165:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110676:227;;;;;;;;;;-1:-1:-1;110676:227:0;;;;;:::i;:::-;;:::i;:::-;;110211:252;;;;;;;;;;-1:-1:-1;110211:252:0;;;;;:::i;:::-;;:::i;112337:184::-;;;;;;;;;;-1:-1:-1;112337:184:0;;;;;:::i;:::-;;:::i;94346:948::-;;;;;;;;;;-1:-1:-1;94346:948:0;;;;;:::i;:::-;;:::i;:::-;;;15976:66:1;15964:79;;;15946:98;;15934:2;15919:18;94346:948:0;;;;;;;;91693:29;;;;;;;;;;;;;;;;;;;14306:25:1;;;14294:2;14279:18;91693:29:0;14261:76:1;101694:401:0;;;;;;:::i;:::-;;:::i;92313:61::-;;;;;;;;;;-1:-1:-1;92313:61:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;96797:658;;;;;;;;;;-1:-1:-1;96797:658:0;;;;;:::i;:::-;;:::i;91798:28::-;;;;;;;;;;;;;;;;76733:200;;;;;;;;;;-1:-1:-1;76733:200:0;;;;;:::i;:::-;;:::i;91514:40::-;;;;;;;;;;-1:-1:-1;91514:40:0;;;;;;;;;;;11256:42:1;11244:55;;;11226:74;;11214:2;11199:18;91514:40:0;11181:125:1;77192:266:0;;;;;;:::i;:::-;;:::i;100132:1278::-;;;;;;;;;;-1:-1:-1;100132:1278:0;;;;;:::i;:::-;;:::i;76352:192::-;;;;;;;;;;;;;:::i;111556:248::-;;;;;;;;;;-1:-1:-1;111556:248:0;;;;;:::i;:::-;;:::i;103050:566::-;;;;;;:::i;:::-;;:::i;59278:103::-;;;;;;;;;;;;;:::i;111975:186::-;;;;;;;;;;-1:-1:-1;111975:186:0;;;;;:::i;:::-;;:::i;102420:158::-;;;;;;;;;;-1:-1:-1;102420:158:0;;;;;:::i;:::-;;:::i;58630:87::-;;;;;;;;;;-1:-1:-1;58703:6:0;;;;58630:87;;93323:619;;;;;;;;;;-1:-1:-1;93323:619:0;;;;;:::i;:::-;;:::i;104157:805::-;;;;;;;;;;-1:-1:-1;104157:805:0;;;;;:::i;:::-;;:::i;98069:1506::-;;;;;;;;;;-1:-1:-1;98069:1506:0;;;;;:::i;:::-;;:::i;111812:155::-;;;;;;;;;;-1:-1:-1;111812:155:0;;;;;:::i;:::-;;:::i;105381:2140::-;;;;;;:::i;:::-;;:::i;107991:1968::-;;;;;;;;;;-1:-1:-1;107991:1968:0;;;;;:::i;:::-;;:::i;91386:37::-;;;;;;;;;;-1:-1:-1;91386:37:0;;;;;;;;91013:47;;;;;;;;;;-1:-1:-1;91013:47:0;;;;;;;;91659:27;;;;;;;;;;;;;;;;112169:160;;;;;;;;;;-1:-1:-1;112169:160:0;;;;;:::i;:::-;;:::i;95494:1076::-;;;;;;;;;;-1:-1:-1;95494:1076:0;;;;;:::i;:::-;;:::i;59536:238::-;;;;;;;;;;-1:-1:-1;59536:238:0;;;;;:::i;:::-;;:::i;110676:227::-;110753:16;110772;;;:5;:16;;;;;:25;;;;;110818:22;110810:36;;;;-1:-1:-1;;;110810:36:0;;17516:2:1;110810:36:0;;;17498:21:1;17555:1;17535:18;;;17528:29;17593:3;17573:18;;;17566:31;17614:18;;110810:36:0;;;;;;;;;110859;110875:9;110886:8;110859:15;:36::i;:::-;110676:227;;:::o;110211:252::-;110331:1;110294:16;;;:5;:16;;;;;:25;;;:39;:25;:39;110286:53;;;;-1:-1:-1;;;110286:53:0;;19602:2:1;110286:53:0;;;19584:21:1;19641:1;19621:18;;;19614:29;19679:3;19659:18;;;19652:31;19700:18;;110286:53:0;19574:150:1;110286:53:0;110372:19;;;;:8;:19;;;;;;:26;;;110352:49;;;;;;;91265:42;;110352:12;;:49;;;;;;;;;;;110372:26;91265:42;110352:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110414:41;110430:9;91265:42;110414:15;:41::i;:::-;110211:252;:::o;112337:184::-;58516:13;:11;:13::i;:::-;112417:25:::1;:37:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;112470:43:::1;::::0;11226:74:1;;;112470:43:0::1;::::0;11214:2:1;11199:18;112470:43:0::1;;;;;;;;112337:184:::0;:::o;94346:948::-;94688:48;;;;;;;30494:25:1;;;94708:10:0;30535:18:1;;;30528:83;94720:15:0;30627:18:1;;;;30620:34;;;;94688:48:0;;;;;;;;;;30467:18:1;;;;94688:48:0;;;94678:59;;;;;-1:-1:-1;;;94843:213:0;94873:39;;;;;;:::i;:::-;94927:9;94951:7;94973:9;94997:10;95022:23;94843:15;:213::i;:::-;95111:125;;;;;95177:4;95111:125;;;12060:34:1;12009:42;12130:15;;12110:18;;;12103:43;12162:18;;;12155:34;;;94826:230:0;;-1:-1:-1;95130:10:0;;95111:43;;11972:18:1;;95111:125:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;95256:30:0;;94346:948;-1:-1:-1;;;;;;;;;;;94346:948:0:o;101694:401::-;101848:1;101814:13;;;:5;:13;;;;;:22;;;:36;:22;:36;101806:50;;;;-1:-1:-1;;;101806:50:0;;19602:2:1;101806:50:0;;;19584:21:1;19641:1;19621:18;;;19614:29;19679:3;19659:18;;;19652:31;19700:18;;101806:50:0;19574:150:1;101806:50:0;91265:42;101916:12;;;101936:9;101916:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102021:66;102039:6;102047:9;91265:42;102081:4;102021:17;:66::i;96797:658::-;96907:16;;;;:5;:16;;;;;:24;;:31;:36;96899:50;;;;-1:-1:-1;;;96899:50:0;;27813:2:1;96899:50:0;;;27795:21:1;27852:1;27832:18;;;27825:29;27890:3;27870:18;;;27863:31;27911:18;;96899:50:0;27785:150:1;96899:50:0;96998:16;97017;;;:5;:16;;;;;:25;;;;;97061:10;:22;;97053:36;;;;-1:-1:-1;;;97053:36:0;;29294:2:1;97053:36:0;;;29276:21:1;29333:1;29313:18;;;29306:29;29371:3;29351:18;;;29344:31;29392:18;;97053:36:0;29266:150:1;97053:36:0;97180:16;;;;:5;:16;;;;;:29;;;;97224:24;;;;97263:23;;;;97324:31;;;;;97146:220;;97180:29;;;;;97263:23;;97301:8;;97324:31;;97146:19;:220::i;:::-;97386:16;;;;:5;:16;;;;;97379:23;;;;;;;;;;;;;;;;;;;;;;;;;;;97386:16;97379:23;;;;97386:16;97379:23;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;-1:-1:-1;97379:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97420:27;;97437:9;;97420:27;;;96797:658;;:::o;76733:200::-;75118:4;75110:23;75127:6;75110:23;;;75088:117;;;;-1:-1:-1;;;75088:117:0;;19931:2:1;75088:117:0;;;19913:21:1;19970:2;19950:18;;;19943:30;20009:34;19989:18;;;19982:62;20080:14;20060:18;;;20053:42;20112:19;;75088:117:0;19903:234:1;75088:117:0;75262:6;75238:30;;:20;66054:66;66428:65;;;;66335:166;75238:20;:30;;;75216:124;;;;-1:-1:-1;;;75216:124:0;;21076:2:1;75216:124:0;;;21058:21:1;21115:2;21095:18;;;21088:30;21154:34;21134:18;;;21127:62;21225:14;21205:18;;;21198:42;21257:19;;75216:124:0;21048:234:1;75216:124:0;76817:36:::1;76835:17;76817;:36::i;:::-;76905:12;::::0;;76915:1:::1;76905:12:::0;;;::::1;::::0;::::1;::::0;;;76864:61:::1;::::0;76886:17;;76905:12;76864:21:::1;:61::i;77192:266::-:0;75118:4;75110:23;75127:6;75110:23;;;75088:117;;;;-1:-1:-1;;;75088:117:0;;19931:2:1;75088:117:0;;;19913:21:1;19970:2;19950:18;;;19943:30;20009:34;19989:18;;;19982:62;20080:14;20060:18;;;20053:42;20112:19;;75088:117:0;19903:234:1;75088:117:0;75262:6;75238:30;;:20;66054:66;66428:65;;;;66335:166;75238:20;:30;;;75216:124;;;;-1:-1:-1;;;75216:124:0;;21076:2:1;75216:124:0;;;21058:21:1;21115:2;21095:18;;;21088:30;21154:34;21134:18;;;21127:62;21225:14;21205:18;;;21198:42;21257:19;;75216:124:0;21048:234:1;75216:124:0;77351:36:::1;77369:17;77351;:36::i;:::-;77398:52;77420:17;77439:4;77445;77398:21;:52::i;100132:1278::-:0;100378:23;100404:9;;;:5;:9;;;;;100434:13;;;;:27;:13;100426:41;;;;-1:-1:-1;;;100426:41:0;;17516:2:1;100426:41:0;;;17498:21:1;17555:1;17535:18;;;17528:29;17593:3;17573:18;;;17566:31;17614:18;;100426:41:0;17488:150:1;100426:41:0;100480:16;100499:115;100531:4;100550:17;;100582:21;100499:17;:115::i;:::-;100695:14;;;;100741:13;;;;100480:134;;-1:-1:-1;100695:14:0;100741:13;;100675:17;100820:495;100840:28;;;100820:495;;;100890:14;100907:156;100950:2;100971:7;;100979:1;100971:10;;;;;-1:-1:-1;;;100971:10:0;;;;;;;;;;;;;;;101000:9;101028:17;;101046:1;101028:20;;;;;-1:-1:-1;;;101028:20:0;;;;;;;;;;;;;;100907:24;:156::i;:::-;100890:173;;101123:140;101186:6;101211:8;101238:7;;101246:1;101238:10;;;;;-1:-1:-1;;;101238:10:0;;;;;;;;;;;;;;;101141:8;101123:44;;;;:140;;;;;;:::i;:::-;101293:7;;101301:1;101293:10;;;;;-1:-1:-1;;;101293:10:0;;;;;;;;;;;;;;;101280:23;;;;;:::i;:::-;;;100820:495;100870:3;;;;;:::i;:::-;;;;100820:495;;;-1:-1:-1;;101376:14:0;;;;:26;;;;-1:-1:-1;;;;;;;100132:1278:0:o;76352:192::-;76484:7;75637:4;75629:23;75646:6;75629:23;;75607:129;;;;-1:-1:-1;;;75607:129:0;;22226:2:1;75607:129:0;;;22208:21:1;22265:2;22245:18;;;22238:30;22304:34;22284:18;;;22277:62;22375:26;22355:18;;;22348:54;22419:19;;75607:129:0;22198:246:1;75607:129:0;-1:-1:-1;66054:66:0::1;76352:192:::0;:::o;111556:248::-;58516:13;:11;:13::i;:::-;111683:12:::1;:24:::0;;;111718:14:::1;:28:::0;;;111762:34:::1;::::0;;32141:25:1;;;32197:2;32182:18;;32175:34;;;111762::0::1;::::0;32114:18:1;111762:34:0::1;;;;;;;111556:248:::0;;:::o;103050:566::-;92910:16;;;;:5;:16;;;;;:20;;;103180:9;;92892:15;:38;:104;;;;-1:-1:-1;92969:16:0;;;;:5;:16;;;;;:27;;;92951:15;:45;92892:104;92870:156;;;;-1:-1:-1;;;92870:156:0;;25614:2:1;92870:156:0;;;25596:21:1;25653:1;25633:18;;;25626:29;25691:4;25671:18;;;25664:32;25713:18;;92870:156:0;25586:151:1;92870:156:0;103252:1:::1;103215:16:::0;;;:5:::1;:16;::::0;;;;:25:::1;;::::0;:39:::1;:25;:39:::0;103207:53:::1;;;::::0;-1:-1:-1;;;103207:53:0;;19602:2:1;103207:53:0::1;::::0;::::1;19584:21:1::0;19641:1;19621:18;;;19614:29;19679:3;19659:18;;;19652:31;19700:18;;103207:53:0::1;19574:150:1::0;103207:53:0::1;103273:22;103298:19:::0;;;:8:::1;:19;::::0;;;;:26;;;103360;;::::1;::::0;103298::::1;::::0;;::::1;::::0;103399:40:::1;103307:9:::0;103422::::1;103433:5:::0;103399:11:::1;:40::i;:::-;103500:28;::::0;::::1;::::0;103496:113:::1;;103545:52;103566:14;103582;103545:20;:52::i;:::-;93037:1;;103050:566:::0;;;:::o;59278:103::-;58516:13;:11;:13::i;:::-;59343:30:::1;59370:1;59343:18;:30::i;:::-;59278:103::o:0;111975:186::-;58516:13;:11;:13::i;:::-;112057:19:::1;:51:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;112124:29:::1;::::0;11226:74:1;;;112124:29:0::1;::::0;11214:2:1;11199:18;112124:29:0::1;11181:125:1::0;102420:158:0;102535:13;;;;:5;:13;;;;;:22;;;102501:69;;102519:6;;102527;;102535:22;;102559:10;102501:17;:69::i;93323:619::-;44254:19;44277:13;;;;;;44276:14;;44324:34;;;;-1:-1:-1;44342:12:0;;44357:1;44342:12;;;;:16;44324:34;44323:146;;;-1:-1:-1;44420:4:0;17448:19;:23;;;44381:87;;-1:-1:-1;44451:12:0;;;;;:17;44381:87;44301:242;;;;-1:-1:-1;;;44301:242:0;;23721:2:1;44301:242:0;;;23703:21:1;23760:2;23740:18;;;23733:30;23799:34;23779:18;;;23772:62;23870:16;23850:18;;;23843:44;23904:19;;44301:242:0;23693:236:1;44301:242:0;44554:12;:16;;;;44569:1;44554:16;;;44581:67;;;;44616:13;:20;;;;;;;;44581:67;93626:28:::1;93640:4;;93626:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;93626:28:0::1;::::0;;::::1;;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;-1:-1:-1;93646:7:0;;-1:-1:-1;93646:7:0;;;;93626:28;::::1;93646:7:::0;;;;93626:28;::::1;;::::0;::::1;::::0;;;;-1:-1:-1;93626:13:0::1;::::0;-1:-1:-1;;;93626:28:0:i:1;:::-;93665:16;:14;:16::i;:::-;93692:12;:24:::0;;;93727:14:::1;:28:::0;;;93766:13:::1;:22:::0;;;93799:19:::1;:51:::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;93861:14:::1;:25:::0;;;;::::1;::::0;;::::1;;::::0;;93897::::1;:37:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;44670:102;;;;44721:5;44705:21;;;;;;44746:14;;-1:-1:-1;16467:36:1;;44746:14:0;;16455:2:1;16440:18;44746:14:0;;;;;;;44670:102;93323:619;;;;;;;;;;;:::o;104157:805::-;92910:16;;;;:5;:16;;;;;:20;;;104295:9;;92892:15;:38;:104;;;;-1:-1:-1;92969:16:0;;;;:5;:16;;;;;:27;;;92951:15;:45;92892:104;92870:156;;;;-1:-1:-1;;;92870:156:0;;25614:2:1;92870:156:0;;;25596:21:1;25653:1;25633:18;;;25626:29;25691:4;25671:18;;;25664:32;25713:18;;92870:156:0;25586:151:1;92870:156:0;104317:16:::1;104336::::0;;;:5:::1;:16;::::0;;;;;;;:25:::1;;::::0;104389:8:::1;:19:::0;;;;;;:26;104336:25:::1;::::0;;::::1;::::0;104389:26:::1;104476:20:::0;;104472:178:::1;;104597:19;::::0;;;:8:::1;:19;::::0;;;;:26:::1;;::::0;104513:125:::1;::::0;:40:::1;::::0;::::1;::::0;104572:6;;104513:40:::1;:125::i;:::-;104775:129;:44;::::0;::::1;104834:10;104867:4;104887:6:::0;104775:44:::1;:129::i;:::-;104917:37;104929:9;104940:6;104948:5;104917:11;:37::i;:::-;93037:1;;104157:805:::0;;;;:::o;98069:1506::-;98313:23;98339:9;;;:5;:9;;;;;98369:13;;;;:27;:13;:27;98361:41;;;;-1:-1:-1;;;98361:41:0;;19602:2:1;98361:41:0;;;19584:21:1;19641:1;19621:18;;;19614:29;19679:3;19659:18;;;19652:31;19700:18;;98361:41:0;19574:150:1;98361:41:0;98415:16;98434:115;98466:4;98485:17;;98517:21;98434:17;:115::i;:::-;98661:14;;;;98415:134;;-1:-1:-1;98641:17:0;;98822:482;98842:28;;;98822:482;;;98892:14;98909:156;98952:2;98973:7;;98981:1;98973:10;;;;;-1:-1:-1;;;98973:10:0;;;;;;;;98909:156;98892:173;-1:-1:-1;91265:42:0;99124:17;98892:173;99158:4;99165:7;;99173:1;99165:10;;;;;-1:-1:-1;;;99165:10:0;;;;;;;;;99124:52;;;;;;;;;;12009:42:1;12078:15;;;99124:52:0;;;12060:34:1;12130:15;;;;12110:18;;;12103:43;-1:-1:-1;99165:10:0;;;;;;12162:18:1;;;12155:34;11972:18;;99124:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;99244:7;;99252:1;99244:10;;;;;-1:-1:-1;;;99244:10:0;;;;;;;;;;;;;;;99235:19;;;;;:::i;:::-;;;99282:7;;99290:1;99282:10;;;;;-1:-1:-1;;;99282:10:0;;;;;;;;;;;;;;;99269:23;;;;;:::i;:::-;;;98822:482;98872:3;;;;;:::i;:::-;;;;98822:482;;;-1:-1:-1;99361:20:0;;;;;;;;14306:25:1;;;91265:42:0;;99361:13;;14279:18:1;;99361:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;99434:14:0;;;:26;;;99534:33;;:26;;;;:33;;;;;99561:5;;99534:33;;;;99561:5;99534:26;:33;;;;;;;;;;;;;;;;;;;111812:155;58516:13;:11;:13::i;:::-;111893::::1;:22:::0;;;111931:28:::1;::::0;14306:25:1;;;111931:28:0::1;::::0;14294:2:1;14279:18;111931:28:0::1;14261:76:1::0;105381:2140:0;92910:16;;;;:5;:16;;;;;:20;;;105501:9;;92892:15;:38;:104;;;;-1:-1:-1;92969:16:0;;;;:5;:16;;;;;:27;;;92951:15;:45;92892:104;92870:156;;;;-1:-1:-1;;;92870:156:0;;25614:2:1;92870:156:0;;;25596:21:1;25653:1;25633:18;;;25626:29;25691:4;25671:18;;;25664:32;25713:18;;92870:156:0;25586:151:1;92870:156:0;54353:1:::1;55128:7;;:19;;55120:63;;;::::0;-1:-1:-1;;;55120:63:0;;29952:2:1;55120:63:0::1;::::0;::::1;29934:21:1::0;29991:2;29971:18;;;29964:30;30030:33;30010:18;;;30003:61;30081:18;;55120:63:0::1;29924:181:1::0;55120:63:0::1;54353:1;55261:7;:18:::0;;;105550:23:::2;105576:16:::0;;;:5:::2;:16;::::0;;;;;;;105634:8:::2;:19:::0;;;;;;105603:50;;::::2;::::0;::::2;::::0;;;;::::2;::::0;;::::2;::::0;;;;::::2;::::0;;;::::2;::::0;;;;;::::2;::::0;;;;;105674:13:::2;::::0;::::2;::::0;105576:16;;105603:50;105674:13:::2;:27:::0;105666:41:::2;;;::::0;-1:-1:-1;;;105666:41:0;;19602:2:1;105666:41:0::2;::::0;::::2;19584:21:1::0;19641:1;19621:18;;;19614:29;19679:3;19659:18;;;19652:31;19700:18;;105666:41:0::2;19574:150:1::0;105666:41:0::2;105861:14:::0;;105821:9:::2;::::0;105847:28:::2;;:10;:28;105843:290;;;105980:14;::::0;::::2;::::0;105962:32:::2;::::0;;::::2;:::i;:::-;;;105843:290;;;106069:52;106090:7;:14;;;106106:7;:14;;;106069:20;:52::i;:::-;106164:13;::::0;::::2;::::0;106208:14:::2;::::0;::::2;::::0;106164:13:::2;::::0;;::::2;::::0;106251:10:::2;106239:22:::0;::::2;::::0;::::2;::::0;:40:::2;;-1:-1:-1::0;106265:14:0;;::::2;106239:40;106235:243;;;106342:41;106363:8;106373:9;106342:20;:41::i;:::-;106439:27;106457:9:::0;106439:27;::::2;:::i;:::-;;;106235:243;91265:42;106556:12;;;106576:14;106556:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;;;106632:12:0::2;::::0;::::2;:19:::0;;-1:-1:-1;106606:23:0::2;106664:758;106688:15;106684:1;:19;106664:758;;;106725:14;106742:4;:12;;106755:1;106742:15;;;;;;-1:-1:-1::0;;;106742:15:0::2;;;;;;;;;;::::0;;;::::2;::::0;;;::::2;::::0;::::2;;::::0;-1:-1:-1;106844:10:0::2;106834:20:::0;::::2;106830:581;;106926:12;106941:174;106991:4;:15;;107007:1;106991:18;;;;;;-1:-1:-1::0;;;106991:18:0::2;;;;;;;;;;;;;;;;;107032:4;:9;;107042:1;107032:12;;;;;;-1:-1:-1::0;;;107032:12:0::2;;;;;;;;;;;;;;;;;107078:4;:15;;107094:1;107078:18;;;;;;-1:-1:-1::0;;;107078:18:0::2;;;;;;;;;;;;;;;;;107067:4;:8;;;:29;;;;:::i;:::-;106941:27;:174::i;:::-;106926:189:::0;-1:-1:-1;107217:22:0::2;106926:189:::0;107217:22;::::2;:::i;:::-;107297:27;::::0;;;;13070:42:1;13058:55;;107297:27:0::2;::::0;::::2;13040:74:1::0;13130:18;;;13123:34;;;107217:22:0;;-1:-1:-1;91265:42:0::2;::::0;107297:13:::2;::::0;13013:18:1;;107297:27:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;107382:6;107350:45;;107371:9;107350:45;107390:4;107350:45;;;;14306:25:1::0;;14294:2;14279:18;;14261:76;107350:45:0::2;;;;;;;;106830:581;;-1:-1:-1::0;106705:3:0;::::2;::::0;::::2;:::i;:::-;;;;106664:758;;;;107434:38;107450:9;107461:10;107434:15;:38::i;:::-;107490:23;::::0;107503:9;;107490:23:::2;::::0;;;::::2;-1:-1:-1::0;;54309:1:0::1;55440:7;:22:::0;-1:-1:-1;;;;;;105381:2140:0:o;107991:1968::-;92910:16;;;;:5;:16;;;;;:20;;;108096:9;;92892:15;:38;:104;;;;-1:-1:-1;92969:16:0;;;;:5;:16;;;;;:27;;;92951:15;:45;92892:104;92870:156;;;;-1:-1:-1;;;92870:156:0;;25614:2:1;92870:156:0;;;25596:21:1;25653:1;25633:18;;;25626:29;25691:4;25671:18;;;25664:32;25713:18;;92870:156:0;25586:151:1;92870:156:0;108123:28:::1;108154:19:::0;;;:8:::1;:19;::::0;;;;;;;108123:50;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;108210:16;;;:5:::1;:16:::0;;;;;108258:13:::1;::::0;::::1;::::0;108123:50;;108210:16;;108258:13:::1;108290:22:::0;108282:36:::1;;;::::0;-1:-1:-1;;;108282:36:0;;17516:2:1;108282:36:0::1;::::0;::::1;17498:21:1::0;17555:1;17535:18;;;17528:29;17593:3;17573:18;;;17566:31;17614:18;;108282:36:0::1;17488:150:1::0;108282:36:0::1;108335:14:::0;;:28:::1;;::::0;108331:298:::1;;108555:14:::0;;108588::::1;::::0;::::1;::::0;108496:121:::1;::::0;:40:::1;::::0;::::1;::::0;::::1;:121::i;:::-;108660:13;::::0;::::1;::::0;108704:14:::1;::::0;::::1;::::0;108660:13:::1;::::0;;::::1;::::0;108747:10:::1;108735:22:::0;::::1;::::0;::::1;::::0;:40:::1;;-1:-1:-1::0;108761:14:0;;::::1;108735:40;108731:300;;;108876:143;:44;::::0;::::1;108939:10;108968:8:::0;108995:9;108876:44:::1;:143::i;:::-;109069:12;::::0;::::1;:19:::0;109043:23:::1;109101:759;109125:15;109121:1;:19;109101:759;;;109162:14;109179:4;:12;;109192:1;109179:15;;;;;;-1:-1:-1::0;;;109179:15:0::1;;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;::::1;;::::0;-1:-1:-1;109281:10:0::1;109271:20:::0;::::1;109267:582;;109363:12;109378:174;109428:4;:15;;109444:1;109428:18;;;;;;-1:-1:-1::0;;;109428:18:0::1;;;;;;;;;;;;;;;;;109469:4;:9;;109479:1;109469:12;;;;;;-1:-1:-1::0;;;109469:12:0::1;;;;;;;;;;;;;;;;;109515:4;:15;;109531:1;109515:18;;;;;;-1:-1:-1::0;;;109515:18:0::1;;;;;;;;;;;;;;;;;109504:4;:8;;;:29;;;;:::i;109378:174::-;109363:189:::0;-1:-1:-1;109610:152:0::1;:44;::::0;::::1;109677:10;109710:6:::0;109363:189;109610:44:::1;:152::i;:::-;109820:6;109788:45;;109809:9;109788:45;109828:4;109788:45;;;;14306:25:1::0;;14294:2;14279:18;;14261:76;109788:45:0::1;;;;;;;;109267:582;;-1:-1:-1::0;109142:3:0;::::1;::::0;::::1;:::i;:::-;;;;109101:759;;;;109872:38;109888:9;109899:10;109872:15;:38::i;:::-;109928:23;::::0;109941:9;;109928:23:::1;::::0;;;::::1;93037:1;;;;;;107991:1968:::0;;:::o;112169:160::-;58516:13;:11;:13::i;:::-;112255:14:::1;:25:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;112296::::1;::::0;11226:74:1;;;112296:25:0::1;::::0;11214:2:1;11199:18;112296:25:0::1;11181:125:1::0;95494:1076:0;95681:6;95708:5;95717:1;95708:10;95700:24;;;;-1:-1:-1;;;95700:24:0;;26719:2:1;95700:24:0;;;26701:21:1;26758:1;26738:18;;;26731:29;26796:3;26776:18;;;26769:31;26817:18;;95700:24:0;26691:150:1;95700:24:0;95904:12;;;95872:45;;;;;;;30494:25:1;;;95892:10:0;30535:18:1;;;30528:83;30627:18;;;;30620:34;;;95872:45:0;;;;;;;;;;30467:18:1;;;;95872:45:0;;;95862:56;;;;;;-1:-1:-1;95970:14:0;95904:12;95970:14;:::i;:::-;;;;-1:-1:-1;96062:14:0;;-1:-1:-1;96079:214:0;96109:39;;;;96120:4;96109:39;:::i;:::-;96163:9;96187:7;96209:9;96233:10;96258:24;96079:15;:214::i;:::-;96348:163;;;;;96419:4;96348:163;;;12564:34:1;12513:42;12634:15;;12614:18;;;12607:43;12666:18;;;12659:34;;;96482:1:0;12709:18:1;;;12702:34;12773:3;12752:19;;;12745:32;-1:-1:-1;12793:19:1;;;12786:33;96062:231:0;;-1:-1:-1;96368:10:0;;96348:48;;12836:19:1;;96348:163:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;96531:31:0;;95494:1076;-1:-1:-1;;;;;;;;;;;;95494:1076:0:o;59536:238::-;58516:13;:11;:13::i;:::-;59639:22:::1;::::0;::::1;59617:110;;;::::0;-1:-1:-1;;;59617:110:0;;18865:2:1;59617:110:0::1;::::0;::::1;18847:21:1::0;18904:2;18884:18;;;18877:30;18943:34;18923:18;;;18916:62;19014:8;18994:18;;;18987:36;19040:19;;59617:110:0::1;18837:228:1::0;59617:110:0::1;59738:28;59757:8;59738:18;:28::i;123617:2525::-:0;123699:23;123725:16;;;:5;:16;;;;;123780:12;;;:19;123892:20;123884:35;;;;-1:-1:-1;;;123884:35:0;;24954:2:1;123884:35:0;;;24936:21:1;24993:1;24973:18;;;24966:29;25031:4;25011:18;;;25004:32;25053:18;;123884:35:0;24926:151:1;123884:35:0;123997:15;123979:4;:15;;;:33;123971:48;;;;-1:-1:-1;;;123971:48:0;;25284:2:1;123971:48:0;;;25266:21:1;25323:1;25303:18;;;25296:29;25361:4;25341:18;;;25334:32;25383:18;;123971:48:0;25256:151:1;123971:48:0;124032:28;124063:19;;;:8;:19;;;;;;;;124032:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124181:1399;124205:15;124201:1;:19;124181:1399;;;124242:14;124259:4;:12;;124272:1;124259:15;;;;;;-1:-1:-1;;;124259:15:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;124361:10:0;124351:20;;124347:1222;;124443:12;124458:174;124508:4;:15;;124524:1;124508:18;;;;;;-1:-1:-1;;;124508:18:0;;;;;;;;;;;;;;;;;124549:4;:9;;124559:1;124549:12;;;;;;-1:-1:-1;;;124549:12:0;;;;;;;;;;;;;;;;;124595:4;:15;;124611:1;124595:18;;;;;;-1:-1:-1;;;124595:18:0;;;;;;;;;;;;;;;;;124584:4;:8;;;:29;;;;:::i;124458:174::-;124443:189;;124675:4;124657:7;:14;;;:22;124653:901;;124854:14;;;;124754:137;;:40;;;;124821:6;;124754:40;:137::i;:::-;124933:1;124916:14;;;;:18;;;124964:153;;14306:25:1;;;124964:153:0;;;;125011:9;;124964:153;;14279:18:1;124964:153:0;;;;;;;125216:5;;;;124653:901;125311:54;:40;;;125352:6;125360:4;125311:40;:54::i;:::-;125455:4;125437:7;:14;;:22;;;;;;;:::i;:::-;;;-1:-1:-1;125489:45:0;;14306:25:1;;;125489:45:0;;;;125510:9;;125489:45;;14294:2:1;14279:18;125489:45:0;;;;;;;124347:1222;;-1:-1:-1;124222:3:0;;;;:::i;:::-;;;;124181:1399;;;-1:-1:-1;125693:14:0;;;;:19;125689:172;;125788:13;;;;125820:14;;;;125729:120;;125788:13;125729:40;;;;125788:13;;;125729:40;:120::i;:::-;125945:14;;125928;;125945:28;;;:89;;126020:14;;125945:89;;;125989:4;:12;;126002:1;125989:15;;;;;;-1:-1:-1;;;125989:15:0;;;;;;;;;;;;;;;;;;;;;125945:89;125928:106;;126047:34;126063:9;126074:6;126047:15;:34::i;:::-;126099:35;;;;;;126116:9;;126099:35;;;;;123617:2525;;;;;;:::o;58795:132::-;58703:6;;58859:23;58703:6;56723:10;58859:23;58851:68;;;;-1:-1:-1;;;58851:68:0;;26358:2:1;58851:68:0;;;26340:21:1;;;26377:18;;;26370:30;26436:34;26416:18;;;26409:62;26488:18;;58851:68:0;26330:182:1;112775:1419:0;113068:18;;;;113031:7;113068:18;;;:7;:18;;;;;;113031:7;;113068:18;113191:20;113187:197;;113260:19;;:43;;;;;:19;11244:55:1;;;113260:43:0;;;11226:74:1;113260:19:0;;;;:32;;11199:18:1;;113260:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;113345:18;;;;;;;;:7;:18;;;;;:27;;;;;;;;;;;;;;-1:-1:-1;113187:197:0;113448:404;;;;;;;;113473:13;:20;;;113448:404;;;;113508:1;113448:404;;;;113524:1;113448:404;;;;113540:7;113448:404;;;;113562:1;113448:404;;;;113592:1;113578:16;;;;;;-1:-1:-1;;;113578:16:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;113578:16:0;-1:-1:-1;113448:404:0;;;;113623:1;113609:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;113609:16:0;-1:-1:-1;113448:404:0;;;;113654:1;113640:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;113640:16:0;-1:-1:-1;113448:404:0;;;;113685:1;113671:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;113671:16:0;;113448:404;;;;113702:12;113448:404;;;;;;113729:13;:22;;;113448:404;;;;;;113766:9;113448:404;;;;;;113790:6;113448:404;;;;;;113811:1;113448:404;;;;113827:14;113448:404;;;;;;-1:-1:-1;;;113448:404:0;;;;;;;;;;;113429:16;;;;:5;:16;;;;;;;;;:423;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;113429:423:0;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;113429:423:0;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;113429:423:0;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;113429:423:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;113429:423:0;;;;;;;;;;;;;-1:-1:-1;;114025:20:0;;114060:17;;;;;114092:20;;;;;114127:22;;;;;113902:258;;;13907:15:1;;;13889:34;;13939:18;;;13932:34;;;13982:18;;;13975:34;;;;14025:18;;;14018:34;;;;14083:3;14068:19;;14061:35;14133:15;;;14127:3;14112:19;;14105:44;113902:258:0;;;;;-1:-1:-1;113928:9:0;;113902:258;;;;;;13815:3:1;113902:258:0;;;114180:6;112775:1419;-1:-1:-1;;;;;;;112775:1419:0:o;117923:3691::-;118077:23;118103:13;;;:5;:13;;;;;118175;;;;:27;:13;118167:42;;;;-1:-1:-1;;;118167:42:0;;23391:2:1;118167:42:0;;;23373:21:1;23430:1;23410:18;;;23403:29;23468:4;23448:18;;;23441:32;23490:18;;118167:42:0;23363:151:1;118167:42:0;118290:4;:8;;;118272:15;:26;118264:41;;;;-1:-1:-1;;;118264:41:0;;21896:2:1;118264:41:0;;;21878:21:1;21935:1;21915:18;;;21908:29;21973:4;21953:18;;;21946:32;21995:18;;118264:41:0;21868:151:1;118264:41:0;118519:11;;118391:6;;118366:22;;118519:15;;118533:1;;118519:15;:::i;:::-;118644:12;;;:19;118493:41;;-1:-1:-1;118627:2491:0;118665:5;;118627:2491;;118692:17;118712:15;;;118728:5;118732:1;118728;:5;:::i;:::-;118712:22;;;;;;-1:-1:-1;;;118712:22:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;118941:15:0;;;118957:5;118961:1;118957;:5;:::i;:::-;118941:22;;;;;;-1:-1:-1;;;118941:22:0;;;;;;;;;;;;;;;;;118923:15;:40;;;;:::i;:::-;118902:61;;118980:29;119025:15;119012:10;:28;:93;;119090:15;119012:93;;;119060:10;119012:93;118980:125;-1:-1:-1;119178:16:0;;119211:211;119259:9;119287;;;119297:5;119301:1;119297;:5;:::i;:::-;119287:16;;;;;;-1:-1:-1;;;119287:16:0;;;;;;;;;;;;;;;;;119322:21;119362:12;;119393:14;;119211:29;:211::i;:::-;119177:245;;-1:-1:-1;119177:245:0;-1:-1:-1;119439:14:0;119456:12;;;119469:5;119473:1;119469;:5;:::i;:::-;119456:19;;;;;;-1:-1:-1;;;119456:19:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;119589:3:0;119566:20;119578:8;119566:9;:20;:::i;:::-;:26;;;;:::i;:::-;119549:14;:43;119545:988;;;119693:241;119746:14;119783:9;;;119793:5;119797:1;119793;:5;:::i;:::-;119783:16;;;;;;-1:-1:-1;;;119783:16:0;;;;;;;;;;;;;;;;;119822:21;119866:12;;119901:14;;119693:30;:241::i;:::-;119664:270;;-1:-1:-1;119664:270:0;-1:-1:-1;119664:270:0;-1:-1:-1;119664:270:0;120039:15;;;120055:5;120059:1;120055;:5;:::i;:::-;120039:22;;;;;;-1:-1:-1;;;120039:22:0;;;;;;;;;;;;;;;;;:35;;;;;;;:::i;:::-;;;;-1:-1:-1;120143:1:0;;-1:-1:-1;119545:988:0;;-1:-1:-1;119545:988:0;;120211:3;120188:20;120200:8;120188:9;:20;:::i;:::-;:26;;;;:::i;:::-;120170:14;:44;120166:367;;;120310:4;:12;;:18;;;;;-1:-1:-1;;;120310:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;120166:367:0;;;120499:4;:12;;:18;;;;;-1:-1:-1;;;120499:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;120166:367;120578:146;120641:4;120664:6;120689:20;120701:8;120689:9;:20;:::i;:::-;120596:8;120578:44;;;;:146;;;;;;:::i;:::-;120852:14;;120766:137;;120852:14;120766:44;;;;120829:4;;120852:14;120885:3;120766:44;:137::i;:::-;121026:3;121003:20;121015:8;121003:9;:20;:::i;:::-;:26;;;;:::i;:::-;120985:44;;;;:::i;:::-;121051:55;;;32422:25:1;;;32478:2;32463:18;;32456:34;;;32506:18;;;32499:34;;;120985:44:0;;-1:-1:-1;121051:55:0;;;;121065:6;;121051:55;;32410:2:1;32395:18;121051:55:0;;;;;;;118627:2491;;;;;;118672:3;;;;;:::i;:::-;;;;118627:2491;;;-1:-1:-1;121134:12:0;;;:19;121130:477;;121269:17;;;;121305:12;;;;121336:11;;;;121366:13;;;;121398:19;;;;121231:201;;121269:17;;;;;121305:12;121336:11;;;121366:13;;121398:19;;121231;:201::i;:::-;121456:13;;;;:5;:13;;;;;121449:20;;;;;;;;;;;;;;;;;;;;;;;;;;;121456:13;121449:20;;;;121456:13;121449:20;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;-1:-1:-1;121449:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121130:477;;;121589:6;121571:4;:14;;;:24;;;;;;;:::i;:::-;;;;-1:-1:-1;;121130:477:0;117923:3691;;;;;;;:::o;126729:436::-;126950:23;126932:14;:41;;;;;;-1:-1:-1;;;126932:41:0;;;;;;;;;;126928:230;;;126990:61;;;;;:34;12078:15:1;;;126990:61:0;;;12060:34:1;12130:15;;;12110:18;;;12103:43;12162:18;;;12155:34;;;126990::0;;;;;11972:18:1;;126990:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126928:230;;;127084:62;;;;;:35;12078:15:1;;;127084:62:0;;;12060:34:1;12130:15;;;12110:18;;;12103:43;12162:18;;;12155:34;;;127084:35:0;;;;;11972:18:1;;127084:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126729:436;;;;;:::o;127702:71::-;58516:13;:11;:13::i;67831:1083::-;65697:66;68285:59;;;68281:626;;;68361:37;68380:17;68361:18;:37::i;:::-;67831:1083;;;:::o;68281:626::-;68481:17;68452:61;;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;68452:63:0;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;68431:397;;68756:56;;-1:-1:-1;;;68756:56:0;;24539:2:1;68756:56:0;;;24521:21:1;24578:2;24558:18;;;24551:30;24617:34;24597:18;;;24590:62;24688:16;24668:18;;;24661:44;24722:19;;68756:56:0;24511:236:1;68431:397:0;66054:66;68601:28;;68571:143;;;;-1:-1:-1;;;68571:143:0;;22651:2:1;68571:143:0;;;22633:21:1;22690:2;22670:18;;;22663:30;22729:34;22709:18;;;22702:62;22800:11;22780:18;;;22773:39;22829:19;;68571:143:0;22623:231:1;68571:143:0;68529:201;68842:53;68860:17;68879:4;68885:9;68842:17;:53::i;114472:1564::-;114728:13;;;;114689:7;;114728:13;;114762:10;:22;;114754:36;;;;-1:-1:-1;;;114754:36:0;;29294:2:1;114754:36:0;;;29276:21:1;29333:1;29313:18;;;29306:29;29371:3;29351:18;;;29344:31;29392:18;;114754:36:0;29266:150:1;114754:36:0;114807:12;;;:19;114803:440;;114922:11;;114908;;114922:29;;114936:15;;114922:29;:::i;:::-;114968:8;;;:14;;;115087:13;;114908:43;;-1:-1:-1;115081:19:0;;114908:43;115081:19;:::i;:::-;115063:15;;;:37;-1:-1:-1;114803:440:0;;;115216:4;:8;;;115198:15;:26;115190:41;;;;-1:-1:-1;;;115190:41:0;;21896:2:1;115190:41:0;;;21878:21:1;21935:1;21915:18;;;21908:29;21973:4;21953:18;;;21946:32;21995:18;;115190:41:0;21868:151:1;115190:41:0;115371:61;;115332:12;;115371:61;;115382:30;;;115414:17;;;;115371:61;;;:::i;:::-;;;;;;;;;;;;;115347:96;;;;;;115332:111;;115488:14;115505:45;115545:4;39688:58;;10278:66:1;39688:58:0;;;10266:79:1;10361:12;;;10354:28;;;39519:7:0;;10398:12:1;;39688:58:0;;;;;;;;;;;;39660:101;;;;;;39640:121;;39423:346;;;;115505:45;115488:62;-1:-1:-1;115592:14:0;115609:170;115488:62;115669:23;;;;;;;;:::i;:::-;115707:21;:23;;;115745:21;:23;;;115609:24;:170::i;:::-;115893:25;;115592:187;;-1:-1:-1;115893:25:0;115883:35;;;115893:25;;115883:35;115875:49;;;;-1:-1:-1;;;115875:49:0;;20747:2:1;115875:49:0;;;20729:21:1;20786:1;20766:18;;;20759:29;20824:3;20804:18;;;20797:31;20845:18;;115875:49:0;20719:150:1;115875:49:0;115964:30;;115945:15;:49;;115937:63;;;;-1:-1:-1;;;115937:63:0;;29623:2:1;115937:63:0;;;29605:21:1;29662:1;29642:18;;;29635:29;29700:3;29680:18;;;29673:31;29721:18;;115937:63:0;29595:150:1;115937:63:0;-1:-1:-1;116020:8:0;;114472:1564;-1:-1:-1;;;;;;;114472:1564:0:o;116257:1460::-;116452:7;116490:12;:22;;;116480:6;:32;;116472:46;;;;-1:-1:-1;;;116472:46:0;;28142:2:1;116472:46:0;;;28124:21:1;28181:1;28161:18;;;28154:29;28219:3;28199:18;;;28192:31;28240:18;;116472:46:0;28114:150:1;116472:46:0;116568:27;;;;116539:25;116548:16;116539:6;:25;:::i;:::-;:56;;116531:71;;;;-1:-1:-1;;;116531:71:0;;18205:2:1;116531:71:0;;;18187:21:1;18244:1;18224:18;;;18217:29;18282:4;18262:18;;;18255:32;18304:18;;116531:71:0;18177:151:1;116531:71:0;116713:251;;;92603:132;116713:251;;;15146:25:1;15187:18;;;15180:34;;;116809:22:0;;;;;15230:18:1;;;15223:34;116850:16:0;;;;;15273:18:1;;;15266:34;116885:27:0;;;;;15316:19:1;;;15309:35;116931:18:0;;;;;15360:19:1;;;15353:35;116668:18:0;;15118:19:1;;116713:251:0;;;;;;;;;;;;116689:286;;;;;;116668:307;;116986:14;117003:28;117020:10;117003:16;:28::i;:::-;116986:45;-1:-1:-1;117080:14:0;117097:143;116986:45;117157:14;;;;;;;;:::i;:::-;117186;;117215;;;;117097:24;:143::i;:::-;117343:10;;;;:6;:10;;;;;;;;:18;;;;;;;;;;;117080:160;;-1:-1:-1;117321:18:0;;;;:40;117313:55;;;;-1:-1:-1;;;117313:55:0;;23061:2:1;117313:55:0;;;23043:21:1;23100:1;23080:18;;;23073:29;23138:4;23118:18;;;23111:32;23160:18;;117313:55:0;23033:151:1;117313:55:0;117379:10;;;;:6;:10;;;;;;;;:18;;;;;;;;;;:20;;;;;;:::i;:::-;;;;-1:-1:-1;;117442:9:0;;;;:5;:9;;;;;;;;:20;;;:33;;;;;;;;;;;;;;;;;;117486:17;;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;117527:14;;;:37;;;;;;;;;;;;;117547:16;;;;117527:37;;;;;117575:20;;;;:42;;;;;;;;;;;;;117601:15;117575:42;;;117635:48;;13370:74:1;;;13460:18;;;13453:34;;;13503:18;;13496:34;117442:9:0;;117635:48;;13358:2:1;13343:18;117635:48:0;;;;;;;117703:6;116257:1460;-1:-1:-1;;;;;;;116257:1460:0:o;24885:296::-;25094:68;;12009:42:1;12078:15;;;25094:68:0;;;12060:34:1;12130:15;;12110:18;;;12103:43;12162:18;;;12155:34;;;25040:133:0;;25074:5;;25117:27;;11972:18:1;;25094:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25040:19;:133::i;:::-;24885:296;;;;:::o;121770:1514::-;121895:23;121921:16;;;:5;:16;;;;;;;;121980:8;:19;;;;;;122047:14;;;:23;;;122142:12;;;:19;122133:28;;122129:890;;122248:4;:12;;122261:5;122248:19;;;;;;-1:-1:-1;;;122248:19:0;;;;;;;;;;;;;;;;;;;;;122234:10;:33;122226:48;;;;-1:-1:-1;;;122226:48:0;;18535:2:1;122226:48:0;;;18517:21:1;18574:1;18554:18;;;18547:29;18612:4;18592:18;;;18585:32;18634:18;;122226:48:0;18507:151:1;122226:48:0;122355:28;122407:9;122402:269;122426:5;122422:1;:9;122402:269;;;122481:174;122531:4;:15;;122547:1;122531:18;;;;;;-1:-1:-1;;;122531:18:0;;;;;;;;;;;;;;;;;122572:4;:9;;122582:1;122572:12;;;;;;-1:-1:-1;;;122572:12:0;;;;;;;;;;;;;;;;;122618:4;:15;;122634:1;122618:18;;;;;;-1:-1:-1;;;122618:18:0;;;;;;;;;;;;;;;;;122607:4;:8;;;:29;;;;:::i;122481:174::-;122457:198;;;;:::i;:::-;;-1:-1:-1;122433:3:0;;;;:::i;:::-;;;;122402:269;;;;122755:20;122745:6;:30;122741:267;;122806:186;122856:4;:15;;122872:5;122856:22;;;;;;-1:-1:-1;;;122856:22:0;;;;;;;;;;;;;;;;;122901:4;:9;;122911:5;122901:16;;;;;;-1:-1:-1;;;122901:16:0;;;;;;;;;;;;;;;;;122951:4;:15;;122967:5;122951:22;;;;;;-1:-1:-1;;;122951:22:0;;;;;;;;;;;;;;;;;122940:4;:8;;;:33;;;;:::i;122806:186::-;122796:196;;;;:::i;:::-;;;122741:267;122129:890;;123120:6;123097:7;:20;;;:29;123089:44;;;;-1:-1:-1;;;123089:44:0;;19272:2:1;123089:44:0;;;19254:21:1;19311:1;19291:18;;;19284:29;19349:4;19329:18;;;19322:32;19371:18;;123089:44:0;19244:151:1;123089:44:0;123146:20;;;:29;;;123186:27;;;;123203:10;123186:27;;;;;123231:45;;;32141:25:1;;;32197:2;32182:18;;32175:34;;;123239:9:0;;123231:45;;32114:18:1;123231:45:0;;;;;;;121770:1514;;;;;:::o;127271:350::-;127402:12;127420:9;:14;;127442:6;127420:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;127401:52;;;127547:7;127542:72;;127571:14;;:31;;:14;;;;;:31;;;;;127595:6;;127571:14;:31;:14;:31;127595:6;127571:14;:31;;;;;;;;;;;;;;;;;;;59934:191;60027:6;;;;60044:17;;;;;;;;;;;60077:40;;60027:6;;;60044:17;60027:6;;60077:40;;60008:16;;60077:40;59934:191;;:::o;49323:172::-;46170:13;;;;;;;46162:69;;;;-1:-1:-1;;;46162:69:0;;28471:2:1;46162:69:0;;;28453:21:1;28510:2;28490:18;;;28483:30;28549:34;28529:18;;;28522:62;28620:13;28600:18;;;28593:41;28651:19;;46162:69:0;28443:233:1;46162:69:0;49449:38:::1;49473:4;49479:7;49449:23;:38::i;58173:97::-:0;46170:13;;;;;;;46162:69;;;;-1:-1:-1;;;46162:69:0;;28471:2:1;46162:69:0;;;28453:21:1;28510:2;28490:18;;;28483:30;28549:34;28529:18;;;28522:62;28620:13;28600:18;;;28593:41;28651:19;;46162:69:0;28443:233:1;46162:69:0;58236:26:::1;:24;:26::i;24618:259::-:0;24800:58;;13070:42:1;13058:55;;24800:58:0;;;13040:74:1;13130:18;;;13123:34;;;24746:123:0;;24780:5;;24823:23;;13013:18:1;;24800:58:0;12995:168:1;88819:358:0;88957:7;89031:15;89042:4;89031:8;:15;:::i;:::-;89030:24;;89050:4;89030:24;:::i;:::-;89019:35;-1:-1:-1;89067:16:0;89117:12;89019:35;89087:15;89099:3;89087:9;:15;:::i;:::-;:26;;;;:::i;:::-;89086:43;;;;:::i;:::-;89067:62;-1:-1:-1;89149:20:0;89067:62;89149:9;:20;:::i;:::-;89142:27;;;88819:358;;;;;;:::o;126234:422::-;126389:16;;;;:5;:16;;;;;:29;;;;126433:24;;;;126472:23;;;;126531:31;;;;;126355:218;;126389:29;;;;;126472:23;;126510:6;;126531:31;;126355:19;:218::i;:::-;126593:19;;;;:8;:19;;;;;;;;126586:26;;;;;;;;;;;;;;;;;;;;126632:5;:16;;;;;;126625:23;;;;;;;;;;;;;;;;;;;;;;;;;;126632:16;126625:23;;;;126593:19;126625:23;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;-1:-1:-1;126625:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;126234:422:0:o;88280:531::-;88484:7;;88567:15;88578:4;88567:8;:15;:::i;:::-;88566:24;;88586:4;88566:24;:::i;:::-;88555:35;-1:-1:-1;88603:20:0;88657:12;88555:35;88627:15;88639:3;88627:9;:15;:::i;:::-;:26;;;;:::i;:::-;88626:43;;;;:::i;:::-;88603:66;-1:-1:-1;88682:15:0;88732:14;88701:27;88716:12;88603:66;88701:27;:::i;:::-;88700:46;;;;:::i;:::-;88682:64;-1:-1:-1;88767:22:0;88682:64;88767:12;:22;:::i;:::-;88791:11;:7;88801:1;88791:11;:::i;:::-;88759:44;;;;;;88280:531;;;;;;;;:::o;89275:1060::-;89521:7;;;;89757:26;89769:14;89757:9;:26;:::i;:::-;:41;;89786:12;89757:41;:::i;:::-;89728:70;-1:-1:-1;89811:28:0;89908:29;89923:14;89908:12;:29;:::i;:::-;89890:14;89901:3;89890:8;:14;:::i;:::-;:48;;;;:::i;:::-;89843:29;:14;89860:12;89843:29;:::i;:::-;89842:97;;;;:::i;:::-;89811:128;-1:-1:-1;89952:17:0;89972:41;89811:128;89972:18;:41;:::i;:::-;89952:61;-1:-1:-1;90080:15:0;90091:4;90080:8;:15;:::i;:::-;90079:24;;90099:4;90079:24;:::i;:::-;90068:35;-1:-1:-1;90116:20:0;90170:12;90068:35;90140:15;90152:3;90140:9;:15;:::i;:::-;:26;;;;:::i;:::-;90139:43;;;;:::i;:::-;90116:66;-1:-1:-1;90195:15:0;90245:14;90214:27;90229:12;90116:66;90214:27;:::i;:::-;90213:46;;;;:::i;:::-;90195:64;-1:-1:-1;90280:9:0;90291:22;90195:64;90291:12;:22;:::i;:::-;90315:11;:7;90325:1;90315:11;:::i;:::-;90272:55;;;;;;;;;;;89275:1060;;;;;;;;;:::o;66597:349::-;17448:19;;;;66671:143;;;;-1:-1:-1;;;66671:143:0;;25944:2:1;66671:143:0;;;25926:21:1;25983:2;25963:18;;;25956:30;26022:34;26002:18;;;25995:62;26093:15;26073:18;;;26066:43;26126:19;;66671:143:0;25916:235:1;66671:143:0;66054:66;66825:113;;;;;;;;;;;;;;;66597:349::o;67355:297::-;67498:29;67509:17;67498:10;:29::i;:::-;67556:1;67542:4;:11;:15;:28;;;;67561:9;67542:28;67538:107;;;67587:46;67609:17;67628:4;67587:21;:46::i;38844:279::-;38972:7;38993:17;39012:18;39034:25;39045:4;39051:1;39054;39057;39034:10;:25::i;:::-;38992:67;;;;39070:18;39082:5;39070:11;:18::i;:::-;-1:-1:-1;39106:9:0;38844:279;-1:-1:-1;;;;;38844:279:0:o;51242:232::-;51355:7;51400:66;51433:20;:18;:20::i;:::-;51455:10;40975:57;;10691:66:1;40975:57:0;;;10679:79:1;10774:11;;;10767:27;;;10810:12;;;10803:28;;;40902:7:0;;10847:12:1;;40975:57:0;;;;;;;;;;;;40947:100;;;;;;40927:120;;40782:273;;;;;51400:66;51380:86;51242:232;-1:-1:-1;;51242:232:0:o;28182:827::-;28631:23;28657:106;28699:4;28657:106;;;;;;;;;;;;;;;;;28665:5;28657:27;;;;:106;;;;;:::i;:::-;28778:17;;28631:132;;-1:-1:-1;28778:21:0;28774:228;;28893:10;28882:30;;;;;;;;;;;;:::i;:::-;28856:134;;;;-1:-1:-1;;;28856:134:0;;28883:2:1;28856:134:0;;;28865:21:1;28922:2;28902:18;;;28895:30;28961:34;28941:18;;;28934:62;29032:12;29012:18;;;29005:40;29062:19;;28856:134:0;28855:232:1;49503:325:0;46170:13;;;;;;;46162:69;;;;-1:-1:-1;;;46162:69:0;;28471:2:1;46162:69:0;;;28453:21:1;28510:2;28490:18;;;28483:30;28549:34;28529:18;;;28522:62;28620:13;28600:18;;;28593:41;28651:19;;46162:69:0;28443:233:1;46162:69:0;49660:22;;::::1;::::0;;::::1;::::0;49717:25;;;;;::::1;::::0;49753:12:::1;:25:::0;;;;49789:15:::1;:31:::0;49503:325::o;58278:113::-;46170:13;;;;;;;46162:69;;;;-1:-1:-1;;;46162:69:0;;28471:2:1;46162:69:0;;;28453:21:1;28510:2;28490:18;;;28483:30;28549:34;28529:18;;;28522:62;28620:13;28600:18;;;28593:41;28651:19;;46162:69:0;28443:233:1;46162:69:0;58351:32:::1;56723:10:::0;58351:18:::1;:32::i;67059:155::-:0;67126:37;67145:17;67126:18;:37::i;:::-;67179:27;;;;;;;;;;;67059:155;:::o;72356:600::-;72457:12;17448:19;;;;72487:125;;;;-1:-1:-1;;;72487:125:0;;27048:2:1;72487:125:0;;;27030:21:1;27087:2;27067:18;;;27060:30;27126:34;27106:18;;;27099:62;27197:8;27177:18;;;27170:36;27223:19;;72487:125:0;27020:228:1;72487:125:0;72686:12;72700:23;72727:6;:19;;72747:4;72727:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72685:67;;;;72783:165;72837:7;72863:10;72783:165;;;;;;;;;;;;;;;;;:35;:165::i;:::-;72763:185;72356:600;-1:-1:-1;;;;;72356:600:0:o;37036:1669::-;37167:7;;38128:66;38102:92;;38084:200;;;-1:-1:-1;38237:1:0;;-1:-1:-1;38241:30:0;38221:51;;38084:200;38298:1;:7;;38303:2;38298:7;;:18;;;;;38309:1;:7;;38314:2;38309:7;;38298:18;38294:102;;;-1:-1:-1;38349:1:0;;-1:-1:-1;38353:30:0;38333:51;;38294:102;38510:24;;;38493:14;38510:24;;;;;;;;;15626:25:1;;;15699:4;15687:17;;15667:18;;;15660:45;;;;15721:18;;;15714:34;;;15764:18;;;15757:34;;;38510:24:0;;15598:19:1;;38510:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;38510:24:0;;;;;;-1:-1:-1;;38549:20:0;;;38545:103;;38602:1;38606:29;38586:50;;;;;;;38545:103;38668:6;-1:-1:-1;38676:20:0;;-1:-1:-1;37036:1669:0;;;;;;;;:::o;32197:643::-;32275:20;32266:5;:29;;;;;;-1:-1:-1;;;32266:29:0;;;;;;;;;;32262:571;;;32197:643;:::o;32262:571::-;32373:29;32364:5;:38;;;;;;-1:-1:-1;;;32364:38:0;;;;;;;;;;32360:473;;;32419:34;;-1:-1:-1;;;32419:34:0;;17163:2:1;32419:34:0;;;17145:21:1;17202:2;17182:18;;;17175:30;17241:26;17221:18;;;17214:54;17285:18;;32419:34:0;17135:174:1;32360:473:0;32484:35;32475:5;:44;;;;;;-1:-1:-1;;;32475:44:0;;;;;;;;;;32471:362;;;32536:41;;-1:-1:-1;;;32536:41:0;;17845:2:1;32536:41:0;;;17827:21:1;17884:2;17864:18;;;17857:30;17923:33;17903:18;;;17896:61;17974:18;;32536:41:0;17817:181:1;32471:362:0;32608:30;32599:5;:39;;;;;;-1:-1:-1;;;32599:39:0;;;;;;;;;;32595:238;;;32655:44;;-1:-1:-1;;;32655:44:0;;20344:2:1;32655:44:0;;;20326:21:1;20383:2;20363:18;;;20356:30;20422:34;20402:18;;;20395:62;20493:4;20473:18;;;20466:32;20515:19;;32655:44:0;20316:224:1;32595:238:0;32730:30;32721:5;:39;;;;;;-1:-1:-1;;;32721:39:0;;;;;;;;;;32717:116;;;32777:44;;-1:-1:-1;;;32777:44:0;;24136:2:1;32777:44:0;;;24118:21:1;24175:2;24155:18;;;24148:30;24214:34;24194:18;;;24187:62;24285:4;24265:18;;;24258:32;24307:19;;32777:44:0;24108:224:1;49919:241:0;49972:7;50012:140;48572:119;50081:17;51803:12;;;51718:105;50081:17;52158:15;;50380:197;;;;;;14601:25:1;;;14642:18;;;14635:34;;;14685:18;;;14678:34;;;50509:13:0;14728:18:1;;;14721:34;50553:4:0;14771:19:1;;;14764:84;50312:7:0;;14573:19:1;;50380:197:0;;;;;;;;;;;;50352:240;;;;;;50332:260;;50168:432;;;;;;50012:140;49992:160;;49919:241;:::o;19995:229::-;20132:12;20164:52;20186:6;20194:4;20200:1;20203:12;20164:21;:52::i;:::-;20157:59;19995:229;-1:-1:-1;;;;19995:229:0:o;23092:762::-;23242:12;23271:7;23267:580;;;-1:-1:-1;23302:10:0;23295:17;;23267:580;23416:17;;:21;23412:424;;23664:10;23658:17;23725:15;23712:10;23708:2;23704:19;23697:44;23612:148;23807:12;23800:20;;-1:-1:-1;;;23800:20:0;;;;;;;;:::i;21211:571::-;21381:12;21453:5;21428:21;:30;;21406:118;;;;-1:-1:-1;;;21406:118:0;;21489:2:1;21406:118:0;;;21471:21:1;21528:2;21508:18;;;21501:30;21567:34;21547:18;;;21540:62;21638:8;21618:18;;;21611:36;21664:19;;21406:118:0;21461:228:1;21406:118:0;17448:19;;;;21535:60;;;;-1:-1:-1;;;21535:60:0;;27455:2:1;21535:60:0;;;27437:21:1;27494:2;27474:18;;;27467:30;27533:31;27513:18;;;27506:59;27582:18;;21535:60:0;27427:179:1;21535:60:0;21609:12;21623:23;21650:6;:11;;21669:5;21690:4;21650:55;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21608:97;;;;21723:51;21740:7;21749:10;21761:12;21723:16;:51::i;:::-;21716:58;21211:571;-1:-1:-1;;;;;;;21211:571:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:395:1;77:8;87:6;141:3;134:4;126:6;122:17;118:27;108:2;;166:8;156;149:26;108:2;-1:-1:-1;196:20:1;;239:18;228:30;;225:2;;;278:8;268;261:26;225:2;322:4;314:6;310:17;298:29;;382:3;375:4;365:6;362:1;358:14;350:6;346:27;342:38;339:47;336:2;;;399:1;396;389:12;336:2;98:311;;;;;:::o;414:375::-;465:8;475:6;529:3;522:4;514:6;510:17;506:27;496:2;;554:8;544;537:26;496:2;-1:-1:-1;584:20:1;;627:18;616:30;;613:2;;;666:8;656;649:26;613:2;710:4;702:6;698:17;686:29;;762:3;755:4;746:6;738;734:19;730:30;727:39;724:2;;;779:1;776;769:12;794:178;868:5;913:3;904:6;899:3;895:16;891:26;888:2;;;934:5;927;920:20;888:2;-1:-1:-1;960:6:1;878:94;-1:-1:-1;878:94:1:o;977:156::-;1043:20;;1103:4;1092:16;;1082:27;;1072:2;;1123:1;1120;1113:12;1072:2;1024:109;;;:::o;1138:257::-;1197:6;1250:2;1238:9;1229:7;1225:23;1221:32;1218:2;;;1271:6;1263;1256:22;1218:2;1315:9;1302:23;1334:31;1359:5;1334:31;:::i;1400:261::-;1470:6;1523:2;1511:9;1502:7;1498:23;1494:32;1491:2;;;1544:6;1536;1529:22;1491:2;1581:9;1575:16;1600:31;1625:5;1600:31;:::i;1936:774::-;2033:6;2041;2049;2057;2065;2118:3;2106:9;2097:7;2093:23;2089:33;2086:2;;;2140:6;2132;2125:22;2086:2;2184:9;2171:23;2203:31;2228:5;2203:31;:::i;:::-;2253:5;-1:-1:-1;2310:2:1;2295:18;;2282:32;2323:33;2282:32;2323:33;:::i;:::-;2375:7;-1:-1:-1;2429:2:1;2414:18;;2401:32;;-1:-1:-1;2484:2:1;2469:18;;2456:32;2511:18;2500:30;;2497:2;;;2548:6;2540;2533:22;2497:2;2592:58;2642:7;2633:6;2622:9;2618:22;2592:58;:::i;:::-;2076:634;;;;-1:-1:-1;2076:634:1;;-1:-1:-1;2669:8:1;;2566:84;2076:634;-1:-1:-1;;;2076:634:1:o;2715:843::-;2821:6;2829;2837;2845;2853;2861;2914:3;2902:9;2893:7;2889:23;2885:33;2882:2;;;2936:6;2928;2921:22;2882:2;2980:9;2967:23;2999:31;3024:5;2999:31;:::i;:::-;3049:5;-1:-1:-1;3106:2:1;3091:18;;3078:32;3119:33;3078:32;3119:33;:::i;:::-;3171:7;-1:-1:-1;3225:2:1;3210:18;;3197:32;;-1:-1:-1;3276:2:1;3261:18;;3248:32;;-1:-1:-1;3331:3:1;3316:19;;3303:33;3359:18;3348:30;;3345:2;;;3396:6;3388;3381:22;3345:2;3440:58;3490:7;3481:6;3470:9;3466:22;3440:58;:::i;:::-;2872:686;;;;-1:-1:-1;2872:686:1;;-1:-1:-1;2872:686:1;;3517:8;;2872:686;-1:-1:-1;;;2872:686:1:o;3563:1002::-;3640:6;3648;3701:2;3689:9;3680:7;3676:23;3672:32;3669:2;;;3722:6;3714;3707:22;3669:2;3766:9;3753:23;3785:31;3810:5;3785:31;:::i;:::-;3835:5;-1:-1:-1;3859:2:1;3897:18;;;3884:32;3935:18;3965:14;;;3962:2;;;3997:6;3989;3982:22;3962:2;4040:6;4029:9;4025:22;4015:32;;4085:7;4078:4;4074:2;4070:13;4066:27;4056:2;;4112:6;4104;4097:22;4056:2;4153;4140:16;4175:2;4171;4168:10;4165:2;;;4181:18;;:::i;:::-;4223:112;4331:2;4262:66;4255:4;4251:2;4247:13;4243:86;4239:95;4223:112;:::i;:::-;4210:125;;4358:2;4351:5;4344:17;4398:7;4393:2;4388;4384;4380:11;4376:20;4373:33;4370:2;;;4424:6;4416;4409:22;4370:2;4484;4479;4475;4471:11;4466:2;4459:5;4455:14;4442:45;4507:14;;4503:23;;;4496:39;;;;3659:906;;4511:5;;-1:-1:-1;3659:906:1;;-1:-1:-1;;3659:906:1:o;4570:297::-;4637:6;4690:2;4678:9;4669:7;4665:23;4661:32;4658:2;;;4711:6;4703;4696:22;4658:2;4748:9;4742:16;4801:5;4794:13;4787:21;4780:5;4777:32;4767:2;;4828:6;4820;4813:22;4872:194;4942:6;4995:2;4983:9;4974:7;4970:23;4966:32;4963:2;;;5016:6;5008;5001:22;4963:2;-1:-1:-1;5044:16:1;;4953:113;-1:-1:-1;4953:113:1:o;5071:1383::-;5225:6;5233;5241;5249;5257;5265;5273;5281;5289;5297;5350:3;5338:9;5329:7;5325:23;5321:33;5318:2;;;5372:6;5364;5357:22;5318:2;5417:9;5404:23;5446:18;5487:2;5479:6;5476:14;5473:2;;;5508:6;5500;5493:22;5473:2;5552:58;5602:7;5593:6;5582:9;5578:22;5552:58;:::i;:::-;5629:8;;-1:-1:-1;5526:84:1;-1:-1:-1;5717:2:1;5702:18;;5689:32;;-1:-1:-1;5733:16:1;;;5730:2;;;5767:6;5759;5752:22;5730:2;;5811:60;5863:7;5852:8;5841:9;5837:24;5811:60;:::i;:::-;5890:8;;-1:-1:-1;5785:86:1;-1:-1:-1;;5972:2:1;5957:18;;5944:32;;-1:-1:-1;6023:2:1;6008:18;;5995:32;;-1:-1:-1;6074:3:1;6059:19;;6046:33;;-1:-1:-1;6129:3:1;6114:19;;6101:33;6143:31;6101:33;6143:31;:::i;:::-;6193:5;-1:-1:-1;6250:3:1;6235:19;;6222:33;6264;6222;6264;:::i;:::-;6316:7;-1:-1:-1;6375:3:1;6360:19;;6347:33;6389;6347;6389;:::i;:::-;6441:7;6431:17;;;5308:1146;;;;;;;;;;;;;:::o;6459:721::-;6549:6;6602:3;6590:9;6581:7;6577:23;6573:33;6570:2;;;6624:6;6616;6609:22;6570:2;6662;6656:9;6704:3;6696:6;6692:16;6774:6;6762:10;6759:22;6738:18;6726:10;6723:34;6720:62;6717:2;;;6785:18;;:::i;:::-;6825:10;6821:2;6814:22;;6873:9;6860:23;6852:6;6845:39;6945:2;6934:9;6930:18;6917:32;6912:2;6904:6;6900:15;6893:57;7011:2;7000:9;6996:18;6983:32;6978:2;6970:6;6966:15;6959:57;7066:2;7055:9;7051:18;7038:32;7079:31;7104:5;7079:31;:::i;:::-;7138:2;7126:15;;7119:30;7130:6;6560:620;-1:-1:-1;;;6560:620:1:o;7185:190::-;7244:6;7297:2;7285:9;7276:7;7272:23;7268:32;7265:2;;;7318:6;7310;7303:22;7265:2;-1:-1:-1;7346:23:1;;7255:120;-1:-1:-1;7255:120:1:o;7380:325::-;7448:6;7456;7509:2;7497:9;7488:7;7484:23;7480:32;7477:2;;;7530:6;7522;7515:22;7477:2;7571:9;7558:23;7548:33;;7631:2;7620:9;7616:18;7603:32;7644:31;7669:5;7644:31;:::i;:::-;7694:5;7684:15;;;7467:238;;;;;:::o;7710:1251::-;7927:6;7935;7943;7951;7959;7967;8020:3;8008:9;7999:7;7995:23;7991:33;7988:2;;;8042:6;8034;8027:22;7988:2;8083:9;8070:23;8060:33;;8144:2;8133:9;8129:18;8116:32;8167:18;8208:2;8200:6;8197:14;8194:2;;;8229:6;8221;8214:22;8194:2;8272:6;8261:9;8257:22;8247:32;;8317:7;8310:4;8306:2;8302:13;8298:27;8288:2;;8344:6;8336;8329:22;8288:2;8389;8376:16;8415:2;8407:6;8404:14;8401:2;;;8436:6;8428;8421:22;8401:2;8496:7;8491:2;8484:3;8476:6;8472:16;8468:2;8464:25;8460:34;8457:47;8454:2;;;8522:6;8514;8507:22;8454:2;8558;8554;8550:11;8540:21;;8580:6;8570:16;;;8639:2;8628:9;8624:18;8611:32;8595:48;;8668:2;8658:8;8655:16;8652:2;;;8689:6;8681;8674:22;8652:2;;8733:72;8797:7;8786:8;8775:9;8771:24;8733:72;:::i;:::-;8824:8;;-1:-1:-1;8707:98:1;-1:-1:-1;8878:77:1;;-1:-1:-1;8947:7:1;8942:2;8927:18;;8878:77;:::i;:::-;8868:87;;7978:983;;;;;;;;:::o;8966:258::-;9034:6;9042;9095:2;9083:9;9074:7;9070:23;9066:32;9063:2;;;9116:6;9108;9101:22;9063:2;-1:-1:-1;;9144:23:1;;;9214:2;9199:18;;;9186:32;;-1:-1:-1;9053:171:1:o;9229:326::-;9306:6;9314;9322;9375:2;9363:9;9354:7;9350:23;9346:32;9343:2;;;9396:6;9388;9381:22;9343:2;-1:-1:-1;;9424:23:1;;;9494:2;9479:18;;9466:32;;-1:-1:-1;9545:2:1;9530:18;;;9517:32;;9333:222;-1:-1:-1;9333:222:1:o;9560:192::-;9617:6;9670:2;9658:9;9649:7;9645:23;9641:32;9638:2;;;9691:6;9683;9676:22;9638:2;9719:27;9736:9;9719:27;:::i;9757:274::-;9886:3;9924:6;9918:13;9940:53;9986:6;9981:3;9974:4;9966:6;9962:17;9940:53;:::i;:::-;10009:16;;;;;9894:137;-1:-1:-1;;9894:137:1:o;16514:442::-;16663:2;16652:9;16645:21;16626:4;16695:6;16689:13;16738:6;16733:2;16722:9;16718:18;16711:34;16754:66;16813:6;16808:2;16797:9;16793:18;16788:2;16780:6;16776:15;16754:66;:::i;:::-;16872:2;16860:15;16877:66;16856:88;16841:104;;;;16947:2;16837:113;;16635:321;-1:-1:-1;;16635:321:1:o;30665:1297::-;30996:25;;;30944:2;31040;31058:18;;;31051:30;;;30969:18;;;31116:22;;;30915:4;;30944:2;31157;;31175:18;;;31216:6;30915:4;31253:683;31267:6;31264:1;31261:13;31253:683;;;31341:6;31328:20;31323:3;31316:33;31408:2;31400:6;31396:15;31383:29;31378:2;31373:3;31369:12;31362:51;31486:4;31451:33;31480:2;31472:6;31468:15;31451:33;:::i;:::-;31447:44;31433:12;;;31426:66;31539:15;;;31526:29;31512:12;;;31505:51;31579:4;31630:15;;;31617:29;31603:12;;;31596:51;31670:4;31721:15;;;31708:29;31694:12;;;31687:51;31761:4;31812:15;;;31799:29;31785:12;;;31778:51;31852:4;31876:12;;;;31911:15;;;;31289:1;31282:9;31253:683;;;-1:-1:-1;31953:3:1;;30924:1038;-1:-1:-1;;;;;;;;;30924:1038:1:o;32544:334::-;32615:2;32609:9;32671:2;32661:13;;32676:66;32657:86;32645:99;;32774:18;32759:34;;32795:22;;;32756:62;32753:2;;;32821:18;;:::i;:::-;32857:2;32850:22;32589:289;;-1:-1:-1;32589:289:1:o;32883:128::-;32923:3;32954:1;32950:6;32947:1;32944:13;32941:2;;;32960:18;;:::i;:::-;-1:-1:-1;32996:9:1;;32931:80::o;33016:274::-;33056:1;33082;33072:2;;-1:-1:-1;;;33114:1:1;33107:88;33218:4;33215:1;33208:15;33246:4;33243:1;33236:15;33072:2;-1:-1:-1;33275:9:1;;33062:228::o;33295:::-;33335:7;33461:1;33393:66;33389:74;33386:1;33383:81;33378:1;33371:9;33364:17;33360:105;33357:2;;;33468:18;;:::i;:::-;-1:-1:-1;33508:9:1;;33347:176::o;33528:125::-;33568:4;33596:1;33593;33590:8;33587:2;;;33601:18;;:::i;:::-;-1:-1:-1;33638:9:1;;33577:76::o;33658:258::-;33730:1;33740:113;33754:6;33751:1;33748:13;33740:113;;;33830:11;;;33824:18;33811:11;;;33804:39;33776:2;33769:10;33740:113;;;33871:6;33868:1;33865:13;33862:2;;;-1:-1:-1;;33906:1:1;33888:16;;33881:27;33711:205::o;33921:196::-;33960:3;33988:5;33978:2;;33997:18;;:::i;:::-;-1:-1:-1;34044:66:1;34033:78;;33968:149::o;34122:195::-;34161:3;34192:66;34185:5;34182:77;34179:2;;;34262:18;;:::i;:::-;-1:-1:-1;34309:1:1;34298:13;;34169:148::o;34322:184::-;-1:-1:-1;;;34371:1:1;34364:88;34471:4;34468:1;34461:15;34495:4;34492:1;34485:15;34511:184;-1:-1:-1;;;34560:1:1;34553:88;34660:4;34657:1;34650:15;34684:4;34681:1;34674:15;34700:154;34786:42;34779:5;34775:54;34768:5;34765:65;34755:2;;34844:1;34841;34834:12
Swarm Source
ipfs://c37cf1022cf4b804ed17a3503023d847e2bff0eceebfaac19ad104fc255be7db
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.