Source Code
Overview
MON Balance
MON Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
TokenizedVault
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity)
/**
*Submitted for verification at monadscan.com on 2025-11-24
*/
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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://consensys.net/diligence/blog/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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or 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 {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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);
}
}
}
/**
* @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 IERC20Permit {
/**
* @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);
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
/**
* @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 SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 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(IERC20 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(IERC20 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(IERC20 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(
IERC20Permit 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(IERC20 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");
}
}
}
/**
* @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]
* ```solidity
* 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.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!Address.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.
*
* 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.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* 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.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
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.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
abstract contract OwnableGuarded {
// ----------------------------------------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------------------------------------
// 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;
// ----------------------------------------------------------------------------------------------------
// Errors
// ----------------------------------------------------------------------------------------------------
error OwnerOnly();
error OwnerAddressRequired();
error ReentrancyGuardReentrantCall();
// ----------------------------------------------------------------------------------------------------
// Storage layout
// ----------------------------------------------------------------------------------------------------
uint256 private _status;
address internal _owner;
// ----------------------------------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------------------------------
/**
* @notice Triggers when contract ownership changes.
* @param previousOwner The previous owner of the contract.
* @param newOwner The new owner of the contract.
*/
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
// ----------------------------------------------------------------------------------------------------
// Modifiers
// ----------------------------------------------------------------------------------------------------
/**
* @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, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// 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 Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
if (msg.sender != _owner) revert OwnerOnly();
_;
}
// ----------------------------------------------------------------------------------------------------
// Functions
// ----------------------------------------------------------------------------------------------------
/**
* @notice Transfers ownership of the contract to the account specified.
* @param newOwner The address of the new owner.
*/
function transferOwnership(address newOwner) external virtual nonReentrant onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
if (newOwner == address(0)) revert OwnerAddressRequired();
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @notice Gets the owner of the contract.
* @return address The address who owns the contract.
*/
function owner() external view virtual returns (address) {
return _owner;
}
}
interface IResourceBasedTimelockedCall {
error Unauthorized();
error HashRequired();
error HashAlreadyEnqueued();
error HashNotEnqueued();
error TimelockInPlace();
error InvalidTimelockDuration();
error InvalidResourceAddress();
struct TimelockedCallInfo {
uint256 targetEpoch; // The unix epoch at which the hash can be consumed
address createdBy; // The address of the scheduler
}
/// @notice Triggers when a hash is scheduled for further execution
event HashScheduled(bytes32 h, address postedBy);
/// @notice Triggers when a hash is consumed by the address specified.
event HashConsumed(bytes32 h, address consumerAddress);
/// @notice Triggers when a hash is cancelled.
event HashCancelled(bytes32 h, address consumerAddress);
function schedule(bytes32 h) external;
function cancel(bytes32 h) external;
function consume(bytes32 h) external;
function hashExists(bytes32 h) external view returns (bool);
function getInfo(bytes32 h) external view returns (TimelockedCallInfo memory);
}
interface IFeeCollectorsAware {
struct CollectorDefinition {
address collectorAddress;
uint256 percentage;
}
function updateFeeCollectors(CollectorDefinition[] calldata collectors) external;
function updatePerformanceFeeCollectors(CollectorDefinition[] calldata collectors) external;
}
interface ISendersWhitelist {
function enableSender(address addr) external;
function disableSender(address addr) external;
function isWhitelisted(address addr) external view returns (bool);
}
abstract contract GuardedProxyOwnable2Steps is Initializable, OwnableGuarded {
error NotConfigured();
error AlreadyConfigured();
error InvalidAddress();
error Unauthorized();
/// @dev The address of the pending owner, if any.
address internal _pendingOwner;
/// @dev Indicates if the contract was configured
bool internal _configured;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/// @dev Throws if the contract is not configured
modifier ifConfigured() {
if (!_configured) revert NotConfigured();
_;
}
/// @dev Throws if the contract was configured already
modifier ifNotConfigured() {
if (_configured) revert AlreadyConfigured();
_;
}
/**
* @notice Starts the ownership transfer of this contract to the address specified.
* @dev The ownership transfer is time-locked. Calling this function cancels any previous scheduled requests.
* @param newOwner The address of the new owner.
*/
function transferOwnership(address newOwner) public virtual override nonReentrant ifConfigured onlyOwner {
_proposeOwnershipTransfer(newOwner);
}
/**
* @notice Accepts the ownership transfer initiated by the current owner of this contract.
*/
function acceptOwnership() public virtual nonReentrant ifConfigured {
if (_pendingOwner != msg.sender) revert Unauthorized();
_transferOwnership(msg.sender);
}
function _proposeOwnershipTransfer(address newOwner) internal {
if ((newOwner == address(0)) || (newOwner == address(this))) revert InvalidAddress();
_pendingOwner = newOwner;
emit OwnershipTransferStarted(_owner, newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @notice Gets the address of the pending owner, if any.
* @return Returns the address of the pending owner. Returns the zero address if there is no pending owner at all.
*/
function pendingOwner() external view returns (address) {
return _pendingOwner;
}
}
abstract contract OperableVault is IFeeCollectorsAware, GuardedProxyOwnable2Steps {
error OperatorOnly();
error OnlyOwnerOrOperator();
error InvalidAccountType();
error InvalidAmount();
error FeesMustSum100();
error SenderNotWhitelisted();
error MissingFeeCollectors();
uint8 constant internal ACCOUNT_TYPE_SUBACCOUNT = 1;
uint8 constant internal ACCOUNT_TYPE_WALLET = 2;
// --------------------------------------------------------------------------
// Storage layout
// --------------------------------------------------------------------------
/// @notice The fee collectors of the vault.
IFeeCollectorsAware.CollectorDefinition[] public feeCollectors;
/// @notice The receipients of performance fees
IFeeCollectorsAware.CollectorDefinition[] public performanceFeeRecipients;
/// @notice The address of the operator.
address public operatorAddress;
/// @notice Indicates whether deposits are paused or not.
bool public depositsPaused;
/// @notice Indicates whether withdrawals are paused or not.
bool public withdrawalsPaused;
/// @notice The contract address for scheduled calls.
address public scheduledCallerAddress;
/// @notice The whitelist of senders, if any.
address public sendersWhitelistAddress;
/// @notice The sub accounts whitelisted
mapping (address => uint8) public whitelistedSubAccounts;
/**
* @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[10] private __gap;
// --------------------------------------------------------------------------
// Events
// --------------------------------------------------------------------------
event SendersWhitelistUpdated(address newWhitelistAddr);
event SubAccountEnabled(address subAccountAddr);
event SubAccountDisabled(address subAccountAddr);
/**
* @notice Triggers when deposits/withdrawals are paused or resumed.
* @param bDepositsPaused The new state for deposits
* @param bWithdrawalsPaused The new state for withdrawals
*/
event DepositWithdrawalStatusChanged(bool bDepositsPaused, bool bWithdrawalsPaused);
// --------------------------------------------------------------------------
// Modifiers
// --------------------------------------------------------------------------
/// @dev Throws if the sender is not the current operator
modifier onlyOperator() {
if (msg.sender != operatorAddress) revert OperatorOnly();
_;
}
/// @dev Throws if the sender is not the current owner or operator
modifier onlyOwnerOrOperator() {
if ((msg.sender != operatorAddress) && (msg.sender != _owner)) revert OnlyOwnerOrOperator();
_;
}
/// @dev Throws if the message sender is not whitelisted, unless there is no whitelist defined.
modifier ifSenderWhitelisted() {
if (
(msg.sender != _owner) &&
(msg.sender != operatorAddress) &&
(sendersWhitelistAddress != address(0)) &&
(!ISendersWhitelist(sendersWhitelistAddress).isWhitelisted(msg.sender))
) revert SenderNotWhitelisted();
_;
}
// --------------------------------------------------------------------------
// Functions
// --------------------------------------------------------------------------
/**
* @notice Pauses and/or resumes deposits and/or withdrawals.
* @param bPauseDeposits Pass "true" to pause deposits. Pass "false" to resume deposits.
* @param bPauseWithdrawals Pass "true" to pause withdrawals. Pass "false" to resume withdrawals.
*/
function pauseDepositsAndWithdrawals(bool bPauseDeposits, bool bPauseWithdrawals) external nonReentrant ifConfigured onlyOwnerOrOperator {
depositsPaused = bPauseDeposits;
withdrawalsPaused = bPauseWithdrawals;
emit DepositWithdrawalStatusChanged(depositsPaused, withdrawalsPaused);
}
/**
* @notice Updates the address of whitelisted message senders.
* @dev The whitelist address specified can be the zero address in order to represent that the vault does not require a whitelist for message senders.
* @param newWhitelistAddr The address of the new whitelist, which can be the zero address.
*/
function updateSendersWhitelist(address newWhitelistAddr) external nonReentrant ifConfigured onlyOwnerOrOperator {
sendersWhitelistAddress = newWhitelistAddr;
emit SendersWhitelistUpdated(newWhitelistAddr);
}
/**
* @notice Enables the sub account specified.
* @param addr The address to enable.
* @param accountType The type of account: 1 = Sub Account, 2 = EOA or Wallet.
*/
function enableSubAccount(
address addr,
uint8 accountType
) external nonReentrant ifConfigured onlyOwnerOrOperator {
if ((addr == address(0)) || (addr == address(this))) revert InvalidAddress();
if ((accountType != ACCOUNT_TYPE_SUBACCOUNT) && (accountType != ACCOUNT_TYPE_WALLET)) revert InvalidAccountType();
whitelistedSubAccounts[addr] = accountType;
emit SubAccountEnabled(addr);
}
/**
* @notice Disables the sub account specified.
* @param addr The address to disable.
*/
function disableSubAccount(address addr) external nonReentrant ifConfigured onlyOwnerOrOperator {
delete whitelistedSubAccounts[addr];
emit SubAccountDisabled(addr);
}
/**
* @notice Updates the fee collectors of this vault.
* @param collectors Specifies the new fee collectors.
*/
function updateFeeCollectors(
IFeeCollectorsAware.CollectorDefinition[] calldata collectors
) external virtual override nonReentrant ifConfigured onlyOwner {
uint256 acum;
uint256 t = collectors.length;
if (t < 1) revert MissingFeeCollectors();
delete feeCollectors;
for (uint256 i; i < t; i++) {
if (collectors[i].percentage < 1) revert InvalidAmount();
if (collectors[i].collectorAddress == address(0)) revert InvalidAddress();
acum += collectors[i].percentage;
feeCollectors.push(collectors[i]);
}
if (acum != 100_0000) revert FeesMustSum100();
}
/**
* @notice Updates the recipients of performance fees.
* @param collectors Specifies the new fee collectors.
*/
function updatePerformanceFeeCollectors(
IFeeCollectorsAware.CollectorDefinition[] calldata collectors
) external override nonReentrant ifConfigured onlyOwner {
uint256 acum;
uint256 t = collectors.length;
if (t < 1) revert MissingFeeCollectors();
delete performanceFeeRecipients;
for (uint256 i; i < t; i++) {
if (collectors[i].percentage < 1) revert InvalidAmount();
if (collectors[i].collectorAddress == address(0)) revert InvalidAddress();
acum += collectors[i].percentage;
performanceFeeRecipients.push(collectors[i]);
}
if (acum != 100_0000) revert FeesMustSum100();
}
/**
* @notice Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* @dev Can only be called by the current owner.
* @param newOwner The address of the new owner.
*/
function transferOwnership(address newOwner) public virtual override nonReentrant ifConfigured onlyOwner {
_scheduleOwnershipTransfer(newOwner);
}
/**
* @notice Accepts the ownership transfer initiated by the current owner of this contract.
*/
function acceptOwnership() public virtual override ifConfigured {
bytes32 h = keccak256(abi.encode(
abi.encodeWithSignature(
"transferOwnership(address)",
msg.sender
)
));
super.acceptOwnership();
IResourceBasedTimelockedCall(scheduledCallerAddress).consume(h);
}
function _scheduleOwnershipTransfer(address newOwner) internal {
bytes32 prevOwnershipHash = (_pendingOwner == address(0)) ? bytes32(0) : keccak256(abi.encode(
abi.encodeWithSignature(
"transferOwnership(address)",
_pendingOwner
)
));
// Schedule the ownership transfer of the future owner specified
bytes32 futureOwnershipHash = keccak256(abi.encode(
abi.encodeWithSignature(
"transferOwnership(address)",
newOwner
)
));
_proposeOwnershipTransfer(newOwner);
if (prevOwnershipHash != bytes32(0)) IResourceBasedTimelockedCall(scheduledCallerAddress).cancel(prevOwnershipHash);
IResourceBasedTimelockedCall(scheduledCallerAddress).schedule(futureOwnershipHash);
}
function getFeeCollectors() external view returns (IFeeCollectorsAware.CollectorDefinition[] memory) {
return feeCollectors;
}
function getPerformanceFeeRecipients() external view returns (IFeeCollectorsAware.CollectorDefinition[] memory) {
return performanceFeeRecipients;
}
}
interface IMintableBurnable {
/**
* @notice Issues a given amount of tokens to the address specified.
* @param addr The address of the receiver.
* @param amount The number of tokens to issue.
*/
function mint(address addr, uint256 amount) external;
/**
* @notice Burns tokens from the address specified.
* @param addr The token holder.
* @param amount The number of tokens to burn.
*/
function burn(address addr, uint256 amount) external;
}
interface IAllocableSubAccount {
function deposit(address tokenAddr, uint256 amount) external;
function withdraw(address tokenAddr, uint256 amount, address payable receivingAddr) external;
}
interface IEnableOnlyAssetsWhitelist {
error ZeroAddressError();
error WhitelistLimitReached();
error InvalidOraclePrice();
error InvalidAddress();
error ReferenceAssetNotPermitted();
error InvalidDecimalPlaces();
error AssetAlreadyEnabled();
error StalePrice();
error RoundNotComplete();
error InvalidTimePeriod();
error InvalidOracleTimestamp();
struct OracleInfo {
address oracleAddress;
address tokenAddress;
uint8 oracleDecimals;
uint8 tokenDecimals;
}
function enableAsset(
address depositableAssetAddr,
address oracleAddr,
uint256 newOracleDuration
) external;
function getWhitelistedAssets() external view returns (address[] memory);
function isWhitelisted(address addr) external view returns (bool);
function getOracleAddress(address assetAddr) external view returns (address);
function fromInputAssetToReferenceAsset(address assetAddr, uint256 amount) external view returns (uint256);
function getTotalAssetsValuation(uint256 externalAssets) external view returns (uint256);
function convertToShares(
address lpTokenAddress,
address assetInAddr,
address vaultAddr,
uint256 assetInAmount,
uint256 externalAssets
) external view returns (uint256 shares, uint256 amountInReferenceTokens);
function REFERENCE_ASSET() external view returns (address);
function REFERENCE_ASSET_DECIMALS() external view returns (uint8);
}
/**
* @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);
}
/**
* @title Represents an oraclized vault. The vault is a guarded proxy, ownable in 2 steps. The oracle is ChainLink by default.
*/
abstract contract OraclizedMultiAssetVault is OperableVault {
using MathUpgradeable for uint256;
error ZeroAddressError();
error WhitelistLimitReached();
error AssetNotWhitelisted();
error CollectableFeesExceeded(uint256 fee, uint256 remaining);
error InvalidTimestamp();
error DepositsPaused();
error InvalidReceiver();
error MaxDepositAmountReached();
error InsufficientShares();
error MaxAllowedChangeReached();
error AccountNotWhitelisted();
error InvalidExternalAssets();
error ReferenceAssetMismatch();
error FeeAmountTooLow();
error DepositCapReached();
// --------------------------------------------------------------------------
// Constants
// --------------------------------------------------------------------------
/// @dev A reasonable time-window for manipulating the block timestamp as a miner.
uint256 constant internal _TIMESTAMP_MANIPULATION_WINDOW = 5 minutes;
/// @dev The number of seconds per year.
uint256 constant internal _SECONDS_PER_YEAR = 60 * 60 * 24 * 365;
// --------------------------------------------------------------------------
// Storage layout
// --------------------------------------------------------------------------
/// @notice The amount of assets available on other chains, as reported by the accountant.
uint256 public externalAssets;
/// @notice The total amount of collectable fees, at any point in time.
uint256 public totalCollectableFees;
/// @notice The maximum allowed change, expressed in bps.
uint256 public maxChangePercent;
/// @notice The last time external assets were updated.
uint256 public assetsUpdatedOn;
/// @notice The last time fees were charged.
uint256 public feesTimestamp;
/// @notice The management fee, expressed in bps.
uint256 public managementFeePercent;
/// @notice The maximum deposit amount, expressed in reference assets.
uint256 public maxDepositAmount;
/// @notice The address of the reference asset.
address internal _referenceAsset;
/// @notice The address of the LP token.
address public lpTokenAddress;
/// @notice The whitelisted assets
address public assetsWhitelistAddress;
/// @notice The deposit cap. It is the valuation of the total assets expressed in reference tokens.
uint256 public depositCap;
/**
* @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[9] private __gap;
// --------------------------------------------------------------------------
// Events
// --------------------------------------------------------------------------
event FeesCollected();
event MaxChangePercentUpdated(uint256 newValue);
/// @notice Triggers when you change the management fee.
event ManagementFeeUpdated(uint256 newManagementFeePercent);
/**
* @notice Triggers when the management fee gets charged.
* @param managementFeeAmount The amount charged as management fee.
*/
event ManagementFeeCharged(uint256 managementFeeAmount);
event Deposit(address assetIn, uint256 amountIn, uint256 shares, address indexed senderAddr, address indexed receiverAddr);
// --------------------------------------------------------------------------
// Modifiers
// --------------------------------------------------------------------------
/// @dev Throws if the asset specified is not whitelisted.
modifier ifAssetWhitelisted(address assetAddr) {
if ((assetAddr != _referenceAsset) && (!IEnableOnlyAssetsWhitelist(assetsWhitelistAddress).isWhitelisted(assetAddr))) revert AssetNotWhitelisted();
_;
}
/// @dev Throws if deposits are paused.
modifier ifDepositsNotPaused() {
if (depositsPaused) revert DepositsPaused();
_;
}
// --------------------------------------------------------------------------
// Functions
// --------------------------------------------------------------------------
/**
* @notice Updates the assets whitelist of this vault.
* @param newWhitelistAddr The address of the new whitelist.
*/
function updateAssetsWhitelist(address newWhitelistAddr) external nonReentrant ifConfigured onlyOwner {
if (newWhitelistAddr == address(0)) revert InvalidAddress();
assetsWhitelistAddress = newWhitelistAddr;
if (_referenceAsset != IEnableOnlyAssetsWhitelist(newWhitelistAddr).REFERENCE_ASSET()) revert ReferenceAssetMismatch();
}
/**
* @notice Updates the total amount of external assets.
* @param externalAssetsAmount The amount of external assets. The amount must be expressed in reference tokens.
*/
function updateTotalAssets(uint256 externalAssetsAmount) external nonReentrant ifConfigured onlyOwnerOrOperator {
uint256 perChange = getChangePercentage(externalAssetsAmount);
uint256 maxAllowedChangePerc = getMaxAllowedChange();
// slither-disable-next-line timestamp
if (perChange > maxAllowedChangePerc) revert MaxAllowedChangeReached();
externalAssets = externalAssetsAmount;
assetsUpdatedOn = block.timestamp;
}
/**
* @notice Deposits a given amount of input tokens in the vault.
* @param assetIn The input token. Reverts if the token is not whitelisted.
* @param amountIn The deposit amount.
* @param receiverAddr The address that will receive the shares.
* @return shares Returns the number of shares
*/
function deposit(
address assetIn,
uint256 amountIn,
address receiverAddr
) external nonReentrant ifConfigured ifDepositsNotPaused ifSenderWhitelisted ifAssetWhitelisted(assetIn) returns (uint256 shares) {
shares = _beforeDeposit(assetIn, amountIn, receiverAddr);
_afterPermit(assetIn, amountIn, receiverAddr, shares);
}
/**
* @notice Deposits a given amount of input tokens in the vault through an ERC20 Permit.
* @param assetIn The input token. Reverts if the token is not whitelisted.
* @param amountIn The deposit amount.
* @param receiverAddr The address that will receive the shares.
* @param deadline The deadline of the permit.
* @param r The signature component "R"
* @param s The signature component "S"
* @param v The signature component "V"
* @return shares Returns the number of shares
*/
function depositWithPermit(
address assetIn,
uint256 amountIn,
address receiverAddr,
uint256 deadline,
bytes32 r,
bytes32 s,
uint8 v
) external nonReentrant ifConfigured ifDepositsNotPaused ifSenderWhitelisted ifAssetWhitelisted(assetIn) returns (uint256 shares) {
shares = _beforeDeposit(assetIn, amountIn, receiverAddr);
IERC20PermitUpgradeable(assetIn).permit(msg.sender, address(this), amountIn, deadline, v, r, s);
_afterPermit(assetIn, amountIn, receiverAddr, shares);
}
/**
* @notice Deposits a given amount of reference assets in the account specified.
* @dev The account must be whitelisted. It can be a sub account or a wallet.
* @param inputAssetAddr The address of the asset to move.
* @param depositAmount The assets amount to deposit.
* @param subAccountAddr The address of the sub account.
*/
function depositToSubaccount(
address inputAssetAddr,
uint256 depositAmount,
address subAccountAddr
) external nonReentrant ifConfigured onlyOwnerOrOperator {
if (depositAmount < 1) revert InvalidAmount();
uint8 accountType = whitelistedSubAccounts[subAccountAddr];
if (accountType < 1) revert AccountNotWhitelisted();
// Convert the input amount to the respective amount in reference tokens
uint256 amountInReferenceAssets = (inputAssetAddr == _referenceAsset) ? depositAmount : _fromInputAssetToReferenceAsset(inputAssetAddr, depositAmount);
externalAssets += amountInReferenceAssets;
if (accountType == ACCOUNT_TYPE_SUBACCOUNT) {
// Deposit funds in the sub account
SafeERC20.safeApprove(IERC20(inputAssetAddr), subAccountAddr, depositAmount);
IAllocableSubAccount(subAccountAddr).deposit(inputAssetAddr, depositAmount);
SafeERC20.safeApprove(IERC20(inputAssetAddr), subAccountAddr, 0);
} else {
// Transfer the funds to a whitelisted wallet or EOA
SafeERC20.safeTransfer(IERC20(inputAssetAddr), subAccountAddr, depositAmount);
}
}
/**
* @notice Withdraws a given amount of reference assets from the sub account specified.
* @param inputAssetAddr The address of the asset to move.
* @param amount The amount of reference assets to withdraw.
* @param subAccountAddr The address of the sub account.
*/
function withdrawFromSubaccount(
address inputAssetAddr,
uint256 amount,
address subAccountAddr
) external nonReentrant ifConfigured onlyOwnerOrOperator {
if (amount < 1) revert InvalidAmount();
uint8 accountType = whitelistedSubAccounts[subAccountAddr];
if (accountType < 1) revert AccountNotWhitelisted();
// Convert the input amount to the respective amount in reference tokens
uint256 amountInReferenceAssets = (inputAssetAddr == _referenceAsset) ? amount : _fromInputAssetToReferenceAsset(inputAssetAddr, amount);
if (amountInReferenceAssets > externalAssets) revert InvalidExternalAssets();
externalAssets -= amountInReferenceAssets;
if (accountType == ACCOUNT_TYPE_SUBACCOUNT) {
IAllocableSubAccount(subAccountAddr).withdraw(inputAssetAddr, amount, payable(address(this)));
} else {
// slither-disable-next-line arbitrary-send-erc20
SafeERC20.safeTransferFrom(IERC20(inputAssetAddr), subAccountAddr, address(this), amount);
}
}
/**
* @notice Updates the maximum allowed change.
* @param newValue The new value, expressed as a percentage with 2 decimal places.
*/
function updateMaxChangePercent(uint256 newValue) external nonReentrant ifConfigured onlyOwnerOrOperator {
// Build the hash of this call and attempt to consume it. The call reverts if the hash can't be consumed.
bytes32 h = keccak256(abi.encode(
abi.encodeWithSignature(
"updateMaxChangePercent(uint256)",
newValue
)
));
maxChangePercent = newValue;
emit MaxChangePercentUpdated(newValue);
IResourceBasedTimelockedCall(scheduledCallerAddress).consume(h);
}
/**
* @notice Updates the management fee.
* @param newManagementFeePercent The management fee. This is a percentage with 2 decimal places.
*/
function updateManagementFee(
uint256 newManagementFeePercent
) external nonReentrant ifConfigured onlyOwner {
// Build the hash of this call and attempt to consume it. The call reverts if the hash can't be consumed.
bytes32 h = keccak256(abi.encode(
abi.encodeWithSignature(
"updateManagementFee(uint256)",
newManagementFeePercent
)
));
managementFeePercent = newManagementFeePercent;
emit ManagementFeeUpdated(newManagementFeePercent);
IResourceBasedTimelockedCall(scheduledCallerAddress).consume(h);
}
/**
* @notice Charges the management fee.
*/
function chargeManagementFee() external virtual nonReentrant ifConfigured {
uint256 totalAssetsAmount = _getTotalAssets();
uint256 applicableManagementFee = (totalAssetsAmount * managementFeePercent * (block.timestamp - feesTimestamp)) / _SECONDS_PER_YEAR / 1e4;
feesTimestamp = block.timestamp;
totalCollectableFees += applicableManagementFee;
emit ManagementFeeCharged(applicableManagementFee);
}
/**
* @notice Collects the fees available in the vault.
* @dev This endpoint can be called by any address.
*/
function collectFees() external nonReentrant ifConfigured {
uint256 t = feeCollectors.length;
if (t < 1) revert MissingFeeCollectors();
uint256 x = totalCollectableFees;
if (x > 0) {
uint256[] memory amounts = new uint256[](t);
for (uint256 i; i < t; i++) {
uint256 collectableFee = (feeCollectors[i].percentage * x) / 1e6;
// slither-disable-next-line timestamp
if (collectableFee > totalCollectableFees) revert CollectableFeesExceeded(collectableFee, totalCollectableFees);
amounts[i] = collectableFee;
totalCollectableFees -= collectableFee;
}
emit FeesCollected();
// Untrusted changes
for (uint256 i; i < t; i++) {
SafeERC20.safeTransfer(IERC20(_referenceAsset), feeCollectors[i].collectorAddress, amounts[i]);
}
}
}
function _afterPermit(
address assetIn,
uint256 amountIn,
address receiverAddr,
uint256 shares
) private {
// Log the event
emit Deposit(assetIn, amountIn, shares, msg.sender, receiverAddr);
// Transfer the input tokens
SafeERC20.safeTransferFrom(IERC20(assetIn), msg.sender, address(this), amountIn);
// Issue (mint) LP tokens to the receiver
IMintableBurnable(lpTokenAddress).mint(receiverAddr, shares);
}
function _beforeDeposit(
address assetIn,
uint256 amountIn,
address receiverAddr
) private view returns (uint256) {
if (amountIn < 1) revert InvalidAmount();
if (receiverAddr == address(0) || receiverAddr == address(this)) revert InvalidReceiver();
(uint256 shares, uint256 depositAmountInReferenceTokens) = previewDeposit(assetIn, amountIn);
if (shares < 1) revert InsufficientShares();
if (depositAmountInReferenceTokens > maxDepositAmount) revert MaxDepositAmountReached();
uint256 totalAssetsValuationInRefTokens = depositAmountInReferenceTokens + _getTotalAssets();
if (totalAssetsValuationInRefTokens > depositCap) revert DepositCapReached();
return shares;
}
/**
* @notice Previews the deposit of a whitelisted asset.
* @param assetIn The asset to deposit
* @param amountIn The deposit amount
* @return uint256 The equivalent number of shares
* @return uint256 The deposit amount expressed in reference tokens
*/
function previewDeposit(
address assetIn,
uint256 amountIn
) public view returns (uint256, uint256) {
return IEnableOnlyAssetsWhitelist(assetsWhitelistAddress).convertToShares(lpTokenAddress, assetIn, address(this), amountIn, externalAssets);
}
/**
* @notice Gets the change percentage of the amount specified.
* @param externalAssetsAmount The amount of external assets.
* @return uint256 The change percentage.
*/
function getChangePercentage(uint256 externalAssetsAmount) public view returns (uint256) {
if (externalAssets < 1) return uint256(0);
if (externalAssetsAmount < 1) return uint256(10000);
return (externalAssetsAmount > externalAssets)
? ((externalAssetsAmount * 10000) / externalAssets) - 10000
: ((externalAssets * 10000) / externalAssetsAmount) - 10000;
}
/**
* @notice Gets the maximum allowed change since the last update.
* @return uint256 The maximum allowed change, as a percentage.
*/
function getMaxAllowedChange() public view returns (uint256) {
// slither-disable-next-line timestamp
if (block.timestamp + _TIMESTAMP_MANIPULATION_WINDOW < assetsUpdatedOn) revert InvalidTimestamp();
// (Max change per day * Time interval in seconds since last update) / (60 * 60 * 24)
return (maxChangePercent * (block.timestamp - assetsUpdatedOn)) / uint256(86400);
}
function _fromInputAssetToReferenceAsset(
address depositableAssetAddr,
uint256 amountIn
) internal virtual view returns (uint256) {
return IEnableOnlyAssetsWhitelist(assetsWhitelistAddress).fromInputAssetToReferenceAsset(depositableAssetAddr, amountIn);
}
/// @dev Internal conversion function (from shares to assets) with support for rounding direction.
function _convertToAssets(uint256 shares, MathUpgradeable.Rounding rounding) internal view returns (uint256) {
uint256 tSupply = IERC20(lpTokenAddress).totalSupply();
return (tSupply < 1) ? shares : shares.mulDiv(_getTotalAssets(), tSupply, rounding);
}
/// @dev Gets the amount of assets managed by the vault. The amount is expressed in reference tokens.
function _getTotalAssets() internal virtual view returns (uint256) {
return IEnableOnlyAssetsWhitelist(assetsWhitelistAddress).getTotalAssetsValuation(externalAssets);
}
/**
* @notice Gets the amount of total assets managed by the vault.
* @return uint256 The amount of total assets managed by the vault.
*/
function getTotalAssets() external virtual view returns (uint256) {
return _getTotalAssets();
}
}
library DateUtils {
// The number of seconds per day
uint256 internal constant SECONDS_PER_DAY = 24 * 60 * 60;
// The number of seconds per hour
uint256 internal constant SECONDS_PER_HOUR = 60 * 60;
// The number of seconds per minute
uint256 internal constant SECONDS_PER_MINUTE = 60;
// The offset from 01/01/1970
int256 internal constant OFFSET19700101 = 2440588;
function timestampToDate(uint256 ts) internal pure returns (uint256 year, uint256 month, uint256 day) {
(year, month, day) = _daysToDate(ts / SECONDS_PER_DAY);
}
function timestampToDateTime(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) {
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
uint256 secs = timestamp % SECONDS_PER_DAY;
hour = secs / SECONDS_PER_HOUR;
secs = secs % SECONDS_PER_HOUR;
minute = secs / SECONDS_PER_MINUTE;
second = secs % SECONDS_PER_MINUTE;
}
function timestampFromDateTime(uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) internal pure returns (uint256 timestamp) {
timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second;
}
/**
* @notice Calculate year/month/day from the number of days since 1970/01/01 using the date conversion algorithm from http://aa.usno.navy.mil/faq/docs/JD_Formula.php and adding the offset 2440588 so that 1970/01/01 is day 0
* @dev Taken from https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary/blob/master/contracts/BokkyPooBahsDateTimeLibrary.sol
* @param _days The year
* @return year The year
* @return month The month
* @return day The day
*/
function _daysToDate (uint256 _days) internal pure returns (uint256 year, uint256 month, uint256 day) {
int256 __days = int256(_days);
int256 x = __days + 68569 + OFFSET19700101;
int256 n = 4 * x / 146097;
x = x - (146097 * n + 3) / 4;
int256 _year = 4000 * (x + 1) / 1461001;
x = x - 1461 * _year / 4 + 31;
int256 _month = 80 * x / 2447;
int256 _day = x - 2447 * _month / 80;
x = _month / 11;
_month = _month + 2 - 12 * x;
_year = 100 * (n - 49) + _year + x;
year = uint256(_year);
month = uint256(_month);
day = uint256(_day);
}
/**
* @notice Calculates the number of days from 1970/01/01 to year/month/day using the date conversion algorithm from http://aa.usno.navy.mil/faq/docs/JD_Formula.php and subtracting the offset 2440588 so that 1970/01/01 is day 0
* @dev Taken from https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary/blob/master/contracts/BokkyPooBahsDateTimeLibrary.sol
* @param year The year
* @param month The month
* @param day The day
* @return _days Returns the number of days
*/
function _daysFromDate (uint256 year, uint256 month, uint256 day) internal pure returns (uint256 _days) {
require(year >= 1970, "Error");
int256 _year = int256(year);
int256 _month = int256(month);
int256 _day = int256(day);
int256 __days = _day
- 32075
+ 1461 * (_year + 4800 + (_month - 14) / 12) / 4
+ 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12
- 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4
- OFFSET19700101;
_days = uint256(__days);
}
}
abstract contract TimelockedVault is OraclizedMultiAssetVault {
error WithdrawalsPaused();
error WithdrawalLimitReached();
error AmountTooLow();
error NoSharesForReceiver();
error TooEarly();
error NothingToProcess();
error LimitRequired();
error VaultNotTimelocked();
error InvalidDepositLimit();
error InvalidWithdrawalLimit();
/// @dev The liquidation hour defaults to 0:00 UTC
uint8 constant internal _DEFAULT_LIQUIDATION_HOUR = 0;
// --------------------------------------------------------------------------
// Storage layout
// --------------------------------------------------------------------------
/// @notice The maximum withdrawal amount.
uint256 public maxWithdrawalAmount;
/// @notice The fee applicable to instant redemptions, expressed in bps.
uint256 public instantRedemptionFee;
/// @notice The duration of lagged redemptions.
uint256 public lagDuration;
/// @notice The fee applicable to lagged redemptions.
uint256 public withdrawalFee;
/// @notice The total number of shares that need to be burned at the current point in time.
uint256 public globalLiabilityShares;
/// @dev The number of shares (LP tokens) that need to be burned on a given point in time.
mapping (bytes32 => uint256) internal _dailyRequirement;
/// @dev The number of shares that can be burned by a given address at a specific point in time
mapping (bytes32 => mapping(address => uint256)) internal _burnableAmounts;
/// @dev The list of addresses that can claim funds at a given point in time.
mapping (bytes32 => address[]) internal _uniqueReceiversPerCluster;
/// @dev The index of each unique receiver per cluster
mapping (bytes32 => mapping(address => uint256)) internal _receiverIndexes;
/// @notice Indicates if the redemption fee stays in the vault, giving a PnL boost.
bool public keepFeeInVault;
/**
* @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[9] private __gap;
// --------------------------------------------------------------------------
// Events
// --------------------------------------------------------------------------
/**
* @notice This event is triggered when the holder of LP tokens requests a redemption.
* @dev This event is triggered if the redemptions are lagged.
* @param shares The number of shares (LP tokens) to burn.
* @param holderAddr The address of the holder.
* @param receiverAddr The address of the receiver.
*/
event WithdrawalRequested(uint256 shares, address indexed holderAddr, address indexed receiverAddr);
/**
* @notice This event is triggered when a lagged redemption is processed.
* @param assetsAmount The amount of underlying assets sent to the receiving address.
* @param receiverAddr The address of the receiver.
*/
event WithdrawalProcessed(uint256 assetsAmount, address indexed receiverAddr);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
// --------------------------------------------------------------------------
// Modifiers
// --------------------------------------------------------------------------
modifier ifWithdrawalsNotPaused() {
if (withdrawalsPaused) revert WithdrawalsPaused();
_;
}
// --------------------------------------------------------------------------
// Functions
// --------------------------------------------------------------------------
/**
* @notice Updates the fee applicable to instant redemptions.
* @param newValue The new fee.
* @param pKeepFeeInVault If true, the redemption fee stays in the vault giving a PnL boost.
*/
function updateInstantRedemptionFee(
uint256 newValue,
bool pKeepFeeInVault
) external nonReentrant ifConfigured onlyOwner {
instantRedemptionFee = newValue;
keepFeeInVault = pKeepFeeInVault;
}
/**
* @notice Updates the issuance and redemption settings of the vault.
* @param newMaxDepositAmount The maximum deposit amount of reference assets (say USDC) investors are allowed to deposit in the vault.
* @param newMaxWithdrawalAmount The maximum withdrawal amount of the vault, expressed in reference assets (for example: USDC)
*/
function updateLimits(
uint256 newMaxDepositAmount,
uint256 newMaxWithdrawalAmount,
uint256 newDepositCap
) external nonReentrant ifConfigured onlyOwner {
if (newMaxDepositAmount < 1) revert InvalidDepositLimit();
if (newMaxWithdrawalAmount < 1) revert InvalidWithdrawalLimit();
maxDepositAmount = newMaxDepositAmount;
maxWithdrawalAmount = newMaxWithdrawalAmount;
depositCap = newDepositCap;
}
/**
* @notice Redeems the number of shares specified, instantly.
* @dev The redemption transfers reference tokens only. Throws in case of insufficient balance.
* @param shares The number of shares to redeem.
* @param receiverAddr The address of the receiver.
*/
function instantRedeem(
uint256 shares,
address receiverAddr
) external nonReentrant ifConfigured ifWithdrawalsNotPaused ifSenderWhitelisted {
// Checks
if ((receiverAddr == address(0)) || (receiverAddr == address(this))) revert InvalidReceiver();
if (shares < 1) revert InvalidAmount();
_executeRedemption(shares, receiverAddr, true);
}
/**
* @notice Requests the redemption of the shares specified.
* @dev Throws if the vault is not time-locked.
* @param shares The number of shares to redeem.
* @param receiverAddr The receiving address.
* @return claimableEpoch The Unix epoch at which the redemption can take place.
*/
function requestRedeem(
uint256 shares,
address receiverAddr
) external nonReentrant ifConfigured ifWithdrawalsNotPaused ifSenderWhitelisted returns (
uint256 claimableEpoch,
uint256 year,
uint256 month,
uint256 day
) {
// Validate the input parameters
if ((receiverAddr == address(0)) || (receiverAddr == address(this))) revert InvalidReceiver();
if (shares < 1) revert InvalidAmount();
(uint256 assetsAmount, uint256 assetsAfterFee) = _previewRedemption(shares, withdrawalFee);
if (assetsAmount > maxWithdrawalAmount) revert WithdrawalLimitReached();
if (assetsAfterFee < 1) revert AmountTooLow();
// If the vault has no time-lock then it doesn't make sense to request a redemption (tx1) and claim later (tx2).
// Users should call the function "instantRedeem()" instead.
if (lagDuration < 1) revert VaultNotTimelocked();
// The time slot (cluster) of the lagged withdrawal
(year, month, day) = DateUtils.timestampToDate(block.timestamp + _TIMESTAMP_MANIPULATION_WINDOW + lagDuration);
// The hash of the cluster
bytes32 dailyCluster = keccak256(abi.encode(year, month, day));
// The withdrawal will be processed at the following epoch
claimableEpoch = DateUtils.timestampFromDateTime(year, month, day, _DEFAULT_LIQUIDATION_HOUR, 0, 0);
// Trusted internal changes
globalLiabilityShares += shares;
_dailyRequirement[dailyCluster] += shares;
// Unique receivers by date. We will transfer underlying tokens to this receiver shortly.
if (_burnableAmounts[dailyCluster][receiverAddr] == 0) {
_uniqueReceiversPerCluster[dailyCluster].push(receiverAddr);
_receiverIndexes[dailyCluster][receiverAddr] = _uniqueReceiversPerCluster[dailyCluster].length;
}
_burnableAmounts[dailyCluster][receiverAddr] += shares;
emit WithdrawalRequested(shares, msg.sender, receiverAddr);
// Trusted external changes
SafeERC20.safeTransferFrom(IERC20(lpTokenAddress), msg.sender, address(this), shares);
}
/**
* @notice Allows any public address to process the scheduled withdrawal requests of the receiver specified.
* @dev Throws if the receiving address is not the legitimate address you registered via "requestRedeem()"
* @param year The year component of the claim. It can be a past date.
* @param month The month component of the claim. It can be a past date.
* @param day The day component of the claim. It can be a past date.
* @param receiverAddr The address of the legitimate receiver of the funds.
* @return uint256 The effective number of shares (LP tokens) that were burnt from the liquidity pool.
* @return uint256 The effective amount of underlying assets that were transfered to the receiver.
*/
function claim(
uint256 year,
uint256 month,
uint256 day,
address receiverAddr
) external nonReentrant ifConfigured ifWithdrawalsNotPaused ifSenderWhitelisted returns (
uint256,
uint256
) {
bytes32 dailyCluster = keccak256(abi.encode(year, month, day));
// The number of shares to burn for a given cluster and receiver
uint256 shares = _burnableAmounts[dailyCluster][receiverAddr];
if (shares < 1) revert NoSharesForReceiver();
// Make sure withdrawals are processed at the expected epoch only.
// slither-disable-next-line timestamp
if (
(lagDuration > 0) &&
(msg.sender != _owner) &&
(msg.sender != operatorAddress) &&
(block.timestamp + _TIMESTAMP_MANIPULATION_WINDOW < DateUtils.timestampFromDateTime(year, month, day, _DEFAULT_LIQUIDATION_HOUR, 0, 0))
) {
revert TooEarly();
}
// Trusted oracle call (view)
(uint256 assetsAmount, uint256 assetsAfterFee) = _previewRedemption(shares, withdrawalFee);
// The withdrawal fee to apply
uint256 applicableFee = assetsAmount - assetsAfterFee;
// Internal state changes (trusted)
_burnableAmounts[dailyCluster][receiverAddr] = 0; // Same as substract, but setting this back to zero is more efficient.
_dailyRequirement[dailyCluster] -= shares;
globalLiabilityShares -= shares;
totalCollectableFees += applicableFee;
_deleteReceiver(dailyCluster, receiverAddr);
emit WithdrawalProcessed(assetsAfterFee, receiverAddr);
// [Trusted external change]: alter the total supply of LP tokens.
// The external call below is considered trusted because the vault is allowed to burn LP tokens.
IMintableBurnable(lpTokenAddress).burn(address(this), shares);
// [Untrusted external change]: defer the ERC20 transfer to the Reference Asset
SafeERC20.safeTransfer(IERC20(_referenceAsset), receiverAddr, assetsAfterFee);
return (shares, assetsAfterFee);
}
/**
* @notice Processes all of the withdrawal requests scheduled for the date specified.
* @dev Throws if the date is earlier than the liquidation/processing hour.
* @param year The year component of the claim. It can be a past date.
* @param month The month component of the claim. It can be a past date.
* @param day The day component of the claim. It can be a past date.
* @param maxLimit The number of transactions to process. The maximum is defined by the function "getScheduledTransactionsByDate()"
*/
function processAllClaimsByDate(
uint256 year,
uint256 month,
uint256 day,
uint256 maxLimit
) external nonReentrant ifConfigured ifWithdrawalsNotPaused {
if (maxLimit < 1) revert LimitRequired();
bytes32 dailyCluster = keccak256(abi.encode(year, month, day));
// Make sure we have pending requests to process.
if (_dailyRequirement[dailyCluster] < 1) revert NothingToProcess();
// Make sure withdrawals are processed at the expected epoch only.
// The owner or the operator are allowed to bypass this check.
if (
(lagDuration > 0) &&
(msg.sender != _owner) &&
(msg.sender != operatorAddress) &&
// slither-disable-next-line timestamp
(block.timestamp + _TIMESTAMP_MANIPULATION_WINDOW < DateUtils.timestampFromDateTime(year, month, day, _DEFAULT_LIQUIDATION_HOUR, 0, 0))
) {
revert TooEarly();
}
// This is the number of unique ERC20 transfers we will need to make in this transaction
uint256 workSize = (_uniqueReceiversPerCluster[dailyCluster].length > maxLimit) ? maxLimit : _uniqueReceiversPerCluster[dailyCluster].length;
uint256 startingPos = _uniqueReceiversPerCluster[dailyCluster].length;
address[] memory receivers = new address[](workSize);
uint256[] memory amounts = new uint256[](workSize);
uint256 sharesToBurn;
address receiverAddr;
uint256 assetsAmount;
uint256 assetsAfterFee;
uint256 x = workSize;
for (uint256 i = startingPos; i > (startingPos - workSize); i--) {
receiverAddr = _uniqueReceiversPerCluster[dailyCluster][i - 1];
x--;
receivers[x] = receiverAddr;
sharesToBurn += _burnableAmounts[dailyCluster][receiverAddr];
// Costly operation inside a loop. The external call is trusted though.
(assetsAmount, assetsAfterFee) = _previewRedemption(_burnableAmounts[dailyCluster][receiverAddr], withdrawalFee);
amounts[x] = assetsAfterFee;
totalCollectableFees += (assetsAmount - assetsAfterFee);
_burnableAmounts[dailyCluster][receiverAddr] = 0;
_uniqueReceiversPerCluster[dailyCluster].pop();
_receiverIndexes[dailyCluster][receiverAddr] = 0;
}
globalLiabilityShares -= sharesToBurn;
_dailyRequirement[dailyCluster] -= sharesToBurn;
IMintableBurnable(lpTokenAddress).burn(address(this), sharesToBurn);
// Untrusted external calls
for (uint256 i; i < receivers.length; i++) {
SafeERC20.safeTransfer(IERC20(_referenceAsset), receivers[i], amounts[i]);
}
}
function _executeRedemption(
uint256 shares,
address receiverAddr,
bool isInstant
) internal returns (uint256 assetsAmount, uint256 assetsAfterFee) {
// Apply the redemption fee
uint256 applicableRedemptionFee = (isInstant) ? instantRedemptionFee : withdrawalFee;
(assetsAmount, assetsAfterFee) = _previewRedemption(shares, applicableRedemptionFee);
if (assetsAmount > maxWithdrawalAmount) revert WithdrawalLimitReached();
if (assetsAfterFee < 1) revert AmountTooLow();
if (!keepFeeInVault) totalCollectableFees += (assetsAmount - assetsAfterFee);
// Emit the withdrawal event
emit Withdraw(msg.sender, receiverAddr, msg.sender, assetsAfterFee, shares);
// Burn the respective number of shares from the token holder
IMintableBurnable(lpTokenAddress).burn(msg.sender, shares);
// Transfer the funds to the receiving address
SafeERC20.safeTransfer(IERC20(_referenceAsset), receiverAddr, assetsAfterFee);
}
function _deleteReceiver(bytes32 dailyCluster, address addr) private {
uint256 idx = _receiverIndexes[dailyCluster][addr] - 1;
uint256 totalReceiversByDate = _uniqueReceiversPerCluster[dailyCluster].length;
address lastItem = _uniqueReceiversPerCluster[dailyCluster][totalReceiversByDate - 1];
if (addr != lastItem) {
_uniqueReceiversPerCluster[dailyCluster][totalReceiversByDate - 1] = _uniqueReceiversPerCluster[dailyCluster][idx];
_uniqueReceiversPerCluster[dailyCluster][idx] = lastItem;
_receiverIndexes[dailyCluster][lastItem] = idx + 1;
}
_uniqueReceiversPerCluster[dailyCluster].pop();
_receiverIndexes[dailyCluster][addr] = 0;
}
function _previewRedemption(
uint256 shares,
uint256 fee
) internal view returns (
uint256 assetsAmount,
uint256 assetsAfterFee
) {
assetsAmount = _convertToAssets(shares, MathUpgradeable.Rounding.Down);
assetsAfterFee = assetsAmount;
uint256 applicableFee = 0;
if (fee > 0) {
applicableFee = (fee * assetsAmount) / 1e4;
assetsAfterFee = assetsAmount - applicableFee;
}
return (assetsAmount, assetsAfterFee);
}
/**
* @notice Previews a redemption.
* @param shares The number of shares to redeem.
* @param isInstant Indicates whether the redemption is lagged or instant.
* @return assetsAmount The withdrawal amount without any applicable fees.
* @return assetsAfterFee The effective withdrawal amount.
*/
function previewRedemption(
uint256 shares,
bool isInstant
) external view returns (
uint256 assetsAmount,
uint256 assetsAfterFee
) {
uint256 applicableRedemptionFee = (isInstant) ? instantRedemptionFee : withdrawalFee;
return _previewRedemption(shares, applicableRedemptionFee);
}
/**
* @notice Gets the date at which your withdrawal request can be claimed.
* @return year The year.
* @return month The month.
* @return day The day.
* @return claimableEpoch The Unix epoch at which your withdrawal request can be claimed.
*/
function getWithdrawalEpoch() external view returns (
uint256 year,
uint256 month,
uint256 day,
uint256 claimableEpoch
) {
(year, month, day) = DateUtils.timestampToDate(block.timestamp + _TIMESTAMP_MANIPULATION_WINDOW + lagDuration);
claimableEpoch = DateUtils.timestampFromDateTime(year, month, day, _DEFAULT_LIQUIDATION_HOUR, 0, 0);
}
/**
* @notice Gets the funding requirement of the date specified.
* @dev This is a forecast on the amount of assets that need to be available at the pool on the date specified.
* @param year The year.
* @param month The month.
* @param day The day.
* @return shares The number of shares (LP tokens) that will be burned on the date specified.
*/
function getRequirementByDate(
uint256 year,
uint256 month,
uint256 day
) external view returns (uint256 shares) {
bytes32 dailyCluster = keccak256(abi.encode(year, month, day));
shares = _dailyRequirement[dailyCluster];
}
/**
* @notice Gets the total number of shares to burn at the date specified for a given receiver.
* @dev This is a forecast on the amount of assets that can be claimed by a given party on the date specified.
* @param year The year.
* @param month The month.
* @param day The day.
* @param receiverAddr The address of the receiver.
* @return uint256 The total number of shares to burn at the date specified for a given receiver.
*/
function getBurnableAmountByReceiver(
uint256 year,
uint256 month,
uint256 day,
address receiverAddr
) external view returns (uint256) {
bytes32 dailyCluster = keccak256(abi.encode(year, month, day));
return _burnableAmounts[dailyCluster][receiverAddr];
}
/**
* @notice Gets the total number of transactions to run at a given date.
* @param year The year.
* @param month The month.
* @param day The day.
* @return totalTransactions The number of transactions to execute.
* @return executionEpoch The Unix epoch at which these transactions should be submitted to the blockchain.
*/
function getScheduledTransactionsByDate(
uint256 year,
uint256 month,
uint256 day
) external view returns (uint256 totalTransactions, uint256 executionEpoch) {
bytes32 dailyCluster = keccak256(abi.encode(year, month, day));
totalTransactions = _uniqueReceiversPerCluster[dailyCluster].length;
executionEpoch = DateUtils.timestampFromDateTime(year, month, day, _DEFAULT_LIQUIDATION_HOUR, 0, 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;
}
/**
* @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);
}
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 amount) 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[45] private __gap;
}
interface ITokenizedVault {
error HighWatermarkViolation();
error HighWatermarkDurationError();
error TokenDecimalsMismatch();
error InvalidLagDuration();
struct ConfigInfo {
uint256 maxDepositAmount;
uint256 maxWithdrawalAmount;
uint256 instantRedemptionFee;
uint256 lagDuration;
uint256 withdrawalFee;
uint256 watermarkTimeWindow;
uint256 maxChangePercent;
uint256 managementFeePercent;
uint256 performanceFeeRate;
address sendersWhitelistAddress;
address operatorAddress;
address scheduledCallerAddress;
address lpTokenAddress;
address referenceAsset;
address futureOwnerAddress;
address assetsWhitelistAddress;
}
/// @notice Triggers when the resource is configured.
event ContractConfigured();
/// @notice Triggers during an emergency withdrawal.
event OnEmergencyWithdraw(address receiverAddr);
function configure(ConfigInfo calldata newConfig) external;
function asset() external view returns (address);
}
/**
* @title Represents an upgradeable tokenized vault.
*/
contract TokenizedVault is ITokenizedVault, TimelockedVault {
/// @notice The high watermark.
uint256 public highWatermark;
/// @notice The update date of the high watermark
uint256 public watermarkUpdatedOn;
/// @notice The interval at which the high watermark can be updated.
uint256 public watermarkTimeWindow;
uint256 public performanceFeeRate;
/**
* @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[10] private __gap;
constructor() {
_disableInitializers();
}
// --------------------------------------------------------------------------
// Functions
// --------------------------------------------------------------------------
/**
* @notice Proxy initialization function.
* @param ownerAddr The owner of the vault.
*/
function initialize(address ownerAddr) external virtual initializer {
depositsPaused = true;
withdrawalsPaused = true;
_owner = ownerAddr;
}
/**
* @notice Configures the vault.
* @param newConfig The vault configuration.
*/
function configure(
ConfigInfo memory newConfig
) external virtual override nonReentrant onlyOwner ifNotConfigured {
if (newConfig.lagDuration < uint256(86400)) revert InvalidLagDuration();
// Set the configuration settings
watermarkTimeWindow = newConfig.watermarkTimeWindow;
maxDepositAmount = newConfig.maxDepositAmount;
maxWithdrawalAmount = newConfig.maxWithdrawalAmount;
depositCap = newConfig.maxDepositAmount;
instantRedemptionFee = newConfig.instantRedemptionFee;
lagDuration = newConfig.lagDuration;
withdrawalFee = newConfig.withdrawalFee;
maxChangePercent = newConfig.maxChangePercent;
managementFeePercent = newConfig.managementFeePercent;
performanceFeeRate = newConfig.performanceFeeRate;
operatorAddress = newConfig.operatorAddress;
scheduledCallerAddress = newConfig.scheduledCallerAddress;
lpTokenAddress = newConfig.lpTokenAddress;
_referenceAsset = newConfig.referenceAsset;
assetsUpdatedOn = block.timestamp;
feesTimestamp = block.timestamp;
assetsWhitelistAddress = newConfig.assetsWhitelistAddress;
sendersWhitelistAddress = newConfig.sendersWhitelistAddress;
depositsPaused = false;
withdrawalsPaused = false;
watermarkUpdatedOn = block.timestamp;
// Mark the contract as configured
_configured = true;
emit ContractConfigured();
// External calls
_scheduleOwnershipTransfer(newConfig.futureOwnerAddress);
// External call validations
if (_referenceAsset != IEnableOnlyAssetsWhitelist(assetsWhitelistAddress).REFERENCE_ASSET()) revert ReferenceAssetMismatch();
if (ERC20Upgradeable(_referenceAsset).decimals() != ERC20Upgradeable(lpTokenAddress).decimals()) revert TokenDecimalsMismatch();
uint256 shares = 1 * (10 ** ERC20Upgradeable(lpTokenAddress).decimals());
uint256 currentSharePrice = _convertToAssets(shares, MathUpgradeable.Rounding.Down);
highWatermark = currentSharePrice;
}
/**
* @notice Updates the timelock for withdrawals.
* @dev Setting the timelock to zero will allow to withdraw funds immediately from the vault.
* @param newDuration The duration of the timelock, expressed in seconds. It can be zero.
*/
function updateTimelockDuration(uint256 newDuration) external nonReentrant ifConfigured onlyOwner {
// The time-lock for withdrawals can be zero
lagDuration = newDuration;
// Build the hash of this call and attempt to consume it. The call reverts if the hash can't be consumed.
bytes32 h = keccak256(abi.encode(
abi.encodeWithSignature(
"updateTimelockDuration(uint256)",
newDuration
)
));
IResourceBasedTimelockedCall(scheduledCallerAddress).consume(h);
}
/**
* @notice Charges the performance fees.
*/
function chargePerformanceFees() external nonReentrant ifConfigured onlyOwnerOrOperator {
if (block.timestamp - watermarkUpdatedOn < watermarkTimeWindow) revert HighWatermarkDurationError();
uint256 currentSharePrice = _getSharePrice();
if (currentSharePrice <= highWatermark) revert HighWatermarkViolation();
// Calculate current high water mark totalAssets in reference asset
uint256 totalShares = IERC20(lpTokenAddress).totalSupply();
uint8 lpTokenDecimals = ERC20Upgradeable(lpTokenAddress).decimals();
uint256 highWatermarkNav = (highWatermark * totalShares) / (10 ** lpTokenDecimals);
uint256 currentTotalAssets = _getTotalAssets();
uint256 totalAssetsIncrease = currentTotalAssets - highWatermarkNav;
uint256 totalPerformanceFee = (totalAssetsIncrease * performanceFeeRate) / 1e6;
uint256 t = performanceFeeRecipients.length;
uint256[] memory amounts = new uint256[](t);
for (uint256 i; i < t; i++) {
uint256 collectableFee = (performanceFeeRecipients[i].percentage * totalPerformanceFee) / 1e6;
if (collectableFee > totalPerformanceFee) revert CollectableFeesExceeded(collectableFee, totalPerformanceFee);
if (collectableFee < 1) revert FeeAmountTooLow();
amounts[i] = collectableFee;
}
watermarkUpdatedOn = block.timestamp;
highWatermark = currentSharePrice;
for (uint256 i; i < t; i++) {
SafeERC20.safeTransfer(IERC20(_referenceAsset), performanceFeeRecipients[i].collectorAddress, amounts[i]);
}
}
/**
* @notice Runs an emergency withdrawal.
* @dev Calling this function pauses deposits and withdrawals automatically.
* @param receiverAddr The receiving address.
*/
function emergencyWithdraw(address receiverAddr) external nonReentrant ifConfigured onlyOwner {
if ((receiverAddr == address(0)) || (receiverAddr == address(this))) revert InvalidReceiver();
// Pause deposits and withdrawals, provided the emergency scenario
depositsPaused = true;
withdrawalsPaused = true;
emit OnEmergencyWithdraw(receiverAddr);
address[] memory assetAddresses = IEnableOnlyAssetsWhitelist(assetsWhitelistAddress).getWhitelistedAssets();
uint256 t = assetAddresses.length;
uint256 b = IERC20(_referenceAsset).balanceOf(address(this));
if (b > 0) SafeERC20.safeTransfer(IERC20(_referenceAsset), receiverAddr, b);
address assetAddr;
for (uint256 i; i < t; i++) {
assetAddr = assetAddresses[i];
b = IERC20(assetAddr).balanceOf(address(this));
if (b > 0) SafeERC20.safeTransfer(IERC20(assetAddr), receiverAddr, b);
}
}
/**
* @notice Gets the reference asset of the vault.
* @return address Returns the address of the reference asset.
*/
function asset() external view override returns (address) {
return _referenceAsset;
}
/**
* @notice Gets the current share price.
* @return uint256 The share price.
*/
function getSharePrice() external view returns (uint256) {
return _getSharePrice();
}
function _getSharePrice() internal view returns (uint256) {
uint256 shares = 1 * (10 ** ERC20Upgradeable(lpTokenAddress).decimals());
return _convertToAssets(shares, MathUpgradeable.Rounding.Down);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccountNotWhitelisted","type":"error"},{"inputs":[],"name":"AlreadyConfigured","type":"error"},{"inputs":[],"name":"AmountTooLow","type":"error"},{"inputs":[],"name":"AssetNotWhitelisted","type":"error"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"remaining","type":"uint256"}],"name":"CollectableFeesExceeded","type":"error"},{"inputs":[],"name":"DepositCapReached","type":"error"},{"inputs":[],"name":"DepositsPaused","type":"error"},{"inputs":[],"name":"FeeAmountTooLow","type":"error"},{"inputs":[],"name":"FeesMustSum100","type":"error"},{"inputs":[],"name":"HighWatermarkDurationError","type":"error"},{"inputs":[],"name":"HighWatermarkViolation","type":"error"},{"inputs":[],"name":"InsufficientShares","type":"error"},{"inputs":[],"name":"InvalidAccountType","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidDepositLimit","type":"error"},{"inputs":[],"name":"InvalidExternalAssets","type":"error"},{"inputs":[],"name":"InvalidLagDuration","type":"error"},{"inputs":[],"name":"InvalidReceiver","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[],"name":"InvalidWithdrawalLimit","type":"error"},{"inputs":[],"name":"LimitRequired","type":"error"},{"inputs":[],"name":"MaxAllowedChangeReached","type":"error"},{"inputs":[],"name":"MaxDepositAmountReached","type":"error"},{"inputs":[],"name":"MissingFeeCollectors","type":"error"},{"inputs":[],"name":"NoSharesForReceiver","type":"error"},{"inputs":[],"name":"NotConfigured","type":"error"},{"inputs":[],"name":"NothingToProcess","type":"error"},{"inputs":[],"name":"OnlyOwnerOrOperator","type":"error"},{"inputs":[],"name":"OperatorOnly","type":"error"},{"inputs":[],"name":"OwnerAddressRequired","type":"error"},{"inputs":[],"name":"OwnerOnly","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"ReferenceAssetMismatch","type":"error"},{"inputs":[],"name":"SenderNotWhitelisted","type":"error"},{"inputs":[],"name":"TokenDecimalsMismatch","type":"error"},{"inputs":[],"name":"TooEarly","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"VaultNotTimelocked","type":"error"},{"inputs":[],"name":"WhitelistLimitReached","type":"error"},{"inputs":[],"name":"WithdrawalLimitReached","type":"error"},{"inputs":[],"name":"WithdrawalsPaused","type":"error"},{"inputs":[],"name":"ZeroAddressError","type":"error"},{"anonymous":false,"inputs":[],"name":"ContractConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"assetIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":true,"internalType":"address","name":"senderAddr","type":"address"},{"indexed":true,"internalType":"address","name":"receiverAddr","type":"address"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"bDepositsPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"bWithdrawalsPaused","type":"bool"}],"name":"DepositWithdrawalStatusChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"FeesCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"managementFeeAmount","type":"uint256"}],"name":"ManagementFeeCharged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newManagementFeePercent","type":"uint256"}],"name":"ManagementFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MaxChangePercentUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"receiverAddr","type":"address"}],"name":"OnEmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newWhitelistAddr","type":"address"}],"name":"SendersWhitelistUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"subAccountAddr","type":"address"}],"name":"SubAccountDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"subAccountAddr","type":"address"}],"name":"SubAccountEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assetsAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiverAddr","type":"address"}],"name":"WithdrawalProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":true,"internalType":"address","name":"holderAddr","type":"address"},{"indexed":true,"internalType":"address","name":"receiverAddr","type":"address"}],"name":"WithdrawalRequested","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetsUpdatedOn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetsWhitelistAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chargeManagementFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chargePerformanceFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"year","type":"uint256"},{"internalType":"uint256","name":"month","type":"uint256"},{"internalType":"uint256","name":"day","type":"uint256"},{"internalType":"address","name":"receiverAddr","type":"address"}],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collectFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"maxDepositAmount","type":"uint256"},{"internalType":"uint256","name":"maxWithdrawalAmount","type":"uint256"},{"internalType":"uint256","name":"instantRedemptionFee","type":"uint256"},{"internalType":"uint256","name":"lagDuration","type":"uint256"},{"internalType":"uint256","name":"withdrawalFee","type":"uint256"},{"internalType":"uint256","name":"watermarkTimeWindow","type":"uint256"},{"internalType":"uint256","name":"maxChangePercent","type":"uint256"},{"internalType":"uint256","name":"managementFeePercent","type":"uint256"},{"internalType":"uint256","name":"performanceFeeRate","type":"uint256"},{"internalType":"address","name":"sendersWhitelistAddress","type":"address"},{"internalType":"address","name":"operatorAddress","type":"address"},{"internalType":"address","name":"scheduledCallerAddress","type":"address"},{"internalType":"address","name":"lpTokenAddress","type":"address"},{"internalType":"address","name":"referenceAsset","type":"address"},{"internalType":"address","name":"futureOwnerAddress","type":"address"},{"internalType":"address","name":"assetsWhitelistAddress","type":"address"}],"internalType":"struct ITokenizedVault.ConfigInfo","name":"newConfig","type":"tuple"}],"name":"configure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"receiverAddr","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputAssetAddr","type":"address"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"address","name":"subAccountAddr","type":"address"}],"name":"depositToSubaccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"receiverAddr","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"name":"depositWithPermit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"disableSubAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiverAddr","type":"address"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint8","name":"accountType","type":"uint8"}],"name":"enableSubAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"externalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"feeCollectors","outputs":[{"internalType":"address","name":"collectorAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feesTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"year","type":"uint256"},{"internalType":"uint256","name":"month","type":"uint256"},{"internalType":"uint256","name":"day","type":"uint256"},{"internalType":"address","name":"receiverAddr","type":"address"}],"name":"getBurnableAmountByReceiver","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"externalAssetsAmount","type":"uint256"}],"name":"getChangePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeCollectors","outputs":[{"components":[{"internalType":"address","name":"collectorAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"}],"internalType":"struct IFeeCollectorsAware.CollectorDefinition[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxAllowedChange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerformanceFeeRecipients","outputs":[{"components":[{"internalType":"address","name":"collectorAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"}],"internalType":"struct IFeeCollectorsAware.CollectorDefinition[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"year","type":"uint256"},{"internalType":"uint256","name":"month","type":"uint256"},{"internalType":"uint256","name":"day","type":"uint256"}],"name":"getRequirementByDate","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"year","type":"uint256"},{"internalType":"uint256","name":"month","type":"uint256"},{"internalType":"uint256","name":"day","type":"uint256"}],"name":"getScheduledTransactionsByDate","outputs":[{"internalType":"uint256","name":"totalTransactions","type":"uint256"},{"internalType":"uint256","name":"executionEpoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSharePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawalEpoch","outputs":[{"internalType":"uint256","name":"year","type":"uint256"},{"internalType":"uint256","name":"month","type":"uint256"},{"internalType":"uint256","name":"day","type":"uint256"},{"internalType":"uint256","name":"claimableEpoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalLiabilityShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"highWatermark","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"ownerAddr","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiverAddr","type":"address"}],"name":"instantRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"instantRedemptionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keepFeeInVault","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lagDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managementFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxChangePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWithdrawalAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"bPauseDeposits","type":"bool"},{"internalType":"bool","name":"bPauseWithdrawals","type":"bool"}],"name":"pauseDepositsAndWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"performanceFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"performanceFeeRecipients","outputs":[{"internalType":"address","name":"collectorAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"bool","name":"isInstant","type":"bool"}],"name":"previewRedemption","outputs":[{"internalType":"uint256","name":"assetsAmount","type":"uint256"},{"internalType":"uint256","name":"assetsAfterFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"year","type":"uint256"},{"internalType":"uint256","name":"month","type":"uint256"},{"internalType":"uint256","name":"day","type":"uint256"},{"internalType":"uint256","name":"maxLimit","type":"uint256"}],"name":"processAllClaimsByDate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiverAddr","type":"address"}],"name":"requestRedeem","outputs":[{"internalType":"uint256","name":"claimableEpoch","type":"uint256"},{"internalType":"uint256","name":"year","type":"uint256"},{"internalType":"uint256","name":"month","type":"uint256"},{"internalType":"uint256","name":"day","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"scheduledCallerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sendersWhitelistAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalCollectableFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWhitelistAddr","type":"address"}],"name":"updateAssetsWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"collectorAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"}],"internalType":"struct IFeeCollectorsAware.CollectorDefinition[]","name":"collectors","type":"tuple[]"}],"name":"updateFeeCollectors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"},{"internalType":"bool","name":"pKeepFeeInVault","type":"bool"}],"name":"updateInstantRedemptionFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxDepositAmount","type":"uint256"},{"internalType":"uint256","name":"newMaxWithdrawalAmount","type":"uint256"},{"internalType":"uint256","name":"newDepositCap","type":"uint256"}],"name":"updateLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newManagementFeePercent","type":"uint256"}],"name":"updateManagementFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"updateMaxChangePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"collectorAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"}],"internalType":"struct IFeeCollectorsAware.CollectorDefinition[]","name":"collectors","type":"tuple[]"}],"name":"updatePerformanceFeeCollectors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWhitelistAddr","type":"address"}],"name":"updateSendersWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"updateTimelockDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"externalAssetsAmount","type":"uint256"}],"name":"updateTotalAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"watermarkTimeWindow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"watermarkUpdatedOn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedSubAccounts","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputAssetAddr","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"subAccountAddr","type":"address"}],"name":"withdrawFromSubaccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801562000010575f80fd5b506200001b62000021565b620000df565b5f54610100900460ff16156200008d5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614620000dd575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b615f7b80620000ed5f395ff3fe608060405234801561000f575f80fd5b5060043610610417575f3560e01c80638ed8327111610221578063d3a8d7181161012a578063e9f2838e116100b4578063f5ae497a11610084578063f5ae497a146108c9578063fa20e0fe146108dc578063fc6fb837146108e5578063ff06002b146108ee578063ff3c63c014610901575f80fd5b8063e9f2838e1461087c578063f2fde38b14610890578063f3cbf47c146108a3578063f45346dc146108b6575f80fd5b8063dece0102116100fa578063dece01021461083e578063e2eb36b914610846578063e30c397814610859578063e62286801461086a578063e976d43114610873575f80fd5b8063d3a8d7181461081b578063d961b58c14610823578063dad361c51461082c578063dbd5edc714610835575f80fd5b8063be1f9214116101ab578063c87965721161017b578063c8796572146107d2578063c8e11e8e146107da578063ca55a557146107ed578063cb3dc357146107f5578063cdb1fb2b14610808575f80fd5b8063be1f921414610786578063c25dd81f14610799578063c3646a0f146107ac578063c4d66de8146107bf575f80fd5b80639efee6be116101f15780639efee6be14610706578063b3c9e83d14610719578063b4db4be81461072c578063b8f82b261461073f578063bb27070914610752575f80fd5b80638ed83271146106ce57806390f1c5f1146106d757806399aa14d0146106ea5780639cb43f81146106fd575f80fd5b8063520cd0361161032357806373f351c8116102ad5780638120b5791161027d5780638120b5791461068f578063820fe4be146106985780638bc7e8c4146106a15780638c0190e3146106aa5780638da5cb5b146106bd575f80fd5b806373f351c814610662578063785c31271461066b578063790739a21461067457806379ba509714610687575f80fd5b806360da3e83116102f357806360da3e83146105f85780636c46407b1461060c5780636e07302b146106345780636f4ab3dd1461063c5780636ff1c9bc1461064f575f80fd5b8063520cd036146105ae5780635486679d146105b65780635b1dac60146105be5780635d9e5cab146105c6575f80fd5b806322928208116103a457806336a0f8a51161037457806336a0f8a51461055157806336b7ea151461056457806338d52e0f1461056d5780633c7ecb4a1461057e578063502bee6614610591575f80fd5b8063229282081461050f57806324e86d671461052257806328f856801461052b57806329451a221461053e575f80fd5b8063127effb2116103ea578063127effb214610498578063184466c9146104c35780631bca5113146104d65780631dddfbe1146104e95780631f4f519c146104fc575f80fd5b8063030d624a1461041b57806309f25fc0146104305780630ffbfda41461044e578063107703ab14610465575b5f80fd5b61042e610429366004615664565b610952565b005b610438610acc565b604051610445919061567b565b60405180910390f35b610457603e5481565b604051908152602001610445565b6104786104733660046156f6565b610b3f565b604080519485526020850193909352918301526060820152608001610445565b6006546104ab906001600160a01b031681565b6040516001600160a01b039091168152602001610445565b61042e6104d1366004615664565b610f20565b61042e6104e4366004615724565b611031565b61042e6104f7366004615793565b611216565b61042e61050a366004615664565b6113f8565b61042e61051d3660046156f6565b6114d5565b610457602a5481565b610457610539366004615664565b611689565b61042e61054c366004615724565b61170f565b61042e61055f3660046157d2565b6118c6565b61045760185481565b601b546001600160a01b03166104ab565b61042e61058c3660046157fb565b611999565b60315461059e9060ff1681565b6040519015158152602001610445565b610457611aed565b61042e611b4b565b610457611f19565b6105d96105d4366004615664565b611f22565b604080516001600160a01b039093168352602083019190915201610445565b60065461059e90600160a01b900460ff1681565b61061f61061a3660046157d2565b611f58565b60408051928352602083019190915201610445565b610457611fb3565b61042e61064a366004615793565b611fbc565b61042e61065d3660046157fb565b61217f565b61045760195481565b61045760145481565b61042e610682366004615664565b612432565b61042e61255f565b610457603b5481565b61045760295481565b610457602b5481565b61042e6106b8366004615823565b61264b565b6002546001600160a01b03166104ab565b610457601a5481565b6105d96106e5366004615664565b612765565b6104576106f836600461585d565b612774565b610457602c5481565b61042e6107143660046158ca565b612a0f565b61061f6107273660046158ed565b612aa9565b61061f61073a3660046158ca565b612e50565b61061f61074d36600461592b565b612e7c565b6107746107603660046157fb565b60096020525f908152604090205460ff1681565b60405160ff9091168152602001610445565b6104576107943660046158ed565b612f17565b6008546104ab906001600160a01b031681565b61042e6107ba3660046157fb565b612f70565b61042e6107cd3660046157fb565b613061565b61042e613195565b61042e6107e83660046157fb565b61337f565b610478613463565b61042e6108033660046159c4565b613498565b601d546104ab906001600160a01b031681565b61042e6138bc565b61045760155481565b610457603d5481565b610457601e5481565b6104386139aa565b6007546104ab906001600160a01b031681565b6003546001600160a01b03166104ab565b61045760165481565b61045760285481565b60065461059e90600160a81b900460ff1681565b61042e61089e3660046157fb565b613a13565b61042e6108b1366004615ab8565b613a99565b6104576108c4366004615793565b613f91565b601c546104ab906001600160a01b031681565b61045760175481565b610457603c5481565b61042e6108fc366004615ae7565b6141a8565b61045761090f3660046157d2565b604080516020808201959095528082019390935260608084019290925280518084039092018252608090920182528051908301205f908152602d90925290205490565b60026001540361097557604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166109a45760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b031633146109cf57604051630b2db9b760e31b815260040160405180910390fd5b5f816040516024016109e391815260200190565b60408051601f19818403018152918152602080830180516001600160e01b0316630186b12560e11b1790529051610a1b929101615b60565b60408051601f19818403018152908290528051602091820120601985905584835292507f2147e2bc8c39e67f74b1a9e08896ea1485442096765942206af1f4bc8bcde91791015b60405180910390a160075460405163af6f8c1b60e01b8152600481018390526001600160a01b039091169063af6f8c1b906024015b5f604051808303815f87803b158015610aae575f80fd5b505af1158015610ac0573d5f803e3d5ffd5b50506001805550505050565b60606005805480602002602001604051908101604052809291908181526020015f905b82821015610b36575f848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101610aef565b50505050905090565b5f805f80600260015403610b6657604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16610b955760405163d311bc3960e01b815260040160405180910390fd5b600654600160a81b900460ff1615610bc057604051636022a9e760e01b815260040160405180910390fd5b6002546001600160a01b03163314801590610be657506006546001600160a01b03163314155b8015610bfc57506008546001600160a01b031615155b8015610c6f5750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa158015610c49573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c6d9190615b72565b155b15610c8d57604051637ed449a960e01b815260040160405180910390fd5b6001600160a01b0385161580610cab57506001600160a01b03851630145b15610cc957604051631e4ec46b60e01b815260040160405180910390fd5b6001861015610ceb5760405163162908e360e11b815260040160405180910390fd5b5f80610cf988602b54614305565b91509150602854821115610d2057604051631b6132ab60e31b815260040160405180910390fd5b6001811015610d4257604051631fbaba3560e01b815260040160405180910390fd5b6001602a541015610d66576040516394fa99e760e01b815260040160405180910390fd5b602a54610d8890610d7961012c42615ba1565b610d839190615ba1565b61434b565b604080516020808201869052818301859052606080830185905283518084039091018152608090920190925280519101209297509095509350610dcf8686865f8080614370565b965088602c5f828254610de29190615ba1565b90915550505f818152602d6020526040812080548b9290610e04908490615ba1565b90915550505f818152602e602090815260408083206001600160a01b038c1684529091528120549003610e82575f818152602f6020908152604080832080546001810182558185528385200180546001600160a01b0319166001600160a01b038e169081179091558585529054603084528285209185529252909120555b5f818152602e602090815260408083206001600160a01b038c168452909152812080548b9290610eb3908490615ba1565b90915550506040518981526001600160a01b0389169033907fcf41fab81bee2456b7007d9d1a9e2261a6627a41eba8c3302b6b07f9a7a463959060200160405180910390a3601c54610f10906001600160a01b031633308c6143cb565b5050600180555092959194509250565b600260015403610f4357604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16610f725760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b03163314610f9d57604051630b2db9b760e31b815260040160405180910390fd5b602a819055604051602481018290525f9060440160408051601f19818403018152918152602080830180516001600160e01b031663184466c960e01b1790529051610fe9929101615b60565b60408051808303601f1901815290829052805160209091012060075463af6f8c1b60e01b8352600483018290529092506001600160a01b03169063af6f8c1b90602401610a97565b60026001540361105457604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166110835760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b031633146110ae57604051630b2db9b760e31b815260040160405180910390fd5b5f8160018110156110d2576040516333f52ff560e01b815260040160405180910390fd5b6110dd60055f615622565b5f5b818110156111e85760018585838181106110fb576110fb615bb4565b9050604002016020013510156111245760405163162908e360e11b815260040160405180910390fd5b5f85858381811061113757611137615bb4565b61114d92602060409092020190810191506157fb565b6001600160a01b0316036111745760405163e6c4247b60e01b815260040160405180910390fd5b84848281811061118657611186615bb4565b905060400201602001358361119b9190615ba1565b925060058585838181106111b1576111b1615bb4565b83546001810185555f94855260209094206040909102929092019260020290910190506111de8282615bc8565b50506001016110df565b5081620f42401461120c5760405163e31ac1db60e01b815260040160405180910390fd5b5050600180555050565b60026001540361123957604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166112685760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b0316331480159061128e57506002546001600160a01b03163314155b156112ac5760405163089b7a0760e41b815260040160405180910390fd5b60018210156112ce5760405163162908e360e11b815260040160405180910390fd5b6001600160a01b0381165f9081526009602052604090205460ff16600181101561130b5760405163014cc88960e21b815260040160405180910390fd5b601b545f906001600160a01b038681169116146113315761132c858561443c565b611333565b835b90506014548111156113585760405163200f4ff760e01b815260040160405180910390fd5b8060145f8282546113699190615bfe565b90915550505f1960ff8316016113e157604051631a4ca37b60e21b81526001600160a01b038681166004830152602482018690523060448301528416906369328dec906064015f604051808303815f87803b1580156113c6575f80fd5b505af11580156113d8573d5f803e3d5ffd5b505050506113ed565b6113ed858430876143cb565b505060018055505050565b60026001540361141b57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff1661144a5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b0316331480159061147057506002546001600160a01b03163314155b1561148e5760405163089b7a0760e41b815260040160405180910390fd5b5f61149882611689565b90505f6114a3611aed565b9050808211156114c657604051631373d6db60e01b815260040160405180910390fd5b50506014554260175560018055565b6002600154036114f857604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166115275760405163d311bc3960e01b815260040160405180910390fd5b600654600160a81b900460ff161561155257604051636022a9e760e01b815260040160405180910390fd5b6002546001600160a01b0316331480159061157857506006546001600160a01b03163314155b801561158e57506008546001600160a01b031615155b80156116015750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa1580156115db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115ff9190615b72565b155b1561161f57604051637ed449a960e01b815260040160405180910390fd5b6001600160a01b038116158061163d57506001600160a01b03811630145b1561165b57604051631e4ec46b60e01b815260040160405180910390fd5b600182101561167d5760405163162908e360e11b815260040160405180910390fd5b61120c828260016144b6565b5f6001601454101561169c57505f919050565b60018210156116ae5750612710919050565b60145482116116e457612710826014546127106116cb9190615c11565b6116d59190615c3c565b6116df9190615bfe565b611709565b601454612710906116f58483615c11565b6116ff9190615c3c565b6117099190615bfe565b92915050565b60026001540361173257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166117615760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b0316331461178c57604051630b2db9b760e31b815260040160405180910390fd5b5f8160018110156117b0576040516333f52ff560e01b815260040160405180910390fd5b6117bb60045f615622565b5f5b818110156111e85760018585838181106117d9576117d9615bb4565b9050604002016020013510156118025760405163162908e360e11b815260040160405180910390fd5b5f85858381811061181557611815615bb4565b61182b92602060409092020190810191506157fb565b6001600160a01b0316036118525760405163e6c4247b60e01b815260040160405180910390fd5b84848281811061186457611864615bb4565b90506040020160200135836118799190615ba1565b9250600485858381811061188f5761188f615bb4565b83546001810185555f94855260209094206040909102929092019260020290910190506118bc8282615bc8565b50506001016117bd565b6002600154036118e957604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166119185760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b0316331461194357604051630b2db9b760e31b815260040160405180910390fd5b600183101561196557604051637fb1277b60e01b815260040160405180910390fd5b60018210156119875760405163e8498be360e01b815260040160405180910390fd5b601a92909255602855601e5560018055565b6002600154036119bc57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166119eb5760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b03163314611a1657604051630b2db9b760e31b815260040160405180910390fd5b6001600160a01b038116611a3d5760405163e6c4247b60e01b815260040160405180910390fd5b601d80546001600160a01b0319166001600160a01b03831690811790915560408051636f6a537f60e11b8152905163ded4a6fe916004808201926020929091908290030181865afa158015611a94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ab89190615c4f565b601b546001600160a01b03908116911614611ae657604051630ecd66ab60e41b815260040160405180910390fd5b5060018055565b6017545f90611afe61012c42615ba1565b1015611b1d5760405163b7d0949760e01b815260040160405180910390fd5b6201518060175442611b2f9190615bfe565b601654611b3c9190615c11565b611b469190615c3c565b905090565b600260015403611b6e57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16611b9d5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b03163314801590611bc357506002546001600160a01b03163314155b15611be15760405163089b7a0760e41b815260040160405180910390fd5b603d54603c54611bf19042615bfe565b1015611c10576040516311b96bf760e31b815260040160405180910390fd5b5f611c19614612565b9050603b548111611c3d5760405163330c780160e11b815260040160405180910390fd5b601c54604080516318160ddd60e01b815290515f926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa158015611c84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ca89190615c6a565b90505f601c5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cfb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d1f9190615c81565b90505f611d2d82600a615d74565b83603b54611d3b9190615c11565b611d459190615c3c565b90505f611d506146b0565b90505f611d5d8383615bfe565b90505f620f4240603e5483611d729190615c11565b611d7c9190615c3c565b6005549091505f8167ffffffffffffffff811115611d9c57611d9c615955565b604051908082528060200260200182016040528015611dc5578160200160208202803683370190505b5090505f5b82811015611e8a575f620f42408560058481548110611deb57611deb615bb4565b905f5260205f20906002020160010154611e059190615c11565b611e0f9190615c3c565b905084811115611e4157604051630abb811560e21b815260048101829052602481018690526044015b60405180910390fd5b6001811015611e635760405163debabab560e01b815260040160405180910390fd5b80838381518110611e7657611e76615bb4565b602090810291909101015250600101611dca565b5042603c55603b8990555f5b82811015611f0957601b5460058054611f01926001600160a01b0316919084908110611ec457611ec4615bb4565b5f91825260209091206002909102015484516001600160a01b0390911690859085908110611ef457611ef4615bb4565b602002602001015161471f565b600101611e96565b5050600180555050505050505050565b5f611b46614612565b60058181548110611f31575f80fd5b5f918252602090912060029091020180546001909101546001600160a01b03909116915082565b604080516020808201869052818301859052606080830185905283518084039091018152608090920183528151918101919091205f818152602f9092529181205491611fa8868686858080614370565b915050935093915050565b5f611b466146b0565b600260015403611fdf57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff1661200e5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b0316331480159061203457506002546001600160a01b03163314155b156120525760405163089b7a0760e41b815260040160405180910390fd5b60018210156120745760405163162908e360e11b815260040160405180910390fd5b6001600160a01b0381165f9081526009602052604090205460ff1660018110156120b15760405163014cc88960e21b815260040160405180910390fd5b601b545f906001600160a01b038681169116146120d7576120d2858561443c565b6120d9565b835b90508060145f8282546120ec9190615ba1565b90915550505f1960ff83160161217457612107858486614754565b6040516311f9fbc960e21b81526001600160a01b038681166004830152602482018690528416906347e7ef24906044015f604051808303815f87803b15801561214e575f80fd5b505af1158015612160573d5f803e3d5ffd5b5050505061216f85845f614754565b6113ed565b6113ed85848661471f565b6002600154036121a257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166121d15760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b031633146121fc57604051630b2db9b760e31b815260040160405180910390fd5b6001600160a01b038116158061221a57506001600160a01b03811630145b1561223857604051631e4ec46b60e01b815260040160405180910390fd5b6006805461ffff60a01b191661010160a01b1790556040516001600160a01b03821681527fc513d827bb73b448f995555eff37d93f4d71b6ef96bc6557e2ec370ba22782ac9060200160405180910390a1601d546040805163a22484d960e01b815290515f926001600160a01b03169163a22484d991600480830192869291908290030181865afa1580156122cf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526122f69190810190615d82565b8051601b546040516370a0823160e01b815230600482015292935090915f916001600160a01b0316906370a0823190602401602060405180830381865afa158015612343573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123679190615c6a565b9050801561238657601b54612386906001600160a01b0316858361471f565b5f805b83811015610ac0578481815181106123a3576123a3615bb4565b60209081029190910101516040516370a0823160e01b81523060048201529092506001600160a01b038316906370a0823190602401602060405180830381865afa1580156123f3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124179190615c6a565b9250821561242a5761242a82878561471f565b600101612389565b60026001540361245557604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166124845760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b031633148015906124aa57506002546001600160a01b03163314155b156124c85760405163089b7a0760e41b815260040160405180910390fd5b5f816040516024016124dc91815260200190565b60408051601f19818403018152918152602080830180516001600160e01b0316633c839cd160e11b1790529051612514929101615b60565b60408051601f19818403018152908290528051602091820120601685905584835292507f30d8cff2601d989fea083347b4501d5e97976f0ce3cfef9d4bd76bef1b7f0e8a9101610a62565b600354600160a01b900460ff166125895760405163d311bc3960e01b815260040160405180910390fd5b6040513360248201525f9060440160408051601f19818403018152918152602080830180516001600160e01b031663f2fde38b60e01b17905290516125cf929101615b60565b6040516020818303038152906040528051906020012090506125ef614867565b60075460405163af6f8c1b60e01b8152600481018390526001600160a01b039091169063af6f8c1b906024015f604051808303815f87803b158015612632575f80fd5b505af1158015612644573d5f803e3d5ffd5b5050505050565b60026001540361266e57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff1661269d5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b031633148015906126c357506002546001600160a01b03163314155b156126e15760405163089b7a0760e41b815260040160405180910390fd5b6006805461ffff60a01b1916600160a01b841515810260ff60a81b191691909117600160a81b841515810291909117928390556040805160ff93850484161515815291909304909116151560208201527f559628b27717ff2f5863f3a218839e17c6bc1b900e9de0dc2b3dc365068841d791015b60405180910390a1505060018055565b60048181548110611f31575f80fd5b5f60026001540361279857604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166127c75760405163d311bc3960e01b815260040160405180910390fd5b600654600160a01b900460ff16156127f25760405163deeb694360e01b815260040160405180910390fd5b6002546001600160a01b0316331480159061281857506006546001600160a01b03163314155b801561282e57506008546001600160a01b031615155b80156128a15750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa15801561287b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061289f9190615b72565b155b156128bf57604051637ed449a960e01b815260040160405180910390fd5b601b5488906001600160a01b038083169116148015906129485750601d54604051633af32abf60e01b81526001600160a01b03838116600483015290911690633af32abf90602401602060405180830381865afa158015612922573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129469190615b72565b155b1561296657604051632188be3960e21b815260040160405180910390fd5b6129718989896148f2565b60405163d505accf60e01b8152336004820152306024820152604481018a90526064810188905260ff8516608482015260a4810187905260c481018690529092506001600160a01b038a169063d505accf9060e4015f604051808303815f87803b1580156129dd575f80fd5b505af11580156129ef573d5f803e3d5ffd5b505050506129ff898989856149e9565b5060018055979650505050505050565b600260015403612a3257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16612a615760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b03163314612a8c57604051630b2db9b760e31b815260040160405180910390fd5b6029919091556031805460ff191691151591909117905560018055565b5f80600260015403612ace57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16612afd5760405163d311bc3960e01b815260040160405180910390fd5b600654600160a81b900460ff1615612b2857604051636022a9e760e01b815260040160405180910390fd5b6002546001600160a01b03163314801590612b4e57506006546001600160a01b03163314155b8015612b6457506008546001600160a01b031615155b8015612bd75750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa158015612bb1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd59190615b72565b155b15612bf557604051637ed449a960e01b815260040160405180910390fd5b6040805160208101889052908101869052606081018590525f9060800160408051601f1981840301815291815281516020928301205f818152602e84528281206001600160a01b03891682529093529120549091506001811015612c6c576040516339c556cd60e11b815260040160405180910390fd5b5f602a54118015612c8857506002546001600160a01b03163314155b8015612c9f57506006546001600160a01b03163314155b8015612cc25750612cb48888885f8080614370565b612cc061012c42615ba1565b105b15612ce05760405163085de62560e01b815260040160405180910390fd5b5f80612cee83602b54614305565b90925090505f612cfe8284615bfe565b5f868152602e602090815260408083206001600160a01b038d1684528252808320839055888352602d909152812080549293508692909190612d41908490615bfe565b9250508190555083602c5f828254612d599190615bfe565b925050819055508060155f828254612d719190615ba1565b90915550612d8190508589614aad565b876001600160a01b03167f2e06b2c9d4ccae2592eda2017cb2fb604b8d7418e85f023375514ab25ff2cc4c83604051612dbc91815260200190565b60405180910390a2601c54604051632770a7eb60e21b8152306004820152602481018690526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015612e0d575f80fd5b505af1158015612e1f573d5f803e3d5ffd5b5050601b54612e3b92506001600160a01b03169050898461471f565b50600180559199919850909650505050505050565b5f805f83612e6057602b54612e64565b6029545b9050612e708582614305565b92509250509250929050565b601d54601c54601454604051632b78daa360e11b81526001600160a01b03928316600482015285831660248201523060448201526064810185905260848101919091525f92839216906356f1b5469060a4016040805180830381865afa158015612ee8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f0c9190615e23565b915091509250929050565b604080516020808201879052818301869052606080830186905283518084039091018152608090920183528151918101919091205f908152602e82528281206001600160a01b038516825290915220545b949350505050565b600260015403612f9357604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16612fc25760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b03163314801590612fe857506002546001600160a01b03163314155b156130065760405163089b7a0760e41b815260040160405180910390fd5b6001600160a01b0381165f81815260096020908152604091829020805460ff1916905590519182527f2f520fb256d37bacc8a5e0fb9e69362d4bb462500c7e54f56ea54416e92d47d691015b60405180910390a15060018055565b5f54610100900460ff161580801561307f57505f54600160ff909116105b806130985750303b15801561309857505f5460ff166001145b6130fb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401611e38565b5f805460ff19166001179055801561311c575f805461ff0019166101001790555b6006805461ffff60a01b191661010160a01b179055600280546001600160a01b0319166001600160a01b0384161790558015613191575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6002600154036131b857604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166131e75760405163d311bc3960e01b815260040160405180910390fd5b600454600181101561320c576040516333f52ff560e01b815260040160405180910390fd5b6015548015613377575f8267ffffffffffffffff81111561322f5761322f615955565b604051908082528060200260200182016040528015613258578160200160208202803683370190505b5090505f5b83811015613313575f620f4240846004848154811061327e5761327e615bb4565b905f5260205f209060020201600101546132989190615c11565b6132a29190615c3c565b90506015548111156132d557601554604051630abb811560e21b8152611e38918391600401918252602082015260400190565b808383815181106132e8576132e8615bb4565b6020026020010181815250508060155f8282546133059190615bfe565b90915550505060010161325d565b506040517f3f33b5ed245dfaf97e122dfc86e9d14ff254c4878a7c9ba8dab46d9c71cc3015905f90a15f5b8381101561337457601b546004805461336c926001600160a01b0316919084908110611ec457611ec4615bb4565b60010161333e565b50505b505060018055565b6002600154036133a257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166133d15760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b031633148015906133f757506002546001600160a01b03163314155b156134155760405163089b7a0760e41b815260040160405180910390fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f7e7afb649fef7779605afaad37b91d9f5044726c260bb394570089d052d5dbb790602001613052565b5f805f8061347b602a5461012c42610d799190615ba1565b919550935091506134908484845f8080614370565b905090919293565b6002600154036134bb57604051633ee5aeb560e01b815260040160405180910390fd5b60026001819055546001600160a01b031633146134eb57604051630b2db9b760e31b815260040160405180910390fd5b600354600160a01b900460ff1615613516576040516308db0db560e11b815260040160405180910390fd5b620151808160600151101561353e57604051630320a41d60e51b815260040160405180910390fd5b60a0810151603d558051601a8190556020820151602855601e556040808201516029556060820151602a556080820151602b5560c082015160165560e0820151601955610100820151603e5561014082015160068054610160850151600780546001600160a01b03199081166001600160a01b0393841617909155610180870151601c805483169184169190911790556101a0870151601b8054831691841691909117905542601781905560188190556101e0880151601d80548416918516919091179055610120880151600880549093169084161790915593166001600160b01b0319909116179055603c5560038054600160a01b60ff60a01b19909116179055517f1eb56c868d62c38b9f2e3bd3d0556bed1dc7df623758318faaaaa05ffff993c7905f90a1613674816101c00151614c92565b601d5f9054906101000a90046001600160a01b03166001600160a01b031663ded4a6fe6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156136c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136e89190615c4f565b601b546001600160a01b0390811691161461371657604051630ecd66ab60e41b815260040160405180910390fd5b601c5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613766573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061378a9190615c81565b60ff16601b5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137dd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138019190615c81565b60ff16146138225760405163697e864b60e01b815260040160405180910390fd5b601c546040805163313ce56760e01b815290515f926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015613869573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061388d9190615c81565b61389890600a615d74565b6138a3906001615c11565b90505f6138b0825f614e44565b603b5550506001805550565b6002600154036138df57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff1661390e5760405163d311bc3960e01b815260040160405180910390fd5b5f6139176146b0565b90505f6127106301e13380601854426139309190615bfe565b60195461393d9086615c11565b6139479190615c11565b6139519190615c3c565b61395b9190615c3c565b9050426018819055508060155f8282546139759190615ba1565b90915550506040518181527f2d46e156a9ac545bd5f27832a0e6293d21c92faf9237534c6b18c51e9cca59df90602001612755565b60606004805480602002602001604051908101604052809291908181526020015f9082821015610b36575f848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101610aef565b600260015403613a3657604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16613a655760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b03163314613a9057604051630b2db9b760e31b815260040160405180910390fd5b611ae681614c92565b600260015403613abc57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16613aeb5760405163d311bc3960e01b815260040160405180910390fd5b600654600160a81b900460ff1615613b1657604051636022a9e760e01b815260040160405180910390fd5b6001811015613b38576040516334e33ddb60e01b815260040160405180910390fd5b6040805160208101869052908101849052606081018390525f906080016040516020818303038152906040528051906020012090506001602d5f8381526020019081526020015f20541015613ba057604051630683f18b60e41b815260040160405180910390fd5b5f602a54118015613bbc57506002546001600160a01b03163314155b8015613bd357506006546001600160a01b03163314155b8015613bf65750613be88585855f8080614370565b613bf461012c42615ba1565b105b15613c145760405163085de62560e01b815260040160405180910390fd5b5f818152602f60205260408120548310613c3b575f828152602f6020526040902054613c3d565b825b5f838152602f60205260408120549192508267ffffffffffffffff811115613c6757613c67615955565b604051908082528060200260200182016040528015613c90578160200160208202803683370190505b5090505f8367ffffffffffffffff811115613cad57613cad615955565b604051908082528060200260200182016040528015613cd6578160200160208202803683370190505b5090505f80808087875b613cea8a8a615bfe565b811115613e92575f8b8152602f60205260409020613d09600183615bfe565b81548110613d1957613d19615bb4565b5f918252602090912001546001600160a01b0316945081613d3981615e45565b92505084888381518110613d4f57613d4f615bb4565b6001600160a01b039283166020918202929092018101919091525f8d8152602e825260408082209389168252929091522054613d8b9087615ba1565b5f8c8152602e602090815260408083206001600160a01b038a168452909152902054602b54919750613dbc91614305565b809450819550505082878381518110613dd757613dd7615bb4565b6020908102919091010152613dec8385615bfe565b60155f828254613dfc9190615ba1565b90915550505f8b8152602e602090815260408083206001600160a01b038916845282528083208390558d8352602f9091529020805480613e3e57613e3e615e5a565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092558c82526030815260408083206001600160a01b038916845290915281205580613e8a81615e45565b915050613ce0565b5084602c5f828254613ea49190615bfe565b90915550505f8a8152602d602052604081208054879290613ec6908490615bfe565b9091555050601c54604051632770a7eb60e21b8152306004820152602481018790526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015613f14575f80fd5b505af1158015613f26573d5f803e3d5ffd5b505050505f5b8751811015613f7c57601b548851613f74916001600160a01b0316908a9084908110613f5a57613f5a615bb4565b6020026020010151898481518110611ef457611ef4615bb4565b600101613f2c565b50506001805550505050505050505050505050565b5f600260015403613fb557604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16613fe45760405163d311bc3960e01b815260040160405180910390fd5b600654600160a01b900460ff161561400f5760405163deeb694360e01b815260040160405180910390fd5b6002546001600160a01b0316331480159061403557506006546001600160a01b03163314155b801561404b57506008546001600160a01b031615155b80156140be5750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa158015614098573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906140bc9190615b72565b155b156140dc57604051637ed449a960e01b815260040160405180910390fd5b601b5484906001600160a01b038083169116148015906141655750601d54604051633af32abf60e01b81526001600160a01b03838116600483015290911690633af32abf90602401602060405180830381865afa15801561413f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141639190615b72565b155b1561418357604051632188be3960e21b815260040160405180910390fd5b61418e8585856148f2565b915061419c858585856149e9565b50600180559392505050565b6002600154036141cb57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166141fa5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b0316331480159061422057506002546001600160a01b03163314155b1561423e5760405163089b7a0760e41b815260040160405180910390fd5b6001600160a01b038216158061425c57506001600160a01b03821630145b1561427a5760405163e6c4247b60e01b815260040160405180910390fd5b60ff8116600114801590614292575060ff8116600214155b156142b05760405163e01b409760e01b815260040160405180910390fd5b6001600160a01b0382165f81815260096020908152604091829020805460ff191660ff861617905590519182527f324201c119d7f14ed24d964257aa0c870524bde20d9ecb31d4b37eadc20336ff9101612755565b5f80614311845f614e44565b91508190505f83156143435761271061432a8486615c11565b6143349190615c3c565b90506143408184615bfe565b91505b509250929050565b5f808061436361435e6201518086615c3c565b614ee5565b9196909550909350915050565b5f8161437d603c85615c11565b614389610e1087615c11565b620151806143988b8b8b615054565b6143a29190615c11565b6143ac9190615ba1565b6143b69190615ba1565b6143c09190615ba1565b979650505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526144369085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526151ba565b50505050565b601d546040516364696fab60e11b81526001600160a01b038481166004830152602482018490525f92169063c8d2df5690604401602060405180830381865afa15801561448b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906144af9190615c6a565b9392505050565b5f805f836144c657602b546144ca565b6029545b90506144d68682614305565b60285491945092508311156144fe57604051631b6132ab60e31b815260040160405180910390fd5b600182101561452057604051631fbaba3560e01b815260040160405180910390fd5b60315460ff1661454a576145348284615bfe565b60155f8282546145449190615ba1565b90915550505b604080518381526020810188905233916001600160a01b0388169183917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a4601c54604051632770a7eb60e21b8152336004820152602481018890526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b1580156145db575f80fd5b505af11580156145ed573d5f803e3d5ffd5b5050601b5461460992506001600160a01b03169050868461471f565b50935093915050565b5f80601c5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015614664573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906146889190615c81565b61469390600a615d74565b61469e906001615c11565b90506146aa815f614e44565b91505090565b601d5460145460405163ad07802160e01b815260048101919091525f916001600160a01b03169063ad07802190602401602060405180830381865afa1580156146fb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b469190615c6a565b6040516001600160a01b03831660248201526044810182905261474f90849063a9059cbb60e01b906064016143ff565b505050565b8015806147cc5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156147a6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906147ca9190615c6a565b155b6148375760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401611e38565b6040516001600160a01b03831660248201526044810182905261474f90849063095ea7b360e01b906064016143ff565b60026001540361488a57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166148b95760405163d311bc3960e01b815260040160405180910390fd5b6003546001600160a01b031633146148e3576040516282b42960e81b815260040160405180910390fd5b6148ec3361528b565b60018055565b5f60018310156149155760405163162908e360e11b815260040160405180910390fd5b6001600160a01b038216158061493357506001600160a01b03821630145b1561495157604051631e4ec46b60e01b815260040160405180910390fd5b5f8061495d8686612e7c565b91509150600182101561498357604051633999656760e01b815260040160405180910390fd5b601a548111156149a657604051639ade546d60e01b815260040160405180910390fd5b5f6149af6146b0565b6149b99083615ba1565b9050601e548111156149de576040516312e7cad560e21b815260040160405180910390fd5b509095945050505050565b604080516001600160a01b038681168252602082018690529181018390529083169033907fc436f473cd90c9b4dd731856a14b80f713d384a1688a506d4230140c5b36d5cd9060600160405180910390a3614a46843330866143cb565b601c546040516340c10f1960e01b81526001600160a01b03848116600483015260248201849052909116906340c10f19906044015f604051808303815f87803b158015614a91575f80fd5b505af1158015614aa3573d5f803e3d5ffd5b5050505050505050565b5f8281526030602090815260408083206001600160a01b0385168452909152812054614adb90600190615bfe565b5f848152602f602052604081208054929350614af8600184615bfe565b81548110614b0857614b08615bb4565b5f918252602090912001546001600160a01b03908116915084168114614c2c575f858152602f60205260409020805484908110614b4757614b47615bb4565b5f918252602080832090910154878352602f90915260409091206001600160a01b0390911690614b78600185615bfe565b81548110614b8857614b88615bb4565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555080602f5f8781526020019081526020015f208481548110614bd657614bd6615bb4565b5f91825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055614c09836001615ba1565b5f8681526030602090815260408083206001600160a01b03861684529091529020555b5f858152602f60205260409020805480614c4857614c48615e5a565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092559581526030865260408082206001600160a01b0396909616825294909552505050812055565b6003545f906001600160a01b031615614d11576003546040516001600160a01b03909116602482015260440160408051601f19818403018152918152602080830180516001600160e01b031663f2fde38b60e01b1790529051614cf6929101615b60565b60405160208183030381529060405280519060200120614d13565b5f5b6040516001600160a01b03841660248201529091505f9060440160408051601f19818403018152918152602080830180516001600160e01b031663f2fde38b60e01b1790529051614d65929101615b60565b604051602081830303815290604052805190602001209050614d86836152a7565b8115614de65760075460405163c4d252f560e01b8152600481018490526001600160a01b039091169063c4d252f5906024015f604051808303815f87803b158015614dcf575f80fd5b505af1158015614de1573d5f803e3d5ffd5b505050505b600754604051631523ab0160e21b8152600481018390526001600160a01b039091169063548eac04906024015f604051808303815f87803b158015614e29575f80fd5b505af1158015614e3b573d5f803e3d5ffd5b50505050505050565b5f80601c5f9054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614e96573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614eba9190615c6a565b905060018110614edd57614ed8614ecf6146b0565b85908386615334565b612f68565b509192915050565b5f8080838162253d8c614efb8362010bd9615e6e565b614f059190615e6e565b90505f62023ab1614f17836004615e95565b614f219190615ec4565b90506004614f328262023ab1615e95565b614f3d906003615e6e565b614f479190615ec4565b614f519083615ef0565b91505f62164b09614f63846001615e6e565b614f6f90610fa0615e95565b614f799190615ec4565b90506004614f89826105b5615e95565b614f939190615ec4565b614f9d9084615ef0565b614fa890601f615e6e565b92505f61098f614fb9856050615e95565b614fc39190615ec4565b90505f6050614fd48361098f615e95565b614fde9190615ec4565b614fe89086615ef0565b9050614ff5600b83615ec4565b945061500285600c615e95565b61500d836002615e6e565b6150179190615ef0565b91508483615026603187615ef0565b615031906064615e95565b61503b9190615e6e565b6150459190615e6e565b9a919950975095505050505050565b5f6107b284101561508f5760405162461bcd60e51b815260206004820152600560248201526422b93937b960d91b6044820152606401611e38565b8383835f62253d8c60046064600c6150a8600e88615ef0565b6150b29190615ec4565b6150be88611324615e6e565b6150c89190615e6e565b6150d29190615ec4565b6150dd906003615e95565b6150e79190615ec4565b600c806150f5600e88615ef0565b6150ff9190615ec4565b61510a90600c615e95565b615115600288615ef0565b61511f9190615ef0565b61512b9061016f615e95565b6151359190615ec4565b6004600c615144600e89615ef0565b61514e9190615ec4565b61515a896112c0615e6e565b6151649190615e6e565b615170906105b5615e95565b61517a9190615ec4565b615186617d4b87615ef0565b6151909190615e6e565b61519a9190615e6e565b6151a49190615ef0565b6151ae9190615ef0565b98975050505050505050565b5f61520e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661538f9092919063ffffffff16565b80519091501561474f578080602001905181019061522c9190615b72565b61474f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611e38565b600380546001600160a01b03191690556152a48161539d565b50565b6001600160a01b03811615806152c557506001600160a01b03811630145b156152e35760405163e6c4247b60e01b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b03838116918217909255600254604051919216907f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700905f90a350565b5f80615341868686615415565b9050600183600281111561535757615357615f16565b14801561537357505f848061536e5761536e615c28565b868809115b1561538657615383600182615ba1565b90505b95945050505050565b6060612f6884845f856154be565b6001600160a01b0381166153c45760405163156fee5160e31b815260040160405180910390fd5b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f80805f19858709858702925082811083820303915050805f0361544c5783828161544257615442615c28565b04925050506144af565b808411615457575f80fd5b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b60608247101561551f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611e38565b5f80866001600160a01b0316858760405161553a9190615f2a565b5f6040518083038185875af1925050503d805f8114615574576040519150601f19603f3d011682016040523d82523d5f602084013e615579565b606091505b50915091506143c087838387606083156155f35782515f036155ec576001600160a01b0385163b6155ec5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611e38565b5081612f68565b612f6883838151156156085781518083602001fd5b8060405162461bcd60e51b8152600401611e389190615b60565b5080545f8255600202905f5260205f20908101906152a491905b808211156156605780546001600160a01b03191681555f600182015560020161563c565b5090565b5f60208284031215615674575f80fd5b5035919050565b602080825282518282018190525f919060409081850190868401855b828110156156c557815180516001600160a01b03168552860151868501529284019290850190600101615697565b5091979650505050505050565b6001600160a01b03811681146152a4575f80fd5b80356156f1816156d2565b919050565b5f8060408385031215615707575f80fd5b823591506020830135615719816156d2565b809150509250929050565b5f8060208385031215615735575f80fd5b823567ffffffffffffffff8082111561574c575f80fd5b818501915085601f83011261575f575f80fd5b81358181111561576d575f80fd5b8660208260061b8501011115615781575f80fd5b60209290920196919550909350505050565b5f805f606084860312156157a5575f80fd5b83356157b0816156d2565b92506020840135915060408401356157c7816156d2565b809150509250925092565b5f805f606084860312156157e4575f80fd5b505081359360208301359350604090920135919050565b5f6020828403121561580b575f80fd5b81356144af816156d2565b80151581146152a4575f80fd5b5f8060408385031215615834575f80fd5b823561583f81615816565b9150602083013561571981615816565b60ff811681146152a4575f80fd5b5f805f805f805f60e0888a031215615873575f80fd5b873561587e816156d2565b9650602088013595506040880135615895816156d2565b9450606088013593506080880135925060a0880135915060c08801356158ba8161584f565b8091505092959891949750929550565b5f80604083850312156158db575f80fd5b82359150602083013561571981615816565b5f805f8060808587031215615900575f80fd5b8435935060208501359250604085013591506060850135615920816156d2565b939692955090935050565b5f806040838503121561593c575f80fd5b8235615947816156d2565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b604051610200810167ffffffffffffffff8111828210171561598d5761598d615955565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156159bc576159bc615955565b604052919050565b5f61020082840312156159d5575f80fd5b6159dd615969565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120615a418185016156e6565b90820152610140615a538482016156e6565b90820152610160615a658482016156e6565b90820152610180615a778482016156e6565b908201526101a0615a898482016156e6565b908201526101c0615a9b8482016156e6565b908201526101e0615aad8482016156e6565b908201529392505050565b5f805f8060808587031215615acb575f80fd5b5050823594602084013594506040840135936060013592509050565b5f8060408385031215615af8575f80fd5b8235615b03816156d2565b915060208301356157198161584f565b5f5b83811015615b2d578181015183820152602001615b15565b50505f910152565b5f8151808452615b4c816020860160208601615b13565b601f01601f19169290920160200192915050565b602081525f6144af6020830184615b35565b5f60208284031215615b82575f80fd5b81516144af81615816565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561170957611709615b8d565b634e487b7160e01b5f52603260045260245ffd5b8135615bd3816156d2565b81546001600160a01b0319166001600160a01b03919091161781556020919091013560019190910155565b8181038181111561170957611709615b8d565b808202811582820484141761170957611709615b8d565b634e487b7160e01b5f52601260045260245ffd5b5f82615c4a57615c4a615c28565b500490565b5f60208284031215615c5f575f80fd5b81516144af816156d2565b5f60208284031215615c7a575f80fd5b5051919050565b5f60208284031215615c91575f80fd5b81516144af8161584f565b600181815b8085111561434357815f1904821115615cbc57615cbc615b8d565b80851615615cc957918102915b93841c9390800290615ca1565b5f82615ce457506001611709565b81615cf057505f611709565b8160018114615d065760028114615d1057615d2c565b6001915050611709565b60ff841115615d2157615d21615b8d565b50506001821b611709565b5060208310610133831016604e8410600b8410161715615d4f575081810a611709565b615d598383615c9c565b805f1904821115615d6c57615d6c615b8d565b029392505050565b5f6144af60ff841683615cd6565b5f6020808385031215615d93575f80fd5b825167ffffffffffffffff80821115615daa575f80fd5b818501915085601f830112615dbd575f80fd5b815181811115615dcf57615dcf615955565b8060051b9150615de0848301615993565b8181529183018401918481019088841115615df9575f80fd5b938501935b838510156151ae5784519250615e13836156d2565b8282529385019390850190615dfe565b5f8060408385031215615e34575f80fd5b505080516020909101519092909150565b5f81615e5357615e53615b8d565b505f190190565b634e487b7160e01b5f52603160045260245ffd5b8082018281125f831280158216821582161715615e8d57615e8d615b8d565b505092915050565b8082025f8212600160ff1b84141615615eb057615eb0615b8d565b818105831482151761170957611709615b8d565b5f82615ed257615ed2615c28565b600160ff1b82145f1984141615615eeb57615eeb615b8d565b500590565b8181035f831280158383131683831282161715615f0f57615f0f615b8d565b5092915050565b634e487b7160e01b5f52602160045260245ffd5b5f8251615f3b818460208701615b13565b919091019291505056fea2646970667358221220a7b6ef1853c0013d977b2bbd29fd244d97f0329f4293dca1fc59bd0dfce2160064736f6c63430008180033
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610417575f3560e01c80638ed8327111610221578063d3a8d7181161012a578063e9f2838e116100b4578063f5ae497a11610084578063f5ae497a146108c9578063fa20e0fe146108dc578063fc6fb837146108e5578063ff06002b146108ee578063ff3c63c014610901575f80fd5b8063e9f2838e1461087c578063f2fde38b14610890578063f3cbf47c146108a3578063f45346dc146108b6575f80fd5b8063dece0102116100fa578063dece01021461083e578063e2eb36b914610846578063e30c397814610859578063e62286801461086a578063e976d43114610873575f80fd5b8063d3a8d7181461081b578063d961b58c14610823578063dad361c51461082c578063dbd5edc714610835575f80fd5b8063be1f9214116101ab578063c87965721161017b578063c8796572146107d2578063c8e11e8e146107da578063ca55a557146107ed578063cb3dc357146107f5578063cdb1fb2b14610808575f80fd5b8063be1f921414610786578063c25dd81f14610799578063c3646a0f146107ac578063c4d66de8146107bf575f80fd5b80639efee6be116101f15780639efee6be14610706578063b3c9e83d14610719578063b4db4be81461072c578063b8f82b261461073f578063bb27070914610752575f80fd5b80638ed83271146106ce57806390f1c5f1146106d757806399aa14d0146106ea5780639cb43f81146106fd575f80fd5b8063520cd0361161032357806373f351c8116102ad5780638120b5791161027d5780638120b5791461068f578063820fe4be146106985780638bc7e8c4146106a15780638c0190e3146106aa5780638da5cb5b146106bd575f80fd5b806373f351c814610662578063785c31271461066b578063790739a21461067457806379ba509714610687575f80fd5b806360da3e83116102f357806360da3e83146105f85780636c46407b1461060c5780636e07302b146106345780636f4ab3dd1461063c5780636ff1c9bc1461064f575f80fd5b8063520cd036146105ae5780635486679d146105b65780635b1dac60146105be5780635d9e5cab146105c6575f80fd5b806322928208116103a457806336a0f8a51161037457806336a0f8a51461055157806336b7ea151461056457806338d52e0f1461056d5780633c7ecb4a1461057e578063502bee6614610591575f80fd5b8063229282081461050f57806324e86d671461052257806328f856801461052b57806329451a221461053e575f80fd5b8063127effb2116103ea578063127effb214610498578063184466c9146104c35780631bca5113146104d65780631dddfbe1146104e95780631f4f519c146104fc575f80fd5b8063030d624a1461041b57806309f25fc0146104305780630ffbfda41461044e578063107703ab14610465575b5f80fd5b61042e610429366004615664565b610952565b005b610438610acc565b604051610445919061567b565b60405180910390f35b610457603e5481565b604051908152602001610445565b6104786104733660046156f6565b610b3f565b604080519485526020850193909352918301526060820152608001610445565b6006546104ab906001600160a01b031681565b6040516001600160a01b039091168152602001610445565b61042e6104d1366004615664565b610f20565b61042e6104e4366004615724565b611031565b61042e6104f7366004615793565b611216565b61042e61050a366004615664565b6113f8565b61042e61051d3660046156f6565b6114d5565b610457602a5481565b610457610539366004615664565b611689565b61042e61054c366004615724565b61170f565b61042e61055f3660046157d2565b6118c6565b61045760185481565b601b546001600160a01b03166104ab565b61042e61058c3660046157fb565b611999565b60315461059e9060ff1681565b6040519015158152602001610445565b610457611aed565b61042e611b4b565b610457611f19565b6105d96105d4366004615664565b611f22565b604080516001600160a01b039093168352602083019190915201610445565b60065461059e90600160a01b900460ff1681565b61061f61061a3660046157d2565b611f58565b60408051928352602083019190915201610445565b610457611fb3565b61042e61064a366004615793565b611fbc565b61042e61065d3660046157fb565b61217f565b61045760195481565b61045760145481565b61042e610682366004615664565b612432565b61042e61255f565b610457603b5481565b61045760295481565b610457602b5481565b61042e6106b8366004615823565b61264b565b6002546001600160a01b03166104ab565b610457601a5481565b6105d96106e5366004615664565b612765565b6104576106f836600461585d565b612774565b610457602c5481565b61042e6107143660046158ca565b612a0f565b61061f6107273660046158ed565b612aa9565b61061f61073a3660046158ca565b612e50565b61061f61074d36600461592b565b612e7c565b6107746107603660046157fb565b60096020525f908152604090205460ff1681565b60405160ff9091168152602001610445565b6104576107943660046158ed565b612f17565b6008546104ab906001600160a01b031681565b61042e6107ba3660046157fb565b612f70565b61042e6107cd3660046157fb565b613061565b61042e613195565b61042e6107e83660046157fb565b61337f565b610478613463565b61042e6108033660046159c4565b613498565b601d546104ab906001600160a01b031681565b61042e6138bc565b61045760155481565b610457603d5481565b610457601e5481565b6104386139aa565b6007546104ab906001600160a01b031681565b6003546001600160a01b03166104ab565b61045760165481565b61045760285481565b60065461059e90600160a81b900460ff1681565b61042e61089e3660046157fb565b613a13565b61042e6108b1366004615ab8565b613a99565b6104576108c4366004615793565b613f91565b601c546104ab906001600160a01b031681565b61045760175481565b610457603c5481565b61042e6108fc366004615ae7565b6141a8565b61045761090f3660046157d2565b604080516020808201959095528082019390935260608084019290925280518084039092018252608090920182528051908301205f908152602d90925290205490565b60026001540361097557604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166109a45760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b031633146109cf57604051630b2db9b760e31b815260040160405180910390fd5b5f816040516024016109e391815260200190565b60408051601f19818403018152918152602080830180516001600160e01b0316630186b12560e11b1790529051610a1b929101615b60565b60408051601f19818403018152908290528051602091820120601985905584835292507f2147e2bc8c39e67f74b1a9e08896ea1485442096765942206af1f4bc8bcde91791015b60405180910390a160075460405163af6f8c1b60e01b8152600481018390526001600160a01b039091169063af6f8c1b906024015b5f604051808303815f87803b158015610aae575f80fd5b505af1158015610ac0573d5f803e3d5ffd5b50506001805550505050565b60606005805480602002602001604051908101604052809291908181526020015f905b82821015610b36575f848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101610aef565b50505050905090565b5f805f80600260015403610b6657604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16610b955760405163d311bc3960e01b815260040160405180910390fd5b600654600160a81b900460ff1615610bc057604051636022a9e760e01b815260040160405180910390fd5b6002546001600160a01b03163314801590610be657506006546001600160a01b03163314155b8015610bfc57506008546001600160a01b031615155b8015610c6f5750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa158015610c49573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c6d9190615b72565b155b15610c8d57604051637ed449a960e01b815260040160405180910390fd5b6001600160a01b0385161580610cab57506001600160a01b03851630145b15610cc957604051631e4ec46b60e01b815260040160405180910390fd5b6001861015610ceb5760405163162908e360e11b815260040160405180910390fd5b5f80610cf988602b54614305565b91509150602854821115610d2057604051631b6132ab60e31b815260040160405180910390fd5b6001811015610d4257604051631fbaba3560e01b815260040160405180910390fd5b6001602a541015610d66576040516394fa99e760e01b815260040160405180910390fd5b602a54610d8890610d7961012c42615ba1565b610d839190615ba1565b61434b565b604080516020808201869052818301859052606080830185905283518084039091018152608090920190925280519101209297509095509350610dcf8686865f8080614370565b965088602c5f828254610de29190615ba1565b90915550505f818152602d6020526040812080548b9290610e04908490615ba1565b90915550505f818152602e602090815260408083206001600160a01b038c1684529091528120549003610e82575f818152602f6020908152604080832080546001810182558185528385200180546001600160a01b0319166001600160a01b038e169081179091558585529054603084528285209185529252909120555b5f818152602e602090815260408083206001600160a01b038c168452909152812080548b9290610eb3908490615ba1565b90915550506040518981526001600160a01b0389169033907fcf41fab81bee2456b7007d9d1a9e2261a6627a41eba8c3302b6b07f9a7a463959060200160405180910390a3601c54610f10906001600160a01b031633308c6143cb565b5050600180555092959194509250565b600260015403610f4357604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16610f725760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b03163314610f9d57604051630b2db9b760e31b815260040160405180910390fd5b602a819055604051602481018290525f9060440160408051601f19818403018152918152602080830180516001600160e01b031663184466c960e01b1790529051610fe9929101615b60565b60408051808303601f1901815290829052805160209091012060075463af6f8c1b60e01b8352600483018290529092506001600160a01b03169063af6f8c1b90602401610a97565b60026001540361105457604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166110835760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b031633146110ae57604051630b2db9b760e31b815260040160405180910390fd5b5f8160018110156110d2576040516333f52ff560e01b815260040160405180910390fd5b6110dd60055f615622565b5f5b818110156111e85760018585838181106110fb576110fb615bb4565b9050604002016020013510156111245760405163162908e360e11b815260040160405180910390fd5b5f85858381811061113757611137615bb4565b61114d92602060409092020190810191506157fb565b6001600160a01b0316036111745760405163e6c4247b60e01b815260040160405180910390fd5b84848281811061118657611186615bb4565b905060400201602001358361119b9190615ba1565b925060058585838181106111b1576111b1615bb4565b83546001810185555f94855260209094206040909102929092019260020290910190506111de8282615bc8565b50506001016110df565b5081620f42401461120c5760405163e31ac1db60e01b815260040160405180910390fd5b5050600180555050565b60026001540361123957604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166112685760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b0316331480159061128e57506002546001600160a01b03163314155b156112ac5760405163089b7a0760e41b815260040160405180910390fd5b60018210156112ce5760405163162908e360e11b815260040160405180910390fd5b6001600160a01b0381165f9081526009602052604090205460ff16600181101561130b5760405163014cc88960e21b815260040160405180910390fd5b601b545f906001600160a01b038681169116146113315761132c858561443c565b611333565b835b90506014548111156113585760405163200f4ff760e01b815260040160405180910390fd5b8060145f8282546113699190615bfe565b90915550505f1960ff8316016113e157604051631a4ca37b60e21b81526001600160a01b038681166004830152602482018690523060448301528416906369328dec906064015f604051808303815f87803b1580156113c6575f80fd5b505af11580156113d8573d5f803e3d5ffd5b505050506113ed565b6113ed858430876143cb565b505060018055505050565b60026001540361141b57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff1661144a5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b0316331480159061147057506002546001600160a01b03163314155b1561148e5760405163089b7a0760e41b815260040160405180910390fd5b5f61149882611689565b90505f6114a3611aed565b9050808211156114c657604051631373d6db60e01b815260040160405180910390fd5b50506014554260175560018055565b6002600154036114f857604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166115275760405163d311bc3960e01b815260040160405180910390fd5b600654600160a81b900460ff161561155257604051636022a9e760e01b815260040160405180910390fd5b6002546001600160a01b0316331480159061157857506006546001600160a01b03163314155b801561158e57506008546001600160a01b031615155b80156116015750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa1580156115db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115ff9190615b72565b155b1561161f57604051637ed449a960e01b815260040160405180910390fd5b6001600160a01b038116158061163d57506001600160a01b03811630145b1561165b57604051631e4ec46b60e01b815260040160405180910390fd5b600182101561167d5760405163162908e360e11b815260040160405180910390fd5b61120c828260016144b6565b5f6001601454101561169c57505f919050565b60018210156116ae5750612710919050565b60145482116116e457612710826014546127106116cb9190615c11565b6116d59190615c3c565b6116df9190615bfe565b611709565b601454612710906116f58483615c11565b6116ff9190615c3c565b6117099190615bfe565b92915050565b60026001540361173257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166117615760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b0316331461178c57604051630b2db9b760e31b815260040160405180910390fd5b5f8160018110156117b0576040516333f52ff560e01b815260040160405180910390fd5b6117bb60045f615622565b5f5b818110156111e85760018585838181106117d9576117d9615bb4565b9050604002016020013510156118025760405163162908e360e11b815260040160405180910390fd5b5f85858381811061181557611815615bb4565b61182b92602060409092020190810191506157fb565b6001600160a01b0316036118525760405163e6c4247b60e01b815260040160405180910390fd5b84848281811061186457611864615bb4565b90506040020160200135836118799190615ba1565b9250600485858381811061188f5761188f615bb4565b83546001810185555f94855260209094206040909102929092019260020290910190506118bc8282615bc8565b50506001016117bd565b6002600154036118e957604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166119185760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b0316331461194357604051630b2db9b760e31b815260040160405180910390fd5b600183101561196557604051637fb1277b60e01b815260040160405180910390fd5b60018210156119875760405163e8498be360e01b815260040160405180910390fd5b601a92909255602855601e5560018055565b6002600154036119bc57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166119eb5760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b03163314611a1657604051630b2db9b760e31b815260040160405180910390fd5b6001600160a01b038116611a3d5760405163e6c4247b60e01b815260040160405180910390fd5b601d80546001600160a01b0319166001600160a01b03831690811790915560408051636f6a537f60e11b8152905163ded4a6fe916004808201926020929091908290030181865afa158015611a94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ab89190615c4f565b601b546001600160a01b03908116911614611ae657604051630ecd66ab60e41b815260040160405180910390fd5b5060018055565b6017545f90611afe61012c42615ba1565b1015611b1d5760405163b7d0949760e01b815260040160405180910390fd5b6201518060175442611b2f9190615bfe565b601654611b3c9190615c11565b611b469190615c3c565b905090565b600260015403611b6e57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16611b9d5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b03163314801590611bc357506002546001600160a01b03163314155b15611be15760405163089b7a0760e41b815260040160405180910390fd5b603d54603c54611bf19042615bfe565b1015611c10576040516311b96bf760e31b815260040160405180910390fd5b5f611c19614612565b9050603b548111611c3d5760405163330c780160e11b815260040160405180910390fd5b601c54604080516318160ddd60e01b815290515f926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa158015611c84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ca89190615c6a565b90505f601c5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cfb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d1f9190615c81565b90505f611d2d82600a615d74565b83603b54611d3b9190615c11565b611d459190615c3c565b90505f611d506146b0565b90505f611d5d8383615bfe565b90505f620f4240603e5483611d729190615c11565b611d7c9190615c3c565b6005549091505f8167ffffffffffffffff811115611d9c57611d9c615955565b604051908082528060200260200182016040528015611dc5578160200160208202803683370190505b5090505f5b82811015611e8a575f620f42408560058481548110611deb57611deb615bb4565b905f5260205f20906002020160010154611e059190615c11565b611e0f9190615c3c565b905084811115611e4157604051630abb811560e21b815260048101829052602481018690526044015b60405180910390fd5b6001811015611e635760405163debabab560e01b815260040160405180910390fd5b80838381518110611e7657611e76615bb4565b602090810291909101015250600101611dca565b5042603c55603b8990555f5b82811015611f0957601b5460058054611f01926001600160a01b0316919084908110611ec457611ec4615bb4565b5f91825260209091206002909102015484516001600160a01b0390911690859085908110611ef457611ef4615bb4565b602002602001015161471f565b600101611e96565b5050600180555050505050505050565b5f611b46614612565b60058181548110611f31575f80fd5b5f918252602090912060029091020180546001909101546001600160a01b03909116915082565b604080516020808201869052818301859052606080830185905283518084039091018152608090920183528151918101919091205f818152602f9092529181205491611fa8868686858080614370565b915050935093915050565b5f611b466146b0565b600260015403611fdf57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff1661200e5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b0316331480159061203457506002546001600160a01b03163314155b156120525760405163089b7a0760e41b815260040160405180910390fd5b60018210156120745760405163162908e360e11b815260040160405180910390fd5b6001600160a01b0381165f9081526009602052604090205460ff1660018110156120b15760405163014cc88960e21b815260040160405180910390fd5b601b545f906001600160a01b038681169116146120d7576120d2858561443c565b6120d9565b835b90508060145f8282546120ec9190615ba1565b90915550505f1960ff83160161217457612107858486614754565b6040516311f9fbc960e21b81526001600160a01b038681166004830152602482018690528416906347e7ef24906044015f604051808303815f87803b15801561214e575f80fd5b505af1158015612160573d5f803e3d5ffd5b5050505061216f85845f614754565b6113ed565b6113ed85848661471f565b6002600154036121a257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166121d15760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b031633146121fc57604051630b2db9b760e31b815260040160405180910390fd5b6001600160a01b038116158061221a57506001600160a01b03811630145b1561223857604051631e4ec46b60e01b815260040160405180910390fd5b6006805461ffff60a01b191661010160a01b1790556040516001600160a01b03821681527fc513d827bb73b448f995555eff37d93f4d71b6ef96bc6557e2ec370ba22782ac9060200160405180910390a1601d546040805163a22484d960e01b815290515f926001600160a01b03169163a22484d991600480830192869291908290030181865afa1580156122cf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526122f69190810190615d82565b8051601b546040516370a0823160e01b815230600482015292935090915f916001600160a01b0316906370a0823190602401602060405180830381865afa158015612343573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123679190615c6a565b9050801561238657601b54612386906001600160a01b0316858361471f565b5f805b83811015610ac0578481815181106123a3576123a3615bb4565b60209081029190910101516040516370a0823160e01b81523060048201529092506001600160a01b038316906370a0823190602401602060405180830381865afa1580156123f3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124179190615c6a565b9250821561242a5761242a82878561471f565b600101612389565b60026001540361245557604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166124845760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b031633148015906124aa57506002546001600160a01b03163314155b156124c85760405163089b7a0760e41b815260040160405180910390fd5b5f816040516024016124dc91815260200190565b60408051601f19818403018152918152602080830180516001600160e01b0316633c839cd160e11b1790529051612514929101615b60565b60408051601f19818403018152908290528051602091820120601685905584835292507f30d8cff2601d989fea083347b4501d5e97976f0ce3cfef9d4bd76bef1b7f0e8a9101610a62565b600354600160a01b900460ff166125895760405163d311bc3960e01b815260040160405180910390fd5b6040513360248201525f9060440160408051601f19818403018152918152602080830180516001600160e01b031663f2fde38b60e01b17905290516125cf929101615b60565b6040516020818303038152906040528051906020012090506125ef614867565b60075460405163af6f8c1b60e01b8152600481018390526001600160a01b039091169063af6f8c1b906024015f604051808303815f87803b158015612632575f80fd5b505af1158015612644573d5f803e3d5ffd5b5050505050565b60026001540361266e57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff1661269d5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b031633148015906126c357506002546001600160a01b03163314155b156126e15760405163089b7a0760e41b815260040160405180910390fd5b6006805461ffff60a01b1916600160a01b841515810260ff60a81b191691909117600160a81b841515810291909117928390556040805160ff93850484161515815291909304909116151560208201527f559628b27717ff2f5863f3a218839e17c6bc1b900e9de0dc2b3dc365068841d791015b60405180910390a1505060018055565b60048181548110611f31575f80fd5b5f60026001540361279857604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166127c75760405163d311bc3960e01b815260040160405180910390fd5b600654600160a01b900460ff16156127f25760405163deeb694360e01b815260040160405180910390fd5b6002546001600160a01b0316331480159061281857506006546001600160a01b03163314155b801561282e57506008546001600160a01b031615155b80156128a15750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa15801561287b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061289f9190615b72565b155b156128bf57604051637ed449a960e01b815260040160405180910390fd5b601b5488906001600160a01b038083169116148015906129485750601d54604051633af32abf60e01b81526001600160a01b03838116600483015290911690633af32abf90602401602060405180830381865afa158015612922573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129469190615b72565b155b1561296657604051632188be3960e21b815260040160405180910390fd5b6129718989896148f2565b60405163d505accf60e01b8152336004820152306024820152604481018a90526064810188905260ff8516608482015260a4810187905260c481018690529092506001600160a01b038a169063d505accf9060e4015f604051808303815f87803b1580156129dd575f80fd5b505af11580156129ef573d5f803e3d5ffd5b505050506129ff898989856149e9565b5060018055979650505050505050565b600260015403612a3257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16612a615760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b03163314612a8c57604051630b2db9b760e31b815260040160405180910390fd5b6029919091556031805460ff191691151591909117905560018055565b5f80600260015403612ace57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16612afd5760405163d311bc3960e01b815260040160405180910390fd5b600654600160a81b900460ff1615612b2857604051636022a9e760e01b815260040160405180910390fd5b6002546001600160a01b03163314801590612b4e57506006546001600160a01b03163314155b8015612b6457506008546001600160a01b031615155b8015612bd75750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa158015612bb1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd59190615b72565b155b15612bf557604051637ed449a960e01b815260040160405180910390fd5b6040805160208101889052908101869052606081018590525f9060800160408051601f1981840301815291815281516020928301205f818152602e84528281206001600160a01b03891682529093529120549091506001811015612c6c576040516339c556cd60e11b815260040160405180910390fd5b5f602a54118015612c8857506002546001600160a01b03163314155b8015612c9f57506006546001600160a01b03163314155b8015612cc25750612cb48888885f8080614370565b612cc061012c42615ba1565b105b15612ce05760405163085de62560e01b815260040160405180910390fd5b5f80612cee83602b54614305565b90925090505f612cfe8284615bfe565b5f868152602e602090815260408083206001600160a01b038d1684528252808320839055888352602d909152812080549293508692909190612d41908490615bfe565b9250508190555083602c5f828254612d599190615bfe565b925050819055508060155f828254612d719190615ba1565b90915550612d8190508589614aad565b876001600160a01b03167f2e06b2c9d4ccae2592eda2017cb2fb604b8d7418e85f023375514ab25ff2cc4c83604051612dbc91815260200190565b60405180910390a2601c54604051632770a7eb60e21b8152306004820152602481018690526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015612e0d575f80fd5b505af1158015612e1f573d5f803e3d5ffd5b5050601b54612e3b92506001600160a01b03169050898461471f565b50600180559199919850909650505050505050565b5f805f83612e6057602b54612e64565b6029545b9050612e708582614305565b92509250509250929050565b601d54601c54601454604051632b78daa360e11b81526001600160a01b03928316600482015285831660248201523060448201526064810185905260848101919091525f92839216906356f1b5469060a4016040805180830381865afa158015612ee8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f0c9190615e23565b915091509250929050565b604080516020808201879052818301869052606080830186905283518084039091018152608090920183528151918101919091205f908152602e82528281206001600160a01b038516825290915220545b949350505050565b600260015403612f9357604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16612fc25760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b03163314801590612fe857506002546001600160a01b03163314155b156130065760405163089b7a0760e41b815260040160405180910390fd5b6001600160a01b0381165f81815260096020908152604091829020805460ff1916905590519182527f2f520fb256d37bacc8a5e0fb9e69362d4bb462500c7e54f56ea54416e92d47d691015b60405180910390a15060018055565b5f54610100900460ff161580801561307f57505f54600160ff909116105b806130985750303b15801561309857505f5460ff166001145b6130fb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401611e38565b5f805460ff19166001179055801561311c575f805461ff0019166101001790555b6006805461ffff60a01b191661010160a01b179055600280546001600160a01b0319166001600160a01b0384161790558015613191575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6002600154036131b857604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166131e75760405163d311bc3960e01b815260040160405180910390fd5b600454600181101561320c576040516333f52ff560e01b815260040160405180910390fd5b6015548015613377575f8267ffffffffffffffff81111561322f5761322f615955565b604051908082528060200260200182016040528015613258578160200160208202803683370190505b5090505f5b83811015613313575f620f4240846004848154811061327e5761327e615bb4565b905f5260205f209060020201600101546132989190615c11565b6132a29190615c3c565b90506015548111156132d557601554604051630abb811560e21b8152611e38918391600401918252602082015260400190565b808383815181106132e8576132e8615bb4565b6020026020010181815250508060155f8282546133059190615bfe565b90915550505060010161325d565b506040517f3f33b5ed245dfaf97e122dfc86e9d14ff254c4878a7c9ba8dab46d9c71cc3015905f90a15f5b8381101561337457601b546004805461336c926001600160a01b0316919084908110611ec457611ec4615bb4565b60010161333e565b50505b505060018055565b6002600154036133a257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166133d15760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b031633148015906133f757506002546001600160a01b03163314155b156134155760405163089b7a0760e41b815260040160405180910390fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f7e7afb649fef7779605afaad37b91d9f5044726c260bb394570089d052d5dbb790602001613052565b5f805f8061347b602a5461012c42610d799190615ba1565b919550935091506134908484845f8080614370565b905090919293565b6002600154036134bb57604051633ee5aeb560e01b815260040160405180910390fd5b60026001819055546001600160a01b031633146134eb57604051630b2db9b760e31b815260040160405180910390fd5b600354600160a01b900460ff1615613516576040516308db0db560e11b815260040160405180910390fd5b620151808160600151101561353e57604051630320a41d60e51b815260040160405180910390fd5b60a0810151603d558051601a8190556020820151602855601e556040808201516029556060820151602a556080820151602b5560c082015160165560e0820151601955610100820151603e5561014082015160068054610160850151600780546001600160a01b03199081166001600160a01b0393841617909155610180870151601c805483169184169190911790556101a0870151601b8054831691841691909117905542601781905560188190556101e0880151601d80548416918516919091179055610120880151600880549093169084161790915593166001600160b01b0319909116179055603c5560038054600160a01b60ff60a01b19909116179055517f1eb56c868d62c38b9f2e3bd3d0556bed1dc7df623758318faaaaa05ffff993c7905f90a1613674816101c00151614c92565b601d5f9054906101000a90046001600160a01b03166001600160a01b031663ded4a6fe6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156136c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136e89190615c4f565b601b546001600160a01b0390811691161461371657604051630ecd66ab60e41b815260040160405180910390fd5b601c5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613766573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061378a9190615c81565b60ff16601b5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137dd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138019190615c81565b60ff16146138225760405163697e864b60e01b815260040160405180910390fd5b601c546040805163313ce56760e01b815290515f926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015613869573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061388d9190615c81565b61389890600a615d74565b6138a3906001615c11565b90505f6138b0825f614e44565b603b5550506001805550565b6002600154036138df57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff1661390e5760405163d311bc3960e01b815260040160405180910390fd5b5f6139176146b0565b90505f6127106301e13380601854426139309190615bfe565b60195461393d9086615c11565b6139479190615c11565b6139519190615c3c565b61395b9190615c3c565b9050426018819055508060155f8282546139759190615ba1565b90915550506040518181527f2d46e156a9ac545bd5f27832a0e6293d21c92faf9237534c6b18c51e9cca59df90602001612755565b60606004805480602002602001604051908101604052809291908181526020015f9082821015610b36575f848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101610aef565b600260015403613a3657604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16613a655760405163d311bc3960e01b815260040160405180910390fd5b6002546001600160a01b03163314613a9057604051630b2db9b760e31b815260040160405180910390fd5b611ae681614c92565b600260015403613abc57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16613aeb5760405163d311bc3960e01b815260040160405180910390fd5b600654600160a81b900460ff1615613b1657604051636022a9e760e01b815260040160405180910390fd5b6001811015613b38576040516334e33ddb60e01b815260040160405180910390fd5b6040805160208101869052908101849052606081018390525f906080016040516020818303038152906040528051906020012090506001602d5f8381526020019081526020015f20541015613ba057604051630683f18b60e41b815260040160405180910390fd5b5f602a54118015613bbc57506002546001600160a01b03163314155b8015613bd357506006546001600160a01b03163314155b8015613bf65750613be88585855f8080614370565b613bf461012c42615ba1565b105b15613c145760405163085de62560e01b815260040160405180910390fd5b5f818152602f60205260408120548310613c3b575f828152602f6020526040902054613c3d565b825b5f838152602f60205260408120549192508267ffffffffffffffff811115613c6757613c67615955565b604051908082528060200260200182016040528015613c90578160200160208202803683370190505b5090505f8367ffffffffffffffff811115613cad57613cad615955565b604051908082528060200260200182016040528015613cd6578160200160208202803683370190505b5090505f80808087875b613cea8a8a615bfe565b811115613e92575f8b8152602f60205260409020613d09600183615bfe565b81548110613d1957613d19615bb4565b5f918252602090912001546001600160a01b0316945081613d3981615e45565b92505084888381518110613d4f57613d4f615bb4565b6001600160a01b039283166020918202929092018101919091525f8d8152602e825260408082209389168252929091522054613d8b9087615ba1565b5f8c8152602e602090815260408083206001600160a01b038a168452909152902054602b54919750613dbc91614305565b809450819550505082878381518110613dd757613dd7615bb4565b6020908102919091010152613dec8385615bfe565b60155f828254613dfc9190615ba1565b90915550505f8b8152602e602090815260408083206001600160a01b038916845282528083208390558d8352602f9091529020805480613e3e57613e3e615e5a565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092558c82526030815260408083206001600160a01b038916845290915281205580613e8a81615e45565b915050613ce0565b5084602c5f828254613ea49190615bfe565b90915550505f8a8152602d602052604081208054879290613ec6908490615bfe565b9091555050601c54604051632770a7eb60e21b8152306004820152602481018790526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015613f14575f80fd5b505af1158015613f26573d5f803e3d5ffd5b505050505f5b8751811015613f7c57601b548851613f74916001600160a01b0316908a9084908110613f5a57613f5a615bb4565b6020026020010151898481518110611ef457611ef4615bb4565b600101613f2c565b50506001805550505050505050505050505050565b5f600260015403613fb557604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff16613fe45760405163d311bc3960e01b815260040160405180910390fd5b600654600160a01b900460ff161561400f5760405163deeb694360e01b815260040160405180910390fd5b6002546001600160a01b0316331480159061403557506006546001600160a01b03163314155b801561404b57506008546001600160a01b031615155b80156140be5750600854604051633af32abf60e01b81523360048201526001600160a01b0390911690633af32abf90602401602060405180830381865afa158015614098573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906140bc9190615b72565b155b156140dc57604051637ed449a960e01b815260040160405180910390fd5b601b5484906001600160a01b038083169116148015906141655750601d54604051633af32abf60e01b81526001600160a01b03838116600483015290911690633af32abf90602401602060405180830381865afa15801561413f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141639190615b72565b155b1561418357604051632188be3960e21b815260040160405180910390fd5b61418e8585856148f2565b915061419c858585856149e9565b50600180559392505050565b6002600154036141cb57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166141fa5760405163d311bc3960e01b815260040160405180910390fd5b6006546001600160a01b0316331480159061422057506002546001600160a01b03163314155b1561423e5760405163089b7a0760e41b815260040160405180910390fd5b6001600160a01b038216158061425c57506001600160a01b03821630145b1561427a5760405163e6c4247b60e01b815260040160405180910390fd5b60ff8116600114801590614292575060ff8116600214155b156142b05760405163e01b409760e01b815260040160405180910390fd5b6001600160a01b0382165f81815260096020908152604091829020805460ff191660ff861617905590519182527f324201c119d7f14ed24d964257aa0c870524bde20d9ecb31d4b37eadc20336ff9101612755565b5f80614311845f614e44565b91508190505f83156143435761271061432a8486615c11565b6143349190615c3c565b90506143408184615bfe565b91505b509250929050565b5f808061436361435e6201518086615c3c565b614ee5565b9196909550909350915050565b5f8161437d603c85615c11565b614389610e1087615c11565b620151806143988b8b8b615054565b6143a29190615c11565b6143ac9190615ba1565b6143b69190615ba1565b6143c09190615ba1565b979650505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526144369085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526151ba565b50505050565b601d546040516364696fab60e11b81526001600160a01b038481166004830152602482018490525f92169063c8d2df5690604401602060405180830381865afa15801561448b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906144af9190615c6a565b9392505050565b5f805f836144c657602b546144ca565b6029545b90506144d68682614305565b60285491945092508311156144fe57604051631b6132ab60e31b815260040160405180910390fd5b600182101561452057604051631fbaba3560e01b815260040160405180910390fd5b60315460ff1661454a576145348284615bfe565b60155f8282546145449190615ba1565b90915550505b604080518381526020810188905233916001600160a01b0388169183917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a4601c54604051632770a7eb60e21b8152336004820152602481018890526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b1580156145db575f80fd5b505af11580156145ed573d5f803e3d5ffd5b5050601b5461460992506001600160a01b03169050868461471f565b50935093915050565b5f80601c5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015614664573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906146889190615c81565b61469390600a615d74565b61469e906001615c11565b90506146aa815f614e44565b91505090565b601d5460145460405163ad07802160e01b815260048101919091525f916001600160a01b03169063ad07802190602401602060405180830381865afa1580156146fb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b469190615c6a565b6040516001600160a01b03831660248201526044810182905261474f90849063a9059cbb60e01b906064016143ff565b505050565b8015806147cc5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156147a6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906147ca9190615c6a565b155b6148375760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401611e38565b6040516001600160a01b03831660248201526044810182905261474f90849063095ea7b360e01b906064016143ff565b60026001540361488a57604051633ee5aeb560e01b815260040160405180910390fd5b6002600155600354600160a01b900460ff166148b95760405163d311bc3960e01b815260040160405180910390fd5b6003546001600160a01b031633146148e3576040516282b42960e81b815260040160405180910390fd5b6148ec3361528b565b60018055565b5f60018310156149155760405163162908e360e11b815260040160405180910390fd5b6001600160a01b038216158061493357506001600160a01b03821630145b1561495157604051631e4ec46b60e01b815260040160405180910390fd5b5f8061495d8686612e7c565b91509150600182101561498357604051633999656760e01b815260040160405180910390fd5b601a548111156149a657604051639ade546d60e01b815260040160405180910390fd5b5f6149af6146b0565b6149b99083615ba1565b9050601e548111156149de576040516312e7cad560e21b815260040160405180910390fd5b509095945050505050565b604080516001600160a01b038681168252602082018690529181018390529083169033907fc436f473cd90c9b4dd731856a14b80f713d384a1688a506d4230140c5b36d5cd9060600160405180910390a3614a46843330866143cb565b601c546040516340c10f1960e01b81526001600160a01b03848116600483015260248201849052909116906340c10f19906044015f604051808303815f87803b158015614a91575f80fd5b505af1158015614aa3573d5f803e3d5ffd5b5050505050505050565b5f8281526030602090815260408083206001600160a01b0385168452909152812054614adb90600190615bfe565b5f848152602f602052604081208054929350614af8600184615bfe565b81548110614b0857614b08615bb4565b5f918252602090912001546001600160a01b03908116915084168114614c2c575f858152602f60205260409020805484908110614b4757614b47615bb4565b5f918252602080832090910154878352602f90915260409091206001600160a01b0390911690614b78600185615bfe565b81548110614b8857614b88615bb4565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555080602f5f8781526020019081526020015f208481548110614bd657614bd6615bb4565b5f91825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055614c09836001615ba1565b5f8681526030602090815260408083206001600160a01b03861684529091529020555b5f858152602f60205260409020805480614c4857614c48615e5a565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092559581526030865260408082206001600160a01b0396909616825294909552505050812055565b6003545f906001600160a01b031615614d11576003546040516001600160a01b03909116602482015260440160408051601f19818403018152918152602080830180516001600160e01b031663f2fde38b60e01b1790529051614cf6929101615b60565b60405160208183030381529060405280519060200120614d13565b5f5b6040516001600160a01b03841660248201529091505f9060440160408051601f19818403018152918152602080830180516001600160e01b031663f2fde38b60e01b1790529051614d65929101615b60565b604051602081830303815290604052805190602001209050614d86836152a7565b8115614de65760075460405163c4d252f560e01b8152600481018490526001600160a01b039091169063c4d252f5906024015f604051808303815f87803b158015614dcf575f80fd5b505af1158015614de1573d5f803e3d5ffd5b505050505b600754604051631523ab0160e21b8152600481018390526001600160a01b039091169063548eac04906024015f604051808303815f87803b158015614e29575f80fd5b505af1158015614e3b573d5f803e3d5ffd5b50505050505050565b5f80601c5f9054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614e96573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614eba9190615c6a565b905060018110614edd57614ed8614ecf6146b0565b85908386615334565b612f68565b509192915050565b5f8080838162253d8c614efb8362010bd9615e6e565b614f059190615e6e565b90505f62023ab1614f17836004615e95565b614f219190615ec4565b90506004614f328262023ab1615e95565b614f3d906003615e6e565b614f479190615ec4565b614f519083615ef0565b91505f62164b09614f63846001615e6e565b614f6f90610fa0615e95565b614f799190615ec4565b90506004614f89826105b5615e95565b614f939190615ec4565b614f9d9084615ef0565b614fa890601f615e6e565b92505f61098f614fb9856050615e95565b614fc39190615ec4565b90505f6050614fd48361098f615e95565b614fde9190615ec4565b614fe89086615ef0565b9050614ff5600b83615ec4565b945061500285600c615e95565b61500d836002615e6e565b6150179190615ef0565b91508483615026603187615ef0565b615031906064615e95565b61503b9190615e6e565b6150459190615e6e565b9a919950975095505050505050565b5f6107b284101561508f5760405162461bcd60e51b815260206004820152600560248201526422b93937b960d91b6044820152606401611e38565b8383835f62253d8c60046064600c6150a8600e88615ef0565b6150b29190615ec4565b6150be88611324615e6e565b6150c89190615e6e565b6150d29190615ec4565b6150dd906003615e95565b6150e79190615ec4565b600c806150f5600e88615ef0565b6150ff9190615ec4565b61510a90600c615e95565b615115600288615ef0565b61511f9190615ef0565b61512b9061016f615e95565b6151359190615ec4565b6004600c615144600e89615ef0565b61514e9190615ec4565b61515a896112c0615e6e565b6151649190615e6e565b615170906105b5615e95565b61517a9190615ec4565b615186617d4b87615ef0565b6151909190615e6e565b61519a9190615e6e565b6151a49190615ef0565b6151ae9190615ef0565b98975050505050505050565b5f61520e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661538f9092919063ffffffff16565b80519091501561474f578080602001905181019061522c9190615b72565b61474f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611e38565b600380546001600160a01b03191690556152a48161539d565b50565b6001600160a01b03811615806152c557506001600160a01b03811630145b156152e35760405163e6c4247b60e01b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b03838116918217909255600254604051919216907f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700905f90a350565b5f80615341868686615415565b9050600183600281111561535757615357615f16565b14801561537357505f848061536e5761536e615c28565b868809115b1561538657615383600182615ba1565b90505b95945050505050565b6060612f6884845f856154be565b6001600160a01b0381166153c45760405163156fee5160e31b815260040160405180910390fd5b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f80805f19858709858702925082811083820303915050805f0361544c5783828161544257615442615c28565b04925050506144af565b808411615457575f80fd5b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b60608247101561551f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611e38565b5f80866001600160a01b0316858760405161553a9190615f2a565b5f6040518083038185875af1925050503d805f8114615574576040519150601f19603f3d011682016040523d82523d5f602084013e615579565b606091505b50915091506143c087838387606083156155f35782515f036155ec576001600160a01b0385163b6155ec5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611e38565b5081612f68565b612f6883838151156156085781518083602001fd5b8060405162461bcd60e51b8152600401611e389190615b60565b5080545f8255600202905f5260205f20908101906152a491905b808211156156605780546001600160a01b03191681555f600182015560020161563c565b5090565b5f60208284031215615674575f80fd5b5035919050565b602080825282518282018190525f919060409081850190868401855b828110156156c557815180516001600160a01b03168552860151868501529284019290850190600101615697565b5091979650505050505050565b6001600160a01b03811681146152a4575f80fd5b80356156f1816156d2565b919050565b5f8060408385031215615707575f80fd5b823591506020830135615719816156d2565b809150509250929050565b5f8060208385031215615735575f80fd5b823567ffffffffffffffff8082111561574c575f80fd5b818501915085601f83011261575f575f80fd5b81358181111561576d575f80fd5b8660208260061b8501011115615781575f80fd5b60209290920196919550909350505050565b5f805f606084860312156157a5575f80fd5b83356157b0816156d2565b92506020840135915060408401356157c7816156d2565b809150509250925092565b5f805f606084860312156157e4575f80fd5b505081359360208301359350604090920135919050565b5f6020828403121561580b575f80fd5b81356144af816156d2565b80151581146152a4575f80fd5b5f8060408385031215615834575f80fd5b823561583f81615816565b9150602083013561571981615816565b60ff811681146152a4575f80fd5b5f805f805f805f60e0888a031215615873575f80fd5b873561587e816156d2565b9650602088013595506040880135615895816156d2565b9450606088013593506080880135925060a0880135915060c08801356158ba8161584f565b8091505092959891949750929550565b5f80604083850312156158db575f80fd5b82359150602083013561571981615816565b5f805f8060808587031215615900575f80fd5b8435935060208501359250604085013591506060850135615920816156d2565b939692955090935050565b5f806040838503121561593c575f80fd5b8235615947816156d2565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b604051610200810167ffffffffffffffff8111828210171561598d5761598d615955565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156159bc576159bc615955565b604052919050565b5f61020082840312156159d5575f80fd5b6159dd615969565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120615a418185016156e6565b90820152610140615a538482016156e6565b90820152610160615a658482016156e6565b90820152610180615a778482016156e6565b908201526101a0615a898482016156e6565b908201526101c0615a9b8482016156e6565b908201526101e0615aad8482016156e6565b908201529392505050565b5f805f8060808587031215615acb575f80fd5b5050823594602084013594506040840135936060013592509050565b5f8060408385031215615af8575f80fd5b8235615b03816156d2565b915060208301356157198161584f565b5f5b83811015615b2d578181015183820152602001615b15565b50505f910152565b5f8151808452615b4c816020860160208601615b13565b601f01601f19169290920160200192915050565b602081525f6144af6020830184615b35565b5f60208284031215615b82575f80fd5b81516144af81615816565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561170957611709615b8d565b634e487b7160e01b5f52603260045260245ffd5b8135615bd3816156d2565b81546001600160a01b0319166001600160a01b03919091161781556020919091013560019190910155565b8181038181111561170957611709615b8d565b808202811582820484141761170957611709615b8d565b634e487b7160e01b5f52601260045260245ffd5b5f82615c4a57615c4a615c28565b500490565b5f60208284031215615c5f575f80fd5b81516144af816156d2565b5f60208284031215615c7a575f80fd5b5051919050565b5f60208284031215615c91575f80fd5b81516144af8161584f565b600181815b8085111561434357815f1904821115615cbc57615cbc615b8d565b80851615615cc957918102915b93841c9390800290615ca1565b5f82615ce457506001611709565b81615cf057505f611709565b8160018114615d065760028114615d1057615d2c565b6001915050611709565b60ff841115615d2157615d21615b8d565b50506001821b611709565b5060208310610133831016604e8410600b8410161715615d4f575081810a611709565b615d598383615c9c565b805f1904821115615d6c57615d6c615b8d565b029392505050565b5f6144af60ff841683615cd6565b5f6020808385031215615d93575f80fd5b825167ffffffffffffffff80821115615daa575f80fd5b818501915085601f830112615dbd575f80fd5b815181811115615dcf57615dcf615955565b8060051b9150615de0848301615993565b8181529183018401918481019088841115615df9575f80fd5b938501935b838510156151ae5784519250615e13836156d2565b8282529385019390850190615dfe565b5f8060408385031215615e34575f80fd5b505080516020909101519092909150565b5f81615e5357615e53615b8d565b505f190190565b634e487b7160e01b5f52603160045260245ffd5b8082018281125f831280158216821582161715615e8d57615e8d615b8d565b505092915050565b8082025f8212600160ff1b84141615615eb057615eb0615b8d565b818105831482151761170957611709615b8d565b5f82615ed257615ed2615c28565b600160ff1b82145f1984141615615eeb57615eeb615b8d565b500590565b8181035f831280158383131683831282161715615f0f57615f0f615b8d565b5092915050565b634e487b7160e01b5f52602160045260245ffd5b5f8251615f3b818460208701615b13565b919091019291505056fea2646970667358221220a7b6ef1853c0013d977b2bbd29fd244d97f0329f4293dca1fc59bd0dfce2160064736f6c63430008180033
Deployed Bytecode Sourcemap
122798:7986:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72218:642;;;;;;:::i;:::-;;:::i;:::-;;56078:162;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123153:33;;;;;;;;;1188:25:1;;;1176:2;1161:18;123153:33:0;1042:177:1;88878:2224:0;;;;;;:::i;:::-;;:::i;:::-;;;;2050:25:1;;;2106:2;2091:18;;2084:34;;;;2134:18;;;2127:34;2192:2;2177:18;;2170:34;2037:3;2022:19;88878:2224:0;1819:391:1;47538:30:0;;;;;-1:-1:-1;;;;;47538:30:0;;;;;;-1:-1:-1;;;;;2379:32:1;;;2361:51;;2349:2;2334:18;47538:30:0;2215:203:1;126562:580:0;;;;;;:::i;:::-;;:::i;53420:716::-;;;;;;:::i;:::-;;:::i;70190:1108::-;;;;;;:::i;:::-;;:::i;65919:488::-;;;;;;:::i;:::-;;:::i;88139:404::-;;;;;;:::i;:::-;;:::i;83541:26::-;;;;;;76625:433;;;;;;:::i;:::-;;:::i;52583:691::-;;;;;;:::i;:::-;;:::i;87355:479::-;;;;;;:::i;:::-;;:::i;62682:28::-;;;;;;130240:99;130316:15;;-1:-1:-1;;;;;130316:15:0;130240:99;;65350:365;;;;;;:::i;:::-;;:::i;84548:26::-;;;;;;;;;;;;4281:14:1;;4274:22;4256:41;;4244:2;4229:18;84548:26:0;4116:187:1;77224:413:0;;;:::i;127214:1672::-;;;:::i;130452:99::-;;;:::i;47410:73::-;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;4500:32:1;;;4482:51;;4564:2;4549:18;;4542:34;;;;4455:18;47410:73:0;4308:274:1;47640:26:0;;;;;-1:-1:-1;;;47640:26:0;;;;;;103106:463;;;;;;:::i;:::-;;:::i;:::-;;;;4761:25:1;;;4817:2;4802:18;;4795:34;;;;4734:18;103106:463:0;4587:248:1;78794:109:0;;;:::i;68641:1238::-;;;;;;:::i;:::-;;:::i;129091:1000::-;;;;;;:::i;:::-;;:::i;62774:35::-;;;;;;62270:29;;;;;;71464:581;;;;;;:::i;:::-;;:::i;54679:369::-;;;:::i;122902:28::-;;;;;;83444:35;;;;;;83635:28;;;;;;50567:326;;;;;;:::i;:::-;;:::i;42373:89::-;42448:6;;-1:-1:-1;;;;;42448:6:0;42373:89;;62894:31;;;;;;47286:62;;;;;;:::i;:::-;;:::i;67681:580::-;;;;;;:::i;:::-;;:::i;83769:36::-;;;;;;86742:240;;;;;;:::i;:::-;;:::i;91875:2186::-;;;;;;:::i;:::-;;:::i;100177:353::-;;;;;;:::i;:::-;;:::i;76136:281::-;;;;;;:::i;:::-;;:::i;48028:56::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;7532:4:1;7520:17;;;7502:36;;7490:2;7475:18;48028:56:0;7360:184:1;102405:321:0;;;;;;:::i;:::-;;:::i;47935:38::-;;;;;-1:-1:-1;;;;;47935:38:0;;;52249:190;;;;;;:::i;:::-;;:::i;123854:172::-;;;;;;:::i;:::-;;:::i;73523:1002::-;;;:::i;51240:231::-;;;;;;:::i;:::-;;:::i;100823:403::-;;;:::i;124140:2148::-;;;;;;:::i;:::-;;:::i;63152:37::-;;;;;-1:-1:-1;;;;;63152:37:0;;;72930:452;;;:::i;62385:35::-;;;;;;123110:34;;;;;;63303:25;;;;;;55930:140;;;:::i;47838:37::-;;;;;-1:-1:-1;;;;;47838:37:0;;;46517:95;46591:13;;-1:-1:-1;;;;;46591:13:0;46517:95;;62492:31;;;;;;83323:34;;;;;;47741:29;;;;;-1:-1:-1;;;47741:29:0;;;;;;54397:160;;;;;;:::i;:::-;;:::i;94624:2825::-;;;;;;:::i;:::-;;:::i;66750:377::-;;;;;;:::i;:::-;;:::i;63074:29::-;;;;;-1:-1:-1;;;;;63074:29:0;;;62593:30;;;;;;122994:33;;;;;;51675:452;;;;;;:::i;:::-;;:::i;101626:287::-;;;;;;:::i;:::-;101817:28;;;;;;;12133:25:1;;;;12174:18;;;12167:34;;;;12217:18;;;;12210:34;;;;101817:28:0;;;;;;;;;;12106:18:1;;;;101817:28:0;;101807:39;;;;;;-1:-1:-1;101874:31:0;;;:17;:31;;;;;;;101626:287;72218:642;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;41399:6:::2;::::0;-1:-1:-1;;;;;41399:6:0::2;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::2;;;;;;;;;;;41381:44;72467:9:::3;72606:23;72514:130;;;;;;1188:25:1::0;;1176:2;1161:18;;1042:177;72514:130:0::3;;::::0;;-1:-1:-1;;72514:130:0;;::::3;::::0;;;;;;::::3;::::0;;::::3;::::0;;-1:-1:-1;;;;;72514:130:0::3;-1:-1:-1::0;;;72514:130:0::3;::::0;;72489:166;;::::3;::::0;72514:130;72489:166:::3;;:::i;:::-;;::::0;;-1:-1:-1;;72489:166:0;;::::3;::::0;;;;;;;72479:177;;72489:166:::3;72479:177:::0;;::::3;::::0;72669:20:::3;:46:::0;;;1188:25:1;;;72479:177:0;-1:-1:-1;72731:45:0::3;::::0;1161:18:1;72731:45:0::3;;;;;;;;72818:22;::::0;72789:63:::3;::::0;-1:-1:-1;;;72789:63:0;;::::3;::::0;::::3;1188:25:1::0;;;-1:-1:-1;;;;;72818:22:0;;::::3;::::0;72789:60:::3;::::0;1161:18:1;;72789:63:0::3;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;-1:-1:-1::0;;38958:1:0;41227:21;;-1:-1:-1;;;;72218:642:0:o;56078:162::-;56140:48;56208:24;56201:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;56201:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56078:162;:::o;88878:2224::-;89062:22;89095:12;89119:13;89144:11;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;86265:17:::2;::::0;-1:-1:-1;;;86265:17:0;::::2;;;86261:49;;;86291:19;;-1:-1:-1::0;;;86291:19:0::2;;;;;;;;;;;86261:49;49830:6:::3;::::0;-1:-1:-1;;;;;49830:6:0::3;49816:10;:20;::::0;::::3;::::0;49815:71:::3;;-1:-1:-1::0;49870:15:0::3;::::0;-1:-1:-1;;;;;49870:15:0::3;49856:10;:29;;49815:71;:128;;;;-1:-1:-1::0;49905:23:0::3;::::0;-1:-1:-1;;;;;49905:23:0::3;:37:::0;::::3;49815:128;:217;;;;-1:-1:-1::0;49981:23:0::3;::::0;49963:68:::3;::::0;-1:-1:-1;;;49963:68:0;;50020:10:::3;49963:68;::::0;::::3;2361:51:1::0;-1:-1:-1;;;;;49981:23:0;;::::3;::::0;49963:56:::3;::::0;2334:18:1;;49963:68:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49962:69;49815:217;49797:276;;;50051:22;;-1:-1:-1::0;;;50051:22:0::3;;;;;;;;;;;49797:276;-1:-1:-1::0;;;;;89221:26:0;::::4;::::0;;89220:63:::4;;-1:-1:-1::0;;;;;;89253:29:0;::::4;89277:4;89253:29;89220:63;89216:93;;;89292:17;;-1:-1:-1::0;;;89292:17:0::4;;;;;;;;;;;89216:93;89333:1;89324:6;:10;89320:38;;;89343:15;;-1:-1:-1::0;;;89343:15:0::4;;;;;;;;;;;89320:38;89372:20;89394:22:::0;89420:41:::4;89439:6;89447:13;;89420:18;:41::i;:::-;89371:90;;;;89491:19;;89476:12;:34;89472:71;;;89519:24;;-1:-1:-1::0;;;89519:24:0::4;;;;;;;;;;;89472:71;89575:1;89558:14;:18;89554:45;;;89585:14;;-1:-1:-1::0;;;89585:14:0::4;;;;;;;;;;;89554:45;89822:1;89808:11;;:15;89804:48;;;89832:20;;-1:-1:-1::0;;;89832:20:0::4;;;;;;;;;;;89804:48;90024:11;::::0;89947:89:::4;::::0;89973:48:::4;61846:9;89973:15;:48;:::i;:::-;:62;;;;:::i;:::-;89947:25;:89::i;:::-;90118:28;::::0;;::::4;::::0;;::::4;12133:25:1::0;;;12174:18;;;12167:34;;;12217:18;;;;12210:34;;;90118:28:0;;;;;;;;;;12106:18:1;;;;90118:28:0;;;90108:39;;;::::4;::::0;12133:25:1;;-1:-1:-1;12167:34:1;;-1:-1:-1;12210:34:1;-1:-1:-1;90245:82:0::4;12133:25:1::0;12167:34;12210;-1:-1:-1;;;90245:31:0::4;:82::i;:::-;90228:99;;90402:6;90377:21;;:31;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;90419:31:0::4;::::0;;;:17:::4;:31;::::0;;;;:41;;90454:6;;90419:31;:41:::4;::::0;90454:6;;90419:41:::4;:::i;:::-;::::0;;;-1:-1:-1;;90576:30:0::4;::::0;;;:16:::4;:30;::::0;;;;;;;-1:-1:-1;;;;;90576:44:0;::::4;::::0;;;;;;;;:49;;90572:250:::4;;90642:40;::::0;;;:26:::4;:40;::::0;;;;;;;:59;;::::4;::::0;::::4;::::0;;;;;;;;::::4;::::0;;-1:-1:-1;;;;;;90642:59:0::4;-1:-1:-1::0;;;;;90642:59:0;::::4;::::0;;::::4;::::0;;;90763:40;;;:47;;90716:16:::4;:30:::0;;;;;:44;;;;;;;;:94;90572:250:::4;90834:30;::::0;;;:16:::4;:30;::::0;;;;;;;-1:-1:-1;;;;;90834:44:0;::::4;::::0;;;;;;;:54;;90882:6;;90834:30;:54:::4;::::0;90882:6;;90834:54:::4;:::i;:::-;::::0;;;-1:-1:-1;;90906:53:0::4;::::0;1188:25:1;;;-1:-1:-1;;;;;90906:53:0;::::4;::::0;90934:10:::4;::::0;90906:53:::4;::::0;1176:2:1;1161:18;90906:53:0::4;;;;;;;91043:14;::::0;91009:85:::4;::::0;-1:-1:-1;;;;;91043:14:0::4;91060:10;91080:4;91087:6:::0;91009:26:::4;:85::i;:::-;-1:-1:-1::0;;38958:1:0;41227:21;;-1:-1:-1;88878:2224:0;;;;-1:-1:-1;88878:2224:0;-1:-1:-1;88878:2224:0:o;126562:580::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;41399:6:::2;::::0;-1:-1:-1;;;;;41399:6:0::2;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::2;;;;;;;;;;;41381:44;126725:11:::3;:25:::0;;;126925:121:::3;::::0;::::3;::::0;::::3;1188:25:1::0;;;126878:9:0::3;::::0;1161:18:1;;126925:121:0::3;::::0;;-1:-1:-1;;126925:121:0;;::::3;::::0;;;;;;::::3;::::0;;::::3;::::0;;-1:-1:-1;;;;;126925:121:0::3;-1:-1:-1::0;;;126925:121:0::3;::::0;;126900:157;;::::3;::::0;126925:121;126900:157:::3;;:::i;:::-;;::::0;;;;::::3;-1:-1:-1::0;;126900:157:0;;;;;;;126890:168;;126900:157:::3;126890:168:::0;;::::3;::::0;127100:22:::3;::::0;-1:-1:-1;;;127071:63:0;;::::3;::::0;::::3;1188:25:1::0;;;126890:168:0;;-1:-1:-1;;;;;;127100:22:0::3;::::0;127071:60:::3;::::0;1161:18:1;;127071:63:0::3;1042:177:1::0;53420:716:0;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;41399:6:::2;::::0;-1:-1:-1;;;;;41399:6:0::2;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::2;;;;;;;;;;;41381:44;53604:12:::3;53639:10:::0;53675:1:::3;53671:5:::0;::::3;53667:40;;;53685:22;;-1:-1:-1::0;;;53685:22:0::3;;;;;;;;;;;53667:40;53720:31;53727:24;;53720:31;:::i;:::-;53769:9;53764:307;53784:1;53780;:5;53764:307;;;53838:1;53811:10;;53822:1;53811:13;;;;;;;:::i;:::-;;;;;;:24;;;:28;53807:56;;;53848:15;;-1:-1:-1::0;;;53848:15:0::3;;;;;;;;;;;53807:56;53924:1;53882:10:::0;;53893:1;53882:13;;::::3;;;;;:::i;:::-;:30;::::0;::::3;:13;::::0;;::::3;;:30:::0;;::::3;::::0;-1:-1:-1;53882:30:0::3;:::i;:::-;-1:-1:-1::0;;;;;53882:44:0::3;::::0;53878:73:::3;;53935:16;;-1:-1:-1::0;;;53935:16:0::3;;;;;;;;;;;53878:73;53976:10;;53987:1;53976:13;;;;;;;:::i;:::-;;;;;;:24;;;53968:32;;;;;:::i;:::-;;;54015:24;54045:10;;54056:1;54045:13;;;;;;;:::i;:::-;54015:44:::0;;::::3;::::0;::::3;::::0;;-1:-1:-1;54015:44:0;;;::::3;::::0;;;54045:13:::3;::::0;;::::3;::::0;;;::::3;::::0;54015:44:::3;;::::0;;::::3;::::0;-1:-1:-1;54015:44:0::3;54045:13:::0;54015:44;::::3;:::i;:::-;-1:-1:-1::0;;53787:3:0::3;;53764:307;;;;54087:4;54095:8;54087:16;54083:45;;54112:16;;-1:-1:-1::0;;;54112:16:0::3;;;;;;;;;;;54083:45;-1:-1:-1::0;;38958:1:0;41227:21;;-1:-1:-1;;53420:716:0:o;70190:1108::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;49554:15:::2;::::0;-1:-1:-1;;;;;49554:15:0::2;49540:10;:29;::::0;::::2;::::0;49539:57:::2;;-1:-1:-1::0;49589:6:0::2;::::0;-1:-1:-1;;;;;49589:6:0::2;49575:10;:20;;49539:57;49535:91;;;49605:21;;-1:-1:-1::0;;;49605:21:0::2;;;;;;;;;;;49535:91;70399:1:::3;70390:6;:10;70386:38;;;70409:15;;-1:-1:-1::0;;;70409:15:0::3;;;;;;;;;;;70386:38;-1:-1:-1::0;;;;;70457:38:0;::::3;70437:17;70457:38:::0;;;:22:::3;:38;::::0;;;;;::::3;;::::0;70510:15;::::3;70506:51;;;70534:23;;-1:-1:-1::0;;;70534:23:0::3;;;;;;;;;;;70506:51;70705:15;::::0;70652:31:::3;::::0;-1:-1:-1;;;;;70687:33:0;;::::3;70705:15:::0;::::3;70687:33;70686:102;;70733:55;70765:14;70781:6;70733:31;:55::i;:::-;70686:102;;;70724:6;70686:102;70652:136;;70831:14;;70805:23;:40;70801:76;;;70854:23;;-1:-1:-1::0;;;70854:23:0::3;;;;;;;;;;;70801:76;70906:23;70888:14;;:41;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;;70946:38:0::3;::::0;::::3;::::0;70942:349:::3;;71001:93;::::0;-1:-1:-1;;;71001:93:0;;-1:-1:-1;;;;;13217:15:1;;;71001:93:0::3;::::0;::::3;13199:34:1::0;13249:18;;;13242:34;;;71087:4:0::3;13292:18:1::0;;;13285:43;71001:45:0;::::3;::::0;::::3;::::0;13134:18:1;;71001:93:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;70942:349;;;71190:89;71224:14;71241;71265:4;71272:6;71190:26;:89::i;:::-;-1:-1:-1::0;;38958:1:0;41227:21;;-1:-1:-1;;;70190:1108:0:o;65919:488::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;49554:15:::2;::::0;-1:-1:-1;;;;;49554:15:0::2;49540:10;:29;::::0;::::2;::::0;49539:57:::2;;-1:-1:-1::0;49589:6:0::2;::::0;-1:-1:-1;;;;;49589:6:0::2;49575:10;:20;;49539:57;49535:91;;;49605:21;;-1:-1:-1::0;;;49605:21:0::2;;;;;;;;;;;49535:91;66042:17:::3;66062:41;66082:20;66062:19;:41::i;:::-;66042:61;;66114:28;66145:21;:19;:21::i;:::-;66114:52;;66251:20;66239:9;:32;66235:70;;;66280:25;;-1:-1:-1::0;;;66280:25:0::3;;;;;;;;;;;66235:70;-1:-1:-1::0;;66318:14:0::3;:37:::0;66384:15:::3;66366;:33:::0;38958:1;41227:21;;65919:488::o;88139:404::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;86265:17:::2;::::0;-1:-1:-1;;;86265:17:0;::::2;;;86261:49;;;86291:19;;-1:-1:-1::0;;;86291:19:0::2;;;;;;;;;;;86261:49;49830:6:::3;::::0;-1:-1:-1;;;;;49830:6:0::3;49816:10;:20;::::0;::::3;::::0;49815:71:::3;;-1:-1:-1::0;49870:15:0::3;::::0;-1:-1:-1;;;;;49870:15:0::3;49856:10;:29;;49815:71;:128;;;;-1:-1:-1::0;49905:23:0::3;::::0;-1:-1:-1;;;;;49905:23:0::3;:37:::0;::::3;49815:128;:217;;;;-1:-1:-1::0;49981:23:0::3;::::0;49963:68:::3;::::0;-1:-1:-1;;;49963:68:0;;50020:10:::3;49963:68;::::0;::::3;2361:51:1::0;-1:-1:-1;;;;;49981:23:0;;::::3;::::0;49963:56:::3;::::0;2334:18:1;;49963:68:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49962:69;49815:217;49797:276;;;50051:22;;-1:-1:-1::0;;;50051:22:0::3;;;;;;;;;;;49797:276;-1:-1:-1::0;;;;;88339:26:0;::::4;::::0;;88338:63:::4;;-1:-1:-1::0;;;;;;88371:29:0;::::4;88395:4;88371:29;88338:63;88334:93;;;88410:17;;-1:-1:-1::0;;;88410:17:0::4;;;;;;;;;;;88334:93;88451:1;88442:6;:10;88438:38;;;88461:15;;-1:-1:-1::0;;;88461:15:0::4;;;;;;;;;;;88438:38;88489:46;88508:6;88516:12;88530:4;88489:18;:46::i;76625:433::-:0;76705:7;76746:1;76729:14;;:18;76725:41;;;-1:-1:-1;76764:1:0;;76625:433;-1:-1:-1;76625:433:0:o;76725:41::-;76804:1;76781:20;:24;76777:51;;;-1:-1:-1;76822:5:0;;76625:433;-1:-1:-1;76625:433:0:o;76777:51::-;76880:14;;76857:20;:37;76856:194;;77045:5;77021:20;76995:14;;77012:5;76995:22;;;;:::i;:::-;76994:47;;;;:::i;:::-;76993:57;;;;:::i;:::-;76856:194;;;76950:14;;76968:5;;76918:28;:20;76968:5;76918:28;:::i;:::-;76917:47;;;;:::i;:::-;76916:57;;;;:::i;:::-;76849:201;76625:433;-1:-1:-1;;76625:433:0:o;52583:691::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;41399:6:::2;::::0;-1:-1:-1;;;;;41399:6:0::2;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::2;;;;;;;;;;;41381:44;52764:12:::3;52799:10:::0;52835:1:::3;52831:5:::0;::::3;52827:40;;;52845:22;;-1:-1:-1::0;;;52845:22:0::3;;;;;;;;;;;52827:40;52880:20;52887:13;;52880:20;:::i;:::-;52918:9;52913:296;52933:1;52929;:5;52913:296;;;52987:1;52960:10;;52971:1;52960:13;;;;;;;:::i;:::-;;;;;;:24;;;:28;52956:56;;;52997:15;;-1:-1:-1::0;;;52997:15:0::3;;;;;;;;;;;52956:56;53073:1;53031:10:::0;;53042:1;53031:13;;::::3;;;;;:::i;:::-;:30;::::0;::::3;:13;::::0;;::::3;;:30:::0;;::::3;::::0;-1:-1:-1;53031:30:0::3;:::i;:::-;-1:-1:-1::0;;;;;53031:44:0::3;::::0;53027:73:::3;;53084:16;;-1:-1:-1::0;;;53084:16:0::3;;;;;;;;;;;53027:73;53125:10;;53136:1;53125:13;;;;;;;:::i;:::-;;;;;;:24;;;53117:32;;;;;:::i;:::-;;;53164:13;53183:10;;53194:1;53183:13;;;;;;;:::i;:::-;53164:33:::0;;::::3;::::0;::::3;::::0;;-1:-1:-1;53164:33:0;;;::::3;::::0;;;53183:13:::3;::::0;;::::3;::::0;;;::::3;::::0;53164:33:::3;;::::0;;::::3;::::0;-1:-1:-1;53164:33:0::3;53183:13:::0;53164:33;::::3;:::i;:::-;-1:-1:-1::0;;52936:3:0::3;;52913:296;;87355:479:::0;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;41399:6:::2;::::0;-1:-1:-1;;;;;41399:6:0::2;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::2;;;;;;;;;;;41381:44;87578:1:::3;87556:19;:23;87552:57;;;87588:21;;-1:-1:-1::0;;;87588:21:0::3;;;;;;;;;;;87552:57;87649:1;87624:22;:26;87620:63;;;87659:24;;-1:-1:-1::0;;;87659:24:0::3;;;;;;;;;;;87620:63;87696:16;:38:::0;;;;87745:19:::3;:44:::0;87800:10:::3;:26:::0;38958:1;41227:21;;87355:479::o;65350:365::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;41399:6:::2;::::0;-1:-1:-1;;;;;41399:6:0::2;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::2;;;;;;;;;;;41381:44;-1:-1:-1::0;;;;;65467:30:0;::::3;65463:59;;65506:16;;-1:-1:-1::0;;;65506:16:0::3;;;;;;;;;;;65463:59;65535:22;:41:::0;;-1:-1:-1;;;;;;65535:41:0::3;-1:-1:-1::0;;;;;65535:41:0;::::3;::::0;;::::3;::::0;;;65612:62:::3;::::0;;-1:-1:-1;;;65612:62:0;;;;:60:::3;::::0;:62:::3;::::0;;::::3;::::0;::::3;::::0;;;;;;;;;65535:41;65612:62:::3;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;65593:15;::::0;-1:-1:-1;;;;;65593:15:0;;::::3;:81:::0;::::3;;65589:118;;65683:24;;-1:-1:-1::0;;;65683:24:0::3;;;;;;;;;;;65589:118;-1:-1:-1::0;38958:1:0;41227:21;;65350:365::o;77224:413::-;77399:15;;77276:7;;77348:48;61846:9;77348:15;:48;:::i;:::-;:66;77344:97;;;77423:18;;-1:-1:-1;;;77423:18:0;;;;;;;;;;;77344:97;77623:5;77595:15;;77577;:33;;;;:::i;:::-;77557:16;;:54;;;;:::i;:::-;77556:73;;;;:::i;:::-;77549:80;;77224:413;:::o;127214:1672::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;49554:15:::2;::::0;-1:-1:-1;;;;;49554:15:0::2;49540:10;:29;::::0;::::2;::::0;49539:57:::2;;-1:-1:-1::0;49589:6:0::2;::::0;-1:-1:-1;;;;;49589:6:0::2;49575:10;:20;;49539:57;49535:91;;;49605:21;;-1:-1:-1::0;;;49605:21:0::2;;;;;;;;;;;49535:91;127356:19:::3;::::0;127335:18:::3;::::0;127317:36:::3;::::0;:15:::3;:36;:::i;:::-;:58;127313:99;;;127384:28;;-1:-1:-1::0;;;127384:28:0::3;;;;;;;;;;;127313:99;127425:25;127453:16;:14;:16::i;:::-;127425:44;;127505:13;;127484:17;:34;127480:71;;127527:24;;-1:-1:-1::0;;;127527:24:0::3;;;;;;;;;;;127480:71;127670:14;::::0;127663:36:::3;::::0;;-1:-1:-1;;;127663:36:0;;;;127641:19:::3;::::0;-1:-1:-1;;;;;127670:14:0::3;::::0;127663:34:::3;::::0;:36:::3;::::0;;::::3;::::0;::::3;::::0;;;;;;;;127670:14;127663:36:::3;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;127641:58;;127710:21;127751:14;;;;;;;;;-1:-1:-1::0;;;;;127751:14:0::3;-1:-1:-1::0;;;;;127734:41:0::3;;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;127710:67:::0;-1:-1:-1;127788:24:0::3;127848:21;127710:67:::0;127848:2:::3;:21;:::i;:::-;127832:11;127816:13;;:27;;;;:::i;:::-;127815:55;;;;:::i;:::-;127788:82;;127891:26;127920:17;:15;:17::i;:::-;127891:46:::0;-1:-1:-1;127948:27:0::3;127978:37;127999:16:::0;127891:46;127978:37:::3;:::i;:::-;127948:67;;128026:27;128101:3;128079:18;;128057:19;:40;;;;:::i;:::-;128056:48;;;;:::i;:::-;128129:24;:31:::0;128026:78;;-1:-1:-1;128117:9:0::3;128129:31:::0;128198:16:::3;::::0;::::3;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;128198:16:0::3;;128171:43;;128232:9;128227:379;128247:1;128243;:5;128227:379;;;128270:22;128360:3;128337:19;128296:24;128321:1;128296:27;;;;;;;;:::i;:::-;;;;;;;;;;;:38;;;:60;;;;:::i;:::-;128295:68;;;;:::i;:::-;128270:93;;128399:19;128382:14;:36;128378:109;;;128427:60;::::0;-1:-1:-1;;;128427:60:0;;::::3;::::0;::::3;4761:25:1::0;;;4802:18;;;4795:34;;;4734:18;;128427:60:0::3;;;;;;;;128378:109;128523:1;128506:14;:18;128502:48;;;128533:17;;-1:-1:-1::0;;;128533:17:0::3;;;;;;;;;;;128502:48;128580:14;128567:7;128575:1;128567:10;;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;;;:27;-1:-1:-1;128250:3:0::3;;128227:379;;;-1:-1:-1::0;128639:15:0::3;128618:18;:36:::0;128673:13:::3;:33:::0;;;-1:-1:-1;128719:160:0::3;128739:1;128735;:5;128719:160;;;128792:15;::::0;128810:24:::3;:27:::0;;128762:105:::3;::::0;-1:-1:-1;;;;;128792:15:0::3;::::0;128810:24;128835:1;;128810:27;::::3;;;;;:::i;:::-;;::::0;;;::::3;::::0;;;::::3;::::0;;::::3;;:44:::0;128856:10;;-1:-1:-1;;;;;128810:44:0;;::::3;::::0;128856:7;;128864:1;;128856:10;::::3;;;;;:::i;:::-;;;;;;;128762:22;:105::i;:::-;128742:3;;128719:160;;;-1:-1:-1::0;;38958:1:0;41227:21;;-1:-1:-1;;;;;;;;127214:1672:0:o;130452:99::-;130500:7;130527:16;:14;:16::i;47410:73::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;47410:73:0;;;;-1:-1:-1;47410:73:0;:::o;103106:463::-;103342:28;;;;;;;12133:25:1;;;12174:18;;;12167:34;;;12217:18;;;;12210:34;;;103342:28:0;;;;;;;;;;12106:18:1;;;;103342:28:0;;103332:39;;;;;;;;;-1:-1:-1;103404:40:0;;;:26;:40;;;;;;:47;;103479:82;12133:25:1;12167:34;12210;-1:-1:-1;;;103479:31:0;:82::i;:::-;103462:99;;103298:271;103106:463;;;;;;:::o;78794:109::-;78851:7;78878:17;:15;:17::i;68641:1238::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;49554:15:::2;::::0;-1:-1:-1;;;;;49554:15:0::2;49540:10;:29;::::0;::::2;::::0;49539:57:::2;;-1:-1:-1::0;49589:6:0::2;::::0;-1:-1:-1;;;;;49589:6:0::2;49575:10;:20;;49539:57;49535:91;;;49605:21;;-1:-1:-1::0;;;49605:21:0::2;;;;;;;;;;;49535:91;68861:1:::3;68845:13;:17;68841:45;;;68871:15;;-1:-1:-1::0;;;68871:15:0::3;;;;;;;;;;;68841:45;-1:-1:-1::0;;;;;68919:38:0;::::3;68899:17;68919:38:::0;;;:22:::3;:38;::::0;;;;;::::3;;::::0;68972:15;::::3;68968:51;;;68996:23;;-1:-1:-1::0;;;68996:23:0::3;;;;;;;;;;;68968:51;69167:15;::::0;69114:31:::3;::::0;-1:-1:-1;;;;;69149:33:0;;::::3;69167:15:::0;::::3;69149:33;69148:116;;69202:62;69234:14;69250:13;69202:31;:62::i;:::-;69148:116;;;69186:13;69148:116;69114:150;;69295:23;69277:14;;:41;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;;69335:38:0::3;::::0;::::3;::::0;69331:541:::3;;69439:76;69468:14;69485;69501:13;69439:21;:76::i;:::-;69530:75;::::0;-1:-1:-1;;;69530:75:0;;-1:-1:-1;;;;;4500:32:1;;;69530:75:0::3;::::0;::::3;4482:51:1::0;4549:18;;;4542:34;;;69530:44:0;::::3;::::0;::::3;::::0;4455:18:1;;69530:75:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;69620:64;69649:14;69666;69682:1;69620:21;:64::i;:::-;69331:541;;;69783:77;69813:14;69830;69846:13;69783:22;:77::i;129091:1000::-:0;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;41399:6:::2;::::0;-1:-1:-1;;;;;41399:6:0::2;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::2;;;;;;;;;;;41381:44;-1:-1:-1::0;;;;;129209:26:0;::::3;::::0;;129208:63:::3;;-1:-1:-1::0;;;;;;129241:29:0;::::3;129265:4;129241:29;129208:63;129204:93;;;129280:17;;-1:-1:-1::0;;;129280:17:0::3;;;;;;;;;;;129204:93;129386:14;:21:::0;;-1:-1:-1;;;;129418:24:0;-1:-1:-1;;;129418:24:0;;;129458:33:::3;::::0;-1:-1:-1;;;;;2379:32:1;;2361:51;;129458:33:0::3;::::0;2349:2:1;2334:18;129458:33:0::3;;;;;;;129565:22;::::0;129538:73:::3;::::0;;-1:-1:-1;;;129538:73:0;;;;129504:31:::3;::::0;-1:-1:-1;;;;;129565:22:0::3;::::0;129538:71:::3;::::0;:73:::3;::::0;;::::3;::::0;129504:31;;129538:73;;;;;;;129565:22;129538:73:::3;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;::::0;;::::3;-1:-1:-1::0;;129538:73:0::3;::::0;::::3;;::::0;::::3;::::0;;;::::3;::::0;::::3;:::i;:::-;129634:21:::0;;129687:15:::3;::::0;129680:48:::3;::::0;-1:-1:-1;;;129680:48:0;;129722:4:::3;129680:48;::::0;::::3;2361:51:1::0;129634:21:0;;-1:-1:-1;129634:21:0;;129622:9:::3;::::0;-1:-1:-1;;;;;129687:15:0::3;::::0;129680:33:::3;::::0;2334:18:1;;129680:48:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;129668:60:::0;-1:-1:-1;129743:5:0;;129739:75:::3;;129780:15;::::0;129750:64:::3;::::0;-1:-1:-1;;;;;129780:15:0::3;129798:12:::0;129812:1;129750:22:::3;:64::i;:::-;129827:17;129860:9:::0;129855:229:::3;129875:1;129871;:5;129855:229;;;129910:14;129925:1;129910:17;;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;;;;129946:42:::3;::::0;-1:-1:-1;;;129946:42:0;;129982:4:::3;129946:42;::::0;::::3;2361:51:1::0;129910:17:0;;-1:-1:-1;;;;;;129946:27:0;::::3;::::0;::::3;::::0;2334:18:1;;129946:42:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;129942:46:::0;-1:-1:-1;130007:5:0;;130003:69:::3;;130014:58;130044:9;130056:12;130070:1;130014:22;:58::i;:::-;129878:3;;129855:229;;71464:581:::0;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;49554:15:::2;::::0;-1:-1:-1;;;;;49554:15:0::2;49540:10;:29;::::0;::::2;::::0;49539:57:::2;;-1:-1:-1::0;49589:6:0::2;::::0;-1:-1:-1;;;;;49589:6:0::2;49575:10;:20;;49539:57;49535:91;;;49605:21;;-1:-1:-1::0;;;49605:21:0::2;;;;;;;;;;;49535:91;71695:9:::3;71837:8;71742:118;;;;;;1188:25:1::0;;1176:2;1161:18;;1042:177;71742:118:0::3;;::::0;;-1:-1:-1;;71742:118:0;;::::3;::::0;;;;;;::::3;::::0;;::::3;::::0;;-1:-1:-1;;;;;71742:118:0::3;-1:-1:-1::0;;;71742:118:0::3;::::0;;71717:154;;::::3;::::0;71742:118;71717:154:::3;;:::i;:::-;;::::0;;-1:-1:-1;;71717:154:0;;::::3;::::0;;;;;;;71707:165;;71717:154:::3;71707:165:::0;;::::3;::::0;71885:16:::3;:27:::0;;;1188:25:1;;;71707:165:0;-1:-1:-1;71928:33:0::3;::::0;1161:18:1;71928:33:0::3;1042:177:1::0;54679:369:0;44723:11;;-1:-1:-1;;;44723:11:0;;;;44718:40;;44743:15;;-1:-1:-1;;;44743:15:0;;;;;;;;;;;44718:40;54801:115:::1;::::0;54891:10:::1;54801:115;::::0;::::1;2361:51:1::0;54754:9:0::1;::::0;2334:18:1;;54801:115:0::1;::::0;;-1:-1:-1;;54801:115:0;;::::1;::::0;;;;;;::::1;::::0;;::::1;::::0;;-1:-1:-1;;;;;54801:115:0::1;-1:-1:-1::0;;;54801:115:0::1;::::0;;54776:151;;::::1;::::0;54801:115;54776:151:::1;;:::i;:::-;;;;;;;;;;;;;54766:162;;;;;;54754:174;;54941:23;:21;:23::i;:::-;55006:22;::::0;54977:63:::1;::::0;-1:-1:-1;;;54977:63:0;;::::1;::::0;::::1;1188:25:1::0;;;-1:-1:-1;;;;;55006:22:0;;::::1;::::0;54977:60:::1;::::0;1161:18:1;;54977:63:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;54743:305;54679:369::o:0;50567:326::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;49554:15:::2;::::0;-1:-1:-1;;;;;49554:15:0::2;49540:10;:29;::::0;::::2;::::0;49539:57:::2;;-1:-1:-1::0;49589:6:0::2;::::0;-1:-1:-1;;;;;49589:6:0::2;49575:10;:20;;49539:57;49535:91;;;49605:21;;-1:-1:-1::0;;;49605:21:0::2;;;;;;;;;;;49535:91;50715:14:::3;:31:::0;;-1:-1:-1;;;;50757:37:0;-1:-1:-1;;;50715:31:0;::::3;;::::0;::::3;-1:-1:-1::0;;;;50757:37:0;;;;;-1:-1:-1;;;50757:37:0;::::3;;::::0;::::3;::::0;;;::::3;::::0;;;;50820:65:::3;::::0;;50715:31:::3;50851:14:::0;;::::3;::::0;::::3;17046::1::0;17039:22;17021:41;;50867:17:0;;;::::3;::::0;;::::3;17105:14:1::0;17098:22;17093:2;17078:18;;17071:50;50820:65:0::3;::::0;16994:18:1;50820:65:0::3;;;;;;;;-1:-1:-1::0;;38958:1:0;41227:21;;50567:326::o;47286:62::-;;;;;;;;;;;;67681:580;67996:14;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;64953:14:::2;::::0;-1:-1:-1;;;64953:14:0;::::2;;;64949:43;;;64976:16;;-1:-1:-1::0;;;64976:16:0::2;;;;;;;;;;;64949:43;49830:6:::3;::::0;-1:-1:-1;;;;;49830:6:0::3;49816:10;:20;::::0;::::3;::::0;49815:71:::3;;-1:-1:-1::0;49870:15:0::3;::::0;-1:-1:-1;;;;;49870:15:0::3;49856:10;:29;;49815:71;:128;;;;-1:-1:-1::0;49905:23:0::3;::::0;-1:-1:-1;;;;;49905:23:0::3;:37:::0;::::3;49815:128;:217;;;;-1:-1:-1::0;49981:23:0::3;::::0;49963:68:::3;::::0;-1:-1:-1;;;49963:68:0;;50020:10:::3;49963:68;::::0;::::3;2361:51:1::0;-1:-1:-1;;;;;49981:23:0;;::::3;::::0;49963:56:::3;::::0;2334:18:1;;49963:68:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49962:69;49815:217;49797:276;;;50051:22;;-1:-1:-1::0;;;50051:22:0::3;;;;;;;;;;;49797:276;64706:15:::4;::::0;67978:7;;-1:-1:-1;;;;;64693:28:0;;::::4;64706:15:::0;::::4;64693:28;::::0;::::4;::::0;64692:112:::4;;-1:-1:-1::0;64755:22:0::4;::::0;64728:75:::4;::::0;-1:-1:-1;;;64728:75:0;;-1:-1:-1;;;;;2379:32:1;;;64728:75:0::4;::::0;::::4;2361:51:1::0;64755:22:0;;::::4;::::0;64728:64:::4;::::0;2334:18:1;;64728:75:0::4;;;;;;;;;;;;;;;;;::::0;::::4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64727:76;64692:112;64688:146;;;64813:21;;-1:-1:-1::0;;;64813:21:0::4;;;;;;;;;;;64688:146;68032:47:::5;68047:7;68056:8;68066:12;68032:14;:47::i;:::-;68092:95;::::0;-1:-1:-1;;;68092:95:0;;68132:10:::5;68092:95;::::0;::::5;17481:34:1::0;68152:4:0::5;17531:18:1::0;;;17524:43;17583:18;;;17576:34;;;17626:18;;;17619:34;;;17702:4;17690:17;;17669:19;;;17662:46;17724:19;;;17717:35;;;17768:19;;;17761:35;;;68023:56:0;;-1:-1:-1;;;;;;68092:39:0;::::5;::::0;::::5;::::0;17415:19:1;;68092:95:0::5;;;;;;;;;;;;;;;;;::::0;::::5;;;;;;;;;;;;::::0;::::5;;;;;;;;;68200:53;68213:7;68222:8;68232:12;68246:6;68200:12;:53::i;:::-;-1:-1:-1::0;38958:1:0;41227:21;;67681:580;;-1:-1:-1;;;;;;;67681:580:0:o;86742:240::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;41399:6:::2;::::0;-1:-1:-1;;;;;41399:6:0::2;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::2;;;;;;;;;;;41381:44;86900:20:::3;:31:::0;;;;86942:14:::3;:32:::0;;-1:-1:-1;;86942:32:0::3;::::0;::::3;;::::0;;;::::3;::::0;;-1:-1:-1;41227:21:0;;86742:240::o;91875:2186::-;92096:7;92115;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;86265:17:::2;::::0;-1:-1:-1;;;86265:17:0;::::2;;;86261:49;;;86291:19;;-1:-1:-1::0;;;86291:19:0::2;;;;;;;;;;;86261:49;49830:6:::3;::::0;-1:-1:-1;;;;;49830:6:0::3;49816:10;:20;::::0;::::3;::::0;49815:71:::3;;-1:-1:-1::0;49870:15:0::3;::::0;-1:-1:-1;;;;;49870:15:0::3;49856:10;:29;;49815:71;:128;;;;-1:-1:-1::0;49905:23:0::3;::::0;-1:-1:-1;;;;;49905:23:0::3;:37:::0;::::3;49815:128;:217;;;;-1:-1:-1::0;49981:23:0::3;::::0;49963:68:::3;::::0;-1:-1:-1;;;49963:68:0;;50020:10:::3;49963:68;::::0;::::3;2361:51:1::0;-1:-1:-1;;;;;49981:23:0;;::::3;::::0;49963:56:::3;::::0;2334:18:1;;49963:68:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49962:69;49815:217;49797:276;;;50051:22;;-1:-1:-1::0;;;50051:22:0::3;;;;;;;;;;;49797:276;92174:28:::4;::::0;;::::4;::::0;::::4;12133:25:1::0;;;12174:18;;;12167:34;;;12217:18;;;12210:34;;;92141:20:0::4;::::0;12106:18:1;;92174:28:0::4;::::0;;-1:-1:-1;;92174:28:0;;::::4;::::0;;;;;;92164:39;;92174:28:::4;92164:39:::0;;::::4;::::0;92290:14:::4;92307:30:::0;;;:16:::4;:30:::0;;;;;-1:-1:-1;;;;;92307:44:0;::::4;::::0;;;;;;;;92164:39;;-1:-1:-1;92375:1:0::4;92366:10:::0;::::4;92362:44;;;92385:21;;-1:-1:-1::0;;;92385:21:0::4;;;;;;;;;;;92362:44;92585:1;92571:11;;:15;92570:57;;;;-1:-1:-1::0;92620:6:0::4;::::0;-1:-1:-1;;;;;92620:6:0::4;92606:10;:20;;92570:57;:106;;;;-1:-1:-1::0;92660:15:0::4;::::0;-1:-1:-1;;;;;92660:15:0::4;92646:10;:29;;92570:106;:259;;;;-1:-1:-1::0;92746:82:0::4;92778:4:::0;92784:5;92791:3;83076:1:::4;::::0;;92746:31:::4;:82::i;:::-;92695:48;61846:9;92695:15;:48;:::i;:::-;:133;92570:259;92552:333;;;92863:10;;-1:-1:-1::0;;;92863:10:0::4;;;;;;;;;;;92552:333;92937:20;92959:22:::0;92985:41:::4;93004:6;93012:13;;92985:18;:41::i;:::-;92936:90:::0;;-1:-1:-1;92936:90:0;-1:-1:-1;93079:21:0::4;93103:29;92936:90:::0;;93103:29:::4;:::i;:::-;93237:1;93190:30:::0;;;:16:::4;:30;::::0;;;;;;;-1:-1:-1;;;;;93190:44:0;::::4;::::0;;;;;;;:48;;;93320:31;;;:17:::4;:31:::0;;;;;:41;;93079:53;;-1:-1:-1;93355:6:0;;93320:31;;93237:1;93320:41:::4;::::0;93355:6;;93320:41:::4;:::i;:::-;;;;;;;;93397:6;93372:21;;:31;;;;;;;:::i;:::-;;;;;;;;93438:13;93414:20;;:37;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;93464:43:0::4;::::0;-1:-1:-1;93480:12:0;93494;93464:15:::4;:43::i;:::-;93561:12;-1:-1:-1::0;;;;;93525:49:0::4;;93545:14;93525:49;;;;1188:25:1::0;;1176:2;1161:18;;1042:177;93525:49:0::4;;;;;;;;93787:14;::::0;93769:61:::4;::::0;-1:-1:-1;;;93769:61:0;;93816:4:::4;93769:61;::::0;::::4;4482:51:1::0;4549:18;;;4542:34;;;-1:-1:-1;;;;;93787:14:0;;::::4;::::0;93769:38:::4;::::0;4455:18:1;;93769:61:0::4;;;;;;;;;;;;;;;;;::::0;::::4;;;;;;;;;;;;::::0;::::4;;;;;-1:-1:-1::0;;93962:15:0::4;::::0;93932:77:::4;::::0;-1:-1:-1;;;;;;93962:15:0::4;::::0;-1:-1:-1;93980:12:0;93994:14;93932:22:::4;:77::i;:::-;-1:-1:-1::0;38958:1:0;41227:21;;94030:6;;;;-1:-1:-1;91875:2186:0;;-1:-1:-1;;;;;;;91875:2186:0:o;100177:353::-;100294:20;100326:22;100367:31;100402:9;100401:50;;100438:13;;100401:50;;;100415:20;;100401:50;100367:84;;100471:51;100490:6;100498:23;100471:18;:51::i;:::-;100464:58;;;;;100177:353;;;;;:::o;76136:281::-;76304:22;;76344:14;;76394;;76277:132;;-1:-1:-1;;;76277:132:0;;-1:-1:-1;;;;;76344:14:0;;;76277:132;;;18104:34:1;18174:15;;;18154:18;;;18147:43;76377:4:0;18206:18:1;;;18199:43;18258:18;;;18251:34;;;18301:19;;;18294:35;;;;76241:7:0;;;;76304:22;;76277:66;;18038:19:1;;76277:132:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76270:139;;;;76136:281;;;;;:::o;102405:321::-;102627:28;;;;;;;12133:25:1;;;12174:18;;;12167:34;;;12217:18;;;;12210:34;;;102627:28:0;;;;;;;;;;12106:18:1;;;;102627:28:0;;102617:39;;;;;;;;;-1:-1:-1;102674:30:0;;;:16;:30;;;;;-1:-1:-1;;;;;102674:44:0;;;;;;;;;102405:321;;;;;;;:::o;52249:190::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;49554:15:::2;::::0;-1:-1:-1;;;;;49554:15:0::2;49540:10;:29;::::0;::::2;::::0;49539:57:::2;;-1:-1:-1::0;49589:6:0::2;::::0;-1:-1:-1;;;;;49589:6:0::2;49575:10;:20;;49539:57;49535:91;;;49605:21;;-1:-1:-1::0;;;49605:21:0::2;;;;;;;;;;;49535:91;-1:-1:-1::0;;;;;52363:28:0;::::3;;::::0;;;:22:::3;:28;::::0;;;;;;;;52356:35;;-1:-1:-1;;52356:35:0::3;::::0;;52407:24;;2361:51:1;;;52407:24:0::3;::::0;2334:18:1;52407:24:0::3;;;;;;;;-1:-1:-1::0;38958:1:0;41227:21;;52249:190::o;123854:172::-;34447:19;34470:13;;;;;;34469:14;;34517:34;;;;-1:-1:-1;34535:12:0;;34550:1;34535:12;;;;:16;34517:34;34516:97;;;-1:-1:-1;34585:4:0;14416:19;:23;;;34557:55;;-1:-1:-1;34595:12:0;;;;;:17;34557:55;34494:193;;;;-1:-1:-1;;;34494:193:0;;18792:2:1;34494:193:0;;;18774:21:1;18831:2;18811:18;;;18804:30;18870:34;18850:18;;;18843:62;-1:-1:-1;;;18921:18:1;;;18914:44;18975:19;;34494:193:0;18590:410:1;34494:193:0;34698:12;:16;;-1:-1:-1;;34698:16:0;34713:1;34698:16;;;34725:67;;;;34760:13;:20;;-1:-1:-1;;34760:20:0;;;;;34725:67;123933:14:::1;:21:::0;;-1:-1:-1;;;;123965:24:0;-1:-1:-1;;;123965:24:0;;;124000:6:::1;:18:::0;;-1:-1:-1;;;;;;124000:18:0::1;-1:-1:-1::0;;;;;124000:18:0;::::1;;::::0;;34814:102;;;;34865:5;34849:21;;-1:-1:-1;;34849:21:0;;;34890:14;;-1:-1:-1;7502:36:1;;34890:14:0;;7490:2:1;7475:18;34890:14:0;;;;;;;34814:102;34436:487;123854:172;:::o;73523:1002::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;73612:13:::2;:20:::0;73651:1:::2;73647:5:::0;::::2;73643:40;;;73661:22;;-1:-1:-1::0;;;73661:22:0::2;;;;;;;;;;;73643:40;73708:20;::::0;73745:5;;73741:777:::2;;73767:24;73808:1;73794:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;73794:16:0::2;;73767:43;;73832:9;73827:436;73847:1;73843;:5;73827:436;;;73874:22;73935:3;73930:1;73900:13;73914:1;73900:16;;;;;;;;:::i;:::-;;;;;;;;;;;:27;;;:31;;;;:::i;:::-;73899:39;;;;:::i;:::-;73874:64;;74052:20;;74035:14;:37;74031:111;;;74121:20;::::0;74081:61:::2;::::0;-1:-1:-1;;;74081:61:0;;::::2;::::0;74105:14;;74081:61:::2;;4761:25:1::0;;;4817:2;4802:18;;4795:34;4749:2;4734:18;;4587:248;74031:111:0::2;74176:14;74163:7;74171:1;74163:10;;;;;;;;:::i;:::-;;;;;;:27;;;::::0;::::2;74233:14;74209:20;;:38;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;73850:3:0::2;;73827:436;;;-1:-1:-1::0;74284:15:0::2;::::0;::::2;::::0;;;::::2;74355:9;74350:157;74370:1;74366;:5;74350:157;;;74427:15;::::0;74445:13:::2;:16:::0;;74397:94:::2;::::0;-1:-1:-1;;;;;74427:15:0::2;::::0;74445:13;74459:1;;74445:16;::::2;;;;;:::i;74397:94::-;74373:3;;74350:157;;;;73752:766;73741:777;-1:-1:-1::0;;38958:1:0;41227:21;;73523:1002::o;51240:231::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;49554:15:::2;::::0;-1:-1:-1;;;;;49554:15:0::2;49540:10;:29;::::0;::::2;::::0;49539:57:::2;;-1:-1:-1::0;49589:6:0::2;::::0;-1:-1:-1;;;;;49589:6:0::2;49575:10;:20;;49539:57;49535:91;;;49605:21;;-1:-1:-1::0;;;49605:21:0::2;;;;;;;;;;;49535:91;51364:23:::3;:42:::0;;-1:-1:-1;;;;;;51364:42:0::3;-1:-1:-1::0;;;;;51364:42:0;::::3;::::0;;::::3;::::0;;;51422:41:::3;::::0;2361:51:1;;;51422:41:0::3;::::0;2349:2:1;2334:18;51422:41:0::3;2215:203:1::0;100823:403:0;100886:12;100910:13;100935:11;100957:22;101019:89;101096:11;;61846:9;101045:15;:48;;;;:::i;101019:89::-;100998:110;;-1:-1:-1;100998:110:0;-1:-1:-1;100998:110:0;-1:-1:-1;101136:82:0;100998:110;;;83076:1;;;101136:31;:82::i;:::-;101119:99;;100823:403;;;;:::o;124140:2148::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;;;41399:6;-1:-1:-1;;;;;41399:6:0::1;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::1;;;;;;;;;;;41381:44;44888:11:::2;::::0;-1:-1:-1;;;44888:11:0;::::2;;;44884:43;;;44908:19;;-1:-1:-1::0;;;44908:19:0::2;;;;;;;;;;;44884:43;124316:5:::3;124284:9;:21;;;:38;124280:71;;;124331:20;;-1:-1:-1::0;;;124331:20:0::3;;;;;;;;;;;124280:71;124429:29;::::0;::::3;::::0;124407:19:::3;:51:::0;124488:26;;124469:16:::3;:45:::0;;;124547:29:::3;::::0;::::3;::::0;124525:19:::3;:51:::0;124587:10:::3;:39:::0;124660:30:::3;::::0;;::::3;::::0;124637:20:::3;:53:::0;124715:21:::3;::::0;::::3;::::0;124701:11:::3;:35:::0;124763:23:::3;::::0;::::3;::::0;124747:13:::3;:39:::0;124816:26:::3;::::0;::::3;::::0;124797:16:::3;:45:::0;124876:30:::3;::::0;::::3;::::0;124853:20:::3;:53:::0;124938:28:::3;::::0;::::3;::::0;124917:18:::3;:49:::0;124995:25:::3;::::0;::::3;::::0;124977:15:::3;:43:::0;;125056:32:::3;::::0;::::3;::::0;125031:22:::3;:57:::0;;-1:-1:-1;;;;;;125031:57:0;;::::3;-1:-1:-1::0;;;;;125031:57:0;;::::3;;::::0;;;125116:24:::3;::::0;::::3;::::0;125099:14:::3;:41:::0;;;::::3;::::0;;::::3;::::0;;;::::3;::::0;;125169:24:::3;::::0;::::3;::::0;125151:15:::3;:42:::0;;;::::3;::::0;;::::3;::::0;;;::::3;::::0;;125222:15:::3;-1:-1:-1::0;125204:33:0;;;-1:-1:-1;125248:31:0;;;125315:32:::3;::::0;::::3;::::0;125290:22:::3;:57:::0;;;::::3;::::0;;::::3;::::0;;;::::3;::::0;;125384:33:::3;::::0;::::3;::::0;-1:-1:-1;125358:59:0;;;;::::3;::::0;;::::3;;::::0;;;124977:43;::::3;-1:-1:-1::0;;;;;;125461:25:0;;;;;;125497:18:::3;:36:::0;-1:-1:-1;125590:18:0;;-1:-1:-1;;;;;;;125590:18:0;;::::3;;::::0;;125626:20;::::3;::::0;-1:-1:-1;;125626:20:0::3;125686:56;125713:9;:28;;;125686:26;:56::i;:::-;125843:22;;;;;;;;;-1:-1:-1::0;;;;;125843:22:0::3;-1:-1:-1::0;;;;;125816:66:0::3;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125797:15;::::0;-1:-1:-1;;;;;125797:15:0;;::::3;:87:::0;::::3;;125793:124;;125893:24;;-1:-1:-1::0;;;125893:24:0::3;;;;;;;;;;;125793:124;125997:14;;;;;;;;;-1:-1:-1::0;;;;;125997:14:0::3;-1:-1:-1::0;;;;;125980:41:0::3;;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125932:91;;125949:15;;;;;;;;;-1:-1:-1::0;;;;;125949:15:0::3;-1:-1:-1::0;;;;;125932:42:0::3;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:91;;;125928:127;;126032:23;;-1:-1:-1::0;;;126032:23:0::3;;;;;;;;;;;125928:127;126113:14;::::0;126096:43:::3;::::0;;-1:-1:-1;;;126096:43:0;;;;126068:14:::3;::::0;-1:-1:-1;;;;;126113:14:0::3;::::0;126096:41:::3;::::0;:43:::3;::::0;;::::3;::::0;::::3;::::0;;;;;;;;126113:14;126096:43:::3;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;126090:49;::::0;:2:::3;:49;:::i;:::-;126085:55;::::0;:1:::3;:55;:::i;:::-;126068:72;;126151:25;126179:55;126196:6;126204:29;126179:16;:55::i;:::-;126247:13;:33:::0;-1:-1:-1;;38958:1:0;41227:21;;-1:-1:-1;124140:2148:0:o;72930:452::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;73015:25:::2;73043:17;:15;:17::i;:::-;73015:45;;73071:31;73206:3;61956:18;73168:13;;73150:15;:31;;;;:::i;:::-;73126:20;::::0;73106:40:::2;::::0;:17;:40:::2;:::i;:::-;:76;;;;:::i;:::-;73105:98;;;;:::i;:::-;:104;;;;:::i;:::-;73071:138;;73238:15;73222:13;:31;;;;73288:23;73264:20;;:47;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;73329:45:0::2;::::0;1188:25:1;;;73329:45:0::2;::::0;1176:2:1;1161:18;73329:45:0::2;1042:177:1::0;55930:140:0;55981:48;56049:13;56042:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;56042:20:0;;;;;;;;;;;;;;;;;;;;;;54397:160;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;41399:6:::2;::::0;-1:-1:-1;;;;;41399:6:0::2;41385:10;:20;41381:44;;41414:11;;-1:-1:-1::0;;;41414:11:0::2;;;;;;;;;;;41381:44;54513:36:::3;54540:8;54513:26;:36::i;94624:2825::-:0;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;86265:17:::2;::::0;-1:-1:-1;;;86265:17:0;::::2;;;86261:49;;;86291:19;;-1:-1:-1::0;;;86291:19:0::2;;;;;;;;;;;86261:49;94845:1:::3;94834:8;:12;94830:40;;;94855:15;;-1:-1:-1::0;;;94855:15:0::3;;;;;;;;;;;94830:40;94916:28;::::0;;::::3;::::0;::::3;12133:25:1::0;;;12174:18;;;12167:34;;;12217:18;;;12210:34;;;94883:20:0::3;::::0;12106:18:1;;94916:28:0::3;;;;;;;;;;;;94906:39;;;;;;94883:62;;95055:1;95021:17;:31;95039:12;95021:31;;;;;;;;;;;;:35;95017:66;;;95065:18;;-1:-1:-1::0;;;95065:18:0::3;;;;;;;;;;;95017:66;95277:1;95263:11;;:15;95262:57;;;;-1:-1:-1::0;95312:6:0::3;::::0;-1:-1:-1;;;;;95312:6:0::3;95298:10;:20;;95262:57;:106;;;;-1:-1:-1::0;95352:15:0::3;::::0;-1:-1:-1;;;;;95352:15:0::3;95338:10;:29;;95262:106;:311;;;;-1:-1:-1::0;95490:82:0::3;95522:4:::0;95528:5;95535:3;83076:1:::3;::::0;;95490:31:::3;:82::i;:::-;95439:48;61846:9;95439:15;:48;:::i;:::-;:133;95262:311;95244:385;;;95607:10;;-1:-1:-1::0;;;95607:10:0::3;;;;;;;;;;;95244:385;95739:16;95759:40:::0;;;:26:::3;:40;::::0;;;;:47;:58;-1:-1:-1;95758:121:0::3;;95832:40;::::0;;;:26:::3;:40;::::0;;;;:47;95758:121:::3;;;95821:8;95758:121;95890:19;95912:40:::0;;;:26:::3;:40;::::0;;;;:47;95739:140;;-1:-1:-1;95739:140:0;96001:23:::3;::::0;::::3;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;96001:23:0::3;;95972:52;;96035:24;96076:8;96062:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;96062:23:0::3;-1:-1:-1::0;96035:50:0;-1:-1:-1;96096:20:0::3;::::0;;;96235:8;96273:11;96256:806:::3;96291:22;96305:8:::0;96291:11;:22:::3;:::i;:::-;96286:1;:28;96256:806;;;96351:40;::::0;;;:26:::3;:40;::::0;;;;96392:5:::3;96396:1;96392::::0;:5:::3;:::i;:::-;96351:47;;;;;;;;:::i;:::-;;::::0;;;::::3;::::0;;;::::3;::::0;-1:-1:-1;;;;;96351:47:0::3;::::0;-1:-1:-1;96413:3:0;::::3;::::0;::::3;:::i;:::-;;;;96446:12;96431:9;96441:1;96431:12;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;96431:27:0;;::::3;:12;::::0;;::::3;::::0;;;;;;:27;;;;96489:30:::3;::::0;;;:16:::3;:30:::0;;;;;;:44;;::::3;::::0;;;;;;;;96473:60:::3;::::0;;::::3;:::i;:::-;96687:30;::::0;;;:16:::3;:30;::::0;;;;;;;-1:-1:-1;;;;;96687:44:0;::::3;::::0;;;;;;;;96733:13:::3;::::0;96473:60;;-1:-1:-1;96668:79:0::3;::::0;:18:::3;:79::i;:::-;96635:112;;;;;;;;96777:14;96764:7;96772:1;96764:10;;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;;;:27;96831:29:::3;96846:14:::0;96831:12;:29:::3;:::i;:::-;96806:20;;:55;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;96925:1:0::3;96878:30:::0;;;:16:::3;:30;::::0;;;;;;;-1:-1:-1;;;;;96878:44:0;::::3;::::0;;;;;;;:48;;;96941:40;;;:26:::3;:40:::0;;;;;:46;;;::::3;;;;:::i;:::-;;::::0;;;::::3;::::0;;;;;-1:-1:-1;;96941:46:0;;;;;-1:-1:-1;;;;;;96941:46:0::3;::::0;;;;;;;;97002:30;;;:16:::3;:30:::0;;;;;;-1:-1:-1;;;;;97002:44:0;::::3;::::0;;;;;;;:48;96316:3;::::3;::::0;::::3;:::i;:::-;;;;96256:806;;;;97099:12;97074:21;;:37;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;97122:31:0::3;::::0;;;:17:::3;:31;::::0;;;;:47;;97157:12;;97122:31;:47:::3;::::0;97157:12;;97122:47:::3;:::i;:::-;::::0;;;-1:-1:-1;;97200:14:0::3;::::0;97182:67:::3;::::0;-1:-1:-1;;;97182:67:0;;97229:4:::3;97182:67;::::0;::::3;4482:51:1::0;4549:18;;;4542:34;;;-1:-1:-1;;;;;97200:14:0;;::::3;::::0;97182:38:::3;::::0;4455:18:1;;97182:67:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;97304:9;97299:143;97319:9;:16;97315:1;:20;97299:143;;;97387:15;::::0;97405:12;;97357:73:::3;::::0;-1:-1:-1;;;;;97387:15:0::3;::::0;97405:9;;97415:1;;97405:12;::::3;;;;;:::i;:::-;;;;;;;97419:7;97427:1;97419:10;;;;;;;;:::i;97357:73::-;97337:3;;97299:143;;;-1:-1:-1::0;;38958:1:0;41227:21;;-1:-1:-1;;;;;;;;;;;;;94624:2825:0:o;66750:377::-;66970:14;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;64953:14:::2;::::0;-1:-1:-1;;;64953:14:0;::::2;;;64949:43;;;64976:16;;-1:-1:-1::0;;;64976:16:0::2;;;;;;;;;;;64949:43;49830:6:::3;::::0;-1:-1:-1;;;;;49830:6:0::3;49816:10;:20;::::0;::::3;::::0;49815:71:::3;;-1:-1:-1::0;49870:15:0::3;::::0;-1:-1:-1;;;;;49870:15:0::3;49856:10;:29;;49815:71;:128;;;;-1:-1:-1::0;49905:23:0::3;::::0;-1:-1:-1;;;;;49905:23:0::3;:37:::0;::::3;49815:128;:217;;;;-1:-1:-1::0;49981:23:0::3;::::0;49963:68:::3;::::0;-1:-1:-1;;;49963:68:0;;50020:10:::3;49963:68;::::0;::::3;2361:51:1::0;-1:-1:-1;;;;;49981:23:0;;::::3;::::0;49963:56:::3;::::0;2334:18:1;;49963:68:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49962:69;49815:217;49797:276;;;50051:22;;-1:-1:-1::0;;;50051:22:0::3;;;;;;;;;;;49797:276;64706:15:::4;::::0;66952:7;;-1:-1:-1;;;;;64693:28:0;;::::4;64706:15:::0;::::4;64693:28;::::0;::::4;::::0;64692:112:::4;;-1:-1:-1::0;64755:22:0::4;::::0;64728:75:::4;::::0;-1:-1:-1;;;64728:75:0;;-1:-1:-1;;;;;2379:32:1;;;64728:75:0::4;::::0;::::4;2361:51:1::0;64755:22:0;;::::4;::::0;64728:64:::4;::::0;2334:18:1;;64728:75:0::4;;;;;;;;;;;;;;;;;::::0;::::4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64727:76;64692:112;64688:146;;;64813:21;;-1:-1:-1::0;;;64813:21:0::4;;;;;;;;;;;64688:146;67006:47:::5;67021:7;67030:8;67040:12;67006:14;:47::i;:::-;66997:56;;67066:53;67079:7;67088:8;67098:12;67112:6;67066:12;:53::i;:::-;-1:-1:-1::0;38958:1:0;41227:21;;66750:377;;-1:-1:-1;;;66750:377:0:o;51675:452::-;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;49554:15:::2;::::0;-1:-1:-1;;;;;49554:15:0::2;49540:10;:29;::::0;::::2;::::0;49539:57:::2;;-1:-1:-1::0;49589:6:0::2;::::0;-1:-1:-1;;;;;49589:6:0::2;49575:10;:20;;49539:57;49535:91;;;49605:21;;-1:-1:-1::0;;;49605:21:0::2;;;;;;;;;;;49535:91;-1:-1:-1::0;;;;;51830:18:0;::::3;::::0;;51829:47:::3;;-1:-1:-1::0;;;;;;51854:21:0;::::3;51870:4;51854:21;51829:47;51825:76;;;51885:16;;-1:-1:-1::0;;;51885:16:0::3;;;;;;;;;;;51825:76;51917:38;::::0;::::3;46983:1;51917:38;::::0;::::3;::::0;51916:80:::3;;-1:-1:-1::0;51961:34:0::3;::::0;::::3;47037:1;51961:34;;51916:80;51912:113;;;52005:20;;-1:-1:-1::0;;;52005:20:0::3;;;;;;;;;;;51912:113;-1:-1:-1::0;;;;;52038:28:0;::::3;;::::0;;;:22:::3;:28;::::0;;;;;;;;:42;;-1:-1:-1;;52038:42:0::3;;::::0;::::3;;::::0;;52096:23;;2361:51:1;;;52096:23:0::3;::::0;2334:18:1;52096:23:0::3;2215:203:1::0;99288:546:0;99403:20;99435:22;99491:55;99508:6;99516:29;99491:16;:55::i;:::-;99476:70;-1:-1:-1;99476:70:0;;-1:-1:-1;99597:21:0;99639:7;;99635:142;;99702:3;99680:18;99686:12;99680:3;:18;:::i;:::-;99679:26;;;;:::i;:::-;99663:42;-1:-1:-1;99737:28:0;99663:42;99737:12;:28;:::i;:::-;99720:45;;99635:142;99789:37;99288:546;;;;;:::o;79332:175::-;79392:12;;;79466:33;79478:20;79019:12;79478:2;:20;:::i;:::-;79466:11;:33::i;:::-;79445:54;;;;-1:-1:-1;79445:54:0;;-1:-1:-1;79332:175:0;-1:-1:-1;;79332:175:0:o;79987:306::-;80129:17;80279:6;80249:27;79228:2;80249:6;:27;:::i;:::-;80223:23;79124:7;80223:4;:23;:::i;:::-;79019:12;80171:31;80185:4;80191:5;80198:3;80171:13;:31::i;:::-;:49;;;;:::i;:::-;:75;;;;:::i;:::-;:105;;;;:::i;:::-;:114;;;;:::i;:::-;80159:126;79987:306;-1:-1:-1;;;;;;;79987:306:0:o;27847:205::-;27975:68;;-1:-1:-1;;;;;19735:15:1;;;27975:68:0;;;19717:34:1;19787:15;;19767:18;;;19760:43;19819:18;;;19812:34;;;27948:96:0;;27968:5;;-1:-1:-1;;;27998:27:0;19652:18:1;;27975:68:0;;;;-1:-1:-1;;27975:68:0;;;;;;;;;;;;;;-1:-1:-1;;;;;27975:68:0;-1:-1:-1;;;;;;27975:68:0;;;;;;;;;;27948:19;:96::i;:::-;27847:205;;;;:::o;77645:294::-;77845:22;;77818:113;;-1:-1:-1;;;77818:113:0;;-1:-1:-1;;;;;4500:32:1;;;77818:113:0;;;4482:51:1;4549:18;;;4542:34;;;77791:7:0;;77845:22;;77818:81;;4455:18:1;;77818:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77811:120;77645:294;-1:-1:-1;;;77645:294:0:o;97457:1059::-;97592:20;97614:22;97686:31;97721:9;97720:50;;97757:13;;97720:50;;;97734:20;;97720:50;97686:84;;97814:51;97833:6;97841:23;97814:18;:51::i;:::-;97897:19;;97781:84;;-1:-1:-1;97781:84:0;-1:-1:-1;97882:34:0;;97878:71;;;97925:24;;-1:-1:-1;;;97925:24:0;;;;;;;;;;;97878:71;97981:1;97964:14;:18;97960:45;;;97991:14;;-1:-1:-1;;;97991:14:0;;;;;;;;;;;97960:45;98023:14;;;;98018:76;;98064:29;98079:14;98064:12;:29;:::i;:::-;98039:20;;:55;;;;;;;:::i;:::-;;;;-1:-1:-1;;98018:76:0;98150:70;;;4761:25:1;;;4817:2;4802:18;;4795:34;;;98185:10:0;;-1:-1:-1;;;;;98150:70:0;;;98185:10;;98150:70;;4734:18:1;98150:70:0;;;;;;;98322:14;;98304:58;;-1:-1:-1;;;98304:58:0;;98343:10;98304:58;;;4482:51:1;4549:18;;;4542:34;;;-1:-1:-1;;;;;98322:14:0;;;;98304:38;;4455:18:1;;98304:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;98461:15:0;;98431:77;;-1:-1:-1;;;;;;98461:15:0;;-1:-1:-1;98479:12:0;98493:14;98431:22;:77::i;:::-;97638:878;97457:1059;;;;;;:::o;130559:222::-;130608:7;130628:14;130673;;;;;;;;;-1:-1:-1;;;;;130673:14:0;-1:-1:-1;;;;;130656:41:0;;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;130650:49;;:2;:49;:::i;:::-;130645:55;;:1;:55;:::i;:::-;130628:72;;130718:55;130735:6;130743:29;130718:16;:55::i;:::-;130711:62;;;130559:222;:::o;78442:183::-;78554:22;;78602:14;;78527:90;;-1:-1:-1;;;78527:90:0;;;;;1188:25:1;;;;78500:7:0;;-1:-1:-1;;;;;78554:22:0;;78527:74;;1161:18:1;;78527:90:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;27662:177::-;27772:58;;-1:-1:-1;;;;;4500:32:1;;27772:58:0;;;4482:51:1;4549:18;;;4542:34;;;27745:86:0;;27765:5;;-1:-1:-1;;;27795:23:0;4455:18:1;;27772:58:0;4308:274:1;27745:86:0;27662:177;;;:::o;28321:582::-;28651:10;;;28650:62;;-1:-1:-1;28667:39:0;;-1:-1:-1;;;28667:39:0;;28691:4;28667:39;;;20069:34:1;-1:-1:-1;;;;;20139:15:1;;;20119:18;;;20112:43;28667:15:0;;;;;20004:18:1;;28667:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;28650:62;28628:166;;;;-1:-1:-1;;;28628:166:0;;20368:2:1;28628:166:0;;;20350:21:1;20407:2;20387:18;;;20380:30;20446:34;20426:18;;;20419:62;-1:-1:-1;;;20497:18:1;;;20490:52;20559:19;;28628:166:0;20166:418:1;28628:166:0;28832:62;;-1:-1:-1;;;;;4500:32:1;;28832:62:0;;;4482:51:1;4549:18;;;4542:34;;;28805:90:0;;28825:5;;-1:-1:-1;;;28855:22:0;4455:18:1;;28832:62:0;4308:274:1;45512:182:0;39001:1;40900:7;;:18;40896:88;;40942:30;;-1:-1:-1;;;40942:30:0;;;;;;;;;;;40896:88;39001:1;41061:7;:17;44723:11:::1;::::0;-1:-1:-1;;;44723:11:0;::::1;;;44718:40;;44743:15;;-1:-1:-1::0;;;44743:15:0::1;;;;;;;;;;;44718:40;45595:13:::2;::::0;-1:-1:-1;;;;;45595:13:0::2;45612:10;45595:27;45591:54;;45631:14;;-1:-1:-1::0;;;45631:14:0::2;;;;;;;;;;;45591:54;45656:30;45675:10;45656:18;:30::i;:::-;38958:1:::0;41227:21;;45512:182::o;75052:781::-;75189:7;75224:1;75213:8;:12;75209:40;;;75234:15;;-1:-1:-1;;;75234:15:0;;;;;;;;;;;75209:40;-1:-1:-1;;;;;75264:26:0;;;;:59;;-1:-1:-1;;;;;;75294:29:0;;75318:4;75294:29;75264:59;75260:89;;;75332:17;;-1:-1:-1;;;75332:17:0;;;;;;;;;;;75260:89;75363:14;75379:38;75421:33;75436:7;75445:8;75421:14;:33::i;:::-;75362:92;;;;75478:1;75469:6;:10;75465:43;;;75488:20;;-1:-1:-1;;;75488:20:0;;;;;;;;;;;75465:43;75556:16;;75523:30;:49;75519:87;;;75581:25;;-1:-1:-1;;;75581:25:0;;;;;;;;;;;75519:87;75619:39;75694:17;:15;:17::i;:::-;75661:50;;:30;:50;:::i;:::-;75619:92;;75761:10;;75727:31;:44;75723:76;;;75780:19;;-1:-1:-1;;;75780:19:0;;;;;;;;;;;75723:76;-1:-1:-1;75819:6:0;;75052:781;-1:-1:-1;;;;;75052:781:0:o;74533:511::-;74721:60;;;-1:-1:-1;;;;;20809:32:1;;;20791:51;;20873:2;20858:18;;20851:34;;;20901:18;;;20894:34;;;74721:60:0;;;;74756:10;;74721:60;;20779:2:1;20764:18;74721:60:0;;;;;;;74832:80;74866:7;74876:10;74896:4;74903:8;74832:26;:80::i;:::-;74994:14;;74976:60;;-1:-1:-1;;;74976:60:0;;-1:-1:-1;;;;;4500:32:1;;;74976:60:0;;;4482:51:1;4549:18;;;4542:34;;;74994:14:0;;;;74976:38;;4455:18:1;;74976:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74533:511;;;;:::o;98524:756::-;98604:11;98618:30;;;:16;:30;;;;;;;;-1:-1:-1;;;;;98618:36:0;;;;;;;;;;:40;;98657:1;;98618:40;:::i;:::-;98669:28;98700:40;;;:26;:40;;;;;:47;;98604:54;;-1:-1:-1;98818:24:0;98841:1;98700:47;98818:24;:::i;:::-;98777:66;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;98777:66:0;;;;-1:-1:-1;98860:16:0;;;;98856:299;;98962:40;;;;:26;:40;;;;;:45;;99003:3;;98962:45;;;;;;:::i;:::-;;;;;;;;;;;;;98893:40;;;:26;:40;;;;;;;-1:-1:-1;;;;;98962:45:0;;;;98934:24;98962:45;98934:20;:24;:::i;:::-;98893:66;;;;;;;;:::i;:::-;;;;;;;;;:114;;;;;-1:-1:-1;;;;;98893:114:0;;;;;-1:-1:-1;;;;;98893:114:0;;;;;;99070:8;99022:26;:40;99049:12;99022:40;;;;;;;;;;;99063:3;99022:45;;;;;;;;:::i;:::-;;;;;;;;;;:56;;-1:-1:-1;;;;;;99022:56:0;-1:-1:-1;;;;;99022:56:0;;;;;;;;;;99136:7;:3;-1:-1:-1;99136:7:0;:::i;:::-;99093:30;;;;:16;:30;;;;;;;;-1:-1:-1;;;;;99093:40:0;;;;;;;;;:50;98856:299;99175:40;;;;:26;:40;;;;;:46;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;99175:46:0;;;;;-1:-1:-1;;;;;;99175:46:0;;;;;;;;;99232:30;;;:16;:30;;;;;;-1:-1:-1;;;;;99232:36:0;;;;;;;;;;-1:-1:-1;;;99232:36:0;;:40;98524:756::o;55056:866::-;55159:13;;55130:25;;-1:-1:-1;;;;;55159:13:0;:27;55158:210;;55328:13;;55238:118;;-1:-1:-1;;;;;55328:13:0;;;55238:118;;;2361:51:1;2334:18;;55238:118:0;;;-1:-1:-1;;55238:118:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;55238:118:0;-1:-1:-1;;;55238:118:0;;;55213:154;;;;55238:118;55213:154;;:::i;:::-;;;;;;;;;;;;;55203:165;;;;;;55158:210;;;55198:1;55158:210;55520:113;;-1:-1:-1;;;;;2379:32:1;;55520:113:0;;;2361:51:1;55130:238:0;;-1:-1:-1;55455:27:0;;2334:18:1;;55520:113:0;;;-1:-1:-1;;55520:113:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;55520:113:0;-1:-1:-1;;;55520:113:0;;;55495:149;;;;55520:113;55495:149;;:::i;:::-;;;;;;;;;;;;;55485:160;;;;;;55455:190;;55658:35;55684:8;55658:25;:35::i;:::-;55710:31;;55706:115;;55772:22;;55743:78;;-1:-1:-1;;;55743:78:0;;;;;1188:25:1;;;-1:-1:-1;;;;;55772:22:0;;;;55743:59;;1161:18:1;;55743:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55706:115;55861:22;;55832:82;;-1:-1:-1;;;55832:82:0;;;;;1188:25:1;;;-1:-1:-1;;;;;55861:22:0;;;;55832:61;;1161:18:1;;55832:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55119:803;;55056:866;:::o;78051:276::-;78151:7;78171:15;78196:14;;;;;;;;;-1:-1:-1;;;;;78196:14:0;-1:-1:-1;;;;;78189:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78171:54;;78254:1;78244:7;:11;78243:76;;78268:51;78282:17;:15;:17::i;:::-;78268:6;;78301:7;78310:8;78268:13;:51::i;:::-;78243:76;;;-1:-1:-1;78259:6:0;;78236:83;-1:-1:-1;;78051:276:0:o;80805:665::-;80865:12;;;80941:5;80865:12;79316:7;80971:14;80941:5;80980;80971:14;:::i;:::-;:31;;;;:::i;:::-;80960:42;-1:-1:-1;81013:8:0;81032:6;81024:5;80960:42;81024:1;:5;:::i;:::-;:14;;;;:::i;:::-;81013:25;-1:-1:-1;81076:1:0;81058:10;81013:25;81058:6;:10;:::i;:::-;:14;;81071:1;81058:14;:::i;:::-;81057:20;;;;:::i;:::-;81053:24;;:1;:24;:::i;:::-;81049:28;-1:-1:-1;81088:12:0;81120:7;81111:5;81049:28;81115:1;81111:5;:::i;:::-;81103:14;;:4;:14;:::i;:::-;:24;;;;:::i;:::-;81088:39;-1:-1:-1;81161:1:0;81146:12;81088:39;81146:4;:12;:::i;:::-;:16;;;;:::i;:::-;81142:20;;:1;:20;:::i;:::-;:25;;81165:2;81142:25;:::i;:::-;81138:29;-1:-1:-1;81178:13:0;81203:4;81194:6;81138:29;81194:2;:6;:::i;:::-;:13;;;;:::i;:::-;81178:29;-1:-1:-1;81218:11:0;81252:2;81236:13;81178:29;81236:4;:13;:::i;:::-;:18;;;;:::i;:::-;81232:22;;:1;:22;:::i;:::-;81218:36;-1:-1:-1;81269:11:0;81278:2;81269:6;:11;:::i;:::-;81265:15;-1:-1:-1;81313:6:0;81265:15;81313:2;:6;:::i;:::-;81300:10;:6;81309:1;81300:10;:::i;:::-;:19;;;;:::i;:::-;81291:28;-1:-1:-1;81363:1:0;81355:5;81345:6;81349:2;81345:1;:6;:::i;:::-;81338:14;;:3;:14;:::i;:::-;:22;;;;:::i;:::-;:26;;;;:::i;:::-;81330:34;81425:6;;-1:-1:-1;81457:4:0;-1:-1:-1;80805:665:0;-1:-1:-1;;;;;;80805:665:0:o;82001:571::-;82090:13;82132:4;82124;:12;;82116:30;;;;-1:-1:-1;;;82116:30:0;;22007:2:1;82116:30:0;;;21989:21:1;22046:1;22026:18;;;22019:29;-1:-1:-1;;;22064:18:1;;;22057:35;22109:18;;82116:30:0;21805:328:1;82116:30:0;82179:4;82218:5;82256:3;82157:12;79316:7;82499:1;82492:3;82486:2;82471:11;82480:2;82218:5;82471:11;:::i;:::-;82470:18;;;;:::i;:::-;82455:12;:5;82463:4;82455:12;:::i;:::-;:33;;;;:::i;:::-;82454:41;;;;:::i;:::-;82449:47;;:1;:47;:::i;:::-;:51;;;;:::i;:::-;82433:2;;82407:11;82416:2;82407:6;:11;:::i;:::-;82406:18;;;;:::i;:::-;:23;;82427:2;82406:23;:::i;:::-;82393:10;82402:1;82393:6;:10;:::i;:::-;:36;;;;:::i;:::-;82386:44;;:3;:44;:::i;:::-;:49;;;;:::i;:::-;82371:1;82365:2;82350:11;82359:2;82350:6;:11;:::i;:::-;82349:18;;;;:::i;:::-;82334:12;:5;82342:4;82334:12;:::i;:::-;:33;;;;:::i;:::-;82326:42;;:4;:42;:::i;:::-;:46;;;;:::i;:::-;82289:23;82307:5;82289:4;:23;:::i;:::-;:83;;;;:::i;:::-;:146;;;;:::i;:::-;:211;;;;:::i;:::-;:239;;;;:::i;:::-;82273:255;82001:571;-1:-1:-1;;;;;;;;82001:571:0:o;30550:716::-;30974:23;31000:69;31028:4;31000:69;;;;;;;;;;;;;;;;;31008:5;-1:-1:-1;;;;;31000:27:0;;;:69;;;;;:::i;:::-;31084:17;;30974:95;;-1:-1:-1;31084:21:0;31080:179;;31181:10;31170:30;;;;;;;;;;;;:::i;:::-;31162:85;;;;-1:-1:-1;;;31162:85:0;;22340:2:1;31162:85:0;;;22322:21:1;22379:2;22359:18;;;22352:30;22418:34;22398:18;;;22391:62;-1:-1:-1;;;22469:18:1;;;22462:40;22519:19;;31162:85:0;22138:406:1;46152:156:0;46242:13;46235:20;;-1:-1:-1;;;;;;46235:20:0;;;46266:34;46291:8;46266:24;:34::i;:::-;46152:156;:::o;45702:260::-;-1:-1:-1;;;;;45780:22:0;;;;45779:55;;-1:-1:-1;;;;;;45808:25:0;;45828:4;45808:25;45779:55;45775:84;;;45843:16;;-1:-1:-1;;;45843:16:0;;;;;;;;;;;45775:84;45872:13;:24;;-1:-1:-1;;;;;;45872:24:0;-1:-1:-1;;;;;45872:24:0;;;;;;;;;45937:6;;45912:42;;45872:24;;45937:6;;45912:42;;-1:-1:-1;;45912:42:0;45702:260;:::o;5809:348::-;5953:7;5973:14;5990:25;5997:1;6000;6003:11;5990:6;:25::i;:::-;5973:42;-1:-1:-1;6042:11:0;6030:8;:23;;;;;;;;:::i;:::-;;:56;;;;;6085:1;6070:11;6057:25;;;;;:::i;:::-;6067:1;6064;6057:25;:29;6030:56;6026:100;;;6103:11;6113:1;6103:11;;:::i;:::-;;;6026:100;6143:6;5809:348;-1:-1:-1;;;;;5809:348:0:o;16877:229::-;17014:12;17046:52;17068:6;17076:4;17082:1;17085:12;17046:21;:52::i;41979:261::-;-1:-1:-1;;;;;42057:22:0;;42053:57;;42088:22;;-1:-1:-1;;;42088:22:0;;;;;;;;;;;42053:57;42142:6;;;-1:-1:-1;;;;;42159:17:0;;;-1:-1:-1;;;;;;42159:17:0;;;;;;;42192:40;;42142:6;;;42159:17;42142:6;;42192:40;;42123:16;;42192:40;42042:198;41979:261;:::o;1667:4005::-;1783:14;;;-1:-1:-1;;2328:1:0;2325;2318:20;2372:1;2369;2365:9;2356:18;;2428:5;2424:2;2421:13;2413:5;2409:2;2405:14;2401:34;2392:43;;;2534:5;2543:1;2534:10;2530:77;;2580:11;2572:5;:19;;;;;:::i;:::-;;2565:26;;;;;;2530:77;2734:5;2720:11;:19;2712:28;;;;;;3003:17;3141:11;3138:1;3135;3128:25;4548:1;3700;3685:12;;:16;;3670:32;;3808:22;;;;4529:1;:15;;4528:21;;4785;;;4781:25;;4770:36;4855:21;;;4851:25;;4840:36;4926:21;;;4922:25;;4911:36;4997:21;;;4993:25;;4982:36;5068:21;;;5064:25;;5053:36;5140:21;;;5136:25;;;5125:36;;;3655:12;4059;;;4055:23;;;4051:31;;;3258:20;;;3247:32;;;4175:12;;;;3306:21;;3909:16;;;;4166:21;;;;5610:15;;;-1:-1:-1;;;;1667:4005:0:o;17963:455::-;18133:12;18191:5;18166:21;:30;;18158:81;;;;-1:-1:-1;;;18158:81:0;;22883:2:1;18158:81:0;;;22865:21:1;22922:2;22902:18;;;22895:30;22961:34;22941:18;;;22934:62;-1:-1:-1;;;23012:18:1;;;23005:36;23058:19;;18158:81:0;22681:402:1;18158:81:0;18251:12;18265:23;18292:6;-1:-1:-1;;;;;18292:11:0;18311:5;18318:4;18292:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18250:73;;;;18341:69;18368:6;18376:7;18385:10;18397:12;20721;20750:7;20746:427;;;20778:10;:17;20799:1;20778:22;20774:290;;-1:-1:-1;;;;;14416:19:0;;;20988:60;;;;-1:-1:-1;;;20988:60:0;;23582:2:1;20988:60:0;;;23564:21:1;23621:2;23601:18;;;23594:30;23660:31;23640:18;;;23633:59;23709:18;;20988:60:0;23380:353:1;20988:60:0;-1:-1:-1;21085:10:0;21078:17;;20746:427;21128:33;21136:10;21148:12;21883:17;;:21;21879:388;;22115:10;22109:17;22172:15;22159:10;22155:2;22151:19;22144:44;21879:388;22242:12;22235:20;;-1:-1:-1;;;22235:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:180:1:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:1;;14:180;-1:-1:-1;14:180:1:o;199:838::-;444:2;496:21;;;566:13;;469:18;;;588:22;;;415:4;;444:2;629;;647:18;;;;688:15;;;415:4;731:280;745:6;742:1;739:13;731:280;;;804:13;;846:9;;-1:-1:-1;;;;;842:35:1;830:48;;918:11;;912:18;898:12;;;891:40;951:12;;;;986:15;;;;874:1;760:9;731:280;;;-1:-1:-1;1028:3:1;;199:838;-1:-1:-1;;;;;;;199:838:1:o;1224:131::-;-1:-1:-1;;;;;1299:31:1;;1289:42;;1279:70;;1345:1;1342;1335:12;1360:134;1428:20;;1457:31;1428:20;1457:31;:::i;:::-;1360:134;;;:::o;1499:315::-;1567:6;1575;1628:2;1616:9;1607:7;1603:23;1599:32;1596:52;;;1644:1;1641;1634:12;1596:52;1680:9;1667:23;1657:33;;1740:2;1729:9;1725:18;1712:32;1753:31;1778:5;1753:31;:::i;:::-;1803:5;1793:15;;;1499:315;;;;;:::o;2423:654::-;2548:6;2556;2609:2;2597:9;2588:7;2584:23;2580:32;2577:52;;;2625:1;2622;2615:12;2577:52;2665:9;2652:23;2694:18;2735:2;2727:6;2724:14;2721:34;;;2751:1;2748;2741:12;2721:34;2789:6;2778:9;2774:22;2764:32;;2834:7;2827:4;2823:2;2819:13;2815:27;2805:55;;2856:1;2853;2846:12;2805:55;2896:2;2883:16;2922:2;2914:6;2911:14;2908:34;;;2938:1;2935;2928:12;2908:34;2991:7;2986:2;2976:6;2973:1;2969:14;2965:2;2961:23;2957:32;2954:45;2951:65;;;3012:1;3009;3002:12;2951:65;3043:2;3035:11;;;;;3065:6;;-1:-1:-1;2423:654:1;;-1:-1:-1;;;;2423:654:1:o;3082:456::-;3159:6;3167;3175;3228:2;3216:9;3207:7;3203:23;3199:32;3196:52;;;3244:1;3241;3234:12;3196:52;3283:9;3270:23;3302:31;3327:5;3302:31;:::i;:::-;3352:5;-1:-1:-1;3404:2:1;3389:18;;3376:32;;-1:-1:-1;3460:2:1;3445:18;;3432:32;3473:33;3432:32;3473:33;:::i;:::-;3525:7;3515:17;;;3082:456;;;;;:::o;3543:316::-;3620:6;3628;3636;3689:2;3677:9;3668:7;3664:23;3660:32;3657:52;;;3705:1;3702;3695:12;3657:52;-1:-1:-1;;3728:23:1;;;3798:2;3783:18;;3770:32;;-1:-1:-1;3849:2:1;3834:18;;;3821:32;;3543:316;-1:-1:-1;3543:316:1:o;3864:247::-;3923:6;3976:2;3964:9;3955:7;3951:23;3947:32;3944:52;;;3992:1;3989;3982:12;3944:52;4031:9;4018:23;4050:31;4075:5;4050:31;:::i;4840:118::-;4926:5;4919:13;4912:21;4905:5;4902:32;4892:60;;4948:1;4945;4938:12;4963:376;5025:6;5033;5086:2;5074:9;5065:7;5061:23;5057:32;5054:52;;;5102:1;5099;5092:12;5054:52;5141:9;5128:23;5160:28;5182:5;5160:28;:::i;:::-;5207:5;-1:-1:-1;5264:2:1;5249:18;;5236:32;5277:30;5236:32;5277:30;:::i;5344:114::-;5428:4;5421:5;5417:16;5410:5;5407:27;5397:55;;5448:1;5445;5438:12;5463:801;5574:6;5582;5590;5598;5606;5614;5622;5675:3;5663:9;5654:7;5650:23;5646:33;5643:53;;;5692:1;5689;5682:12;5643:53;5731:9;5718:23;5750:31;5775:5;5750:31;:::i;:::-;5800:5;-1:-1:-1;5852:2:1;5837:18;;5824:32;;-1:-1:-1;5908:2:1;5893:18;;5880:32;5921:33;5880:32;5921:33;:::i;:::-;5973:7;-1:-1:-1;6027:2:1;6012:18;;5999:32;;-1:-1:-1;6078:3:1;6063:19;;6050:33;;-1:-1:-1;6130:3:1;6115:19;;6102:33;;-1:-1:-1;6187:3:1;6172:19;;6159:33;6201:31;6159:33;6201:31;:::i;:::-;6251:7;6241:17;;;5463:801;;;;;;;;;;:::o;6269:309::-;6334:6;6342;6395:2;6383:9;6374:7;6370:23;6366:32;6363:52;;;6411:1;6408;6401:12;6363:52;6447:9;6434:23;6424:33;;6507:2;6496:9;6492:18;6479:32;6520:28;6542:5;6520:28;:::i;6583:452::-;6669:6;6677;6685;6693;6746:3;6734:9;6725:7;6721:23;6717:33;6714:53;;;6763:1;6760;6753:12;6714:53;6799:9;6786:23;6776:33;;6856:2;6845:9;6841:18;6828:32;6818:42;;6907:2;6896:9;6892:18;6879:32;6869:42;;6961:2;6950:9;6946:18;6933:32;6974:31;6999:5;6974:31;:::i;:::-;6583:452;;;;-1:-1:-1;6583:452:1;;-1:-1:-1;;6583:452:1:o;7040:315::-;7108:6;7116;7169:2;7157:9;7148:7;7144:23;7140:32;7137:52;;;7185:1;7182;7175:12;7137:52;7224:9;7211:23;7243:31;7268:5;7243:31;:::i;:::-;7293:5;7345:2;7330:18;;;;7317:32;;-1:-1:-1;;;7040:315:1:o;7549:127::-;7610:10;7605:3;7601:20;7598:1;7591:31;7641:4;7638:1;7631:15;7665:4;7662:1;7655:15;7681:252;7753:2;7747:9;7795:3;7783:16;;7829:18;7814:34;;7850:22;;;7811:62;7808:88;;;7876:18;;:::i;:::-;7912:2;7905:22;7681:252;:::o;7938:275::-;8009:2;8003:9;8074:2;8055:13;;-1:-1:-1;;8051:27:1;8039:40;;8109:18;8094:34;;8130:22;;;8091:62;8088:88;;;8156:18;;:::i;:::-;8192:2;8185:22;7938:275;;-1:-1:-1;7938:275:1:o;8218:1483::-;8305:6;8358:3;8346:9;8337:7;8333:23;8329:33;8326:53;;;8375:1;8372;8365:12;8326:53;8401:22;;:::i;:::-;8459:9;8446:23;8439:5;8432:38;8530:2;8519:9;8515:18;8502:32;8497:2;8490:5;8486:14;8479:56;8595:2;8584:9;8580:18;8567:32;8562:2;8555:5;8551:14;8544:56;8660:2;8649:9;8645:18;8632:32;8627:2;8620:5;8616:14;8609:56;8726:3;8715:9;8711:19;8698:33;8692:3;8685:5;8681:15;8674:58;8793:3;8782:9;8778:19;8765:33;8759:3;8752:5;8748:15;8741:58;8860:3;8849:9;8845:19;8832:33;8826:3;8819:5;8815:15;8808:58;8927:3;8916:9;8912:19;8899:33;8893:3;8886:5;8882:15;8875:58;8952:3;9015:2;9004:9;9000:18;8987:32;8982:2;8975:5;8971:14;8964:56;;9039:3;9074:38;9108:2;9097:9;9093:18;9074:38;:::i;:::-;9058:14;;;9051:62;9132:3;9167:38;9186:18;;;9167:38;:::i;:::-;9151:14;;;9144:62;9225:3;9260:38;9279:18;;;9260:38;:::i;:::-;9244:14;;;9237:62;9318:3;9353:38;9372:18;;;9353:38;:::i;:::-;9337:14;;;9330:62;9411:3;9446:38;9465:18;;;9446:38;:::i;:::-;9430:14;;;9423:62;9504:3;9539:38;9558:18;;;9539:38;:::i;:::-;9523:14;;;9516:62;9597:3;9632:38;9651:18;;;9632:38;:::i;:::-;9616:14;;;9609:62;9620:5;8218:1483;-1:-1:-1;;;8218:1483:1:o;9706:385::-;9792:6;9800;9808;9816;9869:3;9857:9;9848:7;9844:23;9840:33;9837:53;;;9886:1;9883;9876:12;9837:53;-1:-1:-1;;9909:23:1;;;9979:2;9964:18;;9951:32;;-1:-1:-1;10030:2:1;10015:18;;10002:32;;10081:2;10066:18;10053:32;;-1:-1:-1;9706:385:1;-1:-1:-1;9706:385:1:o;10096:384::-;10162:6;10170;10223:2;10211:9;10202:7;10198:23;10194:32;10191:52;;;10239:1;10236;10229:12;10191:52;10278:9;10265:23;10297:31;10322:5;10297:31;:::i;:::-;10347:5;-1:-1:-1;10404:2:1;10389:18;;10376:32;10417:31;10376:32;10417:31;:::i;10485:250::-;10570:1;10580:113;10594:6;10591:1;10588:13;10580:113;;;10670:11;;;10664:18;10651:11;;;10644:39;10616:2;10609:10;10580:113;;;-1:-1:-1;;10727:1:1;10709:16;;10702:27;10485:250::o;10740:270::-;10781:3;10819:5;10813:12;10846:6;10841:3;10834:19;10862:76;10931:6;10924:4;10919:3;10915:14;10908:4;10901:5;10897:16;10862:76;:::i;:::-;10992:2;10971:15;-1:-1:-1;;10967:29:1;10958:39;;;;10999:4;10954:50;;10740:270;-1:-1:-1;;10740:270:1:o;11015:217::-;11162:2;11151:9;11144:21;11125:4;11182:44;11222:2;11211:9;11207:18;11199:6;11182:44;:::i;11419:245::-;11486:6;11539:2;11527:9;11518:7;11514:23;11510:32;11507:52;;;11555:1;11552;11545:12;11507:52;11587:9;11581:16;11606:28;11628:5;11606:28;:::i;11669:127::-;11730:10;11725:3;11721:20;11718:1;11711:31;11761:4;11758:1;11751:15;11785:4;11782:1;11775:15;11801:125;11866:9;;;11887:10;;;11884:36;;;11900:18;;:::i;12255:127::-;12316:10;12311:3;12307:20;12304:1;12297:31;12347:4;12344:1;12337:15;12371:4;12368:1;12361:15;12387:418;12576:5;12563:19;12591:33;12616:7;12591:33;:::i;:::-;12653:11;;-1:-1:-1;;;;;;12649:54:1;-1:-1:-1;;;;;12705:33:1;;;;12646:93;12633:107;;12794:2;12783:14;;;;12770:28;12735:1;12756:12;;;;12749:50;12387:418::o;12810:128::-;12877:9;;;12898:11;;;12895:37;;;12912:18;;:::i;13339:168::-;13412:9;;;13443;;13460:15;;;13454:22;;13440:37;13430:71;;13481:18;;:::i;13512:127::-;13573:10;13568:3;13564:20;13561:1;13554:31;13604:4;13601:1;13594:15;13628:4;13625:1;13618:15;13644:120;13684:1;13710;13700:35;;13715:18;;:::i;:::-;-1:-1:-1;13749:9:1;;13644:120::o;13769:251::-;13839:6;13892:2;13880:9;13871:7;13867:23;13863:32;13860:52;;;13908:1;13905;13898:12;13860:52;13940:9;13934:16;13959:31;13984:5;13959:31;:::i;14025:184::-;14095:6;14148:2;14136:9;14127:7;14123:23;14119:32;14116:52;;;14164:1;14161;14154:12;14116:52;-1:-1:-1;14187:16:1;;14025:184;-1:-1:-1;14025:184:1:o;14214:247::-;14282:6;14335:2;14323:9;14314:7;14310:23;14306:32;14303:52;;;14351:1;14348;14341:12;14303:52;14383:9;14377:16;14402:29;14425:5;14402:29;:::i;14466:416::-;14555:1;14592:5;14555:1;14606:270;14627:7;14617:8;14614:21;14606:270;;;14686:4;14682:1;14678:6;14674:17;14668:4;14665:27;14662:53;;;14695:18;;:::i;:::-;14745:7;14735:8;14731:22;14728:55;;;14765:16;;;;14728:55;14844:22;;;;14804:15;;;;14606:270;;14887:806;14936:5;14966:8;14956:80;;-1:-1:-1;15007:1:1;15021:5;;14956:80;15055:4;15045:76;;-1:-1:-1;15092:1:1;15106:5;;15045:76;15137:4;15155:1;15150:59;;;;15223:1;15218:130;;;;15130:218;;15150:59;15180:1;15171:10;;15194:5;;;15218:130;15255:3;15245:8;15242:17;15239:43;;;15262:18;;:::i;:::-;-1:-1:-1;;15318:1:1;15304:16;;15333:5;;15130:218;;15432:2;15422:8;15419:16;15413:3;15407:4;15404:13;15400:36;15394:2;15384:8;15381:16;15376:2;15370:4;15367:12;15363:35;15360:77;15357:159;;;-1:-1:-1;15469:19:1;;;15501:5;;15357:159;15548:34;15573:8;15567:4;15548:34;:::i;:::-;15618:6;15614:1;15610:6;15606:19;15597:7;15594:32;15591:58;;;15629:18;;:::i;:::-;15667:20;;14887:806;-1:-1:-1;;;14887:806:1:o;15698:140::-;15756:5;15785:47;15826:4;15816:8;15812:19;15806:4;15785:47;:::i;15843:1011::-;15938:6;15969:2;16012;16000:9;15991:7;15987:23;15983:32;15980:52;;;16028:1;16025;16018:12;15980:52;16061:9;16055:16;16090:18;16131:2;16123:6;16120:14;16117:34;;;16147:1;16144;16137:12;16117:34;16185:6;16174:9;16170:22;16160:32;;16230:7;16223:4;16219:2;16215:13;16211:27;16201:55;;16252:1;16249;16242:12;16201:55;16281:2;16275:9;16303:2;16299;16296:10;16293:36;;;16309:18;;:::i;:::-;16355:2;16352:1;16348:10;16338:20;;16378:28;16402:2;16398;16394:11;16378:28;:::i;:::-;16440:15;;;16510:11;;;16506:20;;;16471:12;;;;16538:19;;;16535:39;;;16570:1;16567;16560:12;16535:39;16594:11;;;;16614:210;16630:6;16625:3;16622:15;16614:210;;;16703:3;16697:10;16684:23;;16720:31;16745:5;16720:31;:::i;:::-;16764:18;;;16647:12;;;;16802;;;;16614:210;;18340:245;18419:6;18427;18480:2;18468:9;18459:7;18455:23;18451:32;18448:52;;;18496:1;18493;18486:12;18448:52;-1:-1:-1;;18519:16:1;;18575:2;18560:18;;;18554:25;18519:16;;18554:25;;-1:-1:-1;18340:245:1:o;19204:136::-;19243:3;19271:5;19261:39;;19280:18;;:::i;:::-;-1:-1:-1;;;19316:18:1;;19204:136::o;19345:127::-;19406:10;19401:3;19397:20;19394:1;19387:31;19437:4;19434:1;19427:15;19461:4;19458:1;19451:15;20939:216;21003:9;;;21031:11;;;20978:3;21061:9;;21089:10;;21085:19;;21114:10;;21106:19;;21082:44;21079:70;;;21129:18;;:::i;:::-;21079:70;;20939:216;;;;:::o;21160:237::-;21232:9;;;21199:7;21257:9;;-1:-1:-1;;;21268:18:1;;21253:34;21250:60;;;21290:18;;:::i;:::-;21363:1;21354:7;21349:16;21346:1;21343:23;21339:1;21332:9;21329:38;21319:72;;21371:18;;:::i;21402:193::-;21441:1;21467;21457:35;;21472:18;;:::i;:::-;-1:-1:-1;;;21508:18:1;;-1:-1:-1;;21528:13:1;;21504:38;21501:64;;;21545:18;;:::i;:::-;-1:-1:-1;21579:10:1;;21402:193::o;21600:200::-;21666:9;;;21639:4;21694:9;;21722:10;;21734:12;;;21718:29;21757:12;;;21749:21;;21715:56;21712:82;;;21774:18;;:::i;:::-;21712:82;21600:200;;;;:::o;22549:127::-;22610:10;22605:3;22601:20;22598:1;22591:31;22641:4;22638:1;22631:15;22665:4;22662:1;22655:15;23088:287;23217:3;23255:6;23249:13;23271:66;23330:6;23325:3;23318:4;23310:6;23306:17;23271:66;:::i;:::-;23353:16;;;;;23088:287;-1:-1:-1;;23088:287:1:o
Swarm Source
ipfs://a7b6ef1853c0013d977b2bbd29fd244d97f0329f4293dca1fc59bd0dfce21600
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MON
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
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.