Source Code
Cross-Chain Transactions
Loading...
Loading
Contract Name:
OdosRouterV3
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity)
/**
*Submitted for verification at fraxscan.com on 2024-12-03
*/
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
/**
* @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);
}
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
/**
* @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 Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return 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);
}
}
}
/**
* @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 Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_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);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() external {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}
/// @title SignatureTransfer
/// @notice Handles ERC20 token transfers through signature based actions
/// @dev Requires user's token approval on the Permit2 contract
interface ISignatureTransfer {
/// @notice Thrown when the requested amount for a transfer is larger than the permissioned amount
/// @param maxAmount The maximum amount a spender can request to transfer
error InvalidAmount(uint256 maxAmount);
/// @notice Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred
/// @dev If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred
error LengthMismatch();
/// @notice Emits an event when the owner successfully invalidates an unordered nonce.
event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask);
/// @notice The token and amount details for a transfer signed in the permit transfer signature
struct TokenPermissions {
// ERC20 token address
address token;
// the maximum amount that can be spent
uint256 amount;
}
/// @notice The signed permit message for a single token transfer
struct PermitTransferFrom {
TokenPermissions permitted;
// a unique value for every token owner's signature to prevent signature replays
uint256 nonce;
// deadline on the permit signature
uint256 deadline;
}
/// @notice Specifies the recipient address and amount for batched transfers.
/// @dev Recipients and amounts correspond to the index of the signed token permissions array.
/// @dev Reverts if the requested amount is greater than the permitted signed amount.
struct SignatureTransferDetails {
// recipient address
address to;
// spender requested amount
uint256 requestedAmount;
}
/// @notice Used to reconstruct the signed permit message for multiple token transfers
/// @dev Do not need to pass in spender address as it is required that it is msg.sender
/// @dev Note that a user still signs over a spender address
struct PermitBatchTransferFrom {
// the tokens and corresponding amounts permitted for a transfer
TokenPermissions[] permitted;
// a unique value for every token owner's signature to prevent signature replays
uint256 nonce;
// deadline on the permit signature
uint256 deadline;
}
/// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection
/// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order
/// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce
/// @dev It returns a uint256 bitmap
/// @dev The index, or wordPosition is capped at type(uint248).max
function nonceBitmap(address, uint256) external view returns (uint256);
/// @notice Transfers a token using a signed permit message
/// @dev Reverts if the requested amount is greater than the permitted signed amount
/// @param permit The permit data signed over by the owner
/// @param owner The owner of the tokens to transfer
/// @param transferDetails The spender's requested transfer details for the permitted token
/// @param signature The signature to verify
function permitTransferFrom(
PermitTransferFrom memory permit,
SignatureTransferDetails calldata transferDetails,
address owner,
bytes calldata signature
) external;
/// @notice Transfers a token using a signed permit message
/// @notice Includes extra data provided by the caller to verify signature over
/// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
/// @dev Reverts if the requested amount is greater than the permitted signed amount
/// @param permit The permit data signed over by the owner
/// @param owner The owner of the tokens to transfer
/// @param transferDetails The spender's requested transfer details for the permitted token
/// @param witness Extra data to include when checking the user signature
/// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
/// @param signature The signature to verify
function permitWitnessTransferFrom(
PermitTransferFrom memory permit,
SignatureTransferDetails calldata transferDetails,
address owner,
bytes32 witness,
string calldata witnessTypeString,
bytes calldata signature
) external;
/// @notice Transfers multiple tokens using a signed permit message
/// @param permit The permit data signed over by the owner
/// @param owner The owner of the tokens to transfer
/// @param transferDetails Specifies the recipient and requested amount for the token transfer
/// @param signature The signature to verify
function permitTransferFrom(
PermitBatchTransferFrom memory permit,
SignatureTransferDetails[] calldata transferDetails,
address owner,
bytes calldata signature
) external;
/// @notice Transfers multiple tokens using a signed permit message
/// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
/// @notice Includes extra data provided by the caller to verify signature over
/// @param permit The permit data signed over by the owner
/// @param owner The owner of the tokens to transfer
/// @param transferDetails Specifies the recipient and requested amount for the token transfer
/// @param witness Extra data to include when checking the user signature
/// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
/// @param signature The signature to verify
function permitWitnessTransferFrom(
PermitBatchTransferFrom memory permit,
SignatureTransferDetails[] calldata transferDetails,
address owner,
bytes32 witness,
string calldata witnessTypeString,
bytes calldata signature
) external;
/// @notice Invalidates the bits specified in mask for the bitmap at the word position
/// @dev The wordPos is maxed at type(uint248).max
/// @param wordPos A number to index the nonceBitmap at
/// @param mask A bitmap masked against msg.sender's current bitmap at the word position
function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external;
}
/// @title V3 Routing contract interface for Odos SOR
/// @author Transaction Assembly
/// @notice Wrapper with security gaurentees around execution of arbitrary operations on user tokens
interface IOdosRouterV3 {
/// @dev Contains all information needed to describe the input and output for a swap
struct permit2Info {
address contractAddress;
uint256 nonce;
uint256 deadline;
bytes signature;
}
/// @dev Contains all information needed to describe the input and output for a swap
struct swapTokenInfo {
address inputToken;
uint256 inputAmount;
address inputReceiver;
address outputToken;
uint256 outputQuote;
uint256 outputMin;
address outputReceiver;
}
/// @dev Contains all information needed to describe an intput token for swapMulti
struct inputTokenInfo {
address tokenAddress;
uint256 amountIn;
address receiver;
}
/// @dev Contains all information needed to describe an output token for swapMulti
struct outputTokenInfo {
address tokenAddress;
uint256 amountQuote;
uint256 amountMin;
address receiver;
}
/// @dev Holds all information for a given referral
struct swapReferralInfo {
uint64 code;
uint64 fee;
address feeRecipient;
}
/// @dev Event emitted on changing the liquidator address
event LiquidatorAddressChanged(address indexed account);
// @dev event for swapping one token for another
event Swap(
address sender,
uint256 inputAmount,
address inputToken,
uint256 amountOut,
address outputToken,
int256 slippage,
uint64 referralCode,
uint64 referralFee,
address referralFeeRecipient
);
/// @dev event for swapping multiple input and/or output tokens
event SwapMulti(
address sender,
uint256[] amountsIn,
address[] tokensIn,
uint256[] amountsOut,
address[] tokensOut,
int256[] slippage,
uint64 referralCode,
uint64 referralFee,
address referralFeeRecipient
);
function swapCompact() external payable returns (uint256);
function swap(
swapTokenInfo memory tokenInfo,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
external payable returns (uint256 amountOut);
function swapPermit2(
permit2Info memory permit2,
swapTokenInfo memory tokenInfo,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
external returns (uint256 amountOut);
function swapMultiCompact() external payable returns (uint256[] memory amountsOut);
function swapMulti(
inputTokenInfo[] memory inputs,
outputTokenInfo[] memory outputs,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
external payable returns (uint256[] memory amountsOut);
function swapMultiPermit2(
permit2Info memory permit2,
inputTokenInfo[] memory inputs,
outputTokenInfo[] memory outputs,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
external payable returns (uint256[] memory amountsOut);
function changeLiquidatorAddress(address account)
external;
function writeAddressList(
address[] calldata addresses
)
external;
function transferRouterFunds(
address[] calldata tokens,
uint256[] calldata amounts,
address dest
)
external;
function swapRouterFunds(
inputTokenInfo[] memory inputs,
outputTokenInfo[] memory outputs,
bytes calldata pathDefinition,
address executor
)
external
returns (uint256[] memory amountsOut);
}
interface IOdosExecutor {
function executePath (
bytes calldata bytecode,
uint256[] memory inputAmount,
address msgSender
) external payable;
}
/// @title V3 Routing contract for Odos SOR
/// @author Transaction Assembly
/// @notice Wrapper with security gaurentees around execution of arbitrary operations on user tokens
contract OdosRouterV3 is IOdosRouterV3, Ownable2Step {
using SafeERC20 for IERC20;
/// @dev The zero address is uniquely used to represent eth since it is already
/// recognized as an invalid ERC20, and due to its gas efficiency
address constant _ETH = address(0);
/// @dev Address list where addresses can be cached for use when reading from storage is cheaper
// than reading from calldata. addressListStart is the storage slot of the first dynamic array element
uint256 private constant addressListStart =
29102676481673041902632991033461445430619272659676223336789171408008386403022;
address[] public addressList;
/// @dev Address which can access and liquidate funds held in the router
address public liquidatorAddress;
// @dev constant for the fee precision
uint256 public constant FEE_DENOM = 1e18;
/// @dev Must exist in order for contract to receive eth
receive() external payable { }
/// @notice Custom decoder to swap with compact calldata for efficient execution on L2s
function swapCompact()
external
payable
returns (uint256)
{
swapTokenInfo memory tokenInfo;
swapReferralInfo memory referralInfo;
address executor;
bytes calldata pathDefinition;
{
assembly {
// Define function to load in token address, either from calldata or from storage
function getAddress(currPos) -> result, newPos {
let inputPos := shr(240, calldataload(currPos))
switch inputPos
// Reserve the null address as a special case that can be specified with 2 null bytes
case 0x0000 {
newPos := add(currPos, 2)
}
// This case means that the address is encoded in the calldata directly following the code
case 0x0001 {
result := and(shr(80, calldataload(currPos)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
newPos := add(currPos, 22)
}
// Otherwise we use the case to load in from the cached address list
default {
result := sload(add(addressListStart, sub(inputPos, 2)))
newPos := add(currPos, 2)
}
}
let result := 0
let pos := 4
// Load in the input and output token addresses
result, pos := getAddress(pos)
mstore(tokenInfo, result)
result, pos := getAddress(pos)
mstore(add(tokenInfo, 0x60), result)
// Load in the input amount - a 0 byte means the full balance is to be used
let inputAmountLength := shr(248, calldataload(pos))
pos := add(pos, 1)
if inputAmountLength {
mstore(add(tokenInfo, 0x20), shr(mul(sub(32, inputAmountLength), 8), calldataload(pos)))
pos := add(pos, inputAmountLength)
}
// Load in the quoted output amount
let quoteAmountLength := shr(248, calldataload(pos))
pos := add(pos, 1)
let outputQuote := shr(mul(sub(32, quoteAmountLength), 8), calldataload(pos))
mstore(add(tokenInfo, 0x80), outputQuote)
pos := add(pos, quoteAmountLength)
// Load the slippage tolerance and use to get the minimum output amount
{
let slippageTolerance := shr(232, calldataload(pos))
mstore(add(tokenInfo, 0xA0), div(mul(outputQuote, sub(0xFFFFFF, slippageTolerance)), 0xFFFFFF))
}
pos := add(pos, 3)
// Load in the executor address
executor, pos := getAddress(pos)
// Load in the destination to send the input to - Zero denotes the executor
result, pos := getAddress(pos)
if eq(result, 0) { result := executor }
mstore(add(tokenInfo, 0x40), result)
// Load in the destination to send the output to - Zero denotes msg.sender
result, pos := getAddress(pos)
mstore(add(tokenInfo, 0xC0), result)
let referralCode := shr(192, calldataload(pos))
pos := add(pos, 8)
mstore(referralInfo, referralCode)
let feeStatus := shr(248, calldataload(pos))
pos := add(pos, 1)
if feeStatus {
let referralFee := shr(192, calldataload(pos))
pos := add(pos, 8)
mstore(add(referralInfo, 0x20), referralFee)
let referralBeneficiary := shr(96, calldataload(pos))
pos := add(pos, 20)
mstore(add(referralInfo, 0x40), referralBeneficiary)
}
// Set the offset and size for the pathDefinition portion of the msg.data
pathDefinition.length := mul(shr(248, calldataload(pos)), 32)
pathDefinition.offset := add(pos, 1)
}
}
return _swapApproval(
tokenInfo,
pathDefinition,
executor,
referralInfo
);
}
/// @notice Externally facing interface for swapping two tokens
/// @param tokenInfo All information about the tokens being swapped
/// @param pathDefinition Encoded path definition for executor
/// @param executor Address of contract that will execute the path
/// @param referralInfo referral info to specify the source of and fee for the swap
function swap(
swapTokenInfo memory tokenInfo,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
external
payable
returns (uint256 amountOut)
{
return _swapApproval(
tokenInfo,
pathDefinition,
executor,
referralInfo
);
}
/// @notice Internal function for initiating approval transfers
/// @param tokenInfo All information about the tokens being swapped
/// @param pathDefinition Encoded path definition for executor
/// @param executor Address of contract that will execute the path
/// @param referralInfo referral info to specify the source of and fee for the swap
function _swapApproval(
swapTokenInfo memory tokenInfo,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
internal
returns (uint256 amountOut)
{
if (tokenInfo.inputToken == _ETH) {
// Support rebasing tokens by allowing the user to trade the entire balance
if (tokenInfo.inputAmount == 0) {
tokenInfo.inputAmount = msg.value;
} else {
require(msg.value == tokenInfo.inputAmount, "Wrong msg.value");
}
}
else {
require(msg.value == 0, "Wrong msg.value");
// Support rebasing tokens by allowing the user to trade the entire balance
if (tokenInfo.inputAmount == 0) {
tokenInfo.inputAmount = IERC20(tokenInfo.inputToken).balanceOf(msg.sender);
}
IERC20(tokenInfo.inputToken).safeTransferFrom(
msg.sender,
tokenInfo.inputReceiver,
tokenInfo.inputAmount
);
}
return _swap(
tokenInfo,
pathDefinition,
executor,
referralInfo
);
}
/// @notice Externally facing interface for swapping two tokens
/// @param permit2 All additional info for Permit2 transfers
/// @param tokenInfo All information about the tokens being swapped
/// @param pathDefinition Encoded path definition for executor
/// @param executor Address of contract that will execute the path
/// @param referralInfo referral info to specify the source of and fee for the swap
function swapPermit2(
permit2Info memory permit2,
swapTokenInfo memory tokenInfo,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
external
returns (uint256 amountOut)
{
ISignatureTransfer(permit2.contractAddress).permitTransferFrom(
ISignatureTransfer.PermitTransferFrom(
ISignatureTransfer.TokenPermissions(
tokenInfo.inputToken,
tokenInfo.inputAmount
),
permit2.nonce,
permit2.deadline
),
ISignatureTransfer.SignatureTransferDetails(
tokenInfo.inputReceiver,
tokenInfo.inputAmount
),
msg.sender,
permit2.signature
);
return _swap(
tokenInfo,
pathDefinition,
executor,
referralInfo
);
}
/// @notice contains the main logic for swapping one token for another
/// Assumes input tokens have already been sent to their destinations and
/// that msg.value is set to expected ETH input value, or 0 for ERC20 input
/// @param tokenInfo All information about the tokens being swapped
/// @param pathDefinition Encoded path definition for executor
/// @param executor Address of contract that will execute the path
/// @param referralInfo referral info to specify the source of and fee for the swap
function _swap(
swapTokenInfo memory tokenInfo,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
internal
returns (uint256 amountOut)
{
// Check for valid output specifications
require(tokenInfo.outputMin <= tokenInfo.outputQuote, "Minimum greater than quote");
require(tokenInfo.outputMin > 0, "Minimum output is zero");
require(tokenInfo.inputToken != tokenInfo.outputToken, "Arbitrage not supported");
uint256 balanceBefore = _universalBalance(tokenInfo.outputToken);
// Delegate the execution of the path to the specified Odos Executor
uint256[] memory amountsIn = new uint256[](1);
amountsIn[0] = tokenInfo.inputAmount;
IOdosExecutor(executor).executePath{value: msg.value}(pathDefinition, amountsIn, msg.sender);
amountOut = _universalBalance(tokenInfo.outputToken) - balanceBefore;
if (referralInfo.fee > 0) {
require(referralInfo.feeRecipient != address(0), "Null fee recipient");
require(referralInfo.fee <= FEE_DENOM / 50, "Fee too high");
if (referralInfo.feeRecipient != address(this)) {
_universalTransfer(
tokenInfo.outputToken,
referralInfo.feeRecipient,
amountOut * referralInfo.fee * 8 / (FEE_DENOM * 10)
);
}
amountOut = amountOut * (FEE_DENOM - referralInfo.fee) / FEE_DENOM;
}
int256 slippage = int256(amountOut) - int256(tokenInfo.outputQuote);
if (slippage > 0) {
amountOut = tokenInfo.outputQuote;
}
require(amountOut >= tokenInfo.outputMin, "Slippage Limit Exceeded");
// Transfer out the final output to the end user
_universalTransfer(
tokenInfo.outputToken,
tokenInfo.outputReceiver == address(0) ? msg.sender : tokenInfo.outputReceiver,
amountOut
);
emit Swap(
msg.sender,
tokenInfo.inputAmount,
tokenInfo.inputToken,
amountOut,
tokenInfo.outputToken,
slippage,
referralInfo.code,
referralInfo.fee,
referralInfo.feeRecipient
);
}
/// @notice Custom decoder to swapMulti with compact calldata for efficient execution on L2s
function swapMultiCompact()
external
payable
returns (uint256[] memory amountsOut)
{
address executor;
inputTokenInfo[] memory inputs;
outputTokenInfo[] memory outputs;
uint256 pos = 6;
{
uint256 numInputs;
uint256 numOutputs;
assembly {
numInputs := shr(248, calldataload(4))
numOutputs := shr(248, calldataload(5))
}
inputs = new inputTokenInfo[](numInputs);
outputs = new outputTokenInfo[](numOutputs);
assembly {
// Define function to load in token address, either from calldata or from storage
function getAddress(currPos) -> result, newPos {
let inputPos := shr(240, calldataload(currPos))
switch inputPos
// Reserve the null address as a special case that can be specified with 2 null bytes
case 0x0000 {
newPos := add(currPos, 2)
}
// This case means that the address is encoded in the calldata directly following the code
case 0x0001 {
result := and(shr(80, calldataload(currPos)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
newPos := add(currPos, 22)
}
// Otherwise we use the case to load in from the cached address list
default {
result := sload(add(addressListStart, sub(inputPos, 2)))
newPos := add(currPos, 2)
}
}
executor, pos := getAddress(pos)
let slippageTolerance := shr(232, calldataload(pos))
pos := add(pos, 3)
let result := 0
let memPos := 0
for { let element := 0 } lt(element, numInputs) { element := add(element, 1) }
{
memPos := mload(add(inputs, add(mul(element, 0x20), 0x20)))
// Load in the token address
result, pos := getAddress(pos)
mstore(memPos, result)
// Load in the input amount - a 0 byte means the full balance is to be used
let inputAmountLength := shr(248, calldataload(pos))
pos := add(pos, 1)
if inputAmountLength {
mstore(add(memPos, 0x20), shr(mul(sub(32, inputAmountLength), 8), calldataload(pos)))
pos := add(pos, inputAmountLength)
}
result, pos := getAddress(pos)
if eq(result, 0) { result := executor }
mstore(add(memPos, 0x40), result)
}
for { let element := 0 } lt(element, numOutputs) { element := add(element, 1) }
{
memPos := mload(add(outputs, add(mul(element, 0x20), 0x20)))
// Load in the token address
result, pos := getAddress(pos)
mstore(memPos, result)
// Load in the quoted output amount
let outputAmountLength := shr(248, calldataload(pos))
pos := add(pos, 1)
let outputQuote := shr(mul(sub(32, outputAmountLength), 8), calldataload(pos))
mstore(add(memPos, 0x20), outputQuote)
pos := add(pos, outputAmountLength)
// Set the minimum output amount as quote with slippage limit applied
mstore(add(memPos, 0x40), div(mul(outputQuote, sub(0xFFFFFF, slippageTolerance)), 0xFFFFFF))
result, pos := getAddress(pos)
mstore(add(memPos, 0x60), result)
}
}
}
swapReferralInfo memory referralInfo;
bytes calldata pathDefinition;
assembly {
let referralCode := shr(192, calldataload(pos))
pos := add(pos, 8)
mstore(referralInfo, referralCode)
let feeStatus := shr(248, calldataload(pos))
pos := add(pos, 1)
if feeStatus {
let referralFee := shr(192, calldataload(pos))
pos := add(pos, 8)
mstore(add(referralInfo, 0x20), referralFee)
let referralBeneficiary := shr(96, calldataload(pos))
pos := add(pos, 20)
mstore(add(referralInfo, 0x40), referralBeneficiary)
}
// Set the offset and size for the pathDefinition portion of the msg.data
pathDefinition.length := mul(shr(248, calldataload(pos)), 32)
pathDefinition.offset := add(pos, 1)
}
return _swapMultiApproval(
inputs,
outputs,
pathDefinition,
executor,
referralInfo
);
}
/// @notice Externally facing interface for swapping between two sets of tokens
/// @param inputs list of input token structs for the path being executed
/// @param outputs list of output token structs for the path being executed
/// @param pathDefinition Encoded path definition for executor
/// @param executor Address of contract that will execute the path
/// @param referralInfo referral info to specify the source of and fee for the swap
function swapMulti(
inputTokenInfo[] memory inputs,
outputTokenInfo[] memory outputs,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
external
payable
returns (uint256[] memory amountsOut)
{
return _swapMultiApproval(
inputs,
outputs,
pathDefinition,
executor,
referralInfo
);
}
/// @notice Internal logic for swapping between two sets of tokens with approvals
/// @param inputs list of input token structs for the path being executed
/// @param outputs list of output token structs for the path being executed
/// @param pathDefinition Encoded path definition for executor
/// @param executor Address of contract that will execute the path
/// @param referralInfo referral info to specify the source of and fee for the swap
function _swapMultiApproval(
inputTokenInfo[] memory inputs,
outputTokenInfo[] memory outputs,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
internal
returns (uint256[] memory amountsOut)
{
// If input amount is still 0 then that means the maximum possible input is to be used
uint256 expected_msg_value = 0;
for (uint256 i = 0; i < inputs.length; i++) {
if (inputs[i].tokenAddress == _ETH) {
if (inputs[i].amountIn == 0) {
inputs[i].amountIn = msg.value;
}
expected_msg_value = inputs[i].amountIn;
}
else {
if (inputs[i].amountIn == 0) {
inputs[i].amountIn = IERC20(inputs[i].tokenAddress).balanceOf(msg.sender);
}
IERC20(inputs[i].tokenAddress).safeTransferFrom(
msg.sender,
inputs[i].receiver,
inputs[i].amountIn
);
}
}
require(msg.value == expected_msg_value, "Wrong msg.value");
return _swapMulti(
inputs,
outputs,
pathDefinition,
executor,
referralInfo
);
}
/// @notice Externally facing interface for swapping between two sets of tokens with Permit2
/// @param permit2 All additional info for Permit2 transfers
/// @param inputs list of input token structs for the path being executed
/// @param outputs list of output token structs for the path being executed
/// @param pathDefinition Encoded path definition for executor
/// @param executor Address of contract that will execute the path
/// @param referralInfo referral info to specify the source of and fee for the swap
function swapMultiPermit2(
permit2Info memory permit2,
inputTokenInfo[] memory inputs,
outputTokenInfo[] memory outputs,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
external
payable
returns (uint256[] memory amountsOut)
{
ISignatureTransfer.PermitBatchTransferFrom memory permit;
ISignatureTransfer.SignatureTransferDetails[] memory transferDetails;
{
uint256 permit_length = msg.value > 0 ? inputs.length - 1 : inputs.length;
permit = ISignatureTransfer.PermitBatchTransferFrom(
new ISignatureTransfer.TokenPermissions[](permit_length),
permit2.nonce,
permit2.deadline
);
transferDetails =
new ISignatureTransfer.SignatureTransferDetails[](permit_length);
}
{
uint256 expected_msg_value = 0;
for (uint256 i = 0; i < inputs.length; i++) {
if (inputs[i].tokenAddress == _ETH) {
if (inputs[i].amountIn == 0) {
inputs[i].amountIn = msg.value;
}
expected_msg_value = inputs[i].amountIn;
}
else {
if (inputs[i].amountIn == 0) {
inputs[i].amountIn = IERC20(inputs[i].tokenAddress).balanceOf(msg.sender);
}
uint256 permit_index = expected_msg_value == 0 ? i : i - 1;
permit.permitted[permit_index].token = inputs[i].tokenAddress;
permit.permitted[permit_index].amount = inputs[i].amountIn;
transferDetails[permit_index].to = inputs[i].receiver;
transferDetails[permit_index].requestedAmount = inputs[i].amountIn;
}
}
require(msg.value == expected_msg_value, "Wrong msg.value");
}
ISignatureTransfer(permit2.contractAddress).permitTransferFrom(
permit,
transferDetails,
msg.sender,
permit2.signature
);
return _swapMulti(
inputs,
outputs,
pathDefinition,
executor,
referralInfo
);
}
/// @notice contains the main logic for swapping between two sets of tokens
/// assumes that inputs have already been sent to the right location and msg.value
/// is set correctly to be 0 for no native input and match native inpuit otherwise
/// @param inputs list of input token structs for the path being executed
/// @param outputs list of output token structs for the path being executed
/// @param pathDefinition Encoded path definition for executor
/// @param executor Address of contract that will execute the path
/// @param referralInfo referral info to specify the source of and fee for the swap
function _swapMulti(
inputTokenInfo[] memory inputs,
outputTokenInfo[] memory outputs,
bytes calldata pathDefinition,
address executor,
swapReferralInfo memory referralInfo
)
internal
returns (uint256[] memory amountsOut)
{
// Extract arrays of input amount values and tokens from the inputs struct list
uint256[] memory amountsIn = new uint256[](inputs.length);
address[] memory tokensIn = new address[](inputs.length);
// Check input specification validity and transfer input tokens to executor
{
for (uint256 i = 0; i < inputs.length; i++) {
amountsIn[i] = inputs[i].amountIn;
tokensIn[i] = inputs[i].tokenAddress;
for (uint256 j = 0; j < i; j++) {
require(
inputs[i].tokenAddress != inputs[j].tokenAddress,
"Duplicate source tokens"
);
}
for (uint256 j = 0; j < outputs.length; j++) {
require(
inputs[i].tokenAddress != outputs[j].tokenAddress,
"Arbitrage not supported"
);
}
}
}
// Check outputs for duplicates and record balances before swap
uint256[] memory balancesBefore = new uint256[](outputs.length);
for (uint256 i = 0; i < outputs.length; i++) {
require(
outputs[i].amountMin <= outputs[i].amountQuote,
"Minimum greater than quote"
);
require(
outputs[i].amountMin > 0,
"Minimum output is zero"
);
for (uint256 j = 0; j < i; j++) {
require(
outputs[i].tokenAddress != outputs[j].tokenAddress,
"Duplicate destination tokens"
);
}
balancesBefore[i] = _universalBalance(outputs[i].tokenAddress);
}
// Delegate the execution of the path to the specified Odos Executor
IOdosExecutor(executor).executePath{value: msg.value}(pathDefinition, amountsIn, msg.sender);
int256[] memory slippage = new int256[](outputs.length);
{
amountsOut = new uint256[](outputs.length);
for (uint256 i = 0; i < outputs.length; i++) {
// Record the destination token balance before the path is executed
amountsOut[i] = _universalBalance(outputs[i].tokenAddress) - balancesBefore[i];
if (referralInfo.fee > 0) {
require(referralInfo.feeRecipient != address(0), "Null fee recipient");
require(referralInfo.fee <= FEE_DENOM / 50, "Fee too high");
if (referralInfo.feeRecipient != address(this)) {
_universalTransfer(
outputs[i].tokenAddress,
referralInfo.feeRecipient,
amountsOut[i] * referralInfo.fee * 8 / (FEE_DENOM * 10)
);
}
amountsOut[i] = amountsOut[i] * (FEE_DENOM - referralInfo.fee) / FEE_DENOM;
}
slippage[i] = int256(amountsOut[i]) - int256(outputs[i].amountQuote);
if (slippage[i] > 0) {
amountsOut[i] = outputs[i].amountQuote;
}
require(amountsOut[i] >= outputs[i].amountMin, "Slippage Limit Exceeded");
_universalTransfer(
outputs[i].tokenAddress,
outputs[i].receiver == address(0) ? msg.sender : outputs[i].receiver,
amountsOut[i]
);
}
}
address[] memory tokensOut = new address[](outputs.length);
for (uint256 i = 0; i < outputs.length; i++) {
tokensOut[i] = outputs[i].tokenAddress;
}
emit SwapMulti(
msg.sender,
amountsIn,
tokensIn,
amountsOut,
tokensOut,
slippage,
referralInfo.code,
referralInfo.fee,
referralInfo.feeRecipient
);
}
/// @notice Changes the liquidator address
/// @param account The address of new liquidator
function changeLiquidatorAddress(address account)
external
onlyOwner
{
liquidatorAddress = account;
emit LiquidatorAddressChanged(account);
}
/// @notice Push new addresses to the cached address list for when storage is cheaper than calldata
/// @param addresses list of addresses to be added to the cached address list
function writeAddressList(
address[] calldata addresses
)
external
onlyOwner
{
for (uint256 i = 0; i < addresses.length; i++) {
addressList.push(addresses[i]);
}
}
/// @notice Allows the owner to transfer funds held by the router contract
/// @param tokens List of token address to be transferred
/// @param amounts List of amounts of each token to be transferred
/// @param dest Address to which the funds should be sent
function transferRouterFunds(
address[] calldata tokens,
uint256[] calldata amounts,
address dest
)
external
{
require(msg.sender == liquidatorAddress || msg.sender == owner(), "Address not allowed");
require(tokens.length == amounts.length, "Invalid funds transfer");
for (uint256 i = 0; i < tokens.length; i++) {
_universalTransfer(
tokens[i],
dest,
amounts[i] == 0 ? _universalBalance(tokens[i]) : amounts[i]
);
}
}
/// @notice Directly swap funds held in router
/// @param inputs list of input token structs for the path being executed
/// @param outputs list of output token structs for the path being executed
/// @param pathDefinition Encoded path definition for executor
/// @param executor Address of contract that will execute the path
function swapRouterFunds(
inputTokenInfo[] memory inputs,
outputTokenInfo[] memory outputs,
bytes calldata pathDefinition,
address executor
)
external
returns (uint256[] memory amountsOut)
{
require(msg.sender == liquidatorAddress || msg.sender == owner(), "Address not allowed");
uint256[] memory amountsIn = new uint256[](inputs.length);
address[] memory tokensIn = new address[](inputs.length);
for (uint256 i = 0; i < inputs.length; i++) {
tokensIn[i] = inputs[i].tokenAddress;
amountsIn[i] = inputs[i].amountIn == 0 ?
_universalBalance(tokensIn[i]) : inputs[i].amountIn;
_universalTransfer(
tokensIn[i],
inputs[i].receiver,
amountsIn[i]
);
}
// Check outputs for duplicates and record balances before swap
uint256[] memory balancesBefore = new uint256[](outputs.length);
address[] memory tokensOut = new address[](outputs.length);
for (uint256 i = 0; i < outputs.length; i++) {
tokensOut[i] = outputs[i].tokenAddress;
balancesBefore[i] = _universalBalance(tokensOut[i]);
}
// Delegate the execution of the path to the specified Odos Executor
IOdosExecutor(executor).executePath{value: 0}(pathDefinition, amountsIn, msg.sender);
amountsOut = new uint256[](outputs.length);
for (uint256 i = 0; i < outputs.length; i++) {
// Record the destination token balance before the path is executed
amountsOut[i] = _universalBalance(tokensOut[i]) - balancesBefore[i];
require(amountsOut[i] >= outputs[i].amountMin, "Slippage Limit Exceeded");
_universalTransfer(
outputs[i].tokenAddress,
outputs[i].receiver == address(0) ? msg.sender : outputs[i].receiver,
amountsOut[i]
);
}
emit SwapMulti(
msg.sender,
amountsIn,
tokensIn,
amountsOut,
tokensOut,
new int256[](outputs.length),
0,
0,
address(0)
);
}
/// @notice helper function to get balance of ERC20 or native coin for this contract
/// @param token address of the token to check, null for native coin
/// @return balance of specified coin or token
function _universalBalance(address token) private view returns(uint256) {
if (token == _ETH) {
return address(this).balance;
} else {
return IERC20(token).balanceOf(address(this));
}
}
/// @notice helper function to transfer ERC20 or native coin
/// @param token address of the token being transferred, null for native coin
/// @param to address to transfer to
/// @param amount to transfer
function _universalTransfer(address token, address to, uint256 amount) private {
if (token == _ETH) {
(bool success,) = payable(to).call{value: amount}("");
require(success, "ETH transfer failed");
} else {
IERC20(token).safeTransfer(to, amount);
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"LiquidatorAddressChanged","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":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"inputAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"inputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"address","name":"outputToken","type":"address"},{"indexed":false,"internalType":"int256","name":"slippage","type":"int256"},{"indexed":false,"internalType":"uint64","name":"referralCode","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"referralFee","type":"uint64"},{"indexed":false,"internalType":"address","name":"referralFeeRecipient","type":"address"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"amountsIn","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"tokensIn","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amountsOut","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"tokensOut","type":"address[]"},{"indexed":false,"internalType":"int256[]","name":"slippage","type":"int256[]"},{"indexed":false,"internalType":"uint64","name":"referralCode","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"referralFee","type":"uint64"},{"indexed":false,"internalType":"address","name":"referralFeeRecipient","type":"address"}],"name":"SwapMulti","type":"event"},{"inputs":[],"name":"FEE_DENOM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"addressList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"changeLiquidatorAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidatorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"inputReceiver","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"outputQuote","type":"uint256"},{"internalType":"uint256","name":"outputMin","type":"uint256"},{"internalType":"address","name":"outputReceiver","type":"address"}],"internalType":"struct IOdosRouterV3.swapTokenInfo","name":"tokenInfo","type":"tuple"},{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"executor","type":"address"},{"components":[{"internalType":"uint64","name":"code","type":"uint64"},{"internalType":"uint64","name":"fee","type":"uint64"},{"internalType":"address","name":"feeRecipient","type":"address"}],"internalType":"struct IOdosRouterV3.swapReferralInfo","name":"referralInfo","type":"tuple"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"swapCompact","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"internalType":"struct IOdosRouterV3.inputTokenInfo[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amountQuote","type":"uint256"},{"internalType":"uint256","name":"amountMin","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"internalType":"struct IOdosRouterV3.outputTokenInfo[]","name":"outputs","type":"tuple[]"},{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"executor","type":"address"},{"components":[{"internalType":"uint64","name":"code","type":"uint64"},{"internalType":"uint64","name":"fee","type":"uint64"},{"internalType":"address","name":"feeRecipient","type":"address"}],"internalType":"struct IOdosRouterV3.swapReferralInfo","name":"referralInfo","type":"tuple"}],"name":"swapMulti","outputs":[{"internalType":"uint256[]","name":"amountsOut","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"swapMultiCompact","outputs":[{"internalType":"uint256[]","name":"amountsOut","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IOdosRouterV3.permit2Info","name":"permit2","type":"tuple"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"internalType":"struct IOdosRouterV3.inputTokenInfo[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amountQuote","type":"uint256"},{"internalType":"uint256","name":"amountMin","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"internalType":"struct IOdosRouterV3.outputTokenInfo[]","name":"outputs","type":"tuple[]"},{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"executor","type":"address"},{"components":[{"internalType":"uint64","name":"code","type":"uint64"},{"internalType":"uint64","name":"fee","type":"uint64"},{"internalType":"address","name":"feeRecipient","type":"address"}],"internalType":"struct IOdosRouterV3.swapReferralInfo","name":"referralInfo","type":"tuple"}],"name":"swapMultiPermit2","outputs":[{"internalType":"uint256[]","name":"amountsOut","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IOdosRouterV3.permit2Info","name":"permit2","type":"tuple"},{"components":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"inputReceiver","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"outputQuote","type":"uint256"},{"internalType":"uint256","name":"outputMin","type":"uint256"},{"internalType":"address","name":"outputReceiver","type":"address"}],"internalType":"struct IOdosRouterV3.swapTokenInfo","name":"tokenInfo","type":"tuple"},{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"executor","type":"address"},{"components":[{"internalType":"uint64","name":"code","type":"uint64"},{"internalType":"uint64","name":"fee","type":"uint64"},{"internalType":"address","name":"feeRecipient","type":"address"}],"internalType":"struct IOdosRouterV3.swapReferralInfo","name":"referralInfo","type":"tuple"}],"name":"swapPermit2","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"internalType":"struct IOdosRouterV3.inputTokenInfo[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amountQuote","type":"uint256"},{"internalType":"uint256","name":"amountMin","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"internalType":"struct IOdosRouterV3.outputTokenInfo[]","name":"outputs","type":"tuple[]"},{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"executor","type":"address"}],"name":"swapRouterFunds","outputs":[{"internalType":"uint256[]","name":"amountsOut","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"dest","type":"address"}],"name":"transferRouterFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"name":"writeAddressList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60806040523480156200001157600080fd5b506200001d3362000023565b62000091565b600180546001600160a01b03191690556200003e8162000041565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b613ba880620000a16000396000f3fe60806040526004361061010d5760003560e01c806384a7f3dd11610095578063cab3473111610064578063cab3473114610291578063e30c3978146102b1578063e5dae17d146102cf578063f2fde38b146102ef578063fef828dc1461030f57600080fd5b806384a7f3dd1461022b5780638da5cb5b146102335780639828146914610251578063b810fb431461027157600080fd5b80634886c675116100dc5780634886c675146101a5578063715018a6146101c157806375c111f2146101d657806379ba50971461020e57806383bd37f91461022357600080fd5b8063108e3a7714610119578063174da6211461014257806330f80b4c146101645780633596f9a21461018557600080fd5b3661011457005b600080fd5b61012c6101273660046131a7565b610322565b60405161013991906132b8565b60405180910390f35b34801561014e57600080fd5b5061016261015d366004613316565b6107cb565b005b610177610172366004613433565b61093a565b604051908152602001610139565b34801561019157600080fd5b506101626101a03660046134a1565b610953565b3480156101b157600080fd5b50610177670de0b6b3a764000081565b3480156101cd57600080fd5b506101626109d8565b3480156101e257600080fd5b506003546101f6906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b34801561021a57600080fd5b506101626109ec565b610177610a66565b61012c610c5f565b34801561023f57600080fd5b506000546001600160a01b03166101f6565b34801561025d57600080fd5b5061012c61026c3660046134e2565b610ed5565b34801561027d57600080fd5b506101f661028c366004613575565b6114ea565b34801561029d57600080fd5b506101776102ac36600461358e565b611514565b3480156102bd57600080fd5b506001546001600160a01b03166101f6565b3480156102db57600080fd5b506101626102ea36600461362e565b6115e1565b3480156102fb57600080fd5b5061016261030a36600461362e565b611633565b61012c61031d366004613649565b6116a4565b606061034860405180606001604052806060815260200160008152602001600081525090565b6060600080341161035a578951610368565b60018a516103689190613702565b90506040518060600160405280826001600160401b0381111561038d5761038d612e19565b6040519080825280602002602001820160405280156103d257816020015b60408051808201909152600080825260208201528152602001906001900390816103ab5790505b5081526020018c6020015181526020018c604001518152509250806001600160401b0381111561040457610404612e19565b60405190808252806020026020018201604052801561044957816020015b60408051808201909152600080825260208201528152602001906001900390816104225790505b509150506000805b8a5181101561071a5760006001600160a01b03168b828151811061047757610477613715565b6020026020010151600001516001600160a01b0316036104ff578a81815181106104a3576104a3613715565b6020026020010151602001516000036104da57348b82815181106104c9576104c9613715565b602002602001015160200181815250505b8a81815181106104ec576104ec613715565b6020026020010151602001519150610708565b8a818151811061051157610511613715565b6020026020010151602001516000036105ce578a818151811061053657610536613715565b6020908102919091010151516040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab919061372b565b8b82815181106105bd576105bd613715565b602002602001015160200181815250505b600082156105e6576105e1600183613702565b6105e8565b815b90508b82815181106105fc576105fc613715565b6020026020010151600001518560000151828151811061061e5761061e613715565b60209081029190910101516001600160a01b0390911690528b518c908390811061064a5761064a613715565b6020026020010151602001518560000151828151811061066c5761066c613715565b602002602001015160200181815250508b828151811061068e5761068e613715565b6020026020010151604001518482815181106106ac576106ac613715565b60209081029190910101516001600160a01b0390911690528b518c90839081106106d8576106d8613715565b6020026020010151602001518482815181106106f6576106f6613715565b60200260200101516020018181525050505b8061071281613744565b915050610451565b508034146107435760405162461bcd60e51b815260040161073a9061375d565b60405180910390fd5b50895160608b015160405163edd9444b60e01b81526001600160a01b039092169163edd9444b9161077d9186918691339190600401613823565b600060405180830381600087803b15801561079757600080fd5b505af11580156107ab573d6000803e3d6000fd5b505050506107bd8989898989896116b4565b9a9950505050505050505050565b6003546001600160a01b03163314806107ee57506000546001600160a01b031633145b6108305760405162461bcd60e51b81526020600482015260136024820152721059191c995cdcc81b9bdd08185b1b1bddd959606a1b604482015260640161073a565b8382146108785760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210333ab73239903a3930b739b332b960511b604482015260640161073a565b60005b848110156109325761092086868381811061089857610898613715565b90506020020160208101906108ad919061362e565b838686858181106108c0576108c0613715565b905060200201356000146108ec578686858181106108e0576108e0613715565b905060200201356121fa565b61091b89898681811061090157610901613715565b9050602002016020810190610916919061362e565b612170565b6121fa565b8061092a81613744565b91505061087b565b505050505050565b600061094986868686866122bb565b9695505050505050565b61095b6123d8565b60005b818110156109d357600283838381811061097a5761097a613715565b905060200201602081019061098f919061362e565b81546001810183556000928352602090922090910180546001600160a01b0319166001600160a01b03909216919091179055806109cb81613744565b91505061095e565b505050565b6109e06123d8565b6109ea6000612432565b565b60015433906001600160a01b03168114610a5a5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161073a565b610a6381612432565b50565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260408051606081018252600080825260208201819052918101919091526000366000610b36565b600080823560f01c808015610b0d5760018114610b18577f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acc8201549350600285019250610b2f565b600285019250610b2f565b6001600160a01b03853560501c1693506016850192505b5050915091565b60006004610b4381610ac5565b91509150818752610b5381610ac5565b606089018290529092506001810191503560f81c8015610b82578135600882602003021c602089015280820191505b50803560f81c6001820191508135600882602003021c8060808a01528183019250823560e81c915062ffffff8262ffffff0382020460a08a01525050600381019050610bcd81610ac5565b91509450610bda81610ac5565b909250905081610be8578491505b816040880152610bf781610ac5565b60c089810192909252803590911c8752600881013560f81c925060090190508115610c3757803560c01c6020870152600881013560601c6040870152601c015b6001810193503560f81c6020029150610c55905085838386886122bb565b9550505050505090565b606060008180600660043560f890811c90600535901c816001600160401b03811115610c8d57610c8d612e19565b604051908082528060200260200182016040528015610cd857816020015b6040805160608101825260008082526020808301829052928201528252600019909201910181610cab5790505b509450806001600160401b03811115610cf357610cf3612e19565b604051908082528060200260200182016040528015610d4557816020015b604080516080810182526000808252602080830182905292820181905260608201528252600019909201910181610d115790505b509350610d5183610ac5565b9096506003810193503560e81c600080805b85811015610dd0576020808202018901519150610d7f87610ac5565b8184526001810198509093503560f81c8015610daa578735600882602003021c602084015280880197505b50610db487610ac5565b9750925082610dc1578992505b60408201839052600101610d63565b5060005b84811015610e47576020808202018801519150610df087610ac5565b97509250828252863560f81c6001880197508735600882602003021c806020850152818901985062ffffff8662ffffff0382020460408501525050610e3487610ac5565b6060840182905297509250600101610dd4565b505050505050610e70604080516060810182526000808252602082018190529181019190915290565b813560c01c8152600982019136906000906008013560f81c8015610eac57843560c01c6020850152600885013560601c6040850152601c909401935b505050600182016020833560f81c02610ec9868684848b8861244b565b97505050505050505090565b6003546060906001600160a01b0316331480610efb57506000546001600160a01b031633145b610f3d5760405162461bcd60e51b81526020600482015260136024820152721059191c995cdcc81b9bdd08185b1b1bddd959606a1b604482015260640161073a565b600086516001600160401b03811115610f5857610f58612e19565b604051908082528060200260200182016040528015610f81578160200160208202803683370190505b509050600087516001600160401b03811115610f9f57610f9f612e19565b604051908082528060200260200182016040528015610fc8578160200160208202803683370190505b50905060005b885181101561111b57888181518110610fe957610fe9613715565b60200260200101516000015182828151811061100757611007613715565b60200260200101906001600160a01b031690816001600160a01b03168152505088818151811061103957611039613715565b60200260200101516020015160001461106f5788818151811061105e5761105e613715565b602002602001015160200151611091565b61109182828151811061108457611084613715565b6020026020010151612170565b8382815181106110a3576110a3613715565b6020026020010181815250506111098282815181106110c4576110c4613715565b60200260200101518a83815181106110de576110de613715565b6020026020010151604001518584815181106110fc576110fc613715565b60200260200101516121fa565b8061111381613744565b915050610fce565b50600087516001600160401b0381111561113757611137612e19565b604051908082528060200260200182016040528015611160578160200160208202803683370190505b509050600088516001600160401b0381111561117e5761117e612e19565b6040519080825280602002602001820160405280156111a7578160200160208202803683370190505b50905060005b895181101561124a578981815181106111c8576111c8613715565b6020026020010151600001518282815181106111e6576111e6613715565b60200260200101906001600160a01b031690816001600160a01b03168152505061121b82828151811061108457611084613715565b83828151811061122d5761122d613715565b60209081029190910101528061124281613744565b9150506111ad565b5060405163cb70e27360e01b81526001600160a01b0387169063cb70e27390600090611280908c908c908a9033906004016138d9565b6000604051808303818588803b15801561129957600080fd5b505af11580156112ad573d6000803e3d6000fd5b505050505088516001600160401b038111156112cb576112cb612e19565b6040519080825280602002602001820160405280156112f4578160200160208202803683370190505b50945060005b89518110156114515782818151811061131557611315613715565b602002602001015161133283838151811061108457611084613715565b61133c9190613702565b86828151811061134e5761134e613715565b60200260200101818152505089818151811061136c5761136c613715565b60200260200101516040015186828151811061138a5761138a613715565b602002602001015110156113b05760405162461bcd60e51b815260040161073a90613931565b61143f8a82815181106113c5576113c5613715565b60200260200101516000015160006001600160a01b03168c84815181106113ee576113ee613715565b6020026020010151606001516001600160a01b03161461142b578b838151811061141a5761141a613715565b60200260200101516060015161142d565b335b8884815181106110fc576110fc613715565b8061144981613744565b9150506112fa565b507f2c96555a96d94780f3a97aeb724514e80e331842f3143742d85da5aa68df9d3033858588858e516001600160401b0381111561149157611491612e19565b6040519080825280602002602001820160405280156114ba578160200160208202803683370190505b5060008060006040516114d5999897969594939291906139a1565b60405180910390a15050505095945050505050565b600281815481106114fa57600080fd5b6000918252602090912001546001600160a01b0316905081565b85516040805160a08101825287516001600160a01b0390811660608084019182526020808c0180516080870152928552808d015181860152858d015185870152855180870187528c870151851681529251908301528b0151935163187945bd60e11b815260009592909216936330f28b7a93611597939092913391600401613a48565b600060405180830381600087803b1580156115b157600080fd5b505af11580156115c5573d6000803e3d6000fd5b505050506115d68686868686612691565b979650505050505050565b6115e96123d8565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f1535fa8f7275b71050af30bf7f74391b45be7ba2b545fd28279dafe9b50f642490600090a250565b61163b6123d8565b600180546001600160a01b0383166001600160a01b0319909116811790915561166c6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60606115d687878787878761244b565b6060600087516001600160401b038111156116d1576116d1612e19565b6040519080825280602002602001820160405280156116fa578160200160208202803683370190505b509050600088516001600160401b0381111561171857611718612e19565b604051908082528060200260200182016040528015611741578160200160208202803683370190505b50905060005b895181101561195b5789818151811061176257611762613715565b60200260200101516020015183828151811061178057611780613715565b60200260200101818152505089818151811061179e5761179e613715565b6020026020010151600001518282815181106117bc576117bc613715565b60200260200101906001600160a01b031690816001600160a01b03168152505060005b81811015611894578a81815181106117f9576117f9613715565b6020026020010151600001516001600160a01b03168b838151811061182057611820613715565b6020026020010151600001516001600160a01b0316036118825760405162461bcd60e51b815260206004820152601760248201527f4475706c696361746520736f7572636520746f6b656e73000000000000000000604482015260640161073a565b8061188c81613744565b9150506117df565b5060005b8951811015611948578981815181106118b3576118b3613715565b6020026020010151600001516001600160a01b03168b83815181106118da576118da613715565b6020026020010151600001516001600160a01b0316036119365760405162461bcd60e51b8152602060048201526017602482015276105c989a5d1c9859d9481b9bdd081cdd5c1c1bdc9d1959604a1b604482015260640161073a565b8061194081613744565b915050611898565b508061195381613744565b915050611747565b50600088516001600160401b0381111561197757611977612e19565b6040519080825280602002602001820160405280156119a0578160200160208202803683370190505b50905060005b8951811015611bad578981815181106119c1576119c1613715565b6020026020010151602001518a82815181106119df576119df613715565b6020026020010151604001511115611a395760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d2067726561746572207468616e2071756f7465000000000000604482015260640161073a565b60008a8281518110611a4d57611a4d613715565b60200260200101516040015111611a9f5760405162461bcd60e51b81526020600482015260166024820152754d696e696d756d206f7574707574206973207a65726f60501b604482015260640161073a565b60005b81811015611b57578a8181518110611abc57611abc613715565b6020026020010151600001516001600160a01b03168b8381518110611ae357611ae3613715565b6020026020010151600001516001600160a01b031603611b455760405162461bcd60e51b815260206004820152601c60248201527f4475706c69636174652064657374696e6174696f6e20746f6b656e7300000000604482015260640161073a565b80611b4f81613744565b915050611aa2565b50611b7e8a8281518110611b6d57611b6d613715565b602002602001015160000151612170565b828281518110611b9057611b90613715565b602090810291909101015280611ba581613744565b9150506119a6565b5060405163cb70e27360e01b81526001600160a01b0387169063cb70e273903490611be2908c908c90899033906004016138d9565b6000604051808303818588803b158015611bfb57600080fd5b505af1158015611c0f573d6000803e3d6000fd5b5050505050600089516001600160401b03811115611c2f57611c2f612e19565b604051908082528060200260200182016040528015611c58578160200160208202803683370190505b50905089516001600160401b03811115611c7457611c74612e19565b604051908082528060200260200182016040528015611c9d578160200160208202803683370190505b50945060005b8a5181101561206457828181518110611cbe57611cbe613715565b6020026020010151611cdb8c8381518110611b6d57611b6d613715565b611ce59190613702565b868281518110611cf757611cf7613715565b602002602001018181525050600087602001516001600160401b03161115611ed35760408701516001600160a01b0316611d685760405162461bcd60e51b8152602060048201526012602482015271139d5b1b08199959481c9958da5c1a595b9d60721b604482015260640161073a565b611d7b6032670de0b6b3a7640000613ac1565b87602001516001600160401b03161115611dc65760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b604482015260640161073a565b60408701516001600160a01b03163014611e5c57611e5c8b8281518110611def57611def613715565b6020026020010151600001518860400151670de0b6b3a7640000600a611e159190613ae3565b8a602001516001600160401b03168a8681518110611e3557611e35613715565b6020026020010151611e479190613ae3565b611e52906008613ae3565b61091b9190613ac1565b670de0b6b3a764000087602001516001600160401b0316670de0b6b3a7640000611e869190613702565b878381518110611e9857611e98613715565b6020026020010151611eaa9190613ae3565b611eb49190613ac1565b868281518110611ec657611ec6613715565b6020026020010181815250505b8a8181518110611ee557611ee5613715565b602002602001015160200151868281518110611f0357611f03613715565b6020026020010151611f159190613afa565b828281518110611f2757611f27613715565b6020026020010181815250506000828281518110611f4757611f47613715565b60200260200101511315611f92578a8181518110611f6757611f67613715565b602002602001015160200151868281518110611f8557611f85613715565b6020026020010181815250505b8a8181518110611fa457611fa4613715565b602002602001015160400151868281518110611fc257611fc2613715565b60200260200101511015611fe85760405162461bcd60e51b815260040161073a90613931565b6120528b8281518110611ffd57611ffd613715565b60200260200101516000015160006001600160a01b03168d848151811061202657612026613715565b6020026020010151606001516001600160a01b03161461142b578c838151811061141a5761141a613715565b8061205c81613744565b915050611ca3565b5060008a516001600160401b0381111561208057612080612e19565b6040519080825280602002602001820160405280156120a9578160200160208202803683370190505b50905060005b8b51811015612112578b81815181106120ca576120ca613715565b6020026020010151600001518282815181106120e8576120e8613715565b6001600160a01b03909216602092830291909101909101528061210a81613744565b9150506120af565b50865160208801516040808a015190517f2c96555a96d94780f3a97aeb724514e80e331842f3143742d85da5aa68df9d30936121599333938b938b938e938a938c936139a1565b60405180910390a150505050509695505050505050565b60006001600160a01b038216612187575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156121cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ef919061372b565b92915050565b919050565b6001600160a01b0383166122a7576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612255576040519150601f19603f3d011682016040523d82523d6000602084013e61225a565b606091505b50509050806122a15760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640161073a565b50505050565b6109d36001600160a01b0384168383612adc565b84516000906001600160a01b031661230c5785602001516000036122e4573460208701526123cb565b856020015134146123075760405162461bcd60e51b815260040161073a9061375d565b6123cb565b341561232a5760405162461bcd60e51b815260040161073a9061375d565b85602001516000036123a75785516040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a1919061372b565b60208701525b6040860151602087015187516123cb926001600160a01b0390911691339190612b3f565b6109498686868686612691565b6000546001600160a01b031633146109ea5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161073a565b600180546001600160a01b0319169055610a6381612b77565b60606000805b88518110156126575760006001600160a01b031689828151811061247757612477613715565b6020026020010151600001516001600160a01b0316036124ff578881815181106124a3576124a3613715565b6020026020010151602001516000036124da57348982815181106124c9576124c9613715565b602002602001015160200181815250505b8881815181106124ec576124ec613715565b6020026020010151602001519150612645565b88818151811061251157612511613715565b6020026020010151602001516000036125ce5788818151811061253657612536613715565b6020908102919091010151516040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ab919061372b565b8982815181106125bd576125bd613715565b602002602001015160200181815250505b612645338a83815181106125e4576125e4613715565b6020026020010151604001518b848151811061260257612602613715565b6020026020010151602001518c858151811061262057612620613715565b6020026020010151600001516001600160a01b0316612b3f909392919063ffffffff16565b8061264f81613744565b915050612451565b508034146126775760405162461bcd60e51b815260040161073a9061375d565b6126858888888888886116b4565b98975050505050505050565b600085608001518660a0015111156126eb5760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d2067726561746572207468616e2071756f7465000000000000604482015260640161073a565b60008660a00151116127385760405162461bcd60e51b81526020600482015260166024820152754d696e696d756d206f7574707574206973207a65726f60501b604482015260640161073a565b85606001516001600160a01b031686600001516001600160a01b03160361279b5760405162461bcd60e51b8152602060048201526017602482015276105c989a5d1c9859d9481b9bdd081cdd5c1c1bdc9d1959604a1b604482015260640161073a565b60006127aa8760600151612170565b60408051600180825281830190925291925060009190602080830190803683370190505090508760200151816000815181106127e8576127e8613715565b602090810291909101015260405163cb70e27360e01b81526001600160a01b0386169063cb70e273903490612827908b908b90879033906004016138d9565b6000604051808303818588803b15801561284057600080fd5b505af1158015612854573d6000803e3d6000fd5b5050505050816128678960600151612170565b6128719190613702565b60208501519093506001600160401b0316156129c35760408401516001600160a01b03166128d65760405162461bcd60e51b8152602060048201526012602482015271139d5b1b08199959481c9958da5c1a595b9d60721b604482015260640161073a565b6128e96032670de0b6b3a7640000613ac1565b84602001516001600160401b031611156129345760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b604482015260640161073a565b60408401516001600160a01b031630146129825761298288606001518560400151670de0b6b3a7640000600a61296a9190613ae3565b6020880151611e47906001600160401b031688613ae3565b670de0b6b3a764000084602001516001600160401b0316670de0b6b3a76400006129ac9190613702565b6129b69085613ae3565b6129c09190613ac1565b92505b60008860800151846129d59190613afa565b905060008113156129e857886080015193505b8860a00151841015612a0c5760405162461bcd60e51b815260040161073a90613931565b606089015160c08a0151612a3b91906001600160a01b031615612a33578a60c00151612a35565b335b866121fa565b6020808a01518a516060808d015189518a8601516040808d01518151338152988901979097526001600160a01b03958616908801529286018a9052908316608086015260a085018690526001600160401b0390811660c08601521660e0840152166101008201527f69db20ca9e32403e6c56e5193b3e3b2827ae5c430ccfdea392ba950d2d1ab2bc906101200160405180910390a150505095945050505050565b6040516001600160a01b0383166024820152604481018290526109d390849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612bc7565b6040516001600160a01b03808516602483015283166044820152606481018290526122a19085906323b872dd60e01b90608401612b08565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000612c1c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612c999092919063ffffffff16565b8051909150156109d35780806020019051810190612c3a9190613b21565b6109d35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161073a565b6060612ca88484600085612cb0565b949350505050565b606082471015612d115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161073a565b600080866001600160a01b03168587604051612d2d9190613b43565b60006040518083038185875af1925050503d8060008114612d6a576040519150601f19603f3d011682016040523d82523d6000602084013e612d6f565b606091505b50915091506115d68783838760608315612dea578251600003612de3576001600160a01b0385163b612de35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161073a565b5081612ca8565b612ca88383815115612dff5781518083602001fd5b8060405162461bcd60e51b815260040161073a9190613b5f565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715612e5157612e51612e19565b60405290565b604051606081016001600160401b0381118282101715612e5157612e51612e19565b604051601f8201601f191681016001600160401b0381118282101715612ea157612ea1612e19565b604052919050565b80356001600160a01b03811681146121f557600080fd5b600060808284031215612ed257600080fd5b612eda612e2f565b9050612ee582612ea9565b8152602080830135818301526040830135604083015260608301356001600160401b0380821115612f1557600080fd5b818501915085601f830112612f2957600080fd5b813581811115612f3b57612f3b612e19565b612f4d601f8201601f19168501612e79565b91508082528684828501011115612f6357600080fd5b808484018584013760008482840101525080606085015250505092915050565b60006001600160401b03821115612f9c57612f9c612e19565b5060051b60200190565b600082601f830112612fb757600080fd5b81356020612fcc612fc783612f83565b612e79565b82815260609283028501820192828201919087851115612feb57600080fd5b8387015b858110156130405781818a0312156130075760008081fd5b61300f612e57565b61301882612ea9565b81528582013586820152604061302f818401612ea9565b908201528452928401928101612fef565b5090979650505050505050565b600082601f83011261305e57600080fd5b8135602061306e612fc783612f83565b82815260079290921b8401810191818101908684111561308d57600080fd5b8286015b848110156130ee57608081890312156130aa5760008081fd5b6130b2612e2f565b6130bb82612ea9565b815281850135858201526040808301359082015260606130dc818401612ea9565b90820152835291830191608001613091565b509695505050505050565b60008083601f84011261310b57600080fd5b5081356001600160401b0381111561312257600080fd5b60208301915083602082850101111561313a57600080fd5b9250929050565b80356001600160401b03811681146121f557600080fd5b60006060828403121561316a57600080fd5b613172612e57565b905061317d82613141565b815261318b60208301613141565b602082015261319c60408301612ea9565b604082015292915050565b6000806000806000806000610100888a0312156131c357600080fd5b87356001600160401b03808211156131da57600080fd5b6131e68b838c01612ec0565b985060208a01359150808211156131fc57600080fd5b6132088b838c01612fa6565b975060408a013591508082111561321e57600080fd5b61322a8b838c0161304d565b965060608a013591508082111561324057600080fd5b5061324d8a828b016130f9565b9095509350613260905060808901612ea9565b915061326f8960a08a01613158565b905092959891949750929550565b600081518084526020808501945080840160005b838110156132ad57815187529582019590820190600101613291565b509495945050505050565b6020815260006132cb602083018461327d565b9392505050565b60008083601f8401126132e457600080fd5b5081356001600160401b038111156132fb57600080fd5b6020830191508360208260051b850101111561313a57600080fd5b60008060008060006060868803121561332e57600080fd5b85356001600160401b038082111561334557600080fd5b61335189838a016132d2565b9097509550602088013591508082111561336a57600080fd5b50613377888289016132d2565b909450925061338a905060408701612ea9565b90509295509295909350565b600060e082840312156133a857600080fd5b60405160e081018181106001600160401b03821117156133ca576133ca612e19565b6040529050806133d983612ea9565b8152602083013560208201526133f160408401612ea9565b604082015261340260608401612ea9565b60608201526080830135608082015260a083013560a082015261342760c08401612ea9565b60c08201525092915050565b6000806000806000610180868803121561344c57600080fd5b6134568787613396565b945060e08601356001600160401b0381111561347157600080fd5b61347d888289016130f9565b909550935061349190506101008701612ea9565b915061338a876101208801613158565b600080602083850312156134b457600080fd5b82356001600160401b038111156134ca57600080fd5b6134d6858286016132d2565b90969095509350505050565b6000806000806000608086880312156134fa57600080fd5b85356001600160401b038082111561351157600080fd5b61351d89838a01612fa6565b9650602088013591508082111561353357600080fd5b61353f89838a0161304d565b9550604088013591508082111561355557600080fd5b50613562888289016130f9565b909450925061338a905060608701612ea9565b60006020828403121561358757600080fd5b5035919050565b6000806000806000806101a087890312156135a857600080fd5b86356001600160401b03808211156135bf57600080fd5b6135cb8a838b01612ec0565b97506135da8a60208b01613396565b96506101008901359150808211156135f157600080fd5b506135fe89828a016130f9565b909550935061361290506101208801612ea9565b9150613622886101408901613158565b90509295509295509295565b60006020828403121561364057600080fd5b6132cb82612ea9565b60008060008060008060e0878903121561366257600080fd5b86356001600160401b038082111561367957600080fd5b6136858a838b01612fa6565b9750602089013591508082111561369b57600080fd5b6136a78a838b0161304d565b965060408901359150808211156136bd57600080fd5b506136ca89828a016130f9565b90955093506136dd905060608801612ea9565b91506136228860808901613158565b634e487b7160e01b600052601160045260246000fd5b818103818111156121ef576121ef6136ec565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561373d57600080fd5b5051919050565b600060018201613756576137566136ec565b5060010190565b6020808252600f908201526e57726f6e67206d73672e76616c756560881b604082015260600190565b600081518084526020808501945080840160005b838110156132ad576137c087835180516001600160a01b03168252602090810151910152565b604096909601959082019060010161379a565b60005b838110156137ee5781810151838201526020016137d6565b50506000910152565b6000815180845261380f8160208601602086016137d3565b601f01601f19169290920160200192915050565b60808152600060e082018651606060808501528181518084526101008601915060209350838301925060005b818110156138885761387583855180516001600160a01b03168252602090810151910152565b928401926040929092019160010161384f565b50508289015160a0860152604089015160c0860152848103838601526138ae8189613786565b925050506138c760408401866001600160a01b03169052565b82810360608401526115d681856137f7565b60608152836060820152838560808301376000608085830101526000601f19601f86011682016080838203016020840152613917608082018661327d565b91505060018060a01b038316604083015295945050505050565b60208082526017908201527f536c697070616765204c696d6974204578636565646564000000000000000000604082015260600190565b600081518084526020808501945080840160005b838110156132ad5781516001600160a01b03168752958201959082019060010161397c565b6001600160a01b038a81168252610120602083018190526000916139c78483018d61327d565b915083820360408501526139db828c613968565b915083820360608501526139ef828b61327d565b91508382036080850152613a03828a613968565b915083820360a0850152613a17828961327d565b6001600160401b0397881660c08601529590961660e084015250509216610100909201919091529695505050505050565b6000610100613a6b83885180516001600160a01b03168252602090810151910152565b6020870151604084015260408701516060840152613a9f608084018780516001600160a01b03168252602090810151910152565b6001600160a01b03851660c084015260e083018190526115d6818401856137f7565b600082613ade57634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176121ef576121ef6136ec565b8181036000831280158383131683831282161715613b1a57613b1a6136ec565b5092915050565b600060208284031215613b3357600080fd5b815180151581146132cb57600080fd5b60008251613b558184602087016137d3565b9190910192915050565b6020815260006132cb60208301846137f756fea26469706673582212208403cc00b2f60ffd39bea8f9569830cb900e249332880f3e2bdf46c037bc0a5764736f6c63430008130033
Deployed Bytecode
0x60806040526004361061010d5760003560e01c806384a7f3dd11610095578063cab3473111610064578063cab3473114610291578063e30c3978146102b1578063e5dae17d146102cf578063f2fde38b146102ef578063fef828dc1461030f57600080fd5b806384a7f3dd1461022b5780638da5cb5b146102335780639828146914610251578063b810fb431461027157600080fd5b80634886c675116100dc5780634886c675146101a5578063715018a6146101c157806375c111f2146101d657806379ba50971461020e57806383bd37f91461022357600080fd5b8063108e3a7714610119578063174da6211461014257806330f80b4c146101645780633596f9a21461018557600080fd5b3661011457005b600080fd5b61012c6101273660046131a7565b610322565b60405161013991906132b8565b60405180910390f35b34801561014e57600080fd5b5061016261015d366004613316565b6107cb565b005b610177610172366004613433565b61093a565b604051908152602001610139565b34801561019157600080fd5b506101626101a03660046134a1565b610953565b3480156101b157600080fd5b50610177670de0b6b3a764000081565b3480156101cd57600080fd5b506101626109d8565b3480156101e257600080fd5b506003546101f6906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b34801561021a57600080fd5b506101626109ec565b610177610a66565b61012c610c5f565b34801561023f57600080fd5b506000546001600160a01b03166101f6565b34801561025d57600080fd5b5061012c61026c3660046134e2565b610ed5565b34801561027d57600080fd5b506101f661028c366004613575565b6114ea565b34801561029d57600080fd5b506101776102ac36600461358e565b611514565b3480156102bd57600080fd5b506001546001600160a01b03166101f6565b3480156102db57600080fd5b506101626102ea36600461362e565b6115e1565b3480156102fb57600080fd5b5061016261030a36600461362e565b611633565b61012c61031d366004613649565b6116a4565b606061034860405180606001604052806060815260200160008152602001600081525090565b6060600080341161035a578951610368565b60018a516103689190613702565b90506040518060600160405280826001600160401b0381111561038d5761038d612e19565b6040519080825280602002602001820160405280156103d257816020015b60408051808201909152600080825260208201528152602001906001900390816103ab5790505b5081526020018c6020015181526020018c604001518152509250806001600160401b0381111561040457610404612e19565b60405190808252806020026020018201604052801561044957816020015b60408051808201909152600080825260208201528152602001906001900390816104225790505b509150506000805b8a5181101561071a5760006001600160a01b03168b828151811061047757610477613715565b6020026020010151600001516001600160a01b0316036104ff578a81815181106104a3576104a3613715565b6020026020010151602001516000036104da57348b82815181106104c9576104c9613715565b602002602001015160200181815250505b8a81815181106104ec576104ec613715565b6020026020010151602001519150610708565b8a818151811061051157610511613715565b6020026020010151602001516000036105ce578a818151811061053657610536613715565b6020908102919091010151516040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab919061372b565b8b82815181106105bd576105bd613715565b602002602001015160200181815250505b600082156105e6576105e1600183613702565b6105e8565b815b90508b82815181106105fc576105fc613715565b6020026020010151600001518560000151828151811061061e5761061e613715565b60209081029190910101516001600160a01b0390911690528b518c908390811061064a5761064a613715565b6020026020010151602001518560000151828151811061066c5761066c613715565b602002602001015160200181815250508b828151811061068e5761068e613715565b6020026020010151604001518482815181106106ac576106ac613715565b60209081029190910101516001600160a01b0390911690528b518c90839081106106d8576106d8613715565b6020026020010151602001518482815181106106f6576106f6613715565b60200260200101516020018181525050505b8061071281613744565b915050610451565b508034146107435760405162461bcd60e51b815260040161073a9061375d565b60405180910390fd5b50895160608b015160405163edd9444b60e01b81526001600160a01b039092169163edd9444b9161077d9186918691339190600401613823565b600060405180830381600087803b15801561079757600080fd5b505af11580156107ab573d6000803e3d6000fd5b505050506107bd8989898989896116b4565b9a9950505050505050505050565b6003546001600160a01b03163314806107ee57506000546001600160a01b031633145b6108305760405162461bcd60e51b81526020600482015260136024820152721059191c995cdcc81b9bdd08185b1b1bddd959606a1b604482015260640161073a565b8382146108785760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210333ab73239903a3930b739b332b960511b604482015260640161073a565b60005b848110156109325761092086868381811061089857610898613715565b90506020020160208101906108ad919061362e565b838686858181106108c0576108c0613715565b905060200201356000146108ec578686858181106108e0576108e0613715565b905060200201356121fa565b61091b89898681811061090157610901613715565b9050602002016020810190610916919061362e565b612170565b6121fa565b8061092a81613744565b91505061087b565b505050505050565b600061094986868686866122bb565b9695505050505050565b61095b6123d8565b60005b818110156109d357600283838381811061097a5761097a613715565b905060200201602081019061098f919061362e565b81546001810183556000928352602090922090910180546001600160a01b0319166001600160a01b03909216919091179055806109cb81613744565b91505061095e565b505050565b6109e06123d8565b6109ea6000612432565b565b60015433906001600160a01b03168114610a5a5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161073a565b610a6381612432565b50565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260408051606081018252600080825260208201819052918101919091526000366000610b36565b600080823560f01c808015610b0d5760018114610b18577f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acc8201549350600285019250610b2f565b600285019250610b2f565b6001600160a01b03853560501c1693506016850192505b5050915091565b60006004610b4381610ac5565b91509150818752610b5381610ac5565b606089018290529092506001810191503560f81c8015610b82578135600882602003021c602089015280820191505b50803560f81c6001820191508135600882602003021c8060808a01528183019250823560e81c915062ffffff8262ffffff0382020460a08a01525050600381019050610bcd81610ac5565b91509450610bda81610ac5565b909250905081610be8578491505b816040880152610bf781610ac5565b60c089810192909252803590911c8752600881013560f81c925060090190508115610c3757803560c01c6020870152600881013560601c6040870152601c015b6001810193503560f81c6020029150610c55905085838386886122bb565b9550505050505090565b606060008180600660043560f890811c90600535901c816001600160401b03811115610c8d57610c8d612e19565b604051908082528060200260200182016040528015610cd857816020015b6040805160608101825260008082526020808301829052928201528252600019909201910181610cab5790505b509450806001600160401b03811115610cf357610cf3612e19565b604051908082528060200260200182016040528015610d4557816020015b604080516080810182526000808252602080830182905292820181905260608201528252600019909201910181610d115790505b509350610d5183610ac5565b9096506003810193503560e81c600080805b85811015610dd0576020808202018901519150610d7f87610ac5565b8184526001810198509093503560f81c8015610daa578735600882602003021c602084015280880197505b50610db487610ac5565b9750925082610dc1578992505b60408201839052600101610d63565b5060005b84811015610e47576020808202018801519150610df087610ac5565b97509250828252863560f81c6001880197508735600882602003021c806020850152818901985062ffffff8662ffffff0382020460408501525050610e3487610ac5565b6060840182905297509250600101610dd4565b505050505050610e70604080516060810182526000808252602082018190529181019190915290565b813560c01c8152600982019136906000906008013560f81c8015610eac57843560c01c6020850152600885013560601c6040850152601c909401935b505050600182016020833560f81c02610ec9868684848b8861244b565b97505050505050505090565b6003546060906001600160a01b0316331480610efb57506000546001600160a01b031633145b610f3d5760405162461bcd60e51b81526020600482015260136024820152721059191c995cdcc81b9bdd08185b1b1bddd959606a1b604482015260640161073a565b600086516001600160401b03811115610f5857610f58612e19565b604051908082528060200260200182016040528015610f81578160200160208202803683370190505b509050600087516001600160401b03811115610f9f57610f9f612e19565b604051908082528060200260200182016040528015610fc8578160200160208202803683370190505b50905060005b885181101561111b57888181518110610fe957610fe9613715565b60200260200101516000015182828151811061100757611007613715565b60200260200101906001600160a01b031690816001600160a01b03168152505088818151811061103957611039613715565b60200260200101516020015160001461106f5788818151811061105e5761105e613715565b602002602001015160200151611091565b61109182828151811061108457611084613715565b6020026020010151612170565b8382815181106110a3576110a3613715565b6020026020010181815250506111098282815181106110c4576110c4613715565b60200260200101518a83815181106110de576110de613715565b6020026020010151604001518584815181106110fc576110fc613715565b60200260200101516121fa565b8061111381613744565b915050610fce565b50600087516001600160401b0381111561113757611137612e19565b604051908082528060200260200182016040528015611160578160200160208202803683370190505b509050600088516001600160401b0381111561117e5761117e612e19565b6040519080825280602002602001820160405280156111a7578160200160208202803683370190505b50905060005b895181101561124a578981815181106111c8576111c8613715565b6020026020010151600001518282815181106111e6576111e6613715565b60200260200101906001600160a01b031690816001600160a01b03168152505061121b82828151811061108457611084613715565b83828151811061122d5761122d613715565b60209081029190910101528061124281613744565b9150506111ad565b5060405163cb70e27360e01b81526001600160a01b0387169063cb70e27390600090611280908c908c908a9033906004016138d9565b6000604051808303818588803b15801561129957600080fd5b505af11580156112ad573d6000803e3d6000fd5b505050505088516001600160401b038111156112cb576112cb612e19565b6040519080825280602002602001820160405280156112f4578160200160208202803683370190505b50945060005b89518110156114515782818151811061131557611315613715565b602002602001015161133283838151811061108457611084613715565b61133c9190613702565b86828151811061134e5761134e613715565b60200260200101818152505089818151811061136c5761136c613715565b60200260200101516040015186828151811061138a5761138a613715565b602002602001015110156113b05760405162461bcd60e51b815260040161073a90613931565b61143f8a82815181106113c5576113c5613715565b60200260200101516000015160006001600160a01b03168c84815181106113ee576113ee613715565b6020026020010151606001516001600160a01b03161461142b578b838151811061141a5761141a613715565b60200260200101516060015161142d565b335b8884815181106110fc576110fc613715565b8061144981613744565b9150506112fa565b507f2c96555a96d94780f3a97aeb724514e80e331842f3143742d85da5aa68df9d3033858588858e516001600160401b0381111561149157611491612e19565b6040519080825280602002602001820160405280156114ba578160200160208202803683370190505b5060008060006040516114d5999897969594939291906139a1565b60405180910390a15050505095945050505050565b600281815481106114fa57600080fd5b6000918252602090912001546001600160a01b0316905081565b85516040805160a08101825287516001600160a01b0390811660608084019182526020808c0180516080870152928552808d015181860152858d015185870152855180870187528c870151851681529251908301528b0151935163187945bd60e11b815260009592909216936330f28b7a93611597939092913391600401613a48565b600060405180830381600087803b1580156115b157600080fd5b505af11580156115c5573d6000803e3d6000fd5b505050506115d68686868686612691565b979650505050505050565b6115e96123d8565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f1535fa8f7275b71050af30bf7f74391b45be7ba2b545fd28279dafe9b50f642490600090a250565b61163b6123d8565b600180546001600160a01b0383166001600160a01b0319909116811790915561166c6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60606115d687878787878761244b565b6060600087516001600160401b038111156116d1576116d1612e19565b6040519080825280602002602001820160405280156116fa578160200160208202803683370190505b509050600088516001600160401b0381111561171857611718612e19565b604051908082528060200260200182016040528015611741578160200160208202803683370190505b50905060005b895181101561195b5789818151811061176257611762613715565b60200260200101516020015183828151811061178057611780613715565b60200260200101818152505089818151811061179e5761179e613715565b6020026020010151600001518282815181106117bc576117bc613715565b60200260200101906001600160a01b031690816001600160a01b03168152505060005b81811015611894578a81815181106117f9576117f9613715565b6020026020010151600001516001600160a01b03168b838151811061182057611820613715565b6020026020010151600001516001600160a01b0316036118825760405162461bcd60e51b815260206004820152601760248201527f4475706c696361746520736f7572636520746f6b656e73000000000000000000604482015260640161073a565b8061188c81613744565b9150506117df565b5060005b8951811015611948578981815181106118b3576118b3613715565b6020026020010151600001516001600160a01b03168b83815181106118da576118da613715565b6020026020010151600001516001600160a01b0316036119365760405162461bcd60e51b8152602060048201526017602482015276105c989a5d1c9859d9481b9bdd081cdd5c1c1bdc9d1959604a1b604482015260640161073a565b8061194081613744565b915050611898565b508061195381613744565b915050611747565b50600088516001600160401b0381111561197757611977612e19565b6040519080825280602002602001820160405280156119a0578160200160208202803683370190505b50905060005b8951811015611bad578981815181106119c1576119c1613715565b6020026020010151602001518a82815181106119df576119df613715565b6020026020010151604001511115611a395760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d2067726561746572207468616e2071756f7465000000000000604482015260640161073a565b60008a8281518110611a4d57611a4d613715565b60200260200101516040015111611a9f5760405162461bcd60e51b81526020600482015260166024820152754d696e696d756d206f7574707574206973207a65726f60501b604482015260640161073a565b60005b81811015611b57578a8181518110611abc57611abc613715565b6020026020010151600001516001600160a01b03168b8381518110611ae357611ae3613715565b6020026020010151600001516001600160a01b031603611b455760405162461bcd60e51b815260206004820152601c60248201527f4475706c69636174652064657374696e6174696f6e20746f6b656e7300000000604482015260640161073a565b80611b4f81613744565b915050611aa2565b50611b7e8a8281518110611b6d57611b6d613715565b602002602001015160000151612170565b828281518110611b9057611b90613715565b602090810291909101015280611ba581613744565b9150506119a6565b5060405163cb70e27360e01b81526001600160a01b0387169063cb70e273903490611be2908c908c90899033906004016138d9565b6000604051808303818588803b158015611bfb57600080fd5b505af1158015611c0f573d6000803e3d6000fd5b5050505050600089516001600160401b03811115611c2f57611c2f612e19565b604051908082528060200260200182016040528015611c58578160200160208202803683370190505b50905089516001600160401b03811115611c7457611c74612e19565b604051908082528060200260200182016040528015611c9d578160200160208202803683370190505b50945060005b8a5181101561206457828181518110611cbe57611cbe613715565b6020026020010151611cdb8c8381518110611b6d57611b6d613715565b611ce59190613702565b868281518110611cf757611cf7613715565b602002602001018181525050600087602001516001600160401b03161115611ed35760408701516001600160a01b0316611d685760405162461bcd60e51b8152602060048201526012602482015271139d5b1b08199959481c9958da5c1a595b9d60721b604482015260640161073a565b611d7b6032670de0b6b3a7640000613ac1565b87602001516001600160401b03161115611dc65760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b604482015260640161073a565b60408701516001600160a01b03163014611e5c57611e5c8b8281518110611def57611def613715565b6020026020010151600001518860400151670de0b6b3a7640000600a611e159190613ae3565b8a602001516001600160401b03168a8681518110611e3557611e35613715565b6020026020010151611e479190613ae3565b611e52906008613ae3565b61091b9190613ac1565b670de0b6b3a764000087602001516001600160401b0316670de0b6b3a7640000611e869190613702565b878381518110611e9857611e98613715565b6020026020010151611eaa9190613ae3565b611eb49190613ac1565b868281518110611ec657611ec6613715565b6020026020010181815250505b8a8181518110611ee557611ee5613715565b602002602001015160200151868281518110611f0357611f03613715565b6020026020010151611f159190613afa565b828281518110611f2757611f27613715565b6020026020010181815250506000828281518110611f4757611f47613715565b60200260200101511315611f92578a8181518110611f6757611f67613715565b602002602001015160200151868281518110611f8557611f85613715565b6020026020010181815250505b8a8181518110611fa457611fa4613715565b602002602001015160400151868281518110611fc257611fc2613715565b60200260200101511015611fe85760405162461bcd60e51b815260040161073a90613931565b6120528b8281518110611ffd57611ffd613715565b60200260200101516000015160006001600160a01b03168d848151811061202657612026613715565b6020026020010151606001516001600160a01b03161461142b578c838151811061141a5761141a613715565b8061205c81613744565b915050611ca3565b5060008a516001600160401b0381111561208057612080612e19565b6040519080825280602002602001820160405280156120a9578160200160208202803683370190505b50905060005b8b51811015612112578b81815181106120ca576120ca613715565b6020026020010151600001518282815181106120e8576120e8613715565b6001600160a01b03909216602092830291909101909101528061210a81613744565b9150506120af565b50865160208801516040808a015190517f2c96555a96d94780f3a97aeb724514e80e331842f3143742d85da5aa68df9d30936121599333938b938b938e938a938c936139a1565b60405180910390a150505050509695505050505050565b60006001600160a01b038216612187575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156121cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ef919061372b565b92915050565b919050565b6001600160a01b0383166122a7576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612255576040519150601f19603f3d011682016040523d82523d6000602084013e61225a565b606091505b50509050806122a15760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640161073a565b50505050565b6109d36001600160a01b0384168383612adc565b84516000906001600160a01b031661230c5785602001516000036122e4573460208701526123cb565b856020015134146123075760405162461bcd60e51b815260040161073a9061375d565b6123cb565b341561232a5760405162461bcd60e51b815260040161073a9061375d565b85602001516000036123a75785516040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561237d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a1919061372b565b60208701525b6040860151602087015187516123cb926001600160a01b0390911691339190612b3f565b6109498686868686612691565b6000546001600160a01b031633146109ea5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161073a565b600180546001600160a01b0319169055610a6381612b77565b60606000805b88518110156126575760006001600160a01b031689828151811061247757612477613715565b6020026020010151600001516001600160a01b0316036124ff578881815181106124a3576124a3613715565b6020026020010151602001516000036124da57348982815181106124c9576124c9613715565b602002602001015160200181815250505b8881815181106124ec576124ec613715565b6020026020010151602001519150612645565b88818151811061251157612511613715565b6020026020010151602001516000036125ce5788818151811061253657612536613715565b6020908102919091010151516040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ab919061372b565b8982815181106125bd576125bd613715565b602002602001015160200181815250505b612645338a83815181106125e4576125e4613715565b6020026020010151604001518b848151811061260257612602613715565b6020026020010151602001518c858151811061262057612620613715565b6020026020010151600001516001600160a01b0316612b3f909392919063ffffffff16565b8061264f81613744565b915050612451565b508034146126775760405162461bcd60e51b815260040161073a9061375d565b6126858888888888886116b4565b98975050505050505050565b600085608001518660a0015111156126eb5760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d2067726561746572207468616e2071756f7465000000000000604482015260640161073a565b60008660a00151116127385760405162461bcd60e51b81526020600482015260166024820152754d696e696d756d206f7574707574206973207a65726f60501b604482015260640161073a565b85606001516001600160a01b031686600001516001600160a01b03160361279b5760405162461bcd60e51b8152602060048201526017602482015276105c989a5d1c9859d9481b9bdd081cdd5c1c1bdc9d1959604a1b604482015260640161073a565b60006127aa8760600151612170565b60408051600180825281830190925291925060009190602080830190803683370190505090508760200151816000815181106127e8576127e8613715565b602090810291909101015260405163cb70e27360e01b81526001600160a01b0386169063cb70e273903490612827908b908b90879033906004016138d9565b6000604051808303818588803b15801561284057600080fd5b505af1158015612854573d6000803e3d6000fd5b5050505050816128678960600151612170565b6128719190613702565b60208501519093506001600160401b0316156129c35760408401516001600160a01b03166128d65760405162461bcd60e51b8152602060048201526012602482015271139d5b1b08199959481c9958da5c1a595b9d60721b604482015260640161073a565b6128e96032670de0b6b3a7640000613ac1565b84602001516001600160401b031611156129345760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b604482015260640161073a565b60408401516001600160a01b031630146129825761298288606001518560400151670de0b6b3a7640000600a61296a9190613ae3565b6020880151611e47906001600160401b031688613ae3565b670de0b6b3a764000084602001516001600160401b0316670de0b6b3a76400006129ac9190613702565b6129b69085613ae3565b6129c09190613ac1565b92505b60008860800151846129d59190613afa565b905060008113156129e857886080015193505b8860a00151841015612a0c5760405162461bcd60e51b815260040161073a90613931565b606089015160c08a0151612a3b91906001600160a01b031615612a33578a60c00151612a35565b335b866121fa565b6020808a01518a516060808d015189518a8601516040808d01518151338152988901979097526001600160a01b03958616908801529286018a9052908316608086015260a085018690526001600160401b0390811660c08601521660e0840152166101008201527f69db20ca9e32403e6c56e5193b3e3b2827ae5c430ccfdea392ba950d2d1ab2bc906101200160405180910390a150505095945050505050565b6040516001600160a01b0383166024820152604481018290526109d390849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612bc7565b6040516001600160a01b03808516602483015283166044820152606481018290526122a19085906323b872dd60e01b90608401612b08565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000612c1c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612c999092919063ffffffff16565b8051909150156109d35780806020019051810190612c3a9190613b21565b6109d35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161073a565b6060612ca88484600085612cb0565b949350505050565b606082471015612d115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161073a565b600080866001600160a01b03168587604051612d2d9190613b43565b60006040518083038185875af1925050503d8060008114612d6a576040519150601f19603f3d011682016040523d82523d6000602084013e612d6f565b606091505b50915091506115d68783838760608315612dea578251600003612de3576001600160a01b0385163b612de35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161073a565b5081612ca8565b612ca88383815115612dff5781518083602001fd5b8060405162461bcd60e51b815260040161073a9190613b5f565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715612e5157612e51612e19565b60405290565b604051606081016001600160401b0381118282101715612e5157612e51612e19565b604051601f8201601f191681016001600160401b0381118282101715612ea157612ea1612e19565b604052919050565b80356001600160a01b03811681146121f557600080fd5b600060808284031215612ed257600080fd5b612eda612e2f565b9050612ee582612ea9565b8152602080830135818301526040830135604083015260608301356001600160401b0380821115612f1557600080fd5b818501915085601f830112612f2957600080fd5b813581811115612f3b57612f3b612e19565b612f4d601f8201601f19168501612e79565b91508082528684828501011115612f6357600080fd5b808484018584013760008482840101525080606085015250505092915050565b60006001600160401b03821115612f9c57612f9c612e19565b5060051b60200190565b600082601f830112612fb757600080fd5b81356020612fcc612fc783612f83565b612e79565b82815260609283028501820192828201919087851115612feb57600080fd5b8387015b858110156130405781818a0312156130075760008081fd5b61300f612e57565b61301882612ea9565b81528582013586820152604061302f818401612ea9565b908201528452928401928101612fef565b5090979650505050505050565b600082601f83011261305e57600080fd5b8135602061306e612fc783612f83565b82815260079290921b8401810191818101908684111561308d57600080fd5b8286015b848110156130ee57608081890312156130aa5760008081fd5b6130b2612e2f565b6130bb82612ea9565b815281850135858201526040808301359082015260606130dc818401612ea9565b90820152835291830191608001613091565b509695505050505050565b60008083601f84011261310b57600080fd5b5081356001600160401b0381111561312257600080fd5b60208301915083602082850101111561313a57600080fd5b9250929050565b80356001600160401b03811681146121f557600080fd5b60006060828403121561316a57600080fd5b613172612e57565b905061317d82613141565b815261318b60208301613141565b602082015261319c60408301612ea9565b604082015292915050565b6000806000806000806000610100888a0312156131c357600080fd5b87356001600160401b03808211156131da57600080fd5b6131e68b838c01612ec0565b985060208a01359150808211156131fc57600080fd5b6132088b838c01612fa6565b975060408a013591508082111561321e57600080fd5b61322a8b838c0161304d565b965060608a013591508082111561324057600080fd5b5061324d8a828b016130f9565b9095509350613260905060808901612ea9565b915061326f8960a08a01613158565b905092959891949750929550565b600081518084526020808501945080840160005b838110156132ad57815187529582019590820190600101613291565b509495945050505050565b6020815260006132cb602083018461327d565b9392505050565b60008083601f8401126132e457600080fd5b5081356001600160401b038111156132fb57600080fd5b6020830191508360208260051b850101111561313a57600080fd5b60008060008060006060868803121561332e57600080fd5b85356001600160401b038082111561334557600080fd5b61335189838a016132d2565b9097509550602088013591508082111561336a57600080fd5b50613377888289016132d2565b909450925061338a905060408701612ea9565b90509295509295909350565b600060e082840312156133a857600080fd5b60405160e081018181106001600160401b03821117156133ca576133ca612e19565b6040529050806133d983612ea9565b8152602083013560208201526133f160408401612ea9565b604082015261340260608401612ea9565b60608201526080830135608082015260a083013560a082015261342760c08401612ea9565b60c08201525092915050565b6000806000806000610180868803121561344c57600080fd5b6134568787613396565b945060e08601356001600160401b0381111561347157600080fd5b61347d888289016130f9565b909550935061349190506101008701612ea9565b915061338a876101208801613158565b600080602083850312156134b457600080fd5b82356001600160401b038111156134ca57600080fd5b6134d6858286016132d2565b90969095509350505050565b6000806000806000608086880312156134fa57600080fd5b85356001600160401b038082111561351157600080fd5b61351d89838a01612fa6565b9650602088013591508082111561353357600080fd5b61353f89838a0161304d565b9550604088013591508082111561355557600080fd5b50613562888289016130f9565b909450925061338a905060608701612ea9565b60006020828403121561358757600080fd5b5035919050565b6000806000806000806101a087890312156135a857600080fd5b86356001600160401b03808211156135bf57600080fd5b6135cb8a838b01612ec0565b97506135da8a60208b01613396565b96506101008901359150808211156135f157600080fd5b506135fe89828a016130f9565b909550935061361290506101208801612ea9565b9150613622886101408901613158565b90509295509295509295565b60006020828403121561364057600080fd5b6132cb82612ea9565b60008060008060008060e0878903121561366257600080fd5b86356001600160401b038082111561367957600080fd5b6136858a838b01612fa6565b9750602089013591508082111561369b57600080fd5b6136a78a838b0161304d565b965060408901359150808211156136bd57600080fd5b506136ca89828a016130f9565b90955093506136dd905060608801612ea9565b91506136228860808901613158565b634e487b7160e01b600052601160045260246000fd5b818103818111156121ef576121ef6136ec565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561373d57600080fd5b5051919050565b600060018201613756576137566136ec565b5060010190565b6020808252600f908201526e57726f6e67206d73672e76616c756560881b604082015260600190565b600081518084526020808501945080840160005b838110156132ad576137c087835180516001600160a01b03168252602090810151910152565b604096909601959082019060010161379a565b60005b838110156137ee5781810151838201526020016137d6565b50506000910152565b6000815180845261380f8160208601602086016137d3565b601f01601f19169290920160200192915050565b60808152600060e082018651606060808501528181518084526101008601915060209350838301925060005b818110156138885761387583855180516001600160a01b03168252602090810151910152565b928401926040929092019160010161384f565b50508289015160a0860152604089015160c0860152848103838601526138ae8189613786565b925050506138c760408401866001600160a01b03169052565b82810360608401526115d681856137f7565b60608152836060820152838560808301376000608085830101526000601f19601f86011682016080838203016020840152613917608082018661327d565b91505060018060a01b038316604083015295945050505050565b60208082526017908201527f536c697070616765204c696d6974204578636565646564000000000000000000604082015260600190565b600081518084526020808501945080840160005b838110156132ad5781516001600160a01b03168752958201959082019060010161397c565b6001600160a01b038a81168252610120602083018190526000916139c78483018d61327d565b915083820360408501526139db828c613968565b915083820360608501526139ef828b61327d565b91508382036080850152613a03828a613968565b915083820360a0850152613a17828961327d565b6001600160401b0397881660c08601529590961660e084015250509216610100909201919091529695505050505050565b6000610100613a6b83885180516001600160a01b03168252602090810151910152565b6020870151604084015260408701516060840152613a9f608084018780516001600160a01b03168252602090810151910152565b6001600160a01b03851660c084015260e083018190526115d6818401856137f7565b600082613ade57634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176121ef576121ef6136ec565b8181036000831280158383131683831282161715613b1a57613b1a6136ec565b5092915050565b600060208284031215613b3357600080fd5b815180151581146132cb57600080fd5b60008251613b558184602087016137d3565b9190910192915050565b6020815260006132cb60208301846137f756fea26469706673582212208403cc00b2f60ffd39bea8f9569830cb900e249332880f3e2bdf46c037bc0a5764736f6c63430008130033
Deployed Bytecode Sourcemap
34684:29689:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53155:2058;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;60529:516;;;;;;;;;;-1:-1:-1;60529:516:0;;;;;:::i;:::-;;:::i;:::-;;39904:340;;;;;;:::i;:::-;;:::i;:::-;;;10558:25:1;;;10546:2;10531:18;39904:340:0;10412:177:1;60048:205:0;;;;;;;;;;-1:-1:-1;60048:205:0;;;;;:::i;:::-;;:::i;35498:40::-;;;;;;;;;;;;35534:4;35498:40;;21014:103;;;;;;;;;;;;;:::i;35417:32::-;;;;;;;;;;-1:-1:-1;35417:32:0;;;;-1:-1:-1;;;;;35417:32:0;;;;;;-1:-1:-1;;;;;11309:32:1;;;11291:51;;11279:2;11264:18;35417:32:0;11145:203:1;23452:210:0;;;;;;;;;;;;;:::i;35732:3807::-;;;:::i;45726:4364::-;;;:::i;20366:87::-;;;;;;;;;;-1:-1:-1;20412:7:0;20439:6;-1:-1:-1;;;;;20439:6:0;20366:87;;61392:2037;;;;;;;;;;-1:-1:-1;61392:2037:0;;;;;:::i;:::-;;:::i;35306:28::-;;;;;;;;;;-1:-1:-1;35306:28:0;;;;;:::i;:::-;;:::i;42124:837::-;;;;;;;;;;-1:-1:-1;42124:837:0;;;;;:::i;:::-;;:::i;22540:101::-;;;;;;;;;;-1:-1:-1;22620:13:0;;-1:-1:-1;;;;;22620:13:0;22540:101;;59691:167;;;;;;;;;;-1:-1:-1;59691:167:0;;;;;:::i;:::-;;:::i;22840:181::-;;;;;;;;;;-1:-1:-1;22840:181:0;;;;;:::i;:::-;;:::i;50558:412::-;;;;;;:::i;:::-;;:::i;53155:2058::-;53438:27;53477:56;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;53477:56:0;53540:68;53624:21;53660:1;53648:9;:13;:49;;53684:6;:13;53648:49;;;53680:1;53664:6;:13;:17;;;;:::i;:::-;53624:73;;53717:169;;;;;;;;53812:13;-1:-1:-1;;;;;53770:56:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;53770:56:0;;;;;;;;;;;;;;;;53717:169;;;;53837:7;:13;;;53717:169;;;;53861:7;:16;;;53717:169;;;53708:178;;53973:13;-1:-1:-1;;;;;53923:64:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;53923:64:0;;;;;;;;;;;;;;;;53895:92;;53615:380;54010:26;54054:9;54049:801;54073:6;:13;54069:1;:17;54049:801;;;34959:1;-1:-1:-1;;;;;54110:30:0;:6;54117:1;54110:9;;;;;;;;:::i;:::-;;;;;;;:22;;;-1:-1:-1;;;;;54110:30:0;;54106:735;;54159:6;54166:1;54159:9;;;;;;;;:::i;:::-;;;;;;;:18;;;54181:1;54159:23;54155:88;;54220:9;54199:6;54206:1;54199:9;;;;;;;;:::i;:::-;;;;;;;:18;;:30;;;;;54155:88;54276:6;54283:1;54276:9;;;;;;;;:::i;:::-;;;;;;;:18;;;54255:39;;54106:735;;;54338:6;54345:1;54338:9;;;;;;;;:::i;:::-;;;;;;;:18;;;54360:1;54338:23;54334:131;;54406:6;54413:1;54406:9;;;;;;;;:::i;:::-;;;;;;;;;;;:22;54399:52;;-1:-1:-1;;;54399:52:0;;54440:10;54399:52;;;11291:51:1;-1:-1:-1;;;;;54399:40:0;;;;;;11264:18:1;;54399:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;54378:6;54385:1;54378:9;;;;;;;;:::i;:::-;;;;;;;:18;;:73;;;;;54334:131;54477:20;54500:23;;:35;;54530:5;54534:1;54530;:5;:::i;:::-;54500:35;;;54526:1;54500:35;54477:58;;54589:6;54596:1;54589:9;;;;;;;;:::i;:::-;;;;;;;:22;;;54550:6;:16;;;54567:12;54550:30;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;54550:61:0;;;;;54664:9;;:6;;54671:1;;54664:9;;;;;;:::i;:::-;;;;;;;:18;;;54624:6;:16;;;54641:12;54624:30;;;;;;;;:::i;:::-;;;;;;;:37;;:58;;;;;54732:6;54739:1;54732:9;;;;;;;;:::i;:::-;;;;;;;:18;;;54697:15;54713:12;54697:29;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;54697:53:0;;;;;54811:9;;:6;;54818:1;;54811:9;;;;;;:::i;:::-;;;;;;;:18;;;54763:15;54779:12;54763:29;;;;;;;;:::i;:::-;;;;;;;:45;;:66;;;;;54321:520;54106:735;54088:3;;;;:::i;:::-;;;;54049:801;;;;54879:18;54866:9;:31;54858:59;;;;-1:-1:-1;;;54858:59:0;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;54950:23:0;;55060:17;;;;54931:153;;-1:-1:-1;;;54931:153:0;;-1:-1:-1;;;;;54931:62:0;;;;;;:153;;55002:6;;55017:15;;55041:10;;55060:17;54931:153;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55098:109;55117:6;55132:7;55148:14;;55171:8;55188:12;55098:10;:109::i;:::-;55091:116;53155:2058;-1:-1:-1;;;;;;;;;;53155:2058:0:o;60529:516::-;60693:17;;-1:-1:-1;;;;;60693:17:0;60679:10;:31;;:56;;-1:-1:-1;20412:7:0;20439:6;-1:-1:-1;;;;;20439:6:0;60714:10;:21;60679:56;60671:88;;;;-1:-1:-1;;;60671:88:0;;18908:2:1;60671:88:0;;;18890:21:1;18947:2;18927:18;;;18920:30;-1:-1:-1;;;18966:18:1;;;18959:49;19025:18;;60671:88:0;18706:343:1;60671:88:0;60774:31;;;60766:66;;;;-1:-1:-1;;;60766:66:0;;19256:2:1;60766:66:0;;;19238:21:1;19295:2;19275:18;;;19268:30;-1:-1:-1;;;19314:18:1;;;19307:52;19376:18;;60766:66:0;19054:346:1;60766:66:0;60850:9;60845:195;60865:17;;;60845:195;;;60898:134;60927:6;;60934:1;60927:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;60948:4;60964:7;;60972:1;60964:10;;;;;;;:::i;:::-;;;;;;;60978:1;60964:15;:59;;61013:7;;61021:1;61013:10;;;;;;;:::i;:::-;;;;;;;60898:18;:134::i;60964:59::-;60982:28;61000:6;;61007:1;61000:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;60982:17;:28::i;:::-;60898:18;:134::i;:::-;60884:3;;;;:::i;:::-;;;;60845:195;;;;60529:516;;;;;:::o;39904:340::-;40103:17;40139:99;40161:9;40179:14;;40202:8;40219:12;40139:13;:99::i;:::-;40132:106;39904:340;-1:-1:-1;;;;;;39904:340:0:o;60048:205::-;20252:13;:11;:13::i;:::-;60159:9:::1;60154:94;60174:20:::0;;::::1;60154:94;;;60210:11;60227:9;;60237:1;60227:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;60210:30:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;60210:30:0;;;::::1;::::0;;;;;::::1;::::0;;-1:-1:-1;;;;;;60210:30:0::1;-1:-1:-1::0;;;;;60210:30:0;;::::1;::::0;;;::::1;::::0;;60196:3;::::1;::::0;::::1;:::i;:::-;;;;60154:94;;;;60048:205:::0;;:::o;21014:103::-;20252:13;:11;:13::i;:::-;21079:30:::1;21106:1;21079:18;:30::i;:::-;21014:103::o:0;23452:210::-;22620:13;;3395:10;;-1:-1:-1;;;;;22620:13:0;23547:24;;23539:78;;;;-1:-1:-1;;;23539:78:0;;19607:2:1;23539:78:0;;;19589:21:1;19646:2;19626:18;;;19619:30;19685:34;19665:18;;;19658:62;-1:-1:-1;;;19736:18:1;;;19729:39;19785:19;;23539:78:0;19405:405:1;23539:78:0;23628:26;23647:6;23628:18;:26::i;:::-;23488:174;23452:210::o;35732:3807::-;-1:-1:-1;;;;;;;;35797:7:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35898:16:0;35921:29;;36077:827;;;36109:6;;36162:21;;36157:3;36153:31;;36322:65;;;;36506:6;36501:169;;;;36801:39;;;36795:46;;-1:-1:-1;36837:1:0;36865:15;;;-1:-1:-1;36198:695:0;;36322:65;36372:1;36363:7;36359:15;36349:25;;36322:65;;36501:169;-1:-1:-1;;;;;36563:7:0;36550:21;36546:2;36542:30;36538:79;36528:89;;36654:2;36645:7;36641:16;36631:26;;36198:695;;;36077:827;;;:::o;:::-;36928:1;36950;37035:15;37046:3;37035:15;:::i;:::-;37020:30;;;;37078:6;37067:9;37060:25;37112:15;37123:3;37112:15;:::i;:::-;37159:4;37144:20;;37137:36;;;37097:30;;-1:-1:-1;37348:1:0;37339:11;;;-1:-1:-1;37304:17:0;37299:3;37295:27;37362:179;;;;37478:3;37465:17;37461:1;37441:17;37437:2;37433:26;37429:34;37425:58;37418:4;37407:9;37403:20;37396:88;37512:17;37507:3;37503:27;37496:34;;37362:179;;37645:3;37632:17;37627:3;37623:27;37676:1;37671:3;37667:11;37660:18;;37762:3;37749:17;37745:1;37725:17;37721:2;37717:26;37713:34;37709:58;37806:11;37799:4;37788:9;37784:20;37777:41;37844:17;37839:3;37835:27;37828:34;;38015:3;38002:17;37997:3;37993:27;37968:52;;38117:8;38096:17;38086:8;38082:32;38069:11;38065:50;38061:65;38054:4;38043:9;38039:20;38032:95;37955:183;;38164:1;38159:3;38155:11;38148:18;;38236:15;38247:3;38236:15;:::i;:::-;38219:32;;;;38363:15;38374:3;38363:15;:::i;:::-;38348:30;;-1:-1:-1;38348:30:0;-1:-1:-1;38348:30:0;38388:39;;38417:8;38407:18;;38388:39;38466:6;38459:4;38448:9;38444:20;38437:36;38584:15;38595:3;38584:15;:::i;:::-;38631:4;38616:20;;;38609:36;;;;38686:17;;38677:27;;;38742:34;;38730:1;38721:11;;38814:17;38809:3;38805:27;;-1:-1:-1;38849:11:0;;;-1:-1:-1;38872:331:0;;;;38926:17;;38921:3;38917:27;39011:4;38993:23;;38986:44;38972:1;38963:11;;39079:17;39075:2;39071:26;39165:4;39147:23;;39140:52;39116:12;;38872:331;39403:1;39394:11;;;-1:-1:-1;39336:17:0;39331:3;39327:27;39356:2;39323:36;;-1:-1:-1;39434:99:0;;-1:-1:-1;39456:9:0;39394:11;39323:36;39497:8;39514:12;39434:13;:99::i;:::-;39427:106;;;;;;;35732:3807;:::o;45726:4364::-;45796:27;45835:16;45796:27;;45952:1;46079;46066:15;46061:3;46057:25;;;;46128:1;46115:15;46106:25;;46057;-1:-1:-1;;;;;46157:31:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;46157:31:0;;-1:-1:-1;;46157:31:0;;;;;;;;;;;;46148:40;;46229:10;-1:-1:-1;;;;;46207:33:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46207:33:0;;-1:-1:-1;;46207:33:0;;;;;;;;;;;;46197:43;;47216:15;47227:3;47216:15;:::i;:::-;47199:32;;-1:-1:-1;47321:1:0;47312:11;;;-1:-1:-1;47277:17:0;47272:3;47268:27;47349:1;;;47387:809;47424:9;47415:7;47412:22;47387:809;;;47540:4;47533;47524:7;47520:18;47516:29;47508:6;47504:42;47498:49;47488:59;;47616:15;47627:3;47616:15;:::i;:::-;47643:22;;;47846:1;47837:11;;;-1:-1:-1;47601:30:0;;-1:-1:-1;47800:17:0;47795:3;47791:27;47862:183;;;;47978:3;47965:17;47961:1;47941:17;47937:2;47933:26;47929:34;47925:58;47918:4;47910:6;47906:17;47899:85;48014:17;48009:3;48005:27;47998:34;;47862:183;;48072:15;48083:3;48072:15;:::i;:::-;48057:30;-1:-1:-1;48057:30:0;-1:-1:-1;48057:30:0;48099:39;;48128:8;48118:18;;48099:39;48171:4;48159:17;;48152:33;;;47461:1;47448:15;47387:809;;;47391:20;48227:1;48206:902;48243:10;48234:7;48231:23;48206:902;;;48361:4;48354;48345:7;48341:18;48337:29;48328:7;48324:43;48318:50;48308:60;;48437:15;48448:3;48437:15;:::i;:::-;48422:30;;;;48479:6;48471;48464:22;48595:3;48582:17;48577:3;48573:27;48628:1;48623:3;48619:11;48612:18;;48717:3;48704:17;48700:1;48679:18;48675:2;48671:27;48667:35;48663:59;48760:11;48753:4;48745:6;48741:17;48734:38;48800:18;48795:3;48791:28;48784:35;;48996:8;48975:17;48965:8;48961:32;48948:11;48944:50;48940:65;48933:4;48925:6;48921:17;48914:92;;;49035:15;49046:3;49035:15;:::i;:::-;49083:4;49071:17;;49064:33;;;49020:30;-1:-1:-1;49020:30:0;-1:-1:-1;48281:1:0;48268:15;48206:902;;;48210:20;;;;46260:2857;;49130:36;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;49130:36:0;49258:17;;49253:3;49249:27;49310:34;;49413:11;;;;49173:29;;;;49300:1;49291:11;49380:17;49375:3;49371:27;49434:317;;;;49486:17;;49481:3;49477:27;49567:4;49549:23;;49542:44;49530:1;49521:11;;49633:17;49629:2;49625:26;49715:4;49697:23;;49690:52;49668:12;;;;;49434:317;-1:-1:-1;;;49945:1:0;49936:11;;49900:2;49880:17;;49875:3;49871:27;49867:36;49967:117;49994:6;50009:7;49936:11;49867:36;50048:8;50065:12;49967:18;:117::i;:::-;49960:124;;;;;;;;;45726:4364;:::o;61392:2037::-;61646:17;;61585:27;;-1:-1:-1;;;;;61646:17:0;61632:10;:31;;:56;;-1:-1:-1;20412:7:0;20439:6;-1:-1:-1;;;;;20439:6:0;61667:10;:21;61632:56;61624:88;;;;-1:-1:-1;;;61624:88:0;;18908:2:1;61624:88:0;;;18890:21:1;18947:2;18927:18;;;18920:30;-1:-1:-1;;;18966:18:1;;;18959:49;19025:18;;61624:88:0;18706:343:1;61624:88:0;61721:26;61764:6;:13;-1:-1:-1;;;;;61750:28:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;61750:28:0;;61721:57;;61785:25;61827:6;:13;-1:-1:-1;;;;;61813:28:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;61813:28:0;;61785:56;;61855:9;61850:322;61874:6;:13;61870:1;:17;61850:322;;;61917:6;61924:1;61917:9;;;;;;;;:::i;:::-;;;;;;;:22;;;61903:8;61912:1;61903:11;;;;;;;;:::i;:::-;;;;;;:36;-1:-1:-1;;;;;61903:36:0;;;-1:-1:-1;;;;;61903:36:0;;;;;61965:6;61972:1;61965:9;;;;;;;;:::i;:::-;;;;;;;:18;;;61987:1;61965:23;:87;;62034:6;62041:1;62034:9;;;;;;;;:::i;:::-;;;;;;;:18;;;61965:87;;;62001:30;62019:8;62028:1;62019:11;;;;;;;;:::i;:::-;;;;;;;62001:17;:30::i;:::-;61950:9;61960:1;61950:12;;;;;;;;:::i;:::-;;;;;;:102;;;;;62063:101;62092:8;62101:1;62092:11;;;;;;;;:::i;:::-;;;;;;;62114:6;62121:1;62114:9;;;;;;;;:::i;:::-;;;;;;;:18;;;62143:9;62153:1;62143:12;;;;;;;;:::i;:::-;;;;;;;62063:18;:101::i;:::-;61889:3;;;;:::i;:::-;;;;61850:322;;;;62247:31;62295:7;:14;-1:-1:-1;;;;;62281:29:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62281:29:0;;62247:63;;62317:26;62360:7;:14;-1:-1:-1;;;;;62346:29:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62346:29:0;;62317:58;;62387:9;62382:160;62406:7;:14;62402:1;:18;62382:160;;;62451:7;62459:1;62451:10;;;;;;;;:::i;:::-;;;;;;;:23;;;62436:9;62446:1;62436:12;;;;;;;;:::i;:::-;;;;;;:38;-1:-1:-1;;;;;62436:38:0;;;-1:-1:-1;;;;;62436:38:0;;;;;62503:31;62521:9;62531:1;62521:12;;;;;;;;:::i;62503:31::-;62483:14;62498:1;62483:17;;;;;;;;:::i;:::-;;;;;;;;;;:51;62422:3;;;;:::i;:::-;;;;62382:160;;;-1:-1:-1;62622:84:0;;-1:-1:-1;;;62622:84:0;;-1:-1:-1;;;;;62622:35:0;;;;;62665:1;;62622:84;;62668:14;;;;62684:9;;62695:10;;62622:84;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62742:7;:14;-1:-1:-1;;;;;62728:29:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62728:29:0;;62715:42;;62769:9;62764:465;62788:7;:14;62784:1;:18;62764:465;;;62945:14;62960:1;62945:17;;;;;;;;:::i;:::-;;;;;;;62911:31;62929:9;62939:1;62929:12;;;;;;;;:::i;62911:31::-;:51;;;;:::i;:::-;62895:10;62906:1;62895:13;;;;;;;;:::i;:::-;;;;;;:67;;;;;62998:7;63006:1;62998:10;;;;;;;;:::i;:::-;;;;;;;:20;;;62981:10;62992:1;62981:13;;;;;;;;:::i;:::-;;;;;;;:37;;62973:73;;;;-1:-1:-1;;;62973:73:0;;;;;;;:::i;:::-;63057:164;63086:7;63094:1;63086:10;;;;;;;;:::i;:::-;;;;;;;:23;;;63151:1;-1:-1:-1;;;;;63120:33:0;:7;63128:1;63120:10;;;;;;;;:::i;:::-;;;;;;;:19;;;-1:-1:-1;;;;;63120:33:0;;:68;;63169:7;63177:1;63169:10;;;;;;;;:::i;:::-;;;;;;;:19;;;63120:68;;;63156:10;63120:68;63199:10;63210:1;63199:13;;;;;;;;:::i;63057:164::-;62804:3;;;;:::i;:::-;;;;62764:465;;;;63240:183;63258:10;63277:9;63295:8;63312:10;63331:9;63362:7;:14;-1:-1:-1;;;;;63349:28:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63349:28:0;;63386:1;63396;63414;63240:183;;;;;;;;;;;;;;:::i;:::-;;;;;;;;61617:1812;;;;61392:2037;;;;;;;:::o;35306:28::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;35306:28:0;;-1:-1:-1;35306:28:0;:::o;42124:837::-;42398:23;;42450:221;;;42498:113;;;;;42546:20;;-1:-1:-1;;;;;42498:113:0;;;42450:221;;;;42498:113;;;;42579:21;;;;;42498:113;;;;42450:221;;;42622:13;;;;42450:221;;;;42646:16;;;;42450:221;;;;42680:118;;;;;;;42734:23;;;;42680:118;;;;42768:21;;42680:118;;;;42826:17;;;42379:471;;-1:-1:-1;;;42379:471:0;;42350:17;;42379:62;;;;;;;:471;;42450:221;;42680:118;42807:10;;42379:471;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42864:91;42878:9;42896:14;;42919:8;42936:12;42864:5;:91::i;:::-;42857:98;42124:837;-1:-1:-1;;;;;;;42124:837:0:o;59691:167::-;20252:13;:11;:13::i;:::-;59780:17:::1;:27:::0;;-1:-1:-1;;;;;;59780:27:0::1;-1:-1:-1::0;;;;;59780:27:0;::::1;::::0;;::::1;::::0;;;59819:33:::1;::::0;::::1;::::0;-1:-1:-1;;59819:33:0::1;59691:167:::0;:::o;22840:181::-;20252:13;:11;:13::i;:::-;22930::::1;:24:::0;;-1:-1:-1;;;;;22930:24:0;::::1;-1:-1:-1::0;;;;;;22930:24:0;;::::1;::::0;::::1;::::0;;;22995:7:::1;20412::::0;20439:6;-1:-1:-1;;;;;20439:6:0;;20366:87;22995:7:::1;-1:-1:-1::0;;;;;22970:43:0::1;;;;;;;;;;;22840:181:::0;:::o;50558:412::-;50801:27;50847:117;50874:6;50889:7;50905:14;;50928:8;50945:12;50847:18;:117::i;55849:3738::-;56080:27;56204:26;56247:6;:13;-1:-1:-1;;;;;56233:28:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;56233:28:0;;56204:57;;56268:25;56310:6;:13;-1:-1:-1;;;;;56296:28:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;56296:28:0;;56268:56;;56428:9;56423:543;56447:6;:13;56443:1;:17;56423:543;;;56495:6;56502:1;56495:9;;;;;;;;:::i;:::-;;;;;;;:18;;;56480:9;56490:1;56480:12;;;;;;;;:::i;:::-;;;;;;:33;;;;;56538:6;56545:1;56538:9;;;;;;;;:::i;:::-;;;;;;;:22;;;56524:8;56533:1;56524:11;;;;;;;;:::i;:::-;;;;;;:36;-1:-1:-1;;;;;56524:36:0;;;-1:-1:-1;;;;;56524:36:0;;;;;56578:9;56573:180;56597:1;56593;:5;56573:180;;;56666:6;56673:1;56666:9;;;;;;;;:::i;:::-;;;;;;;:22;;;-1:-1:-1;;;;;56640:48:0;:6;56647:1;56640:9;;;;;;;;:::i;:::-;;;;;;;:22;;;-1:-1:-1;;;;;56640:48:0;;56618:123;;;;-1:-1:-1;;;56618:123:0;;24313:2:1;56618:123:0;;;24295:21:1;24352:2;24332:18;;;24325:30;24391:25;24371:18;;;24364:53;24434:18;;56618:123:0;24111:347:1;56618:123:0;56600:3;;;;:::i;:::-;;;;56573:180;;;;56768:9;56763:194;56787:7;:14;56783:1;:18;56763:194;;;56869:7;56877:1;56869:10;;;;;;;;:::i;:::-;;;;;;;:23;;;-1:-1:-1;;;;;56843:49:0;:6;56850:1;56843:9;;;;;;;;:::i;:::-;;;;;;;:22;;;-1:-1:-1;;;;;56843:49:0;;56821:124;;;;-1:-1:-1;;;56821:124:0;;24665:2:1;56821:124:0;;;24647:21:1;24704:2;24684:18;;;24677:30;-1:-1:-1;;;24723:18:1;;;24716:53;24786:18;;56821:124:0;24463:347:1;56821:124:0;56803:3;;;;:::i;:::-;;;;56763:194;;;-1:-1:-1;56462:3:0;;;;:::i;:::-;;;;56423:543;;;;57048:31;57096:7;:14;-1:-1:-1;;;;;57082:29:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;57082:29:0;;57048:63;;57123:9;57118:525;57142:7;:14;57138:1;:18;57118:525;;;57214:7;57222:1;57214:10;;;;;;;;:::i;:::-;;;;;;;:22;;;57190:7;57198:1;57190:10;;;;;;;;:::i;:::-;;;;;;;:20;;;:46;;57172:112;;;;-1:-1:-1;;;57172:112:0;;25017:2:1;57172:112:0;;;24999:21:1;25056:2;25036:18;;;25029:30;25095:28;25075:18;;;25068:56;25141:18;;57172:112:0;24815:350:1;57172:112:0;57334:1;57311:7;57319:1;57311:10;;;;;;;;:::i;:::-;;;;;;;:20;;;:24;57293:86;;;;-1:-1:-1;;;57293:86:0;;25372:2:1;57293:86:0;;;25354:21:1;25411:2;25391:18;;;25384:30;-1:-1:-1;;;25430:18:1;;;25423:52;25492:18;;57293:86:0;25170:346:1;57293:86:0;57393:9;57388:177;57412:1;57408;:5;57388:177;;;57478:7;57486:1;57478:10;;;;;;;;:::i;:::-;;;;;;;:23;;;-1:-1:-1;;;;;57451:50:0;:7;57459:1;57451:10;;;;;;;;:::i;:::-;;;;;;;:23;;;-1:-1:-1;;;;;57451:50:0;;57431:124;;;;-1:-1:-1;;;57431:124:0;;25723:2:1;57431:124:0;;;25705:21:1;25762:2;25742:18;;;25735:30;25801;25781:18;;;25774:58;25849:18;;57431:124:0;25521:352:1;57431:124:0;57415:3;;;;:::i;:::-;;;;57388:177;;;;57593:42;57611:7;57619:1;57611:10;;;;;;;;:::i;:::-;;;;;;;:23;;;57593:17;:42::i;:::-;57573:14;57588:1;57573:17;;;;;;;;:::i;:::-;;;;;;;;;;:62;57158:3;;;;:::i;:::-;;;;57118:525;;;-1:-1:-1;57723:92:0;;-1:-1:-1;;;57723:92:0;;-1:-1:-1;;;;;57723:35:0;;;;;57766:9;;57723:92;;57777:14;;;;57793:9;;57804:10;;57723:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57824:24;57864:7;:14;-1:-1:-1;;;;;57851:28:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;57851:28:0;;57824:55;;57922:7;:14;-1:-1:-1;;;;;57908:29:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;57908:29:0;;57895:42;;57953:9;57948:1233;57972:7;:14;57968:1;:18;57948:1233;;;58142:14;58157:1;58142:17;;;;;;;;:::i;:::-;;;;;;;58097:42;58115:7;58123:1;58115:10;;;;;;;;:::i;58097:42::-;:62;;;;:::i;:::-;58081:10;58092:1;58081:13;;;;;;;;:::i;:::-;;;;;;:78;;;;;58195:1;58176:12;:16;;;-1:-1:-1;;;;;58176:20:0;;58172:558;;;58219:25;;;;-1:-1:-1;;;;;58219:39:0;58211:70;;;;-1:-1:-1;;;58211:70:0;;26080:2:1;58211:70:0;;;26062:21:1;26119:2;26099:18;;;26092:30;-1:-1:-1;;;26138:18:1;;;26131:48;26196:18;;58211:70:0;25878:342:1;58211:70:0;58322:14;58334:2;35534:4;58322:14;:::i;:::-;58302:12;:16;;;-1:-1:-1;;;;;58302:34:0;;;58294:59;;;;-1:-1:-1;;;58294:59:0;;26649:2:1;58294:59:0;;;26631:21:1;26688:2;26668:18;;;26661:30;-1:-1:-1;;;26707:18:1;;;26700:42;26759:18;;58294:59:0;26447:336:1;58294:59:0;58372:25;;;;-1:-1:-1;;;;;58372:42:0;58409:4;58372:42;58368:264;;58431:187;58466:7;58474:1;58466:10;;;;;;;;:::i;:::-;;;;;;;:23;;;58506:12;:25;;;35534:4;58600:2;58588:14;;;;:::i;:::-;58564:12;:16;;;-1:-1:-1;;;;;58548:32:0;:10;58559:1;58548:13;;;;;;;;:::i;:::-;;;;;;;:32;;;;:::i;:::-;:36;;58583:1;58548:36;:::i;:::-;:55;;;;:::i;58431:187::-;35534:4;58689:12;:16;;;-1:-1:-1;;;;;58677:28:0;35534:4;58677:28;;;;:::i;:::-;58660:10;58671:1;58660:13;;;;;;;;:::i;:::-;;;;;;;:46;;;;:::i;:::-;:58;;;;:::i;:::-;58644:10;58655:1;58644:13;;;;;;;;:::i;:::-;;;;;;:74;;;;;58172:558;58785:7;58793:1;58785:10;;;;;;;;:::i;:::-;;;;;;;:22;;;58761:10;58772:1;58761:13;;;;;;;;:::i;:::-;;;;;;;58754:54;;;;:::i;:::-;58740:8;58749:1;58740:11;;;;;;;;:::i;:::-;;;;;;:68;;;;;58837:1;58823:8;58832:1;58823:11;;;;;;;;:::i;:::-;;;;;;;:15;58819:84;;;58869:7;58877:1;58869:10;;;;;;;;:::i;:::-;;;;;;;:22;;;58853:10;58864:1;58853:13;;;;;;;;:::i;:::-;;;;;;:38;;;;;58819:84;58938:7;58946:1;58938:10;;;;;;;;:::i;:::-;;;;;;;:20;;;58921:10;58932:1;58921:13;;;;;;;;:::i;:::-;;;;;;;:37;;58913:73;;;;-1:-1:-1;;;58913:73:0;;;;;;;:::i;:::-;58999:172;59030:7;59038:1;59030:10;;;;;;;;:::i;:::-;;;;;;;:23;;;59097:1;-1:-1:-1;;;;;59066:33:0;:7;59074:1;59066:10;;;;;;;;:::i;:::-;;;;;;;:19;;;-1:-1:-1;;;;;59066:33:0;;:68;;59115:7;59123:1;59115:10;;;;;;;;:::i;58999:172::-;57988:3;;;;:::i;:::-;;;;57948:1233;;;;59194:26;59237:7;:14;-1:-1:-1;;;;;59223:29:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;59223:29:0;;59194:58;;59264:9;59259:102;59283:7;:14;59279:1;:18;59259:102;;;59330:7;59338:1;59330:10;;;;;;;;:::i;:::-;;;;;;;:23;;;59315:9;59325:1;59315:12;;;;;;;;:::i;:::-;-1:-1:-1;;;;;59315:38:0;;;:12;;;;;;;;;;;:38;59299:3;;;;:::i;:::-;;;;59259:102;;;-1:-1:-1;59498:17:0;;59524:16;;;;59549:25;;;;;59372:209;;;;;;59390:10;;59409:9;;59427:8;;59444:10;;59463:9;;59481:8;;59372:209;:::i;:::-;;;;;;;;56112:3475;;;;;55849:3738;;;;;;;;:::o;63643:216::-;63706:7;-1:-1:-1;;;;;63726:13:0;;63722:132;;-1:-1:-1;63757:21:0;;63643:216;-1:-1:-1;63643:216:0:o;63722:132::-;63808:38;;-1:-1:-1;;;63808:38:0;;63840:4;63808:38;;;11291:51:1;-1:-1:-1;;;;;63808:23:0;;;;;11264:18:1;;63808:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63801:45;63643:216;-1:-1:-1;;63643:216:0:o;63722:132::-;63643:216;;;:::o;64081:289::-;-1:-1:-1;;;;;64171:13:0;;64167:198;;64196:12;64221:2;-1:-1:-1;;;;;64213:16:0;64237:6;64213:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64195:53;;;64265:7;64257:39;;;;-1:-1:-1;;;64257:39:0;;29075:2:1;64257:39:0;;;29057:21:1;29114:2;29094:18;;;29087:30;-1:-1:-1;;;29133:18:1;;;29126:49;29192:18;;64257:39:0;28873:343:1;64257:39:0;64186:118;60154:94:::1;60048:205:::0;;:::o;64167:198::-;64319:38;-1:-1:-1;;;;;64319:26:0;;64346:2;64350:6;64319:26;:38::i;40611:1082::-;40839:20;;40806:17;;-1:-1:-1;;;;;40839:28:0;40835:748;;40965:9;:21;;;40990:1;40965:26;40961:175;;41028:9;41004:21;;;:33;40835:748;;40961:175;41085:9;:21;;;41072:9;:34;41064:62;;;;-1:-1:-1;;;41064:62:0;;;;;;;:::i;:::-;40835:748;;;41171:9;:14;41163:42;;;;-1:-1:-1;;;41163:42:0;;;;;;;:::i;:::-;41303:9;:21;;;41328:1;41303:26;41299:127;;41373:20;;41366:50;;-1:-1:-1;;;41366:50:0;;41405:10;41366:50;;;11291:51:1;-1:-1:-1;;;;;41366:38:0;;;;;;11264:18:1;;41366:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41342:21;;;:74;41299:127;41511:23;;;;41545:21;;;;41441:20;;41434:141;;-1:-1:-1;;;;;41434:45:0;;;;41490:10;;41511:23;41434:45;:141::i;:::-;41596:91;41610:9;41628:14;;41651:8;41668:12;41596:5;:91::i;20531:132::-;20412:7;20439:6;-1:-1:-1;;;;;20439:6:0;3395:10;20595:23;20587:68;;;;-1:-1:-1;;;20587:68:0;;29423:2:1;20587:68:0;;;29405:21:1;;;29442:18;;;29435:30;29501:34;29481:18;;;29474:62;29553:18;;20587:68:0;29221:356:1;23211:156:0;23301:13;23294:20;;-1:-1:-1;;;;;;23294:20:0;;;23325:34;23350:8;23325:24;:34::i;51440:1170::-;51679:27;51810:26;51854:9;51849:565;51873:6;:13;51869:1;:17;51849:565;;;34959:1;-1:-1:-1;;;;;51906:30:0;:6;51913:1;51906:9;;;;;;;;:::i;:::-;;;;;;;:22;;;-1:-1:-1;;;;;51906:30:0;;51902:505;;51953:6;51960:1;51953:9;;;;;;;;:::i;:::-;;;;;;;:18;;;51975:1;51953:23;51949:84;;52012:9;51991:6;51998:1;51991:9;;;;;;;;:::i;:::-;;;;;;;:18;;:30;;;;;51949:84;52064:6;52071:1;52064:9;;;;;;;;:::i;:::-;;;;;;;:18;;;52043:39;;51902:505;;;52121:6;52128:1;52121:9;;;;;;;;:::i;:::-;;;;;;;:18;;;52143:1;52121:23;52117:127;;52187:6;52194:1;52187:9;;;;;;;;:::i;:::-;;;;;;;;;;;:22;52180:52;;-1:-1:-1;;;52180:52:0;;52221:10;52180:52;;;11291:51:1;-1:-1:-1;;;;;52180:40:0;;;;;;11264:18:1;;52180:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52159:6;52166:1;52159:9;;;;;;;;:::i;:::-;;;;;;;:18;;:73;;;;;52117:127;52254:143;52314:10;52337:6;52344:1;52337:9;;;;;;;;:::i;:::-;;;;;;;:18;;;52368:6;52375:1;52368:9;;;;;;;;:::i;:::-;;;;;;;:18;;;52261:6;52268:1;52261:9;;;;;;;;:::i;:::-;;;;;;;:22;;;-1:-1:-1;;;;;52254:47:0;;;:143;;;;;;:::i;:::-;51888:3;;;;:::i;:::-;;;;51849:565;;;;52441:18;52428:9;:31;52420:59;;;;-1:-1:-1;;;52420:59:0;;;;;;;:::i;:::-;52495:109;52514:6;52529:7;52545:14;;52568:8;52585:12;52495:10;:109::i;:::-;52488:116;51440:1170;-1:-1:-1;;;;;;;;51440:1170:0:o;43491:2133::-;43678:17;43784:9;:21;;;43761:9;:19;;;:44;;43753:83;;;;-1:-1:-1;;;43753:83:0;;25017:2:1;43753:83:0;;;24999:21:1;25056:2;25036:18;;;25029:30;25095:28;25075:18;;;25068:56;25141:18;;43753:83:0;24815:350:1;43753:83:0;43873:1;43851:9;:19;;;:23;43843:58;;;;-1:-1:-1;;;43843:58:0;;25372:2:1;43843:58:0;;;25354:21:1;25411:2;25391:18;;;25384:30;-1:-1:-1;;;25430:18:1;;;25423:52;25492:18;;43843:58:0;25170:346:1;43843:58:0;43940:9;:21;;;-1:-1:-1;;;;;43916:45:0;:9;:20;;;-1:-1:-1;;;;;43916:45:0;;43908:81;;;;-1:-1:-1;;;43908:81:0;;24665:2:1;43908:81:0;;;24647:21:1;24704:2;24684:18;;;24677:30;-1:-1:-1;;;24723:18:1;;;24716:53;24786:18;;43908:81:0;24463:347:1;43908:81:0;43998:21;44022:40;44040:9;:21;;;44022:17;:40::i;:::-;44174:16;;;44188:1;44174:16;;;;;;;;;43998:64;;-1:-1:-1;44145:26:0;;44174:16;;;;;;;;;;;;-1:-1:-1;44174:16:0;44145:45;;44212:9;:21;;;44197:9;44207:1;44197:12;;;;;;;;:::i;:::-;;;;;;;;;;:36;44242:92;;-1:-1:-1;;;44242:92:0;;-1:-1:-1;;;;;44242:35:0;;;;;44285:9;;44242:92;;44296:14;;;;44312:9;;44323:10;;44242:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44398:13;44355:40;44373:9;:21;;;44355:17;:40::i;:::-;:56;;;;:::i;:::-;44424:16;;;;44343:68;;-1:-1:-1;;;;;;44424:20:0;;44420:500;;44463:25;;;;-1:-1:-1;;;;;44463:39:0;44455:70;;;;-1:-1:-1;;;44455:70:0;;26080:2:1;44455:70:0;;;26062:21:1;26119:2;26099:18;;;26092:30;-1:-1:-1;;;26138:18:1;;;26131:48;26196:18;;44455:70:0;25878:342:1;44455:70:0;44562:14;44574:2;35534:4;44562:14;:::i;:::-;44542:12;:16;;;-1:-1:-1;;;;;44542:34:0;;;44534:59;;;;-1:-1:-1;;;44534:59:0;;26649:2:1;44534:59:0;;;26631:21:1;26688:2;26668:18;;;26661:30;-1:-1:-1;;;26707:18:1;;;26700:42;26759:18;;44534:59:0;26447:336:1;44534:59:0;44608:25;;;;-1:-1:-1;;;;;44608:42:0;44645:4;44608:42;44604:234;;44663:165;44694:9;:21;;;44728:12;:25;;;35534:4;44814:2;44802:14;;;;:::i;:::-;44778:16;;;;44766:28;;-1:-1:-1;;;;;44766:28:0;:9;:28;:::i;44663:165::-;35534:4;44883:12;:16;;;-1:-1:-1;;;;;44871:28:0;35534:4;44871:28;;;;:::i;:::-;44858:42;;:9;:42;:::i;:::-;:54;;;;:::i;:::-;44846:66;;44420:500;44926:15;44971:9;:21;;;44951:9;44944:49;;;;:::i;:::-;44926:67;;45015:1;45004:8;:12;45000:68;;;45039:9;:21;;;45027:33;;45000:68;45095:9;:19;;;45082:9;:32;;45074:68;;;;-1:-1:-1;;;45074:68:0;;;;;;;:::i;:::-;45232:21;;;;45263:24;;;;45205:162;;45232:21;-1:-1:-1;;;;;45263:38:0;;:78;;45317:9;:24;;;45263:78;;;45304:10;45263:78;45351:9;45205:18;:162::i;:::-;45411:21;;;;;45441:20;;45488:21;;;;;45535:17;;45561:16;;;;45586:25;;;;;45379:239;;45392:10;29985:34:1;;30035:18;;;30028:34;;;;-1:-1:-1;;;;;30098:15:1;;;30078:18;;;30071:43;30130:18;;;30123:34;;;30194:15;;;30188:3;30173:19;;30166:44;29965:3;30226:19;;30219:35;;;-1:-1:-1;;;;;30328:15:1;;;30322:3;30307:19;;30300:44;30381:15;30375:3;30360:19;;30353:44;30434:15;30428:3;30413:19;;30406:44;45379:239:0;;29934:3:1;29919:19;45379:239:0;;;;;;;43700:1924;;;43491:2133;;;;;;;:::o;15499:211::-;15643:58;;-1:-1:-1;;;;;30653:32:1;;15643:58:0;;;30635:51:1;30702:18;;;30695:34;;;15616:86:0;;15636:5;;-1:-1:-1;;;15666:23:0;30608:18:1;;15643:58:0;;;;-1:-1:-1;;15643:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;15643:58:0;-1:-1:-1;;;;;;15643:58:0;;;;;;;;;;15616:19;:86::i;15718:248::-;15889:68;;-1:-1:-1;;;;;30998:15:1;;;15889:68:0;;;30980:34:1;31050:15;;31030:18;;;31023:43;31082:18;;;31075:34;;;15862:96:0;;15882:5;;-1:-1:-1;;;15912:27:0;30915:18:1;;15889:68:0;30740:375:1;21633:191:0;21707:16;21726:6;;-1:-1:-1;;;;;21743:17:0;;;-1:-1:-1;;;;;;21743:17:0;;;;;;21776:40;;21726:6;;;;;;;21776:40;;21707:16;21776:40;21696:128;21633:191;:::o;18566:716::-;18990:23;19016:69;19044:4;19016:69;;;;;;;;;;;;;;;;;19024:5;-1:-1:-1;;;;;19016:27:0;;;:69;;;;;:::i;:::-;19100:17;;18990:95;;-1:-1:-1;19100:21:0;19096:179;;19197:10;19186:30;;;;;;;;;;;;:::i;:::-;19178:85;;;;-1:-1:-1;;;19178:85:0;;31604:2:1;19178:85:0;;;31586:21:1;31643:2;31623:18;;;31616:30;31682:34;31662:18;;;31655:62;-1:-1:-1;;;31733:18:1;;;31726:40;31783:19;;19178:85:0;31402:406:1;9535:229:0;9672:12;9704:52;9726:6;9734:4;9740:1;9743:12;9704:21;:52::i;:::-;9697:59;9535:229;-1:-1:-1;;;;9535:229:0:o;10655:455::-;10825:12;10883:5;10858:21;:30;;10850:81;;;;-1:-1:-1;;;10850:81:0;;32015:2:1;10850:81:0;;;31997:21:1;32054:2;32034:18;;;32027:30;32093:34;32073:18;;;32066:62;-1:-1:-1;;;32144:18:1;;;32137:36;32190:19;;10850:81:0;31813:402:1;10850:81:0;10943:12;10957:23;10984:6;-1:-1:-1;;;;;10984:11:0;11003:5;11010:4;10984:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10942:73;;;;11033:69;11060:6;11068:7;11077:10;11089:12;13413;13442:7;13438:427;;;13470:10;:17;13491:1;13470:22;13466:290;;-1:-1:-1;;;;;7073:19:0;;;13680:60;;;;-1:-1:-1;;;13680:60:0;;32714:2:1;13680:60:0;;;32696:21:1;32753:2;32733:18;;;32726:30;32792:31;32772:18;;;32765:59;32841:18;;13680:60:0;32512:353:1;13680:60:0;-1:-1:-1;13777:10:0;13770:17;;13438:427;13820:33;13828:10;13840:12;14575:17;;:21;14571:388;;14807:10;14801:17;14864:15;14851:10;14847:2;14843:19;14836:44;14571:388;14934:12;14927:20;;-1:-1:-1;;;14927:20:0;;;;;;;;:::i;14:127:1:-;75:10;70:3;66:20;63:1;56:31;106:4;103:1;96:15;130:4;127:1;120:15;146:253;218:2;212:9;260:4;248:17;;-1:-1:-1;;;;;280:34:1;;316:22;;;277:62;274:88;;;342:18;;:::i;:::-;378:2;371:22;146:253;:::o;404:::-;476:2;470:9;518:4;506:17;;-1:-1:-1;;;;;538:34:1;;574:22;;;535:62;532:88;;;600:18;;:::i;662:275::-;733:2;727:9;798:2;779:13;;-1:-1:-1;;775:27:1;763:40;;-1:-1:-1;;;;;818:34:1;;854:22;;;815:62;812:88;;;880:18;;:::i;:::-;916:2;909:22;662:275;;-1:-1:-1;662:275:1:o;942:173::-;1010:20;;-1:-1:-1;;;;;1059:31:1;;1049:42;;1039:70;;1105:1;1102;1095:12;1120:988;1178:5;1226:4;1214:9;1209:3;1205:19;1201:30;1198:50;;;1244:1;1241;1234:12;1198:50;1266:22;;:::i;:::-;1257:31;;1311:29;1330:9;1311:29;:::i;:::-;1304:5;1297:44;1360:2;1422;1411:9;1407:18;1394:32;1389:2;1382:5;1378:14;1371:56;1487:2;1476:9;1472:18;1459:32;1454:2;1447:5;1443:14;1436:56;1543:2;1532:9;1528:18;1515:32;-1:-1:-1;;;;;1607:2:1;1599:6;1596:14;1593:34;;;1623:1;1620;1613:12;1593:34;1661:6;1650:9;1646:22;1636:32;;1706:3;1699:4;1695:2;1691:13;1687:23;1677:51;;1724:1;1721;1714:12;1677:51;1760:2;1747:16;1782:2;1778;1775:10;1772:36;;;1788:18;;:::i;:::-;1830:53;1873:2;1854:13;;-1:-1:-1;;1850:27:1;1846:36;;1830:53;:::i;:::-;1817:66;;1906:2;1899:5;1892:17;1946:3;1941:2;1936;1932;1928:11;1924:20;1921:29;1918:49;;;1963:1;1960;1953:12;1918:49;2018:2;2013;2009;2005:11;2000:2;1993:5;1989:14;1976:45;2062:1;2057:2;2052;2045:5;2041:14;2037:23;2030:34;;2096:5;2091:2;2084:5;2080:14;2073:29;;;;1120:988;;;;:::o;2113:197::-;2187:4;-1:-1:-1;;;;;2212:6:1;2209:30;2206:56;;;2242:18;;:::i;:::-;-1:-1:-1;2287:1:1;2283:14;2299:4;2279:25;;2113:197::o;2315:1083::-;2383:5;2436:3;2429:4;2421:6;2417:17;2413:27;2403:55;;2454:1;2451;2444:12;2403:55;2490:6;2477:20;2516:4;2540:74;2556:57;2610:2;2556:57;:::i;:::-;2540:74;:::i;:::-;2648:15;;;2710:4;2753:11;;;2741:24;;2737:33;;;2679:12;;;;2636:3;2782:15;;;2779:35;;;2810:1;2807;2800:12;2779:35;2846:2;2838:6;2834:15;2858:511;2874:6;2869:3;2866:15;2858:511;;;2950:2;2944:3;2939;2935:13;2931:22;2928:112;;;2994:1;3023:2;3019;3012:14;2928:112;3066:22;;:::i;:::-;3115:23;3134:3;3115:23;:::i;:::-;3108:5;3101:38;3197:2;3192:3;3188:12;3175:26;3170:2;3163:5;3159:14;3152:50;3225:2;3263:32;3291:2;3286:3;3282:12;3263:32;:::i;:::-;3247:14;;;3240:56;3309:18;;3347:12;;;;2891;;2858:511;;;-1:-1:-1;3387:5:1;;2315:1083;-1:-1:-1;;;;;;;2315:1083:1:o;3403:1152::-;3472:5;3525:3;3518:4;3510:6;3506:17;3502:27;3492:55;;3543:1;3540;3533:12;3492:55;3579:6;3566:20;3605:4;3629:74;3645:57;3699:2;3645:57;:::i;3629:74::-;3737:15;;;3823:1;3819:10;;;;3807:23;;3803:32;;;3768:12;;;;3847:15;;;3844:35;;;3875:1;3872;3865:12;3844:35;3911:2;3903:6;3899:15;3923:603;3939:6;3934:3;3931:15;3923:603;;;4017:4;4011:3;4006;4002:13;3998:24;3995:114;;;4063:1;4092:2;4088;4081:14;3995:114;4135:22;;:::i;:::-;4184:23;4203:3;4184:23;:::i;:::-;4170:38;;4257:12;;;4244:26;4228:14;;;4221:50;4294:2;4345:12;;;4332:26;4316:14;;;4309:50;4382:2;4420:32;4439:12;;;4420:32;:::i;:::-;4404:14;;;4397:56;4466:18;;4504:12;;;;3965:4;3956:14;3923:603;;;-1:-1:-1;4544:5:1;3403:1152;-1:-1:-1;;;;;;3403:1152:1:o;4560:347::-;4611:8;4621:6;4675:3;4668:4;4660:6;4656:17;4652:27;4642:55;;4693:1;4690;4683:12;4642:55;-1:-1:-1;4716:20:1;;-1:-1:-1;;;;;4748:30:1;;4745:50;;;4791:1;4788;4781:12;4745:50;4828:4;4820:6;4816:17;4804:29;;4880:3;4873:4;4864:6;4856;4852:19;4848:30;4845:39;4842:59;;;4897:1;4894;4887:12;4842:59;4560:347;;;;;:::o;4912:171::-;4979:20;;-1:-1:-1;;;;;5028:30:1;;5018:41;;5008:69;;5073:1;5070;5063:12;5088:372;5151:5;5199:4;5187:9;5182:3;5178:19;5174:30;5171:50;;;5217:1;5214;5207:12;5171:50;5239:22;;:::i;:::-;5230:31;;5284:28;5302:9;5284:28;:::i;:::-;5277:5;5270:43;5345:37;5378:2;5367:9;5363:18;5345:37;:::i;:::-;5340:2;5333:5;5329:14;5322:61;5415:38;5449:2;5438:9;5434:18;5415:38;:::i;:::-;5410:2;5403:5;5399:14;5392:62;5088:372;;;;:::o;5465:1417::-;5758:6;5766;5774;5782;5790;5798;5806;5859:3;5847:9;5838:7;5834:23;5830:33;5827:53;;;5876:1;5873;5866:12;5827:53;5916:9;5903:23;-1:-1:-1;;;;;5986:2:1;5978:6;5975:14;5972:34;;;6002:1;5999;5992:12;5972:34;6025:62;6079:7;6070:6;6059:9;6055:22;6025:62;:::i;:::-;6015:72;;6140:2;6129:9;6125:18;6112:32;6096:48;;6169:2;6159:8;6156:16;6153:36;;;6185:1;6182;6175:12;6153:36;6208:77;6277:7;6266:8;6255:9;6251:24;6208:77;:::i;:::-;6198:87;;6338:2;6327:9;6323:18;6310:32;6294:48;;6367:2;6357:8;6354:16;6351:36;;;6383:1;6380;6373:12;6351:36;6406:78;6476:7;6465:8;6454:9;6450:24;6406:78;:::i;:::-;6396:88;;6537:2;6526:9;6522:18;6509:32;6493:48;;6566:2;6556:8;6553:16;6550:36;;;6582:1;6579;6572:12;6550:36;;6621:60;6673:7;6662:8;6651:9;6647:24;6621:60;:::i;:::-;6700:8;;-1:-1:-1;6595:86:1;-1:-1:-1;6754:39:1;;-1:-1:-1;6788:3:1;6773:19;;6754:39;:::i;:::-;6744:49;;6812:64;6868:7;6862:3;6851:9;6847:19;6812:64;:::i;:::-;6802:74;;5465:1417;;;;;;;;;;:::o;6887:435::-;6940:3;6978:5;6972:12;7005:6;7000:3;6993:19;7031:4;7060:2;7055:3;7051:12;7044:19;;7097:2;7090:5;7086:14;7118:1;7128:169;7142:6;7139:1;7136:13;7128:169;;;7203:13;;7191:26;;7237:12;;;;7272:15;;;;7164:1;7157:9;7128:169;;;-1:-1:-1;7313:3:1;;6887:435;-1:-1:-1;;;;;6887:435:1:o;7327:261::-;7506:2;7495:9;7488:21;7469:4;7526:56;7578:2;7567:9;7563:18;7555:6;7526:56;:::i;:::-;7518:64;7327:261;-1:-1:-1;;;7327:261:1:o;7593:367::-;7656:8;7666:6;7720:3;7713:4;7705:6;7701:17;7697:27;7687:55;;7738:1;7735;7728:12;7687:55;-1:-1:-1;7761:20:1;;-1:-1:-1;;;;;7793:30:1;;7790:50;;;7836:1;7833;7826:12;7790:50;7873:4;7865:6;7861:17;7849:29;;7933:3;7926:4;7916:6;7913:1;7909:14;7901:6;7897:27;7893:38;7890:47;7887:67;;;7950:1;7947;7940:12;7965:847;8096:6;8104;8112;8120;8128;8181:2;8169:9;8160:7;8156:23;8152:32;8149:52;;;8197:1;8194;8187:12;8149:52;8237:9;8224:23;-1:-1:-1;;;;;8307:2:1;8299:6;8296:14;8293:34;;;8323:1;8320;8313:12;8293:34;8362:70;8424:7;8415:6;8404:9;8400:22;8362:70;:::i;:::-;8451:8;;-1:-1:-1;8336:96:1;-1:-1:-1;8539:2:1;8524:18;;8511:32;;-1:-1:-1;8555:16:1;;;8552:36;;;8584:1;8581;8574:12;8552:36;;8623:72;8687:7;8676:8;8665:9;8661:24;8623:72;:::i;:::-;8714:8;;-1:-1:-1;8597:98:1;-1:-1:-1;8768:38:1;;-1:-1:-1;8802:2:1;8787:18;;8768:38;:::i;:::-;8758:48;;7965:847;;;;;;;;:::o;8817:838::-;8877:5;8925:4;8913:9;8908:3;8904:19;8900:30;8897:50;;;8943:1;8940;8933:12;8897:50;8976:2;8970:9;9018:4;9010:6;9006:17;9089:6;9077:10;9074:22;-1:-1:-1;;;;;9041:10:1;9038:34;9035:62;9032:88;;;9100:18;;:::i;:::-;9136:2;9129:22;9169:6;-1:-1:-1;9169:6:1;9199:29;9218:9;9199:29;:::i;:::-;9191:6;9184:45;9290:2;9279:9;9275:18;9262:32;9257:2;9249:6;9245:15;9238:57;9328:38;9362:2;9351:9;9347:18;9328:38;:::i;:::-;9323:2;9315:6;9311:15;9304:63;9400:38;9434:2;9423:9;9419:18;9400:38;:::i;:::-;9395:2;9387:6;9383:15;9376:63;9501:3;9490:9;9486:19;9473:33;9467:3;9459:6;9455:16;9448:59;9569:3;9558:9;9554:19;9541:33;9535:3;9527:6;9523:16;9516:59;9609:39;9643:3;9632:9;9628:19;9609:39;:::i;:::-;9603:3;9595:6;9591:16;9584:65;;8817:838;;;;:::o;9660:747::-;9822:6;9830;9838;9846;9854;9907:3;9895:9;9886:7;9882:23;9878:33;9875:53;;;9924:1;9921;9914:12;9875:53;9947:51;9990:7;9979:9;9947:51;:::i;:::-;9937:61;;10049:3;10038:9;10034:19;10021:33;-1:-1:-1;;;;;10069:6:1;10066:30;10063:50;;;10109:1;10106;10099:12;10063:50;10148:58;10198:7;10189:6;10178:9;10174:22;10148:58;:::i;:::-;10225:8;;-1:-1:-1;10122:84:1;-1:-1:-1;10279:39:1;;-1:-1:-1;10313:3:1;10298:19;;10279:39;:::i;:::-;10269:49;;10337:64;10393:7;10387:3;10376:9;10372:19;10337:64;:::i;10594:437::-;10680:6;10688;10741:2;10729:9;10720:7;10716:23;10712:32;10709:52;;;10757:1;10754;10747:12;10709:52;10797:9;10784:23;-1:-1:-1;;;;;10822:6:1;10819:30;10816:50;;;10862:1;10859;10852:12;10816:50;10901:70;10963:7;10954:6;10943:9;10939:22;10901:70;:::i;:::-;10990:8;;10875:96;;-1:-1:-1;10594:437:1;-1:-1:-1;;;;10594:437:1:o;11353:1051::-;11565:6;11573;11581;11589;11597;11650:3;11638:9;11629:7;11625:23;11621:33;11618:53;;;11667:1;11664;11657:12;11618:53;11707:9;11694:23;-1:-1:-1;;;;;11777:2:1;11769:6;11766:14;11763:34;;;11793:1;11790;11783:12;11763:34;11816:75;11883:7;11874:6;11863:9;11859:22;11816:75;:::i;:::-;11806:85;;11944:2;11933:9;11929:18;11916:32;11900:48;;11973:2;11963:8;11960:16;11957:36;;;11989:1;11986;11979:12;11957:36;12012:78;12082:7;12071:8;12060:9;12056:24;12012:78;:::i;:::-;12002:88;;12143:2;12132:9;12128:18;12115:32;12099:48;;12172:2;12162:8;12159:16;12156:36;;;12188:1;12185;12178:12;12156:36;;12227:60;12279:7;12268:8;12257:9;12253:24;12227:60;:::i;:::-;12306:8;;-1:-1:-1;12201:86:1;-1:-1:-1;12360:38:1;;-1:-1:-1;12394:2:1;12379:18;;12360:38;:::i;12409:180::-;12468:6;12521:2;12509:9;12500:7;12496:23;12492:32;12489:52;;;12537:1;12534;12527:12;12489:52;-1:-1:-1;12560:23:1;;12409:180;-1:-1:-1;12409:180:1:o;12594:999::-;12794:6;12802;12810;12818;12826;12834;12887:3;12875:9;12866:7;12862:23;12858:33;12855:53;;;12904:1;12901;12894:12;12855:53;12944:9;12931:23;-1:-1:-1;;;;;13014:2:1;13006:6;13003:14;13000:34;;;13030:1;13027;13020:12;13000:34;13053:62;13107:7;13098:6;13087:9;13083:22;13053:62;:::i;:::-;13043:72;;13134:60;13186:7;13181:2;13170:9;13166:18;13134:60;:::i;:::-;13124:70;;13247:3;13236:9;13232:19;13219:33;13203:49;;13277:2;13267:8;13264:16;13261:36;;;13293:1;13290;13283:12;13261:36;;13332:60;13384:7;13373:8;13362:9;13358:24;13332:60;:::i;:::-;13411:8;;-1:-1:-1;13306:86:1;-1:-1:-1;13465:39:1;;-1:-1:-1;13499:3:1;13484:19;;13465:39;:::i;:::-;13455:49;;13523:64;13579:7;13573:3;13562:9;13558:19;13523:64;:::i;:::-;13513:74;;12594:999;;;;;;;;:::o;13598:186::-;13657:6;13710:2;13698:9;13689:7;13685:23;13681:32;13678:52;;;13726:1;13723;13716:12;13678:52;13749:29;13768:9;13749:29;:::i;13789:1185::-;14044:6;14052;14060;14068;14076;14084;14137:3;14125:9;14116:7;14112:23;14108:33;14105:53;;;14154:1;14151;14144:12;14105:53;14194:9;14181:23;-1:-1:-1;;;;;14264:2:1;14256:6;14253:14;14250:34;;;14280:1;14277;14270:12;14250:34;14303:75;14370:7;14361:6;14350:9;14346:22;14303:75;:::i;:::-;14293:85;;14431:2;14420:9;14416:18;14403:32;14387:48;;14460:2;14450:8;14447:16;14444:36;;;14476:1;14473;14466:12;14444:36;14499:78;14569:7;14558:8;14547:9;14543:24;14499:78;:::i;:::-;14489:88;;14630:2;14619:9;14615:18;14602:32;14586:48;;14659:2;14649:8;14646:16;14643:36;;;14675:1;14672;14665:12;14643:36;;14714:60;14766:7;14755:8;14744:9;14740:24;14714:60;:::i;:::-;14793:8;;-1:-1:-1;14688:86:1;-1:-1:-1;14847:38:1;;-1:-1:-1;14881:2:1;14866:18;;14847:38;:::i;:::-;14837:48;;14904:64;14960:7;14954:3;14943:9;14939:19;14904:64;:::i;14979:127::-;15040:10;15035:3;15031:20;15028:1;15021:31;15071:4;15068:1;15061:15;15095:4;15092:1;15085:15;15111:128;15178:9;;;15199:11;;;15196:37;;;15213:18;;:::i;15244:127::-;15305:10;15300:3;15296:20;15293:1;15286:31;15336:4;15333:1;15326:15;15360:4;15357:1;15350:15;15376:184;15446:6;15499:2;15487:9;15478:7;15474:23;15470:32;15467:52;;;15515:1;15512;15505:12;15467:52;-1:-1:-1;15538:16:1;;15376:184;-1:-1:-1;15376:184:1:o;15565:135::-;15604:3;15625:17;;;15622:43;;15645:18;;:::i;:::-;-1:-1:-1;15692:1:1;15681:13;;15565:135::o;15705:339::-;15907:2;15889:21;;;15946:2;15926:18;;;15919:30;-1:-1:-1;;;15980:2:1;15965:18;;15958:45;16035:2;16020:18;;15705:339::o;16237:489::-;16314:3;16352:5;16346:12;16379:6;16374:3;16367:19;16405:4;16434:2;16429:3;16425:12;16418:19;;16471:2;16464:5;16460:14;16492:1;16502:199;16516:6;16513:1;16510:13;16502:199;;;16565:54;16615:3;16606:6;16600:13;16135:12;;-1:-1:-1;;;;;16131:38:1;16119:51;;16219:4;16208:16;;;16202:23;16186:14;;16179:47;16049:183;16565:54;16648:4;16639:14;;;;;16676:15;;;;16538:1;16531:9;16502:199;;16731:250;16816:1;16826:113;16840:6;16837:1;16834:13;16826:113;;;16916:11;;;16910:18;16897:11;;;16890:39;16862:2;16855:10;16826:113;;;-1:-1:-1;;16973:1:1;16955:16;;16948:27;16731:250::o;16986:270::-;17027:3;17065:5;17059:12;17092:6;17087:3;17080:19;17108:76;17177:6;17170:4;17165:3;17161:14;17154:4;17147:5;17143:16;17108:76;:::i;:::-;17238:2;17217:15;-1:-1:-1;;17213:29:1;17204:39;;;;17245:4;17200:50;;16986:270;-1:-1:-1;;16986:270:1:o;17261:1440::-;17704:3;17693:9;17686:22;17667:4;17746:3;17735:9;17731:19;17785:6;17779:13;17829:4;17823:3;17812:9;17808:19;17801:33;17854:6;17889:12;17883:19;17926:6;17918;17911:22;17964:3;17953:9;17949:19;17942:26;;17987:4;17977:14;;18032:2;18018:12;18014:21;18000:35;;18053:1;18063:199;18077:6;18074:1;18071:13;18063:199;;;18126:54;18176:3;18167:6;18161:13;16135:12;;-1:-1:-1;;;;;16131:38:1;16119:51;;16219:4;16208:16;;;16202:23;16186:14;;16179:47;16049:183;18126:54;18237:15;;;;18209:4;18200:14;;;;;18099:1;18092:9;18063:199;;;18067:3;;18317:2;18309:6;18305:15;18299:22;18293:3;18282:9;18278:19;18271:51;18377:4;18369:6;18365:17;18359:24;18353:3;18342:9;18338:19;18331:53;18429:9;18424:3;18420:19;18415:2;18404:9;18400:18;18393:47;18463:65;18524:3;18516:6;18463:65;:::i;:::-;18449:79;;;;18537:48;18579:4;18568:9;18564:20;18556:6;-1:-1:-1;;;;;11102:31:1;11090:44;;11036:104;18537:48;18635:9;18627:6;18623:22;18616:4;18605:9;18601:20;18594:52;18663:32;18688:6;18680;18663:32;:::i;19815:692::-;20078:2;20067:9;20060:21;20117:6;20112:2;20101:9;20097:18;20090:34;20175:6;20167;20161:3;20150:9;20146:19;20133:49;20232:1;20226:3;20217:6;20206:9;20202:22;20198:32;20191:43;20041:4;20293:2;20289:7;20284:2;20276:6;20272:15;20268:29;20257:9;20253:45;20360:3;20348:9;20344:2;20340:18;20336:28;20329:4;20318:9;20314:20;20307:58;20382:50;20427:3;20423:2;20419:12;20411:6;20382:50;:::i;:::-;20374:58;;;20497:1;20493;20488:3;20484:11;20480:19;20472:6;20468:32;20463:2;20452:9;20448:18;20441:60;19815:692;;;;;;;:::o;20512:347::-;20714:2;20696:21;;;20753:2;20733:18;;;20726:30;20792:25;20787:2;20772:18;;20765:53;20850:2;20835:18;;20512:347::o;20864:461::-;20917:3;20955:5;20949:12;20982:6;20977:3;20970:19;21008:4;21037:2;21032:3;21028:12;21021:19;;21074:2;21067:5;21063:14;21095:1;21105:195;21119:6;21116:1;21113:13;21105:195;;;21184:13;;-1:-1:-1;;;;;21180:39:1;21168:52;;21240:12;;;;21275:15;;;;21216:1;21134:9;21105:195;;21769:1510;-1:-1:-1;;;;;22444:15:1;;;22426:34;;22376:3;22491:2;22476:18;;22469:30;;;22347:4;;22522:56;22559:18;;;22551:6;22522:56;:::i;:::-;22508:70;;22626:9;22618:6;22614:22;22609:2;22598:9;22594:18;22587:50;22660:44;22697:6;22689;22660:44;:::i;:::-;22646:58;;22752:9;22744:6;22740:22;22735:2;22724:9;22720:18;22713:50;22786:44;22823:6;22815;22786:44;:::i;:::-;22772:58;;22879:9;22871:6;22867:22;22861:3;22850:9;22846:19;22839:51;22913:44;22950:6;22942;22913:44;:::i;:::-;22899:58;;23006:9;22998:6;22994:22;22988:3;22977:9;22973:19;22966:51;23034:43;23070:6;23062;23034:43;:::i;:::-;-1:-1:-1;;;;;23151:15:1;;;23145:3;23130:19;;23123:44;23204:15;;;;23198:3;23183:19;;23176:44;-1:-1:-1;;23257:15:1;;23251:3;23236:19;;;23229:44;;;;23026:51;21769:1510;-1:-1:-1;;;;;;21769:1510:1:o;23284:822::-;23630:4;23659:3;23671:60;23721:9;23712:6;23706:13;16135:12;;-1:-1:-1;;;;;16131:38:1;16119:51;;16219:4;16208:16;;;16202:23;16186:14;;16179:47;16049:183;23671:60;23787:4;23779:6;23775:17;23769:24;23762:4;23751:9;23747:20;23740:54;23850:4;23842:6;23838:17;23832:24;23825:4;23814:9;23810:20;23803:54;23866:63;23924:3;23913:9;23909:19;23901:6;16135:12;;-1:-1:-1;;;;;16131:38:1;16119:51;;16219:4;16208:16;;;16202:23;16186:14;;16179:47;16049:183;23866:63;-1:-1:-1;;;;;23966:32:1;;23960:3;23945:19;;23938:61;24030:3;24015:19;;24008:31;;;24056:44;24081:18;;;24073:6;24056:44;:::i;26225:217::-;26265:1;26291;26281:132;;26335:10;26330:3;26326:20;26323:1;26316:31;26370:4;26367:1;26360:15;26398:4;26395:1;26388:15;26281:132;-1:-1:-1;26427:9:1;;26225:217::o;26788:168::-;26861:9;;;26892;;26909:15;;;26903:22;;26889:37;26879:71;;26930:18;;:::i;26961:200::-;27027:9;;;27000:4;27055:9;;27083:10;;27095:12;;;27079:29;27118:12;;;27110:21;;27076:56;27073:82;;;27135:18;;:::i;:::-;27073:82;26961:200;;;;:::o;31120:277::-;31187:6;31240:2;31228:9;31219:7;31215:23;31211:32;31208:52;;;31256:1;31253;31246:12;31208:52;31288:9;31282:16;31341:5;31334:13;31327:21;31320:5;31317:32;31307:60;;31363:1;31360;31353:12;32220:287;32349:3;32387:6;32381:13;32403:66;32462:6;32457:3;32450:4;32442:6;32438:17;32403:66;:::i;:::-;32485:16;;;;;32220:287;-1:-1:-1;;32220:287:1:o;32870:219::-;33019:2;33008:9;33001:21;32982:4;33039:44;33079:2;33068:9;33064:18;33056:6;33039:44;:::i
Swarm Source
ipfs://8403cc00b2f60ffd39bea8f9569830cb900e249332880f3e2bdf46c037bc0a57
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0.000001
Token Allocations
FRAX
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| FRAXTAL | 100.00% | $0.787425 | 0.000000751561 | $0.000001 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.