Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Factory Sett... | 10019889 | 29 hrs ago | IN | 0 S | 0.00274747 |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
DexSpan
Compiler Version
v0.8.21+commit.d9974bed
Contract Source Code (Solidity)
/** *Submitted for verification at SonicScan.org on 2025-02-25 */ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0 ^0.8.1 ^0.8.2 ^0.8.20; // contracts/dexspan/interface/IAugustusSwapper.sol interface IAugustusSwapper { function getTokenTransferProxy() external view returns (address); } // contracts/dexspan/interface/IEthHandler.sol interface IEthHandler { function withdraw(address WETH, uint256) external; } // contracts/dexspan/interface/IHandlerReserve.sol interface IHandlerReserve { function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); } // contracts/dexspan/libraries/TransferHelper.sol // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove(address token, address to, uint256 value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call( abi.encodeWithSelector(0x095ea7b3, to, value) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeApprove: approve failed" ); } function safeTransfer(address token, address to, uint256 value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call( abi.encodeWithSelector(0xa9059cbb, to, value) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeTransfer: transfer failed" ); } function safeTransferFrom( address token, address from, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call( abi.encodeWithSelector(0x23b872dd, from, to, value) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::transferFrom: transferFrom failed" ); } } // contracts/interfaces/IAssetForwarder.sol /// @title Interface for handler contracts that support deposits and deposit executions. /// @author Router Protocol. interface IAssetForwarder { event FundsDeposited( uint256 partnerId, uint256 amount, bytes32 destChainIdBytes, uint256 destAmount, uint256 depositId, address srcToken, address depositor, bytes recipient, bytes destToken ); event FundsDepositedWithMessage( uint256 partnerId, uint256 amount, bytes32 destChainIdBytes, uint256 destAmount, uint256 depositId, address srcToken, bytes recipient, address depositor, bytes destToken, bytes message ); event FundsPaid(bytes32 messageHash, address forwarder, uint256 nonce); event DepositInfoUpdate( address srcToken, uint256 feeAmount, uint256 depositId, uint256 eventNonce, bool initiatewithdrawal, address depositor ); event FundsPaidWithMessage( bytes32 messageHash, address forwarder, uint256 nonce, bool execFlag, bytes execData ); struct RelayData { uint256 amount; bytes32 srcChainId; uint256 depositId; address destToken; address recipient; } struct RelayDataMessage { uint256 amount; bytes32 srcChainId; uint256 depositId; address destToken; address recipient; bytes message; } struct DepositData { uint256 partnerId; uint256 amount; uint256 destAmount; address srcToken; address refundRecipient; bytes32 destChainIdBytes; } function iDeposit( DepositData memory depositData, bytes memory destToken, bytes memory recipient ) external payable; function iDepositInfoUpdate( address srcToken, uint256 feeAmount, uint256 depositId, bool initiatewithdrawal ) external payable; function iDepositMessage( DepositData memory depositData, bytes memory destToken, bytes memory recipient, bytes memory message ) external payable; function iRelay(RelayData memory relayData) external payable; function iRelayMessage(RelayDataMessage memory relayData) external payable; } // contracts/interfaces/IMessageHandler.sol /// @title Handles ERC20 deposits and deposit executions. /// @author Router Protocol. /// @notice This contract is intended to be used with the Bridge contract. interface IMessageHandler { function handleMessage( address tokenSent, uint256 amount, bytes memory message ) external; } // node_modules/@openzeppelin/contracts/access/IAccessControl.sol // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; } // node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); } // node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) /** * @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); } // node_modules/@openzeppelin/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/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); } } } // node_modules/@openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // node_modules/@openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } } // node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } } // node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); } // node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20PermitUpgradeable { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/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); } } } // node_modules/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) /** * @dev Standard math utilities missing in the Solidity language. */ library MathUpgradeable { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } } // node_modules/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } } // contracts/dexspan/IDexSpan.sol contract DexSpanFlags { // flags = FLAG_DISABLE_UNISWAP + FLAG_DISABLE_BANCOR + ... uint256 internal constant FLAG_DISABLE_UNISWAP = 0x400; uint256 internal constant FLAG_DISABLE_SPLIT_RECALCULATION = 0x800000000000; uint256 internal constant FLAG_DISABLE_ALL_SPLIT_SOURCES = 0x20000000; uint256 internal constant FLAG_DISABLE_UNISWAP_V2_ALL = 0x400; uint256 internal constant FLAG_DISABLE_EMPTY = 0x100000000000; uint256 internal constant FLAG_DISABLE_DFYN = 0x800; uint256 internal constant FLAG_DISABLE_PANCAKESWAP = 0x80; uint256 internal constant FLAG_DISABLE_QUICKSWAP = 0x40000000000; uint256 internal constant FLAG_DISABLE_SUSHISWAP = 0x1000000; uint256 internal constant FLAG_DISABLE_ONEINCH = 0x100000; } abstract contract IDexSpan is DexSpanFlags { function getExpectedReturn( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 parts, uint256 flags // See constants in IOneSplit.sol ) public view virtual returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGasMulti( IERC20Upgradeable[] memory tokens, uint256 amount, uint256[] memory parts, uint256[] memory flags, uint256[] memory destTokenEthPriceTimesGasPrices ) public view virtual returns ( uint256[] memory returnAmounts, uint256 estimateGasAmount, uint256[] memory distribution ); function getExpectedReturnWithGas( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 parts, uint256 flags, // See constants in IOneSplit.sol uint256 destTokenEthPriceTimesGasPrice ) public view virtual returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); function setHandlerAddress( address _handlerAddress ) external virtual returns (bool); function setReserveAddress( address _reserveAddress ) external virtual returns (bool); function setBridgeAddress( address _bridgeAddress ) external virtual returns (bool); function withdraw( address tokenAddress, address recipient, uint256 amount ) public payable virtual returns (bool); function swap( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper ) public payable virtual returns (uint256 returnAmount); function swapWithRecipient( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory dataTx, bool isWrapper, address recipient ) public payable virtual returns (uint256 returnAmount); function swapMulti( IERC20Upgradeable[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper ) public payable virtual returns (uint256 returnAmount); function swapMultiWithRecipient( IERC20Upgradeable[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper, address recipient ) public payable virtual returns (uint256 returnAmount); function getExpectedReturnETH( IERC20Upgradeable srcStablefromtoken, uint256 srcStableFromTokenAmount, uint256 parts, uint256 flags ) public view virtual returns (uint256 returnAmount); function swapInSameChain( address[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper, address recipient, uint256 widgetID ) public payable virtual returns (uint256 returnAmount); } // contracts/dexspan/interface/IUniswapExchange.sol interface IUniswapExchange { function getEthToTokenInputPrice( uint256 ethSold ) external view returns (uint256 tokensBought); function getTokenToEthInputPrice( uint256 tokensSold ) external view returns (uint256 ethBought); function ethToTokenSwapInput( uint256 minTokens, uint256 deadline ) external payable returns (uint256 tokensBought); function tokenToEthSwapInput( uint256 tokensSold, uint256 minEth, uint256 deadline ) external returns (uint256 ethBought); function tokenToTokenSwapInput( uint256 tokensSold, uint256 minTokensBought, uint256 minEthBought, uint256 deadline, address tokenAddr ) external returns (uint256 tokensBought); } // contracts/dexspan/interface/IWETH.sol abstract contract IWETH is IERC20Upgradeable { function deposit() external payable virtual; function withdraw(uint256 amount) external virtual; } // node_modules/@openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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); } } // node_modules/@openzeppelin/contracts/utils/Multicall.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/Multicall.sol) /** * @dev Provides a function to batch together multiple calls in a single external call. * * _Available since v4.1._ */ abstract contract Multicall_0 { /** * @dev Receives and executes a batch of function calls on this contract. * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { results[i] = Address.functionDelegateCall(address(this), data[i]); } return results; } } // node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } } // contracts/dexspan/interface/IUniswapFactory.sol interface IUniswapFactory { function getExchange( IERC20Upgradeable token ) external view returns (IUniswapExchange exchange); } // contracts/dexspan/libraries/Multicall.sol /// @notice Helper utility that enables calling multiple local methods in a single call. /// @author Modified from Uniswap (https://github.com/Uniswap/v3-periphery/blob/main/contracts/base/Multicall.sol) /// License-Identifier: GPL-2.0-or-later abstract contract Multicall_1 is Initializable { function __Multicall_init() internal onlyInitializing {} function __Multicall_init_unchained() internal onlyInitializing {} function multicall( bytes[] calldata data ) public payable returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i; i < data.length; ) { (bool success, bytes memory result) = address(this).delegatecall( data[i] ); if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 if (result.length < 68) revert(); assembly { result := add(result, 0x04) } revert(abi.decode(result, (string))); } results[i] = result; // cannot realistically overflow on human timescales unchecked { ++i; } } } } // node_modules/@openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } } // node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) /** * @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; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ 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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ 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"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ 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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } } // node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20Upgradeable { using AddressUpgradeable for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20PermitUpgradeable token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token)); } } // contracts/dexspan/UniversalERC20.sol library UniversalERC20 { using SafeMathUpgradeable for uint256; using SafeERC20Upgradeable for IERC20Upgradeable; IERC20Upgradeable private constant ZERO_ADDRESS = IERC20Upgradeable(0x0000000000000000000000000000000000000000); IERC20Upgradeable private constant ETH_ADDRESS = IERC20Upgradeable(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); function universalTransfer( IERC20Upgradeable token, address to, uint256 amount ) internal returns (bool) { if (amount == 0) { return true; } if (isETH(token)) { (bool success, ) = payable(address(uint160(to))).call{ value: amount }(""); assert(success == true); } else { TransferHelper.safeTransfer(address(token), to, amount); return true; } } function universalTransferFrom( IERC20Upgradeable token, address from, address to, uint256 amount ) internal { if (amount == 0) { return; } if (isETH(token)) { require( from == msg.sender && msg.value >= amount, "Wrong usage of ETH.universalTransferFrom()" ); if (to != address(this)) { (bool success, ) = payable(address(uint160(to))).call{ value: amount }(""); assert(success == true); } if (msg.value > amount) { (bool success, ) = payable(msg.sender).call{ value: msg.value.sub(amount) }(""); assert(success == true); } } else { TransferHelper.safeTransferFrom(address(token), from, to, amount); } } function universalTransferFromSenderToThis( IERC20Upgradeable token, uint256 amount ) internal { if (amount == 0) { return; } if (isETH(token)) { if (msg.value > amount) { // Return remainder if exist (bool success, ) = payable(msg.sender).call{ value: msg.value.sub(amount) }(""); assert(success == true); } } else { TransferHelper.safeTransferFrom( address(token), msg.sender, address(this), amount ); } } function universalApprove( IERC20Upgradeable token, address to, uint256 amount ) internal { if (!isETH(token)) { // if (amount == 0) { // TransferHelper.safeApprove(address(token), to, 0); // return; // } // uint256 allowance = token.allowance(address(this), to); // if (allowance < amount) { // if (allowance > 0) { // TransferHelper.safeApprove(address(token), to, 0); // } // TransferHelper.safeApprove(address(token), to, amount); // } TransferHelper.safeApprove(address(token), to, 0); TransferHelper.safeApprove(address(token), to, amount); } } function universalBalanceOf( IERC20Upgradeable token, address who ) internal view returns (uint256) { if (isETH(token)) { return who.balance; } else { return token.balanceOf(who); } } function isETH(IERC20Upgradeable token) internal pure returns (bool) { return (address(token) == address(ZERO_ADDRESS) || address(token) == address(ETH_ADDRESS)); } function eq( IERC20Upgradeable a, IERC20Upgradeable b ) internal pure returns (bool) { return a == b || (isETH(a) && isETH(b)); } } // node_modules/@openzeppelin/contracts/access/AccessControl.sol // OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol) /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } } // contracts/dexspan/interface/IUniswapV2Exchange.sol interface IUniswapV2Exchange { function getReserves() external view returns ( uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast ); function swap( uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data ) external; function skim(address to) external; function sync() external; } library UniswapV2ExchangeLib { using MathUpgradeable for uint256; using SafeMathUpgradeable for uint256; using UniversalERC20 for IERC20Upgradeable; function getReturn( IUniswapV2Exchange exchange, IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amountIn ) internal view returns (uint256 result, bool needSync, bool needSkim) { uint256 reserveIn = fromToken.universalBalanceOf(address(exchange)); uint256 reserveOut = destToken.universalBalanceOf(address(exchange)); (uint112 reserve0, uint112 reserve1, ) = exchange.getReserves(); if (fromToken > destToken) { (reserve0, reserve1) = (reserve1, reserve0); } needSync = (reserveIn < reserve0 || reserveOut < reserve1); needSkim = !needSync && (reserveIn > reserve0 || reserveOut > reserve1); uint256 amountInWithFee = amountIn.mul(997); uint256 numerator = amountInWithFee.mul( MathUpgradeable.min(reserveOut, reserve1) ); uint256 denominator = MathUpgradeable .min(reserveIn, reserve0) .mul(1000) .add(amountInWithFee); result = (denominator == 0) ? 0 : numerator.div(denominator); } } // contracts/dexspan/interface/IUniswapV2Factory.sol interface IUniswapV2Factory { function getPair( IERC20Upgradeable tokenA, IERC20Upgradeable tokenB ) external view returns (IUniswapV2Exchange pair); } // contracts/dexspan/DexSpanRoot.sol // import "./libraries/Multicall.sol"; library DisableFlags { function check(uint256 flags, uint256 flag) internal pure returns (bool) { return (flags & flag) != 0; } } contract DexSpanRoot { using SafeMath for uint256; using DisableFlags for uint256; using UniversalERC20 for IERC20Upgradeable; using UniversalERC20 for IWETH; using UniswapV2ExchangeLib for IUniswapV2Exchange; uint256 internal constant DEXES_COUNT = 4; uint256 public constant DEXES_COUNT_UPDATED = 1; IERC20Upgradeable internal ZERO_ADDRESS; int256 internal constant VERY_NEGATIVE_VALUE = -1e72; IWETH public wnativeAddress; IERC20Upgradeable public nativeAddress; function _findBestDistribution( uint256 s, // parts int256[][] memory amounts // exchangesReturns ) internal pure returns (int256 returnAmount, uint256[] memory distribution) { uint256 n = amounts.length; int256[][] memory answer = new int256[][](n); // int[n][s+1] uint256[][] memory parent = new uint256[][](n); // int[n][s+1] for (uint256 i; i < n; i++) { answer[i] = new int256[](s + 1); parent[i] = new uint256[](s + 1); } for (uint256 j; j <= s; j++) { answer[0][j] = amounts[0][j]; for (uint256 i = 1; i < n; i++) { answer[i][j] = -1e72; } parent[0][j] = 0; } for (uint256 i = 1; i < n; i++) { for (uint256 j; j <= s; j++) { answer[i][j] = answer[i - 1][j]; parent[i][j] = j; for (uint256 k = 1; k <= j; k++) { if (answer[i - 1][j - k] + amounts[i][k] > answer[i][j]) { answer[i][j] = answer[i - 1][j - k] + amounts[i][k]; parent[i][j] = j - k; } } } } distribution = new uint256[](DEXES_COUNT_UPDATED); uint256 partsLeft = s; for (uint256 curExchange = n - 1; partsLeft > 0; curExchange--) { distribution[curExchange] = partsLeft - parent[curExchange][partsLeft]; partsLeft = parent[curExchange][partsLeft]; } returnAmount = (answer[n - 1][s] == VERY_NEGATIVE_VALUE) ? int256(0) : answer[n - 1][s]; } function _linearInterpolation( uint256 value, uint256 parts ) internal pure returns (uint256[] memory rets) { rets = new uint256[](parts); for (uint256 i = 0; i < parts; i++) { rets[i] = value.mul(i + 1).div(parts); } } function _tokensEqual( IERC20Upgradeable tokenA, IERC20Upgradeable tokenB ) internal pure returns (bool) { return ((tokenA.isETH() && tokenB.isETH()) || tokenA == tokenB); } } // contracts/dexspan/DexSpanView.sol abstract contract IDexSpanView is DexSpanFlags { function getExpectedReturn( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 parts, uint256 flags ) public view virtual returns (uint256 returnAmount, uint256[] memory distribution); function getExpectedReturnWithGas( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 parts, uint256 flags, uint256 destTokenEthPriceTimesGasPrice ) public view virtual returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ); } contract DexSpanView is IDexSpanView, DexSpanRoot, AccessControl { using SafeMath for uint256; using DisableFlags for uint256; using SafeERC20 for IERC20Upgradeable; using UniversalERC20 for IERC20Upgradeable; constructor() { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); } function getExpectedReturn( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 parts, uint256 flags // See constants in IOneSplit.sol ) public view override returns (uint256 returnAmount, uint256[] memory distribution) { (returnAmount, , distribution) = getExpectedReturnWithGas( fromToken, destToken, amount, parts, flags, 0 ); } function getExpectedReturnWithGas( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 parts, uint256 flags, // See constants in IOneSplit.sol uint256 destTokenEthPriceTimesGasPrice ) public view override returns ( uint256 returnAmount, uint256 estimateGasAmount, uint256[] memory distribution ) { distribution = new uint256[](DEXES_COUNT_UPDATED); if (fromToken == destToken) { return (amount, 0, distribution); } function(IERC20Upgradeable, IERC20Upgradeable, uint256, uint256) view returns (uint256[] memory, uint256)[DEXES_COUNT_UPDATED] memory reserves = _getAllReserves(flags); int256[][] memory matrix = new int256[][](DEXES_COUNT_UPDATED); uint256[DEXES_COUNT_UPDATED] memory gases; bool atLeastOnePositive = false; for (uint256 i; i < DEXES_COUNT_UPDATED; i++) { uint256[] memory rets; (rets, gases[i]) = reserves[i](fromToken, destToken, amount, parts); // Prepend zero and sub gas int256 gas = int256( gases[i].mul(destTokenEthPriceTimesGasPrice).div(1e18) ); matrix[i] = new int256[](parts + 1); for (uint256 j; j < rets.length; j++) { matrix[i][j + 1] = int256(rets[j]) - gas; atLeastOnePositive = atLeastOnePositive || (matrix[i][j + 1] > 0); } } if (!atLeastOnePositive) { for (uint256 i; i < DEXES_COUNT_UPDATED; i++) { for (uint256 j = 1; j < parts + 1; j++) { if (matrix[i][j] == 0) { matrix[i][j] = VERY_NEGATIVE_VALUE; } } } } (, distribution) = _findBestDistribution(parts, matrix); (returnAmount, estimateGasAmount) = _getReturnAndGasByDistribution( Args({ fromToken: fromToken, destToken: destToken, amount: amount, parts: parts, flags: flags, destTokenEthPriceTimesGasPrice: destTokenEthPriceTimesGasPrice, distribution: distribution, matrix: matrix, gases: gases, reserves: reserves }) ); return (returnAmount, estimateGasAmount, distribution); } struct Args { IERC20Upgradeable fromToken; IERC20Upgradeable destToken; uint256 amount; uint256 parts; uint256 flags; uint256 destTokenEthPriceTimesGasPrice; uint256[] distribution; int256[][] matrix; uint256[DEXES_COUNT_UPDATED] gases; function(IERC20Upgradeable, IERC20Upgradeable, uint256, uint256) view returns (uint256[] memory, uint256)[DEXES_COUNT_UPDATED] reserves; } function _getReturnAndGasByDistribution( Args memory args ) internal view returns (uint256 returnAmount, uint256 estimateGasAmount) { bool[DEXES_COUNT_UPDATED] memory exact = [ true //empty ]; for (uint256 i; i < DEXES_COUNT_UPDATED; i++) { if (args.distribution[i] > 0) { if ( args.distribution[i] == args.parts || exact[i] || args.flags.check(FLAG_DISABLE_SPLIT_RECALCULATION) ) { estimateGasAmount = estimateGasAmount.add(args.gases[i]); int256 value = args.matrix[i][args.distribution[i]]; returnAmount = returnAmount.add( uint256( (value == VERY_NEGATIVE_VALUE ? int256(0) : value) + int256( args .gases[i] .mul( args.destTokenEthPriceTimesGasPrice ) .div(1e18) ) ) ); } else { (uint256[] memory rets, uint256 gas) = args.reserves[i]( args.fromToken, args.destToken, args.amount.mul(args.distribution[i]).div(args.parts), 1 ); estimateGasAmount = estimateGasAmount.add(gas); returnAmount = returnAmount.add(rets[0]); } } } } function _getAllReserves( uint256 flags ) internal pure returns ( function(IERC20Upgradeable, IERC20Upgradeable, uint256, uint256) view returns (uint256[] memory, uint256)[DEXES_COUNT_UPDATED] memory ) { return [_calculateNoReturn]; } function _calculateUniswapFormula( uint256 fromBalance, uint256 toBalance, uint256 amount ) internal pure returns (uint256) { if (amount == 0) { return 0; } return amount.mul(toBalance).mul(997).div( fromBalance.mul(1000).add(amount.mul(997)) ); } function _calculateSwap( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256[] memory amounts, IUniswapV2Factory exchangeInstance ) internal view returns (uint256[] memory rets, uint256 gas) { rets = new uint256[](amounts.length); IERC20Upgradeable fromTokenReal = fromToken.isETH() ? wnativeAddress : fromToken; IERC20Upgradeable destTokenReal = destToken.isETH() ? wnativeAddress : destToken; IUniswapV2Exchange exchange = exchangeInstance.getPair( fromTokenReal, destTokenReal ); if (exchange != IUniswapV2Exchange(address(0))) { uint256 fromTokenBalance = fromTokenReal.universalBalanceOf( address(exchange) ); uint256 destTokenBalance = destTokenReal.universalBalanceOf( address(exchange) ); for (uint256 i = 0; i < amounts.length; i++) { rets[i] = _calculateUniswapFormula( fromTokenBalance, destTokenBalance, amounts[i] ); } return (rets, 50_000); } } function _calculateNoReturn( IERC20Upgradeable /*fromToken*/, IERC20Upgradeable /*destToken*/, uint256 /*amount*/, uint256 parts ) internal view returns (uint256[] memory rets, uint256 gas) { this; return (new uint256[](parts), 0); } } // contracts/dexspan/DexSpan.sol // import "./libraries/Multicall.sol"; contract DexSpan is DexSpanFlags, DexSpanRoot, AccessControl, Multicall_0 { using UniversalERC20 for IERC20Upgradeable; using SafeMath for uint256; using DisableFlags for uint256; using UniswapV2ExchangeLib for IUniswapV2Exchange; IAssetForwarder public assetForwarder; address public assetBridge; address public univ2SkimAddress; address public newOwner; // IWETH public wnativeAddress; mapping(uint256 => address) public flagToAddress; event Swap( string indexed funcName, IERC20Upgradeable[] tokenPath, uint256 amount, address indexed sender, address indexed receiver, uint256 finalAmt, uint256[] flags, uint256 widgetID ); event SwapWithRecipient( string indexed funcName, IERC20Upgradeable[] tokenPath, uint256 amount, address indexed sender, address indexed receiver, uint256 finalAmt, uint256[] flags, uint256 widgetID ); event SwapOnSameChain( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint amount, bytes _data, uint256 flags ); event SetAssetForwarder(address assetForwarder, address admin); event SetAssetBridge(address assetBridge, address admin); event SetFlagToFactory(uint flag, address factoryAddress); event SetFactorySetter(address factorySetter); event SetWNativeAddresses(address wrappedNative); event TransferOwnership(address newOwner); event ClaimOwnership(address newOwner); error InvalidPool(); error InvalidCaller(); error ZeroAddress(); error ZeroFlag(); error RestrictNativeToken(); error WrongTokenSent(); error WrongDataLength(); error AmountTooLow(); error ExcecutionFailed(); error AlreadyFactorySetter(); error InvalidDepositType(); struct DexesArgs { IERC20Upgradeable factoryAddress; uint256 _exchangeCode; } struct SwapParams { IERC20Upgradeable[] tokens; uint256 amount; uint256 minReturn; uint256 destAmount; uint256[] flags; bytes[] dataTx; bool isWrapper; address recipient; bytes destToken; } bytes32 public constant FACTORY_SETTER_ROLE = keccak256("FACTORY_SETTER_ROLE"); bytes4 internal constant SWAP_MULTI_WITH_RECEPIENT_SELECTOR = 0xe738aa8d; receive() external payable {} constructor( address _assetForwarderAddress, address _native, address _wrappedNative, address _univ2SkimAddress ) { if (_assetForwarderAddress == address(0)) revert ZeroAddress(); if (_native == address(0)) revert ZeroAddress(); if (_wrappedNative == address(0)) revert ZeroAddress(); if (_univ2SkimAddress == address(0)) revert ZeroAddress(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); assetForwarder = IAssetForwarder(_assetForwarderAddress); nativeAddress = IERC20Upgradeable(_native); wnativeAddress = IWETH(_wrappedNative); univ2SkimAddress = _univ2SkimAddress; } function transferOwnership( address _newOwner ) external onlyRole(DEFAULT_ADMIN_ROLE) { if (_newOwner == address(0)) revert ZeroAddress(); newOwner = _newOwner; emit TransferOwnership(_newOwner); } function claimOwnership() external { if (newOwner != msg.sender) { revert InvalidCaller(); } _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); emit ClaimOwnership(msg.sender); } function setAssetForwarder( address _forwarder ) external onlyRole(DEFAULT_ADMIN_ROLE) { if (_forwarder == address(0)) revert ZeroAddress(); assetForwarder = IAssetForwarder(_forwarder); emit SetAssetForwarder(_forwarder, msg.sender); } function setAssetBridge( address _assetBridge ) external onlyRole(DEFAULT_ADMIN_ROLE) { if (_assetBridge == address(0)) revert ZeroAddress(); assetBridge = _assetBridge; emit SetAssetBridge(_assetBridge, msg.sender); } function setFlagToFactoryAddress( uint256 _flagCode, address _factoryAddress ) external onlyRole(FACTORY_SETTER_ROLE) { if (_flagCode == 0) revert ZeroFlag(); if (_factoryAddress == address(0)) revert ZeroAddress(); flagToAddress[_flagCode] = address(_factoryAddress); emit SetFlagToFactory(_flagCode, _factoryAddress); } function setFactorySetter( address _factorySetter ) external onlyRole(DEFAULT_ADMIN_ROLE) { if (_factorySetter == address(0)) revert ZeroAddress(); if (hasRole(FACTORY_SETTER_ROLE, _factorySetter)) revert AlreadyFactorySetter(); _setupRole(FACTORY_SETTER_ROLE, _factorySetter); emit SetFactorySetter(_factorySetter); } function setWNativeAddresses( address _native, address _wrappedNative ) external onlyRole(DEFAULT_ADMIN_ROLE) { if (_native == address(0)) revert ZeroAddress(); if (_wrappedNative == address(0)) revert ZeroAddress(); nativeAddress = IERC20Upgradeable(_native); wnativeAddress = IWETH(_wrappedNative); emit SetWNativeAddresses(_wrappedNative); } function handleMessage( address _tokenSent, uint256 _amount, bytes memory message ) external { if ( msg.sender != address(assetForwarder) && msg.sender != address(assetBridge) ) revert InvalidCaller(); messageHandler(_tokenSent, _amount, message); } function swapInSameChain( IERC20Upgradeable[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper, address recipient, uint256 widgetID ) public payable returns (uint256 returnAmount) { returnAmount = swapMultiWithRecipient( tokens, amount, minReturn, flags, dataTx, isWrapper, recipient ); emit Swap( "swapInSameChain", tokens, amount, msg.sender, recipient, returnAmount, flags, widgetID ); } function swapMultiWithRecipient( IERC20Upgradeable[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper, address recipient ) public payable returns (uint256 returnAmount) { returnAmount = _swapMultiInternal( tokens, amount, minReturn, flags, dataTx, isWrapper, recipient ); emit SwapWithRecipient( "swapMultiWithRecipient", tokens, amount, msg.sender, recipient, returnAmount, flags, 0 ); } function swapAndDeposit( uint256 partnerId, bytes32 destChainIdBytes, bytes calldata recipient, uint8 depositType, uint256 feeAmount, bytes memory message, SwapParams memory swapData, address refundRecipient ) public payable { _swapMultiInternal( swapData.tokens, swapData.amount, swapData.minReturn, swapData.flags, swapData.dataTx, swapData.isWrapper, address(this) ); IERC20Upgradeable reserveToken = swapData.tokens[ swapData.tokens.length - 1 ]; // swapAndDeposit if (depositType == 0) { uint256 amount = reserveToken.universalBalanceOf(address(this)); reserveToken.universalApprove(address(assetForwarder), amount); assetForwarder.iDeposit{value: reserveToken.isETH() ? amount : 0}( IAssetForwarder.DepositData( partnerId, amount, amount - feeAmount, address(reserveToken), refundRecipient, destChainIdBytes ), swapData.destToken, recipient ); return; } // swapAndDepositWithMessage if (depositType == 1) { uint256 amount = reserveToken.universalBalanceOf(address(this)); reserveToken.universalApprove( address(assetForwarder), swapData.minReturn ); assetForwarder.iDepositMessage{ value: reserveToken.isETH() ? amount : 0 }( IAssetForwarder.DepositData( partnerId, swapData.minReturn, swapData.destAmount, address(reserveToken), refundRecipient, destChainIdBytes ), swapData.destToken, recipient, message ); if (amount > swapData.minReturn) { reserveToken.universalTransfer( refundRecipient, amount - swapData.minReturn ); } return; } if (depositType == 2) { uint256 amount = reserveToken.universalBalanceOf(address(this)); reserveToken.universalApprove(address(assetForwarder), amount); assetForwarder.iDeposit{value: reserveToken.isETH() ? amount : 0}( IAssetForwarder.DepositData( partnerId, amount, swapData.destAmount, address(reserveToken), refundRecipient, destChainIdBytes ), swapData.destToken, recipient ); return; } revert InvalidDepositType(); } function messageHandler( address _tokenSent, uint256 _amount, bytes memory message ) internal { ( IERC20Upgradeable[] memory tokens, uint256 minReturn, bytes[] memory dataTx, uint256[] memory flags, address recipient, bool isInstruction, bytes memory instruction ) = abi.decode( message, ( IERC20Upgradeable[], uint256, bytes[], uint256[], address, bool, bytes ) ); if (_tokenSent != address(tokens[0])) revert WrongTokenSent(); bytes memory execData; bool execFlag; (execFlag, execData) = address(this).call( abi.encodeWithSelector( SWAP_MULTI_WITH_RECEPIENT_SELECTOR, tokens, _amount, minReturn, flags, dataTx, true, recipient ) ); if (!execFlag) { tokens[0].universalTransfer(recipient, _amount); } if (isInstruction) { uint256 finalAmount = execFlag ? uint256(bytes32(execData)) : _amount; address finalToken = execFlag ? address(tokens[tokens.length - 1]) : _tokenSent; (execFlag, execData) = recipient.call( abi.encodeWithSelector( IMessageHandler.handleMessage.selector, finalToken, finalAmount, instruction ) ); } } function _swapMultiInternal( IERC20Upgradeable[] memory tokens, uint256 amount, uint256 minReturn, uint256[] memory flags, bytes[] memory dataTx, bool isWrapper, address recipient ) internal returns (uint256 returnAmount) { if (recipient == address(0)) revert ZeroAddress(); if (tokens.length - 1 != flags.length) { revert WrongDataLength(); } if (!isWrapper) { if (!tokens[0].isETH() && msg.value != 0) { revert RestrictNativeToken(); } tokens[0].universalTransferFrom(msg.sender, address(this), amount); } returnAmount = tokens[0].universalBalanceOf(address(this)); IERC20Upgradeable destinationToken = tokens[tokens.length - 1]; for (uint256 i = 1; i < tokens.length; i++) { if (tokens[i - 1] == tokens[i]) { continue; } returnAmount = _swapFloor( tokens[i - 1], tokens[i], returnAmount, 0, flags[i - 1], dataTx[i - 1] ); } if (destinationToken.isETH()) { returnAmount = wnativeAddress.balanceOf(address(this)); wnativeAddress.withdraw(returnAmount); } if (recipient != address(this)) { uint256 userBalanceOld = destinationToken.universalBalanceOf( recipient ); destinationToken.universalTransfer(recipient, returnAmount); uint256 userBalanceNew = destinationToken.universalBalanceOf( recipient ); uint receivedTokens = userBalanceNew - userBalanceOld; if (receivedTokens <= minReturn) { revert AmountTooLow(); } returnAmount = receivedTokens; } } function _swapFloor( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory _data ) internal returns (uint returnAmount) { returnAmount = _swap( fromToken, destToken, amount, minReturn, flags, _data ); } function _swap( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 minReturn, uint256 flags, bytes memory _data ) internal returns (uint256 returnAmount) { if (fromToken == destToken) { return amount; } function( IERC20Upgradeable, IERC20Upgradeable, uint256, bytes memory, uint256 ) reserve = _getReserveExchange(flags); uint256 remainingAmount = fromToken.universalBalanceOf(address(this)); reserve(fromToken, destToken, remainingAmount, _data, flags); returnAmount = destToken.universalBalanceOf(address(this)); } function _getReserveExchange( uint256 flag ) internal pure returns ( function( IERC20Upgradeable, IERC20Upgradeable, uint256, bytes memory, uint256 ) ) { if (flag < 0x03E9 && flag >= 0x0001) { // 1 - 1000 return _swapOnUniswapV2; } else if (flag == 0x07D2) { return _swapOnParaswap; // 2002 } else { return _swapOnGenericAggregator; } revert("RA: Exchange not found"); } function _swapOnUniswapV2( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, bytes memory _data, uint256 flags ) internal { _swapOnExchangeInternal(fromToken, destToken, amount, flags); } function _swapOnGenericAggregator( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, bytes memory _data, uint256 flagCode ) internal { if (_data.length < 0) { revert WrongDataLength(); } address aggregatorFactoryAddress = flagToAddress[flagCode]; if (aggregatorFactoryAddress == address(0)) { revert ZeroAddress(); } if (fromToken.isETH()) { wnativeAddress.deposit{value: amount}(); } IERC20Upgradeable fromTokenReal = fromToken.isETH() ? wnativeAddress : fromToken; fromTokenReal.universalApprove(address(aggregatorFactoryAddress), amount); // solhint-disable-next-line avoid-low-level-calls (bool success, ) = address(aggregatorFactoryAddress).call(_data); if (!success) revert ExcecutionFailed(); } function _swapOnParaswap( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, bytes memory _data, uint256 flagCode ) internal { if (_data.length < 0) { revert WrongDataLength(); } address paraswap = flagToAddress[flagCode]; if (paraswap == address(0)) { revert ZeroAddress(); } if (fromToken.isETH()) { wnativeAddress.deposit{value: amount}(); } IERC20Upgradeable fromTokenReal = fromToken.isETH() ? wnativeAddress : fromToken; fromTokenReal.universalApprove( IAugustusSwapper(paraswap).getTokenTransferProxy(), amount ); // solhint-disable-next-line avoid-low-level-calls (bool success, ) = address(paraswap).call(_data); if (!success) { revert ExcecutionFailed(); } } function _swapOnExchangeInternal( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, uint256 flagCode ) internal returns (uint256 returnAmount) { if (fromToken.isETH()) { wnativeAddress.deposit{value: amount}(); } address dexAddress = flagToAddress[flagCode]; require(dexAddress != address(0), "RA: Exchange not found"); IUniswapV2Factory factory = IUniswapV2Factory(address(dexAddress)); IERC20Upgradeable fromTokenReal = fromToken.isETH() ? wnativeAddress : fromToken; IERC20Upgradeable toTokenReal = destToken.isETH() ? wnativeAddress : destToken; if (fromTokenReal == toTokenReal) { return amount; } IUniswapV2Exchange pool = factory.getPair(fromTokenReal, toTokenReal); if (address(pool) == address(0)) revert InvalidPool(); bool needSync; bool needSkim; (returnAmount, needSync, needSkim) = pool.getReturn( fromTokenReal, toTokenReal, amount ); if (needSync) { pool.sync(); } else if (needSkim) { pool.skim(univ2SkimAddress); } fromTokenReal.universalTransfer(address(pool), amount); if ( uint256(uint160(address(fromTokenReal))) < uint256(uint160(address(toTokenReal))) ) { pool.swap(0, returnAmount, address(this), ""); } else { pool.swap(returnAmount, 0, address(this), ""); } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_assetForwarderAddress","type":"address"},{"internalType":"address","name":"_native","type":"address"},{"internalType":"address","name":"_wrappedNative","type":"address"},{"internalType":"address","name":"_univ2SkimAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyFactorySetter","type":"error"},{"inputs":[],"name":"AmountTooLow","type":"error"},{"inputs":[],"name":"ExcecutionFailed","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidDepositType","type":"error"},{"inputs":[],"name":"InvalidPool","type":"error"},{"inputs":[],"name":"RestrictNativeToken","type":"error"},{"inputs":[],"name":"WrongDataLength","type":"error"},{"inputs":[],"name":"WrongTokenSent","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroFlag","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"ClaimOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"assetBridge","type":"address"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"SetAssetBridge","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"assetForwarder","type":"address"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"SetAssetForwarder","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"factorySetter","type":"address"}],"name":"SetFactorySetter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"flag","type":"uint256"},{"indexed":false,"internalType":"address","name":"factoryAddress","type":"address"}],"name":"SetFlagToFactory","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wrappedNative","type":"address"}],"name":"SetWNativeAddresses","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"funcName","type":"string"},{"indexed":false,"internalType":"contract IERC20Upgradeable[]","name":"tokenPath","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"finalAmt","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"flags","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"widgetID","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IERC20Upgradeable","name":"fromToken","type":"address"},{"indexed":false,"internalType":"contract IERC20Upgradeable","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"flags","type":"uint256"}],"name":"SwapOnSameChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"funcName","type":"string"},{"indexed":false,"internalType":"contract IERC20Upgradeable[]","name":"tokenPath","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"finalAmt","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"flags","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"widgetID","type":"uint256"}],"name":"SwapWithRecipient","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"TransferOwnership","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEXES_COUNT_UPDATED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FACTORY_SETTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetForwarder","outputs":[{"internalType":"contract IAssetForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"flagToAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenSent","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"handleMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nativeAddress","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_assetBridge","type":"address"}],"name":"setAssetBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_forwarder","type":"address"}],"name":"setAssetForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_factorySetter","type":"address"}],"name":"setFactorySetter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_flagCode","type":"uint256"},{"internalType":"address","name":"_factoryAddress","type":"address"}],"name":"setFlagToFactoryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_native","type":"address"},{"internalType":"address","name":"_wrappedNative","type":"address"}],"name":"setWNativeAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"partnerId","type":"uint256"},{"internalType":"bytes32","name":"destChainIdBytes","type":"bytes32"},{"internalType":"bytes","name":"recipient","type":"bytes"},{"internalType":"uint8","name":"depositType","type":"uint8"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"},{"components":[{"internalType":"contract IERC20Upgradeable[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256[]","name":"flags","type":"uint256[]"},{"internalType":"bytes[]","name":"dataTx","type":"bytes[]"},{"internalType":"bool","name":"isWrapper","type":"bool"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"destToken","type":"bytes"}],"internalType":"struct DexSpan.SwapParams","name":"swapData","type":"tuple"},{"internalType":"address","name":"refundRecipient","type":"address"}],"name":"swapAndDeposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20Upgradeable[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"flags","type":"uint256[]"},{"internalType":"bytes[]","name":"dataTx","type":"bytes[]"},{"internalType":"bool","name":"isWrapper","type":"bool"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"widgetID","type":"uint256"}],"name":"swapInSameChain","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20Upgradeable[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"flags","type":"uint256[]"},{"internalType":"bytes[]","name":"dataTx","type":"bytes[]"},{"internalType":"bool","name":"isWrapper","type":"bool"},{"internalType":"address","name":"recipient","type":"address"}],"name":"swapMultiWithRecipient","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"univ2SkimAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wnativeAddress","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162004f7838038062004f78833981016040819052620000349162000206565b6001600160a01b0384166200005c5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038316620000845760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038216620000ac5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038116620000d45760405163d92e233d60e01b815260040160405180910390fd5b620000e160003362000135565b600480546001600160a01b039586166001600160a01b031991821617909155600280549486169482169490941790935560018054928516928416929092179091556006805491909316911617905562000263565b62000141828262000145565b5050565b60008281526003602090815260408083206001600160a01b038516845290915290205460ff16620001415760008281526003602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620001a53390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b80516001600160a01b03811681146200020157600080fd5b919050565b600080600080608085870312156200021d57600080fd5b6200022885620001e9565b93506200023860208601620001e9565b92506200024860408601620001e9565b91506200025860608601620001e9565b905092959194509250565b614d0580620002736000396000f3fe6080604052600436106101bb5760003560e01c80639e99ec39116100ec578063d4ee1d901161008a578063e2a4ac2d11610064578063e2a4ac2d146105a9578063e738aa8d146105d6578063f2fde38b146105e9578063f9636f301461060957600080fd5b8063d4ee1d901461053c578063d547741f14610569578063da6689f01461058957600080fd5b8063ac9650d8116100c6578063ac9650d81461048c578063adb88982146104b9578063c75a57e4146104d9578063d00a2d5f1461051c57600080fd5b80639e99ec391461042a578063a217fddf1461044a578063a2625efc1461045f57600080fd5b80632e476337116101595780634e71e0c8116101335780634e71e0c8146103825780637fe68917146103975780638a2e12a5146103c457806391d14854146103d757600080fd5b80632e476337146103155780632f2ff15d1461034257806336568abe1461036257600080fd5b806318137a411161019557806318137a4114610260578063183d9c9514610280578063248a9ca314610293578063285f94a0146102c357600080fd5b806301ffc9a7146101c7578063086efdc4146101fc578063169651601461023e57600080fd5b366101c257005b600080fd5b3480156101d357600080fd5b506101e76101e2366004613a62565b61061e565b60405190151581526020015b60405180910390f35b34801561020857600080fd5b506102307fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee097581565b6040519081526020016101f3565b34801561024a57600080fd5b5061025e610259366004613ad6565b6106b7565b005b34801561026c57600080fd5b5061025e61027b366004613b06565b6107f5565b61023061028e366004613dee565b6108cd565b34801561029f57600080fd5b506102306102ae366004613eb5565b60009081526003602052604090206001015490565b3480156102cf57600080fd5b506005546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b34801561032157600080fd5b506002546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b34801561034e57600080fd5b5061025e61035d366004613ad6565b610977565b34801561036e57600080fd5b5061025e61037d366004613ad6565b6109a1565b34801561038e57600080fd5b5061025e610a59565b3480156103a357600080fd5b506004546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b61025e6103d2366004614024565b610aea565b3480156103e357600080fd5b506101e76103f2366004613ad6565b600091825260036020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561043657600080fd5b5061025e610445366004613b06565b610f80565b34801561045657600080fd5b50610230600081565b34801561046b57600080fd5b506006546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b34801561049857600080fd5b506104ac6104a73660046140f3565b611050565b6040516101f3919061422b565b3480156104c557600080fd5b5061025e6104d4366004613b06565b611145565b3480156104e557600080fd5b506102f06104f4366004613eb5565b60086020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b34801561052857600080fd5b5061025e61053736600461423e565b61128c565b34801561054857600080fd5b506007546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057557600080fd5b5061025e610584366004613ad6565b61130e565b34801561059557600080fd5b5061025e6105a4366004614297565b611333565b3480156105b557600080fd5b506001546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b6102306105e43660046142c5565b61145b565b3480156105f557600080fd5b5061025e610604366004613b06565b611505565b34801561061557600080fd5b50610230600181565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806106b157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b7fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee09756106e1816115d0565b8260000361071b576040517f196de28b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216610768576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526008602090815260409182902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86169081179091558251868152918201527f11f5b5361c420666dc3452b8107601e1702f94b951f15bd93c26262c8147874e91015b60405180910390a1505050565b6000610800816115d0565b73ffffffffffffffffffffffffffffffffffffffff821661084d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155604080519182523360208301527f61b6fe2922f0180b98d305419bf3dcf432f5d8df894388c61c1f599c2194ec1d91015b60405180910390a15050565b60006108de8989898989898961145b565b6040517f73776170496e53616d65436861696e0000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8416903390600f0160405180910390207fe3716b48e7d01d727d68472c873c69c2c4407365e4f68b2b6c8dd4569cd16dc78c8c868c89604051610963959493929190614409565b60405180910390a498975050505050505050565b600082815260036020526040902060010154610992816115d0565b61099c83836115dd565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610a4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610a5582826116d1565b5050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610aaa576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ab560003361178c565b6040513381527f85a8c8100c1d48466310240af79644f50cdae7d09cb4820d60dfc5b2462f0fd09060200160405180910390a1565b610b1182600001518360200151846040015185608001518660a001518760c0015130611796565b508151805160009190610b269060019061447c565b81518110610b3657610b3661448f565b602002602001015190508560ff16600003610c95576000610b6d73ffffffffffffffffffffffffffffffffffffffff831630611cac565b600454909150610b979073ffffffffffffffffffffffffffffffffffffffff848116911683611d71565b60045473ffffffffffffffffffffffffffffffffffffffff9081169063f452ed4d90610bc4908516611d95565b610bcf576000610bd1565b825b6040518060c001604052808f81526020018581526020018a86610bf4919061447c565b81526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508761010001518d8d6040518663ffffffff1660e01b8152600401610c5c9493929190614507565b6000604051808303818588803b158015610c7557600080fd5b505af1158015610c89573d6000803e3d6000fd5b50505050505050610f75565b8560ff16600103610e2e576000610cc273ffffffffffffffffffffffffffffffffffffffff831630611cac565b6004546040860151919250610cf19173ffffffffffffffffffffffffffffffffffffffff858116921690611d71565b60045473ffffffffffffffffffffffffffffffffffffffff90811690630421caf090610d1e908516611d95565b610d29576000610d2b565b825b6040518060c001604052808f815260200188604001518152602001886060015181526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508761010001518d8d8b6040518763ffffffff1660e01b8152600401610db595949392919061458e565b6000604051808303818588803b158015610dce57600080fd5b505af1158015610de2573d6000803e3d6000fd5b50505050508360400151811115610e2757610e2583856040015183610e07919061447c565b73ffffffffffffffffffffffffffffffffffffffff85169190611de8565b505b5050610f75565b8560ff16600203610f43576000610e5b73ffffffffffffffffffffffffffffffffffffffff831630611cac565b600454909150610e859073ffffffffffffffffffffffffffffffffffffffff848116911683611d71565b60045473ffffffffffffffffffffffffffffffffffffffff9081169063f452ed4d90610eb2908516611d95565b610ebd576000610ebf565b825b6040518060c001604052808f8152602001858152602001886060015181526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508761010001518d8d6040518663ffffffff1660e01b8152600401610c5c9493929190614507565b6040517f26667fc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050565b6000610f8b816115d0565b73ffffffffffffffffffffffffffffffffffffffff8216610fd8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155604080519182523360208301527f45085069ced50a4d2e82656a82ba8f5a1a28694489d8ea262252e40899a930a291016108c1565b60608167ffffffffffffffff81111561106b5761106b613b23565b60405190808252806020026020018201604052801561109e57816020015b60608152602001906001900390816110895790505b50905060005b8281101561113e5761110e308585848181106110c2576110c261448f565b90506020028101906110d49190614636565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e9a92505050565b8282815181106111205761112061448f565b602002602001018190525080806111369061469b565b9150506110a4565b5092915050565b6000611150816115d0565b73ffffffffffffffffffffffffffffffffffffffff821661119d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081527f3ab9add546f7e3b43565da9bc7e65e47b969d3856bb01a7dcac7bc8ff5080cbd602052604090205460ff161561121c576040517fe4e970d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112467fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee09758361178c565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fd2b69bde5a989d23ef605a0dd4e0edf7662105058ab69f2559e482857b599ed8906020016108c1565b60045473ffffffffffffffffffffffffffffffffffffffff1633148015906112cc575060055473ffffffffffffffffffffffffffffffffffffffff163314155b15611303576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61099c838383611ebf565b600082815260036020526040902060010154611329816115d0565b61099c83836116d1565b600061133e816115d0565b73ffffffffffffffffffffffffffffffffffffffff831661138b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166113d8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556001805492851692909116821790556040519081527fcc4166d40cf68104cdf710f65ce022efd296742868a22b42e4695f89b8863636906020016107e8565b600061146c88888888888888611796565b6040517f737761704d756c746957697468526563697069656e7400000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff831690339060160160405180910390207fc40fae9d5f584875c393ac222c6f88b6c9dced1e9cc6251483648ac2e902c8b08b8b868b60006040516114f2959493929190614409565b60405180910390a4979650505050505050565b6000611510816115d0565b73ffffffffffffffffffffffffffffffffffffffff821661155d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527fcfaaa26691e16e66e73290fc725eee1a6b4e0e693a1640484937aac25ffb55a4906020016108c1565b6115da8133612232565b50565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a5557600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556116733390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1615610a5557600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b610a5582826115dd565b600073ffffffffffffffffffffffffffffffffffffffff82166117e5576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451600189516117f5919061447c565b1461182c576040517fcc513c7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826118f45761186a886000815181106118475761184761448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611d95565b15801561187657503415155b156118ad576040517f694b150300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118f43330898b6000815181106118c6576118c661448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff166122ec909392919063ffffffff16565b611937308960008151811061190b5761190b61448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611cac90919063ffffffff16565b905060008860018a5161194a919061447c565b8151811061195a5761195a61448f565b602002602001015190506000600190505b8951811015611a90578981815181106119865761198661448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168a6001836119b2919061447c565b815181106119c2576119c261448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff160315611a7e57611a7b8a6119f560018461447c565b81518110611a0557611a0561448f565b60200260200101518b8381518110611a1f57611a1f61448f565b60200260200101518560008b600187611a38919061447c565b81518110611a4857611a4861448f565b60200260200101518b600188611a5e919061447c565b81518110611a6e57611a6e61448f565b60200260200101516124cc565b92505b80611a888161469b565b91505061196b565b50611ab08173ffffffffffffffffffffffffffffffffffffffff16611d95565b15611bcd576001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015611b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4791906146d3565b6001546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905291935073ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b158015611bb457600080fd5b505af1158015611bc8573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff83163014611ca0576000611c0c73ffffffffffffffffffffffffffffffffffffffff831685611cac565b9050611c2f73ffffffffffffffffffffffffffffffffffffffff83168585611de8565b506000611c5273ffffffffffffffffffffffffffffffffffffffff841686611cac565b90506000611c60838361447c565b9050898111611c9b576040517f1fbaba3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b935050505b50979650505050505050565b6000611cb783611d95565b15611cda575073ffffffffffffffffffffffffffffffffffffffff8116316106b1565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015611d46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6a91906146d3565b90506106b1565b611d7a83611d95565b61099c57611d8a838360006124e7565b61099c8383836124e7565b600073ffffffffffffffffffffffffffffffffffffffff821615806106b1575073ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b600081600003611dfa57506001611e93565b611e0384611d95565b15611e845760008373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d8060008114611e62576040519150601f19603f3d011682016040523d82523d6000602084013e611e67565b606091505b5090915050600181151514611e7e57611e7e6146ec565b50611e93565b611e8f84848461267d565b5060015b9392505050565b6060611e938383604051806060016040528060278152602001614ca96027913961280c565b600080600080600080600087806020019051810190611ede91906148b5565b965096509650965096509650965086600081518110611eff57611eff61448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff1614611f6b576040517f198b098900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606060003073ffffffffffffffffffffffffffffffffffffffff1663e738aa8d60e01b8a8d8b8a8c60018c604051602401611fac979695949392919061498d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516120359190614a04565b6000604051808303816000865af19150503d8060008114612072576040519150601f19603f3d011682016040523d82523d6000602084013e612077565b606091505b5092509050806120c8576120c6858c8b6000815181106120995761209961448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611de89092919063ffffffff16565b505b8315612224576000816120db578b6120e4565b6120e483614a20565b90506000826120f3578d61211b565b8a60018c51612102919061447c565b815181106121125761211261448f565b60200260200101515b90508673ffffffffffffffffffffffffffffffffffffffff1663d00a2d5f60e01b82848860405160240161215193929190614a65565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516121da9190614a04565b6000604051808303816000865af19150503d8060008114612217576040519150601f19603f3d011682016040523d82523d6000602084013e61221c565b606091505b509450925050505b505050505050505050505050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a555761227281612891565b61227d8360206128b0565b60405160200161228e929190614aa3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a0000000000000000000000000000000000000000000000000000000008252610a4291600401614b24565b80156124c6576122fb84611d95565b156124ba5773ffffffffffffffffffffffffffffffffffffffff8316331480156123255750803410155b6123b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f57726f6e67207573616765206f66204554482e756e6976657273616c5472616e60448201527f7366657246726f6d2829000000000000000000000000000000000000000000006064820152608401610a42565b73ffffffffffffffffffffffffffffffffffffffff821630146124465760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612428576040519150601f19603f3d011682016040523d82523d6000602084013e61242d565b606091505b5090915050600181151514612444576124446146ec565b505b803411156124b55760003361245b3484612af3565b604051600081818185875af1925050503d8060008114612497576040519150601f19603f3d011682016040523d82523d6000602084013e61249c565b606091505b50909150506001811515146124b3576124b36146ec565b505b6124c6565b6124c684848484612aff565b50505050565b60006124dc878787878787612c9e565b979650505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052915160009283929087169161257e9190614a04565b6000604051808303816000865af19150503d80600081146125bb576040519150601f19603f3d011682016040523d82523d6000602084013e6125c0565b606091505b50915091508180156125ea5750805115806125ea5750808060200190518101906125ea9190614b37565b612676576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5472616e7366657248656c7065723a3a73616665417070726f76653a2061707060448201527f726f7665206661696c65640000000000000000000000000000000000000000006064820152608401610a42565b5050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916127149190614a04565b6000604051808303816000865af19150503d8060008114612751576040519150601f19603f3d011682016040523d82523d6000602084013e612756565b606091505b50915091508180156127805750805115806127805750808060200190518101906127809190614b37565b612676576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201527f616e73666572206661696c6564000000000000000000000000000000000000006064820152608401610a42565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516128369190614a04565b600060405180830381855af49150503d8060008114612871576040519150601f19603f3d011682016040523d82523d6000602084013e612876565b606091505b509150915061288786838387612d4a565b9695505050505050565b60606106b173ffffffffffffffffffffffffffffffffffffffff831660145b606060006128bf836002614b54565b6128ca906002614b6b565b67ffffffffffffffff8111156128e2576128e2613b23565b6040519080825280601f01601f19166020018201604052801561290c576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106129435761294361448f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106129a6576129a661448f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006129e2846002614b54565b6129ed906001614b6b565b90505b6001811115612a8a577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110612a2e57612a2e61448f565b1a60f81b828281518110612a4457612a4461448f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93612a8381614b7e565b90506129f0565b508315611e93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a42565b6000611e93828461447c565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691612b9e9190614a04565b6000604051808303816000865af19150503d8060008114612bdb576040519150601f19603f3d011682016040523d82523d6000602084013e612be0565b606091505b5091509150818015612c0a575080511580612c0a575080806020019051810190612c0a9190614b37565b612c96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c65640000000000000000000000000000006064820152608401610a42565b505050505050565b60008573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603612cda575083612887565b613a58612ce684612df2565b90506000612d0a73ffffffffffffffffffffffffffffffffffffffff8a1630611cac565b9050612d1d89898387898763ffffffff16565b612d3d73ffffffffffffffffffffffffffffffffffffffff891630611cac565b9998505050505050505050565b60608315612de0578251600003612dd95773ffffffffffffffffffffffffffffffffffffffff85163b612dd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a42565b5081612dea565b612dea8383612e30565b949350505050565b613a586103e982108015612e07575060018210155b15612e155750612e74919050565b816107d203612e275750612e80919050565b50613109919050565b815115612e405781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a429190614b24565b612c9685858584613275565b60008181526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680612edc576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612efb8673ffffffffffffffffffffffffffffffffffffffff16611d95565b15612f8457600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015612f6a57600080fd5b505af1158015612f7e573d6000803e3d6000fd5b50505050505b6000612fa58773ffffffffffffffffffffffffffffffffffffffff16611d95565b612faf5786612fc9565b60015473ffffffffffffffffffffffffffffffffffffffff165b905061305b8273ffffffffffffffffffffffffffffffffffffffff1663d2c4b5986040518163ffffffff1660e01b8152600401602060405180830381865afa158015613019573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303d9190614bb3565b73ffffffffffffffffffffffffffffffffffffffff83169087611d71565b60008273ffffffffffffffffffffffffffffffffffffffff16856040516130829190614a04565b6000604051808303816000865af19150503d80600081146130bf576040519150601f19603f3d011682016040523d82523d6000602084013e6130c4565b606091505b50509050806130ff576040517f5987947500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b60008181526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680613165576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6131848673ffffffffffffffffffffffffffffffffffffffff16611d95565b1561320d57600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b1580156131f357600080fd5b505af1158015613207573d6000803e3d6000fd5b50505050505b600061322e8773ffffffffffffffffffffffffffffffffffffffff16611d95565b6132385786613252565b60015473ffffffffffffffffffffffffffffffffffffffff165b905061305b73ffffffffffffffffffffffffffffffffffffffff82168387611d71565b60006132968573ffffffffffffffffffffffffffffffffffffffff16611d95565b1561331f57600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b15801561330557600080fd5b505af1158015613319573d6000803e3d6000fd5b50505050505b60008281526008602052604090205473ffffffffffffffffffffffffffffffffffffffff16806133ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52413a2045786368616e6765206e6f7420666f756e64000000000000000000006044820152606401610a42565b8060006133cd73ffffffffffffffffffffffffffffffffffffffff8916611d95565b6133d757876133f1565b60015473ffffffffffffffffffffffffffffffffffffffff165b905060006134148873ffffffffffffffffffffffffffffffffffffffff16611d95565b61341e5787613438565b60015473ffffffffffffffffffffffffffffffffffffffff165b90508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036134795786945050505050612dea565b6040517fe6a4390500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282811660248301526000919085169063e6a4390590604401602060405180830381865afa1580156134f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135159190614bb3565b905073ffffffffffffffffffffffffffffffffffffffff8116613564576040517f2083cd4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008061358973ffffffffffffffffffffffffffffffffffffffff841686868d613828565b9199509250905081156135fb578273ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156135de57600080fd5b505af11580156135f2573d6000803e3d6000fd5b50505050613687565b8015613687576006546040517fbc25cf7700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201529084169063bc25cf7790602401600060405180830381600087803b15801561366e57600080fd5b505af1158015613682573d6000803e3d6000fd5b505050505b6136a873ffffffffffffffffffffffffffffffffffffffff8616848c611de8565b508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16101561377d576040517f022c0d9f000000000000000000000000000000000000000000000000000000008152600060048201819052602482018a905230604483015260806064830152608482015273ffffffffffffffffffffffffffffffffffffffff84169063022c0d9f9060a401600060405180830381600087803b15801561376057600080fd5b505af1158015613774573d6000803e3d6000fd5b50505050613819565b6040517f022c0d9f0000000000000000000000000000000000000000000000000000000081526004810189905260006024820181905230604483015260806064830152608482015273ffffffffffffffffffffffffffffffffffffffff84169063022c0d9f9060a401600060405180830381600087803b15801561380057600080fd5b505af1158015613814573d6000803e3d6000fd5b505050505b50505050505050949350505050565b600080808061384d73ffffffffffffffffffffffffffffffffffffffff881689611cac565b9050600061387173ffffffffffffffffffffffffffffffffffffffff88168a611cac565b90506000808a73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156138c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138e59190614bee565b50915091508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16111561392057905b816dffffffffffffffffffffffffffff1684108061394d5750806dffffffffffffffffffffffffffff1683105b9550851580156139855750816dffffffffffffffffffffffffffff168411806139855750806dffffffffffffffffffffffffffff1683115b94506000613995896103e5613a1e565b905060006139bd6139b686856dffffffffffffffffffffffffffff16613a2a565b8390613a1e565b905060006139f1836139eb6103e86139e58b8a6dffffffffffffffffffffffffffff16613a2a565b90613a1e565b90613a40565b90508015613a0857613a038282613a4c565b613a0b565b60005b9950505050505050509450945094915050565b6000611e938284614b54565b6000818310613a395781611e93565b5090919050565b6000611e938284614b6b565b6000611e938284614c3e565b613a60614c79565b565b600060208284031215613a7457600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9357600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146115da57600080fd5b8035613ad181613aa4565b919050565b60008060408385031215613ae957600080fd5b823591506020830135613afb81613aa4565b809150509250929050565b600060208284031215613b1857600080fd5b8135611e9381613aa4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715613b7657613b76613b23565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613bc357613bc3613b23565b604052919050565b600067ffffffffffffffff821115613be557613be5613b23565b5060051b60200190565b600082601f830112613c0057600080fd5b81356020613c15613c1083613bcb565b613b7c565b82815260059290921b84018101918181019086841115613c3457600080fd5b8286015b84811015613c58578035613c4b81613aa4565b8352918301918301613c38565b509695505050505050565b600082601f830112613c7457600080fd5b81356020613c84613c1083613bcb565b82815260059290921b84018101918181019086841115613ca357600080fd5b8286015b84811015613c585780358352918301918301613ca7565b600067ffffffffffffffff821115613cd857613cd8613b23565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613d1557600080fd5b8135613d23613c1082613cbe565b818152846020838601011115613d3857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112613d6657600080fd5b81356020613d76613c1083613bcb565b82815260059290921b84018101918181019086841115613d9557600080fd5b8286015b84811015613c5857803567ffffffffffffffff811115613db95760008081fd5b613dc78986838b0101613d04565b845250918301918301613d99565b80151581146115da57600080fd5b8035613ad181613dd5565b600080600080600080600080610100898b031215613e0b57600080fd5b883567ffffffffffffffff80821115613e2357600080fd5b613e2f8c838d01613bef565b995060208b0135985060408b0135975060608b0135915080821115613e5357600080fd5b613e5f8c838d01613c63565b965060808b0135915080821115613e7557600080fd5b50613e828b828c01613d55565b945050613e9160a08a01613de3565b9250613e9f60c08a01613ac6565b915060e089013590509295985092959890939650565b600060208284031215613ec757600080fd5b5035919050565b60008083601f840112613ee057600080fd5b50813567ffffffffffffffff811115613ef857600080fd5b602083019150836020828501011115613f1057600080fd5b9250929050565b803560ff81168114613ad157600080fd5b60006101208284031215613f3b57600080fd5b613f43613b52565b9050813567ffffffffffffffff80821115613f5d57600080fd5b613f6985838601613bef565b83526020840135602084015260408401356040840152606084013560608401526080840135915080821115613f9d57600080fd5b613fa985838601613c63565b608084015260a0840135915080821115613fc257600080fd5b613fce85838601613d55565b60a0840152613fdf60c08501613de3565b60c0840152613ff060e08501613ac6565b60e08401526101009150818401358181111561400b57600080fd5b61401786828701613d04565b8385015250505092915050565b60008060008060008060008060006101008a8c03121561404357600080fd5b8935985060208a0135975060408a013567ffffffffffffffff8082111561406957600080fd5b6140758d838e01613ece565b909950975087915061408960608d01613f17565b965060808c0135955060a08c01359150808211156140a657600080fd5b6140b28d838e01613d04565b945060c08c01359150808211156140c857600080fd5b506140d58c828d01613f28565b9250506140e460e08b01613ac6565b90509295985092959850929598565b6000806020838503121561410657600080fd5b823567ffffffffffffffff8082111561411e57600080fd5b818501915085601f83011261413257600080fd5b81358181111561414157600080fd5b8660208260051b850101111561415657600080fd5b60209290920196919550909350505050565b60005b8381101561418357818101518382015260200161416b565b50506000910152565b600081518084526141a4816020860160208601614168565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b8581101561421e57828403895261420c84835161418c565b988501989350908401906001016141f4565b5091979650505050505050565b602081526000611e9360208301846141d6565b60008060006060848603121561425357600080fd5b833561425e81613aa4565b925060208401359150604084013567ffffffffffffffff81111561428157600080fd5b61428d86828701613d04565b9150509250925092565b600080604083850312156142aa57600080fd5b82356142b581613aa4565b91506020830135613afb81613aa4565b600080600080600080600060e0888a0312156142e057600080fd5b873567ffffffffffffffff808211156142f857600080fd5b6143048b838c01613bef565b985060208a0135975060408a0135965060608a013591508082111561432857600080fd5b6143348b838c01613c63565b955060808a013591508082111561434a57600080fd5b506143578a828b01613d55565b93505060a088013561436881613dd5565b915060c088013561437881613aa4565b8091505092959891949750929550565b600081518084526020808501945080840160005b838110156143ce57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161439c565b509495945050505050565b600081518084526020808501945080840160005b838110156143ce578151875295820195908201906001016143ed565b60a08152600061441c60a0830188614388565b866020840152856040840152828103606084015261443a81866143d9565b9150508260808301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106b1576106b161444d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60006101006145678388805182526020810151602083015260408101516040830152606081015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080840151166080850152505060a081015160a08301525050565b8060c08401526145798184018761418c565b905082810360e08401526124dc8185876144be565b60006101206145ee8389805182526020810151602083015260408101516040830152606081015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080840151166080850152505060a081015160a08301525050565b8060c08401526146008184018861418c565b905082810360e08401526146158186886144be565b905082810361010084015261462a818561418c565b98975050505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261466b57600080fd5b83018035915067ffffffffffffffff82111561468657600080fd5b602001915036819003821315613f1057600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036146cc576146cc61444d565b5060010190565b6000602082840312156146e557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082601f83011261472c57600080fd5b8151602061473c613c1083613bcb565b82815260059290921b8401810191818101908684111561475b57600080fd5b8286015b84811015613c5857805161477281613aa4565b835291830191830161475f565b600082601f83011261479057600080fd5b815161479e613c1082613cbe565b8181528460208386010111156147b357600080fd5b612dea826020830160208701614168565b600082601f8301126147d557600080fd5b815160206147e5613c1083613bcb565b82815260059290921b8401810191818101908684111561480457600080fd5b8286015b84811015613c5857805167ffffffffffffffff8111156148285760008081fd5b6148368986838b010161477f565b845250918301918301614808565b600082601f83011261485557600080fd5b81516020614865613c1083613bcb565b82815260059290921b8401810191818101908684111561488457600080fd5b8286015b84811015613c585780518352918301918301614888565b8051613ad181613aa4565b8051613ad181613dd5565b600080600080600080600060e0888a0312156148d057600080fd5b875167ffffffffffffffff808211156148e857600080fd5b6148f48b838c0161471b565b985060208a0151975060408a015191508082111561491157600080fd5b61491d8b838c016147c4565b965060608a015191508082111561493357600080fd5b61493f8b838c01614844565b955061494d60808b0161489f565b945061495b60a08b016148aa565b935060c08a015191508082111561497157600080fd5b5061497e8a828b0161477f565b91505092959891949750929550565b60e0815260006149a060e083018a614388565b88602084015287604084015282810360608401526149be81886143d9565b905082810360808401526149d281876141d6565b94151560a0840152505073ffffffffffffffffffffffffffffffffffffffff9190911660c09091015295945050505050565b60008251614a16818460208701614168565b9190910192915050565b80516020808301519190811015614a5f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000614a9a606083018461418c565b95945050505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614adb816017850160208801614168565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614b18816028840160208801614168565b01602801949350505050565b602081526000611e93602083018461418c565b600060208284031215614b4957600080fd5b8151611e9381613dd5565b80820281158282048414176106b1576106b161444d565b808201808211156106b1576106b161444d565b600081614b8d57614b8d61444d565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b600060208284031215614bc557600080fd5b8151611e9381613aa4565b80516dffffffffffffffffffffffffffff81168114613ad157600080fd5b600080600060608486031215614c0357600080fd5b614c0c84614bd0565b9250614c1a60208501614bd0565b9150604084015163ffffffff81168114614c3357600080fd5b809150509250925092565b600082614c74577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212204f8bc88753261c0edad1003917da2a98ae0c20588845f73fe617d7b954cbe5cd64736f6c63430008150033000000000000000000000000f0773508c585246bd09bfb401aa18b72685b03f9000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270000000000000000000000000b1b64005b11350a94c4d069eff4215592d98f2e2
Deployed Bytecode
0x6080604052600436106101bb5760003560e01c80639e99ec39116100ec578063d4ee1d901161008a578063e2a4ac2d11610064578063e2a4ac2d146105a9578063e738aa8d146105d6578063f2fde38b146105e9578063f9636f301461060957600080fd5b8063d4ee1d901461053c578063d547741f14610569578063da6689f01461058957600080fd5b8063ac9650d8116100c6578063ac9650d81461048c578063adb88982146104b9578063c75a57e4146104d9578063d00a2d5f1461051c57600080fd5b80639e99ec391461042a578063a217fddf1461044a578063a2625efc1461045f57600080fd5b80632e476337116101595780634e71e0c8116101335780634e71e0c8146103825780637fe68917146103975780638a2e12a5146103c457806391d14854146103d757600080fd5b80632e476337146103155780632f2ff15d1461034257806336568abe1461036257600080fd5b806318137a411161019557806318137a4114610260578063183d9c9514610280578063248a9ca314610293578063285f94a0146102c357600080fd5b806301ffc9a7146101c7578063086efdc4146101fc578063169651601461023e57600080fd5b366101c257005b600080fd5b3480156101d357600080fd5b506101e76101e2366004613a62565b61061e565b60405190151581526020015b60405180910390f35b34801561020857600080fd5b506102307fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee097581565b6040519081526020016101f3565b34801561024a57600080fd5b5061025e610259366004613ad6565b6106b7565b005b34801561026c57600080fd5b5061025e61027b366004613b06565b6107f5565b61023061028e366004613dee565b6108cd565b34801561029f57600080fd5b506102306102ae366004613eb5565b60009081526003602052604090206001015490565b3480156102cf57600080fd5b506005546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b34801561032157600080fd5b506002546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b34801561034e57600080fd5b5061025e61035d366004613ad6565b610977565b34801561036e57600080fd5b5061025e61037d366004613ad6565b6109a1565b34801561038e57600080fd5b5061025e610a59565b3480156103a357600080fd5b506004546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b61025e6103d2366004614024565b610aea565b3480156103e357600080fd5b506101e76103f2366004613ad6565b600091825260036020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561043657600080fd5b5061025e610445366004613b06565b610f80565b34801561045657600080fd5b50610230600081565b34801561046b57600080fd5b506006546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b34801561049857600080fd5b506104ac6104a73660046140f3565b611050565b6040516101f3919061422b565b3480156104c557600080fd5b5061025e6104d4366004613b06565b611145565b3480156104e557600080fd5b506102f06104f4366004613eb5565b60086020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b34801561052857600080fd5b5061025e61053736600461423e565b61128c565b34801561054857600080fd5b506007546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057557600080fd5b5061025e610584366004613ad6565b61130e565b34801561059557600080fd5b5061025e6105a4366004614297565b611333565b3480156105b557600080fd5b506001546102f09073ffffffffffffffffffffffffffffffffffffffff1681565b6102306105e43660046142c5565b61145b565b3480156105f557600080fd5b5061025e610604366004613b06565b611505565b34801561061557600080fd5b50610230600181565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806106b157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b7fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee09756106e1816115d0565b8260000361071b576040517f196de28b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216610768576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526008602090815260409182902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86169081179091558251868152918201527f11f5b5361c420666dc3452b8107601e1702f94b951f15bd93c26262c8147874e91015b60405180910390a1505050565b6000610800816115d0565b73ffffffffffffffffffffffffffffffffffffffff821661084d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155604080519182523360208301527f61b6fe2922f0180b98d305419bf3dcf432f5d8df894388c61c1f599c2194ec1d91015b60405180910390a15050565b60006108de8989898989898961145b565b6040517f73776170496e53616d65436861696e0000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8416903390600f0160405180910390207fe3716b48e7d01d727d68472c873c69c2c4407365e4f68b2b6c8dd4569cd16dc78c8c868c89604051610963959493929190614409565b60405180910390a498975050505050505050565b600082815260036020526040902060010154610992816115d0565b61099c83836115dd565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610a4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610a5582826116d1565b5050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610aaa576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ab560003361178c565b6040513381527f85a8c8100c1d48466310240af79644f50cdae7d09cb4820d60dfc5b2462f0fd09060200160405180910390a1565b610b1182600001518360200151846040015185608001518660a001518760c0015130611796565b508151805160009190610b269060019061447c565b81518110610b3657610b3661448f565b602002602001015190508560ff16600003610c95576000610b6d73ffffffffffffffffffffffffffffffffffffffff831630611cac565b600454909150610b979073ffffffffffffffffffffffffffffffffffffffff848116911683611d71565b60045473ffffffffffffffffffffffffffffffffffffffff9081169063f452ed4d90610bc4908516611d95565b610bcf576000610bd1565b825b6040518060c001604052808f81526020018581526020018a86610bf4919061447c565b81526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508761010001518d8d6040518663ffffffff1660e01b8152600401610c5c9493929190614507565b6000604051808303818588803b158015610c7557600080fd5b505af1158015610c89573d6000803e3d6000fd5b50505050505050610f75565b8560ff16600103610e2e576000610cc273ffffffffffffffffffffffffffffffffffffffff831630611cac565b6004546040860151919250610cf19173ffffffffffffffffffffffffffffffffffffffff858116921690611d71565b60045473ffffffffffffffffffffffffffffffffffffffff90811690630421caf090610d1e908516611d95565b610d29576000610d2b565b825b6040518060c001604052808f815260200188604001518152602001886060015181526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508761010001518d8d8b6040518763ffffffff1660e01b8152600401610db595949392919061458e565b6000604051808303818588803b158015610dce57600080fd5b505af1158015610de2573d6000803e3d6000fd5b50505050508360400151811115610e2757610e2583856040015183610e07919061447c565b73ffffffffffffffffffffffffffffffffffffffff85169190611de8565b505b5050610f75565b8560ff16600203610f43576000610e5b73ffffffffffffffffffffffffffffffffffffffff831630611cac565b600454909150610e859073ffffffffffffffffffffffffffffffffffffffff848116911683611d71565b60045473ffffffffffffffffffffffffffffffffffffffff9081169063f452ed4d90610eb2908516611d95565b610ebd576000610ebf565b825b6040518060c001604052808f8152602001858152602001886060015181526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508761010001518d8d6040518663ffffffff1660e01b8152600401610c5c9493929190614507565b6040517f26667fc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050565b6000610f8b816115d0565b73ffffffffffffffffffffffffffffffffffffffff8216610fd8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155604080519182523360208301527f45085069ced50a4d2e82656a82ba8f5a1a28694489d8ea262252e40899a930a291016108c1565b60608167ffffffffffffffff81111561106b5761106b613b23565b60405190808252806020026020018201604052801561109e57816020015b60608152602001906001900390816110895790505b50905060005b8281101561113e5761110e308585848181106110c2576110c261448f565b90506020028101906110d49190614636565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e9a92505050565b8282815181106111205761112061448f565b602002602001018190525080806111369061469b565b9150506110a4565b5092915050565b6000611150816115d0565b73ffffffffffffffffffffffffffffffffffffffff821661119d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081527f3ab9add546f7e3b43565da9bc7e65e47b969d3856bb01a7dcac7bc8ff5080cbd602052604090205460ff161561121c576040517fe4e970d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112467fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee09758361178c565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fd2b69bde5a989d23ef605a0dd4e0edf7662105058ab69f2559e482857b599ed8906020016108c1565b60045473ffffffffffffffffffffffffffffffffffffffff1633148015906112cc575060055473ffffffffffffffffffffffffffffffffffffffff163314155b15611303576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61099c838383611ebf565b600082815260036020526040902060010154611329816115d0565b61099c83836116d1565b600061133e816115d0565b73ffffffffffffffffffffffffffffffffffffffff831661138b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166113d8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556001805492851692909116821790556040519081527fcc4166d40cf68104cdf710f65ce022efd296742868a22b42e4695f89b8863636906020016107e8565b600061146c88888888888888611796565b6040517f737761704d756c746957697468526563697069656e7400000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff831690339060160160405180910390207fc40fae9d5f584875c393ac222c6f88b6c9dced1e9cc6251483648ac2e902c8b08b8b868b60006040516114f2959493929190614409565b60405180910390a4979650505050505050565b6000611510816115d0565b73ffffffffffffffffffffffffffffffffffffffff821661155d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527fcfaaa26691e16e66e73290fc725eee1a6b4e0e693a1640484937aac25ffb55a4906020016108c1565b6115da8133612232565b50565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a5557600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556116733390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1615610a5557600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b610a5582826115dd565b600073ffffffffffffffffffffffffffffffffffffffff82166117e5576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451600189516117f5919061447c565b1461182c576040517fcc513c7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826118f45761186a886000815181106118475761184761448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611d95565b15801561187657503415155b156118ad576040517f694b150300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118f43330898b6000815181106118c6576118c661448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff166122ec909392919063ffffffff16565b611937308960008151811061190b5761190b61448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611cac90919063ffffffff16565b905060008860018a5161194a919061447c565b8151811061195a5761195a61448f565b602002602001015190506000600190505b8951811015611a90578981815181106119865761198661448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168a6001836119b2919061447c565b815181106119c2576119c261448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff160315611a7e57611a7b8a6119f560018461447c565b81518110611a0557611a0561448f565b60200260200101518b8381518110611a1f57611a1f61448f565b60200260200101518560008b600187611a38919061447c565b81518110611a4857611a4861448f565b60200260200101518b600188611a5e919061447c565b81518110611a6e57611a6e61448f565b60200260200101516124cc565b92505b80611a888161469b565b91505061196b565b50611ab08173ffffffffffffffffffffffffffffffffffffffff16611d95565b15611bcd576001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015611b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4791906146d3565b6001546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905291935073ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b158015611bb457600080fd5b505af1158015611bc8573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff83163014611ca0576000611c0c73ffffffffffffffffffffffffffffffffffffffff831685611cac565b9050611c2f73ffffffffffffffffffffffffffffffffffffffff83168585611de8565b506000611c5273ffffffffffffffffffffffffffffffffffffffff841686611cac565b90506000611c60838361447c565b9050898111611c9b576040517f1fbaba3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b935050505b50979650505050505050565b6000611cb783611d95565b15611cda575073ffffffffffffffffffffffffffffffffffffffff8116316106b1565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015611d46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6a91906146d3565b90506106b1565b611d7a83611d95565b61099c57611d8a838360006124e7565b61099c8383836124e7565b600073ffffffffffffffffffffffffffffffffffffffff821615806106b1575073ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b600081600003611dfa57506001611e93565b611e0384611d95565b15611e845760008373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d8060008114611e62576040519150601f19603f3d011682016040523d82523d6000602084013e611e67565b606091505b5090915050600181151514611e7e57611e7e6146ec565b50611e93565b611e8f84848461267d565b5060015b9392505050565b6060611e938383604051806060016040528060278152602001614ca96027913961280c565b600080600080600080600087806020019051810190611ede91906148b5565b965096509650965096509650965086600081518110611eff57611eff61448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff1614611f6b576040517f198b098900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606060003073ffffffffffffffffffffffffffffffffffffffff1663e738aa8d60e01b8a8d8b8a8c60018c604051602401611fac979695949392919061498d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516120359190614a04565b6000604051808303816000865af19150503d8060008114612072576040519150601f19603f3d011682016040523d82523d6000602084013e612077565b606091505b5092509050806120c8576120c6858c8b6000815181106120995761209961448f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611de89092919063ffffffff16565b505b8315612224576000816120db578b6120e4565b6120e483614a20565b90506000826120f3578d61211b565b8a60018c51612102919061447c565b815181106121125761211261448f565b60200260200101515b90508673ffffffffffffffffffffffffffffffffffffffff1663d00a2d5f60e01b82848860405160240161215193929190614a65565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516121da9190614a04565b6000604051808303816000865af19150503d8060008114612217576040519150601f19603f3d011682016040523d82523d6000602084013e61221c565b606091505b509450925050505b505050505050505050505050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a555761227281612891565b61227d8360206128b0565b60405160200161228e929190614aa3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a0000000000000000000000000000000000000000000000000000000008252610a4291600401614b24565b80156124c6576122fb84611d95565b156124ba5773ffffffffffffffffffffffffffffffffffffffff8316331480156123255750803410155b6123b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f57726f6e67207573616765206f66204554482e756e6976657273616c5472616e60448201527f7366657246726f6d2829000000000000000000000000000000000000000000006064820152608401610a42565b73ffffffffffffffffffffffffffffffffffffffff821630146124465760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612428576040519150601f19603f3d011682016040523d82523d6000602084013e61242d565b606091505b5090915050600181151514612444576124446146ec565b505b803411156124b55760003361245b3484612af3565b604051600081818185875af1925050503d8060008114612497576040519150601f19603f3d011682016040523d82523d6000602084013e61249c565b606091505b50909150506001811515146124b3576124b36146ec565b505b6124c6565b6124c684848484612aff565b50505050565b60006124dc878787878787612c9e565b979650505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052915160009283929087169161257e9190614a04565b6000604051808303816000865af19150503d80600081146125bb576040519150601f19603f3d011682016040523d82523d6000602084013e6125c0565b606091505b50915091508180156125ea5750805115806125ea5750808060200190518101906125ea9190614b37565b612676576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5472616e7366657248656c7065723a3a73616665417070726f76653a2061707060448201527f726f7665206661696c65640000000000000000000000000000000000000000006064820152608401610a42565b5050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916127149190614a04565b6000604051808303816000865af19150503d8060008114612751576040519150601f19603f3d011682016040523d82523d6000602084013e612756565b606091505b50915091508180156127805750805115806127805750808060200190518101906127809190614b37565b612676576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201527f616e73666572206661696c6564000000000000000000000000000000000000006064820152608401610a42565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516128369190614a04565b600060405180830381855af49150503d8060008114612871576040519150601f19603f3d011682016040523d82523d6000602084013e612876565b606091505b509150915061288786838387612d4a565b9695505050505050565b60606106b173ffffffffffffffffffffffffffffffffffffffff831660145b606060006128bf836002614b54565b6128ca906002614b6b565b67ffffffffffffffff8111156128e2576128e2613b23565b6040519080825280601f01601f19166020018201604052801561290c576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106129435761294361448f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106129a6576129a661448f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006129e2846002614b54565b6129ed906001614b6b565b90505b6001811115612a8a577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110612a2e57612a2e61448f565b1a60f81b828281518110612a4457612a4461448f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93612a8381614b7e565b90506129f0565b508315611e93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a42565b6000611e93828461447c565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691612b9e9190614a04565b6000604051808303816000865af19150503d8060008114612bdb576040519150601f19603f3d011682016040523d82523d6000602084013e612be0565b606091505b5091509150818015612c0a575080511580612c0a575080806020019051810190612c0a9190614b37565b612c96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c65640000000000000000000000000000006064820152608401610a42565b505050505050565b60008573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603612cda575083612887565b613a58612ce684612df2565b90506000612d0a73ffffffffffffffffffffffffffffffffffffffff8a1630611cac565b9050612d1d89898387898763ffffffff16565b612d3d73ffffffffffffffffffffffffffffffffffffffff891630611cac565b9998505050505050505050565b60608315612de0578251600003612dd95773ffffffffffffffffffffffffffffffffffffffff85163b612dd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a42565b5081612dea565b612dea8383612e30565b949350505050565b613a586103e982108015612e07575060018210155b15612e155750612e74919050565b816107d203612e275750612e80919050565b50613109919050565b815115612e405781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a429190614b24565b612c9685858584613275565b60008181526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680612edc576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612efb8673ffffffffffffffffffffffffffffffffffffffff16611d95565b15612f8457600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015612f6a57600080fd5b505af1158015612f7e573d6000803e3d6000fd5b50505050505b6000612fa58773ffffffffffffffffffffffffffffffffffffffff16611d95565b612faf5786612fc9565b60015473ffffffffffffffffffffffffffffffffffffffff165b905061305b8273ffffffffffffffffffffffffffffffffffffffff1663d2c4b5986040518163ffffffff1660e01b8152600401602060405180830381865afa158015613019573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303d9190614bb3565b73ffffffffffffffffffffffffffffffffffffffff83169087611d71565b60008273ffffffffffffffffffffffffffffffffffffffff16856040516130829190614a04565b6000604051808303816000865af19150503d80600081146130bf576040519150601f19603f3d011682016040523d82523d6000602084013e6130c4565b606091505b50509050806130ff576040517f5987947500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b60008181526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680613165576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6131848673ffffffffffffffffffffffffffffffffffffffff16611d95565b1561320d57600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b1580156131f357600080fd5b505af1158015613207573d6000803e3d6000fd5b50505050505b600061322e8773ffffffffffffffffffffffffffffffffffffffff16611d95565b6132385786613252565b60015473ffffffffffffffffffffffffffffffffffffffff165b905061305b73ffffffffffffffffffffffffffffffffffffffff82168387611d71565b60006132968573ffffffffffffffffffffffffffffffffffffffff16611d95565b1561331f57600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b15801561330557600080fd5b505af1158015613319573d6000803e3d6000fd5b50505050505b60008281526008602052604090205473ffffffffffffffffffffffffffffffffffffffff16806133ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52413a2045786368616e6765206e6f7420666f756e64000000000000000000006044820152606401610a42565b8060006133cd73ffffffffffffffffffffffffffffffffffffffff8916611d95565b6133d757876133f1565b60015473ffffffffffffffffffffffffffffffffffffffff165b905060006134148873ffffffffffffffffffffffffffffffffffffffff16611d95565b61341e5787613438565b60015473ffffffffffffffffffffffffffffffffffffffff165b90508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036134795786945050505050612dea565b6040517fe6a4390500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282811660248301526000919085169063e6a4390590604401602060405180830381865afa1580156134f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135159190614bb3565b905073ffffffffffffffffffffffffffffffffffffffff8116613564576040517f2083cd4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008061358973ffffffffffffffffffffffffffffffffffffffff841686868d613828565b9199509250905081156135fb578273ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156135de57600080fd5b505af11580156135f2573d6000803e3d6000fd5b50505050613687565b8015613687576006546040517fbc25cf7700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201529084169063bc25cf7790602401600060405180830381600087803b15801561366e57600080fd5b505af1158015613682573d6000803e3d6000fd5b505050505b6136a873ffffffffffffffffffffffffffffffffffffffff8616848c611de8565b508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16101561377d576040517f022c0d9f000000000000000000000000000000000000000000000000000000008152600060048201819052602482018a905230604483015260806064830152608482015273ffffffffffffffffffffffffffffffffffffffff84169063022c0d9f9060a401600060405180830381600087803b15801561376057600080fd5b505af1158015613774573d6000803e3d6000fd5b50505050613819565b6040517f022c0d9f0000000000000000000000000000000000000000000000000000000081526004810189905260006024820181905230604483015260806064830152608482015273ffffffffffffffffffffffffffffffffffffffff84169063022c0d9f9060a401600060405180830381600087803b15801561380057600080fd5b505af1158015613814573d6000803e3d6000fd5b505050505b50505050505050949350505050565b600080808061384d73ffffffffffffffffffffffffffffffffffffffff881689611cac565b9050600061387173ffffffffffffffffffffffffffffffffffffffff88168a611cac565b90506000808a73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156138c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138e59190614bee565b50915091508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16111561392057905b816dffffffffffffffffffffffffffff1684108061394d5750806dffffffffffffffffffffffffffff1683105b9550851580156139855750816dffffffffffffffffffffffffffff168411806139855750806dffffffffffffffffffffffffffff1683115b94506000613995896103e5613a1e565b905060006139bd6139b686856dffffffffffffffffffffffffffff16613a2a565b8390613a1e565b905060006139f1836139eb6103e86139e58b8a6dffffffffffffffffffffffffffff16613a2a565b90613a1e565b90613a40565b90508015613a0857613a038282613a4c565b613a0b565b60005b9950505050505050509450945094915050565b6000611e938284614b54565b6000818310613a395781611e93565b5090919050565b6000611e938284614b6b565b6000611e938284614c3e565b613a60614c79565b565b600060208284031215613a7457600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9357600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146115da57600080fd5b8035613ad181613aa4565b919050565b60008060408385031215613ae957600080fd5b823591506020830135613afb81613aa4565b809150509250929050565b600060208284031215613b1857600080fd5b8135611e9381613aa4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715613b7657613b76613b23565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613bc357613bc3613b23565b604052919050565b600067ffffffffffffffff821115613be557613be5613b23565b5060051b60200190565b600082601f830112613c0057600080fd5b81356020613c15613c1083613bcb565b613b7c565b82815260059290921b84018101918181019086841115613c3457600080fd5b8286015b84811015613c58578035613c4b81613aa4565b8352918301918301613c38565b509695505050505050565b600082601f830112613c7457600080fd5b81356020613c84613c1083613bcb565b82815260059290921b84018101918181019086841115613ca357600080fd5b8286015b84811015613c585780358352918301918301613ca7565b600067ffffffffffffffff821115613cd857613cd8613b23565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613d1557600080fd5b8135613d23613c1082613cbe565b818152846020838601011115613d3857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112613d6657600080fd5b81356020613d76613c1083613bcb565b82815260059290921b84018101918181019086841115613d9557600080fd5b8286015b84811015613c5857803567ffffffffffffffff811115613db95760008081fd5b613dc78986838b0101613d04565b845250918301918301613d99565b80151581146115da57600080fd5b8035613ad181613dd5565b600080600080600080600080610100898b031215613e0b57600080fd5b883567ffffffffffffffff80821115613e2357600080fd5b613e2f8c838d01613bef565b995060208b0135985060408b0135975060608b0135915080821115613e5357600080fd5b613e5f8c838d01613c63565b965060808b0135915080821115613e7557600080fd5b50613e828b828c01613d55565b945050613e9160a08a01613de3565b9250613e9f60c08a01613ac6565b915060e089013590509295985092959890939650565b600060208284031215613ec757600080fd5b5035919050565b60008083601f840112613ee057600080fd5b50813567ffffffffffffffff811115613ef857600080fd5b602083019150836020828501011115613f1057600080fd5b9250929050565b803560ff81168114613ad157600080fd5b60006101208284031215613f3b57600080fd5b613f43613b52565b9050813567ffffffffffffffff80821115613f5d57600080fd5b613f6985838601613bef565b83526020840135602084015260408401356040840152606084013560608401526080840135915080821115613f9d57600080fd5b613fa985838601613c63565b608084015260a0840135915080821115613fc257600080fd5b613fce85838601613d55565b60a0840152613fdf60c08501613de3565b60c0840152613ff060e08501613ac6565b60e08401526101009150818401358181111561400b57600080fd5b61401786828701613d04565b8385015250505092915050565b60008060008060008060008060006101008a8c03121561404357600080fd5b8935985060208a0135975060408a013567ffffffffffffffff8082111561406957600080fd5b6140758d838e01613ece565b909950975087915061408960608d01613f17565b965060808c0135955060a08c01359150808211156140a657600080fd5b6140b28d838e01613d04565b945060c08c01359150808211156140c857600080fd5b506140d58c828d01613f28565b9250506140e460e08b01613ac6565b90509295985092959850929598565b6000806020838503121561410657600080fd5b823567ffffffffffffffff8082111561411e57600080fd5b818501915085601f83011261413257600080fd5b81358181111561414157600080fd5b8660208260051b850101111561415657600080fd5b60209290920196919550909350505050565b60005b8381101561418357818101518382015260200161416b565b50506000910152565b600081518084526141a4816020860160208601614168565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b8581101561421e57828403895261420c84835161418c565b988501989350908401906001016141f4565b5091979650505050505050565b602081526000611e9360208301846141d6565b60008060006060848603121561425357600080fd5b833561425e81613aa4565b925060208401359150604084013567ffffffffffffffff81111561428157600080fd5b61428d86828701613d04565b9150509250925092565b600080604083850312156142aa57600080fd5b82356142b581613aa4565b91506020830135613afb81613aa4565b600080600080600080600060e0888a0312156142e057600080fd5b873567ffffffffffffffff808211156142f857600080fd5b6143048b838c01613bef565b985060208a0135975060408a0135965060608a013591508082111561432857600080fd5b6143348b838c01613c63565b955060808a013591508082111561434a57600080fd5b506143578a828b01613d55565b93505060a088013561436881613dd5565b915060c088013561437881613aa4565b8091505092959891949750929550565b600081518084526020808501945080840160005b838110156143ce57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161439c565b509495945050505050565b600081518084526020808501945080840160005b838110156143ce578151875295820195908201906001016143ed565b60a08152600061441c60a0830188614388565b866020840152856040840152828103606084015261443a81866143d9565b9150508260808301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106b1576106b161444d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60006101006145678388805182526020810151602083015260408101516040830152606081015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080840151166080850152505060a081015160a08301525050565b8060c08401526145798184018761418c565b905082810360e08401526124dc8185876144be565b60006101206145ee8389805182526020810151602083015260408101516040830152606081015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080840151166080850152505060a081015160a08301525050565b8060c08401526146008184018861418c565b905082810360e08401526146158186886144be565b905082810361010084015261462a818561418c565b98975050505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261466b57600080fd5b83018035915067ffffffffffffffff82111561468657600080fd5b602001915036819003821315613f1057600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036146cc576146cc61444d565b5060010190565b6000602082840312156146e557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082601f83011261472c57600080fd5b8151602061473c613c1083613bcb565b82815260059290921b8401810191818101908684111561475b57600080fd5b8286015b84811015613c5857805161477281613aa4565b835291830191830161475f565b600082601f83011261479057600080fd5b815161479e613c1082613cbe565b8181528460208386010111156147b357600080fd5b612dea826020830160208701614168565b600082601f8301126147d557600080fd5b815160206147e5613c1083613bcb565b82815260059290921b8401810191818101908684111561480457600080fd5b8286015b84811015613c5857805167ffffffffffffffff8111156148285760008081fd5b6148368986838b010161477f565b845250918301918301614808565b600082601f83011261485557600080fd5b81516020614865613c1083613bcb565b82815260059290921b8401810191818101908684111561488457600080fd5b8286015b84811015613c585780518352918301918301614888565b8051613ad181613aa4565b8051613ad181613dd5565b600080600080600080600060e0888a0312156148d057600080fd5b875167ffffffffffffffff808211156148e857600080fd5b6148f48b838c0161471b565b985060208a0151975060408a015191508082111561491157600080fd5b61491d8b838c016147c4565b965060608a015191508082111561493357600080fd5b61493f8b838c01614844565b955061494d60808b0161489f565b945061495b60a08b016148aa565b935060c08a015191508082111561497157600080fd5b5061497e8a828b0161477f565b91505092959891949750929550565b60e0815260006149a060e083018a614388565b88602084015287604084015282810360608401526149be81886143d9565b905082810360808401526149d281876141d6565b94151560a0840152505073ffffffffffffffffffffffffffffffffffffffff9190911660c09091015295945050505050565b60008251614a16818460208701614168565b9190910192915050565b80516020808301519190811015614a5f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000614a9a606083018461418c565b95945050505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614adb816017850160208801614168565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614b18816028840160208801614168565b01602801949350505050565b602081526000611e93602083018461418c565b600060208284031215614b4957600080fd5b8151611e9381613dd5565b80820281158282048414176106b1576106b161444d565b808201808211156106b1576106b161444d565b600081614b8d57614b8d61444d565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b600060208284031215614bc557600080fd5b8151611e9381613aa4565b80516dffffffffffffffffffffffffffff81168114613ad157600080fd5b600080600060608486031215614c0357600080fd5b614c0c84614bd0565b9250614c1a60208501614bd0565b9150604084015163ffffffff81168114614c3357600080fd5b809150509250925092565b600082614c74577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212204f8bc88753261c0edad1003917da2a98ae0c20588845f73fe617d7b954cbe5cd64736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f0773508c585246bd09bfb401aa18b72685b03f9000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270000000000000000000000000b1b64005b11350a94c4d069eff4215592d98f2e2
-----Decoded View---------------
Arg [0] : _assetForwarderAddress (address): 0xF0773508C585246BD09BfB401Aa18B72685b03F9
Arg [1] : _native (address): 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Arg [2] : _wrappedNative (address): 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270
Arg [3] : _univ2SkimAddress (address): 0xB1b64005B11350a94c4D069eff4215592d98F2E2
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000f0773508c585246bd09bfb401aa18b72685b03f9
Arg [1] : 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
Arg [2] : 0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270
Arg [3] : 000000000000000000000000b1b64005b11350a94c4d069eff4215592d98f2e2
Deployed Bytecode Sourcemap
142983:20178:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123033:204;;;;;;;;;;-1:-1:-1;123033:204:0;;;;;:::i;:::-;;:::i;:::-;;;516:14:1;;509:22;491:41;;479:2;464:18;123033:204:0;;;;;;;;145327:87;;;;;;;;;;;;145382:32;145327:87;;;;;689:25:1;;;677:2;662:18;145327:87:0;543:177:1;147289:385:0;;;;;;;;;;-1:-1:-1;147289:385:0;;;;;:::i;:::-;;:::i;:::-;;146727:282;;;;;;;;;;-1:-1:-1;146727:282:0;;;;;:::i;:::-;;:::i;148848:766::-;;;;;;:::i;:::-;;:::i;124856:131::-;;;;;;;;;;-1:-1:-1;124856:131:0;;;;;:::i;:::-;124930:7;124957:12;;;:6;:12;;;;;:22;;;;124856:131;143283:26;;;;;;;;;;-1:-1:-1;143283:26:0;;;;;;;;;;;7711:42:1;7699:55;;;7681:74;;7669:2;7654:18;143283:26:0;7535:226:1;131479:38:0;;;;;;;;;;-1:-1:-1;131479:38:0;;;;;;;;125297:147;;;;;;;;;;-1:-1:-1;125297:147:0;;;;;:::i;:::-;;:::i;126441:218::-;;;;;;;;;;-1:-1:-1;126441:218:0;;;;;:::i;:::-;;:::i;146494:225::-;;;;;;;;;;;;;:::i;143239:37::-;;;;;;;;;;-1:-1:-1;143239:37:0;;;;;;;;150385:3144;;;;;;:::i;:::-;;:::i;123329:147::-;;;;;;;;;;-1:-1:-1;123329:147:0;;;;;:::i;:::-;123415:4;123439:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;;;;123329:147;147017:264;;;;;;;;;;-1:-1:-1;147017:264:0;;;;;:::i;:::-;;:::i;122434:49::-;;;;;;;;;;-1:-1:-1;122434:49:0;122479:4;122434:49;;143316:31;;;;;;;;;;-1:-1:-1;143316:31:0;;;;;;;;89659:314;;;;;;;;;;-1:-1:-1;89659:314:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;147682:386::-;;;;;;;;;;-1:-1:-1;147682:386:0;;;;;:::i;:::-;;:::i;143425:48::-;;;;;;;;;;-1:-1:-1;143425:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;148501:339;;;;;;;;;;-1:-1:-1;148501:339:0;;;;;:::i;:::-;;:::i;143354:23::-;;;;;;;;;;-1:-1:-1;143354:23:0;;;;;;;;125737:149;;;;;;;;;;-1:-1:-1;125737:149:0;;;;;:::i;:::-;;:::i;148076:417::-;;;;;;;;;;-1:-1:-1;148076:417:0;;;;;:::i;:::-;;:::i;131445:27::-;;;;;;;;;;-1:-1:-1;131445:27:0;;;;;;;;149622:755;;;;;;:::i;:::-;;:::i;146243:243::-;;;;;;;;;;-1:-1:-1;146243:243:0;;;;;:::i;:::-;;:::i;131282:47::-;;;;;;;;;;;;131328:1;131282:47;;123033:204;123118:4;123142:47;;;123157:32;123142:47;;:87;;-1:-1:-1;90945:25:0;90930:40;;;;123193:36;123135:94;123033:204;-1:-1:-1;;123033:204:0:o;147289:385::-;145382:32;122925:16;122936:4;122925:10;:16::i;:::-;147445:9:::1;147458:1;147445:14:::0;147441:37:::1;;147468:10;;;;;;;;;;;;;;147441:37;147493:29;::::0;::::1;147489:55;;147531:13;;;;;;;;;;;;;;147489:55;147555:24;::::0;;;:13:::1;:24;::::0;;;;;;;;:51;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;147622:44;;16597:25:1;;;16638:18;;;16631:83;147622:44:0::1;::::0;16570:18:1;147622:44:0::1;;;;;;;;147289:385:::0;;;:::o;146727:282::-;122479:4;122925:16;122479:4;122925:10;:16::i;:::-;146843:24:::1;::::0;::::1;146839:50;;146876:13;;;;;;;;;;;;;;146839:50;146900:14;:44:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;146960:41:::1;::::0;;16960:34:1;;;146990:10:0::1;17025:2:1::0;17010:18;;17003:43;146960:41:0::1;::::0;16872:18:1;146960:41:0::1;;;;;;;;146727:282:::0;;:::o;148848:766::-;149146:20;149194:188;149231:6;149252;149273:9;149297:5;149317:6;149338:9;149362;149194:22;:188::i;:::-;149398:208;;17271:17:1;17259:30;;149179:203:0;;-1:-1:-1;149398:208:0;;;;149491:10;;17314:2:1;17305:12;149398:208:0;;;;;;;;149449:6;149470;149540:12;149567:5;149587:8;149398:208;;;;;;;;;;:::i;:::-;;;;;;;;148848:766;;;;;;;;;;:::o;125297:147::-;124930:7;124957:12;;;:6;:12;;;;;:22;;;122925:16;122936:4;122925:10;:16::i;:::-;125411:25:::1;125422:4;125428:7;125411:10;:25::i;:::-;125297:147:::0;;;:::o;126441:218::-;126537:23;;;23676:10;126537:23;126529:83;;;;;;;19209:2:1;126529:83:0;;;19191:21:1;19248:2;19228:18;;;19221:30;19287:34;19267:18;;;19260:62;19358:17;19338:18;;;19331:45;19393:19;;126529:83:0;;;;;;;;;126625:26;126637:4;126643:7;126625:11;:26::i;:::-;126441:218;;:::o;146494:225::-;146544:8;;:22;:8;146556:10;146544:22;146540:77;;146590:15;;;;;;;;;;;;;;146540:77;146627:42;122479:4;146658:10;146627;:42::i;:::-;146685:26;;146700:10;7681:74:1;;146685:26:0;;7669:2:1;7654:18;146685:26:0;;;;;;;146494:225::o;150385:3144::-;150698:242;150731:8;:15;;;150761:8;:15;;;150791:8;:18;;;150824:8;:14;;;150853:8;:15;;;150883:8;:18;;;150924:4;150698:18;:242::i;:::-;-1:-1:-1;150984:15:0;;151014:22;;150951:30;;150984:15;151014:26;;151039:1;;151014:26;:::i;:::-;150984:67;;;;;;;;:::i;:::-;;;;;;;150951:100;;151095:11;:16;;151110:1;151095:16;151091:658;;151128:14;151145:46;:31;;;151185:4;151145:31;:46::i;:::-;151244:14;;151128:63;;-1:-1:-1;151206:62:0;;151244:14;151206:29;;;;151244:14;151128:63;151206:29;:62::i;:::-;151283:14;;;;;;;:23;;151314:20;;:18;;;:20::i;:::-;:33;;151346:1;151314:33;;;151337:6;151314:33;151367:269;;;;;;;;151417:9;151367:269;;;;151449:6;151367:269;;;;151487:9;151478:6;:18;;;;:::i;:::-;151367:269;;;;151527:12;151367:269;;;;;;151563:15;151367:269;;;;;;151601:16;151367:269;;;151655:8;:18;;;151692:9;;151283:433;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;151731:7;;;;151091:658;151803:11;:16;;151818:1;151803:16;151799:1016;;151836:14;151853:46;:31;;;151893:4;151853:31;:46::i;:::-;151970:14;;152004:18;;;;151836:63;;-1:-1:-1;151914:123:0;;151970:14;151914:29;;;;151970:14;;151914:29;:123::i;:::-;152052:14;;;;;;;:30;;152108:20;;:18;;;:20::i;:::-;:33;;152140:1;152108:33;;;152131:6;152108:33;152175:282;;;;;;;;152225:9;152175:282;;;;152257:8;:18;;;152175:282;;;;152298:8;:19;;;152175:282;;;;152348:12;152175:282;;;;;;152384:15;152175:282;;;;;;152422:16;152175:282;;;152476:8;:18;;;152513:9;;152541:7;152052:511;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;152591:8;:18;;;152582:6;:27;152578:205;;;152630:137;152683:15;152730:8;:18;;;152721:6;:27;;;;:::i;:::-;152630:30;;;;:137;:30;:137::i;:::-;;152578:205;152797:7;;;;151799:1016;152829:11;:16;;152844:1;152829:16;152825:659;;152862:14;152879:46;:31;;;152919:4;152879:31;:46::i;:::-;152978:14;;152862:63;;-1:-1:-1;152940:62:0;;152978:14;152940:29;;;;152978:14;152862:63;152940:29;:62::i;:::-;153017:14;;;;;;;:23;;153048:20;;:18;;;:20::i;:::-;:33;;153080:1;153048:33;;;153071:6;153048:33;153101:270;;;;;;;;153151:9;153101:270;;;;153183:6;153101:270;;;;153212:8;:19;;;153101:270;;;;153262:12;153101:270;;;;;;153298:15;153101:270;;;;;;153336:16;153101:270;;;153390:8;:18;;;153427:9;;153017:434;;;;;;;;;;;;;;;;;;:::i;152825:659::-;153501:20;;;;;;;;;;;;;;150385:3144;;;;;;;;;;:::o;147017:264::-;122479:4;122925:16;122479:4;122925:10;:16::i;:::-;147132:26:::1;::::0;::::1;147128:52;;147167:13;;;;;;;;;;;;;;147128:52;147191:11;:26:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;147233:40:::1;::::0;;16960:34:1;;;147262:10:0::1;17025:2:1::0;17010:18;;17003:43;147233:40:0::1;::::0;16872:18:1;147233:40:0::1;16725:327:1::0;89659:314:0;89727:22;89784:4;89772:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89762:34;;89812:9;89807:134;89827:15;;;89807:134;;;89877:52;89914:4;89921;;89926:1;89921:7;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;89877:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89877:28:0;;-1:-1:-1;;;89877:52:0:i;:::-;89864:7;89872:1;89864:10;;;;;;;;:::i;:::-;;;;;;:65;;;;89844:3;;;;;:::i;:::-;;;;89807:134;;;;89659:314;;;;:::o;147682:386::-;122479:4;122925:16;122479:4;122925:10;:16::i;:::-;147801:28:::1;::::0;::::1;147797:54;;147838:13;;;;;;;;;;;;;;147797:54;123439:29:::0;;;123415:4;123439:29;;;:12;;:29;:12;:29;;;;;147862:92:::1;;;147932:22;;;;;;;;;;;;;;147862:92;147965:47;145382:32;147997:14;147965:10;:47::i;:::-;148028:32;::::0;7711:42:1;7699:55;;7681:74;;148028:32:0::1;::::0;7669:2:1;7654:18;148028:32:0::1;7535:226:1::0;148501:339:0;148677:14;;;;148655:10;:37;;;;:88;;-1:-1:-1;148731:11:0;;;;148709:10;:34;;148655:88;148637:140;;;148762:15;;;;;;;;;;;;;;148637:140;148788:44;148803:10;148815:7;148824;148788:14;:44::i;125737:149::-;124930:7;124957:12;;;:6;:12;;;;;:22;;;122925:16;122936:4;122925:10;:16::i;:::-;125852:26:::1;125864:4;125870:7;125852:11;:26::i;148076:417::-:0;122479:4;122925:16;122479:4;122925:10;:16::i;:::-;148224:21:::1;::::0;::::1;148220:47;;148254:13;;;;;;;;;;;;;;148220:47;148282:28;::::0;::::1;148278:54;;148319:13;;;;;;;;;;;;;;148278:54;148343:13;:42:::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;-1:-1:-1;148396:38:0;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;148450:35:::1;::::0;7681:74:1;;;148450:35:0::1;::::0;7669:2:1;7654:18;148450:35:0::1;7535:226:1::0;149622:755:0;149900:20;149948:184;149981:6;150002;150023:9;150047:5;150067:6;150088:9;150112;149948:18;:184::i;:::-;150148:221;;23091:24:1;23079:37;;149933:199:0;;-1:-1:-1;150148:221:0;;;;150261:10;;23141:2:1;23132:12;150148:221:0;;;;;;;;150219:6;150240;150310:12;150337:5;150357:1;150148:221;;;;;;;;;;:::i;:::-;;;;;;;;149622:755;;;;;;;;;:::o;146243:243::-;122479:4;122925:16;122479:4;122925:10;:16::i;:::-;146358:23:::1;::::0;::::1;146354:49;;146390:13;;;;;;;;;;;;;;146354:49;146414:8;:20:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;146450:28:::1;::::0;7681:74:1;;;146450:28:0::1;::::0;7669:2:1;7654:18;146450:28:0::1;7535:226:1::0;123780:105:0;123847:30;123858:4;23676:10;123847;:30::i;:::-;123780:105;:::o;128038:238::-;123415:4;123439:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;128117:152;;128161:12;;;;:6;:12;;;;;;;;:29;;;;;;;;;;:36;;;;128193:4;128161:36;;;128244:12;23676:10;;23596:98;128244:12;128217:40;;128235:7;128217:40;;128229:4;128217:40;;;;;;;;;;128038:238;;:::o;128456:239::-;123415:4;123439:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;128536:152;;;128611:5;128579:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;:37;;;;;;128636:40;23676:10;;128579:12;;128636:40;;128611:5;128636:40;128456:239;;:::o;127366:112::-;127445:25;127456:4;127462:7;127445:10;:25::i;155423:1980::-;155691:20;155728:23;;;155724:49;;155760:13;;;;;;;;;;;;;;155724:49;155809:5;:12;155804:1;155788:6;:13;:17;;;;:::i;:::-;:33;155784:90;;155845:17;;;;;;;;;;;;;;155784:90;155889:9;155884:228;;155920:17;:6;155927:1;155920:9;;;;;;;;:::i;:::-;;;;;;;:15;;;:17::i;:::-;155919:18;:36;;;;-1:-1:-1;155941:9:0;:14;;155919:36;155915:105;;;155983:21;;;;;;;;;;;;;;155915:105;156034:66;156066:10;156086:4;156093:6;156034;156041:1;156034:9;;;;;;;;:::i;:::-;;;;;;;:31;;;;:66;;;;;;:::i;:::-;156137:43;156174:4;156137:6;156144:1;156137:9;;;;;;;;:::i;:::-;;;;;;;:28;;;;:43;;;;:::i;:::-;156122:58;;156191:34;156228:6;156251:1;156235:6;:13;:17;;;;:::i;:::-;156228:25;;;;;;;;:::i;:::-;;;;;;;156191:62;;156269:9;156281:1;156269:13;;156264:374;156288:6;:13;156284:1;:17;156264:374;;;156344:6;156351:1;156344:9;;;;;;;;:::i;:::-;;;;;;;156327:26;;:6;156338:1;156334;:5;;;;:::i;:::-;156327:13;;;;;;;;:::i;:::-;;;;;;;:26;;;156323:75;156374:8;156323:75;156427:199;156456:6;156463:5;156467:1;156463;:5;:::i;:::-;156456:13;;;;;;;;:::i;:::-;;;;;;;156488:6;156495:1;156488:9;;;;;;;;:::i;:::-;;;;;;;156516:12;156547:1;156567:5;156577:1;156573;:5;;;;:::i;:::-;156567:12;;;;;;;;:::i;:::-;;;;;;;156598:6;156609:1;156605;:5;;;;:::i;:::-;156598:13;;;;;;;;:::i;:::-;;;;;;;156427:10;:199::i;:::-;156412:214;;156264:374;156303:3;;;;:::i;:::-;;;;156264:374;;;;156654:24;:16;:22;;;:24::i;:::-;156650:163;;;156710:14;;:39;;;;;156743:4;156710:39;;;7681:74:1;156710:14:0;;;;;:24;;7654:18:1;;156710:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;156764:14;;:37;;;;;;;;689:25:1;;;156695:54:0;;-1:-1:-1;156764:14:0;;;:23;;662:18:1;;156764:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;156650:163;156829:26;;;156850:4;156829:26;156825:571;;156872:22;156897:78;:35;;;156951:9;156897:35;:78::i;:::-;156872:103;-1:-1:-1;156990:59:0;:34;;;157025:9;157036:12;156990:34;:59::i;:::-;-1:-1:-1;157064:22:0;157089:78;:35;;;157143:9;157089:35;:78::i;:::-;157064:103;-1:-1:-1;157184:19:0;157206:31;157223:14;157064:103;157206:31;:::i;:::-;157184:53;;157274:9;157256:14;:27;157252:89;;157311:14;;;;;;;;;;;;;;157252:89;157370:14;-1:-1:-1;;;156825:571:0;155713:1690;155423:1980;;;;;;;;;:::o;119715:264::-;119829:7;119853:12;119859:5;119853;:12::i;:::-;119849:123;;;-1:-1:-1;119889:11:0;;;;119882:18;;119849:123;119940:20;;;;;:15;7699:55:1;;;119940:20:0;;;7681:74:1;119940:15:0;;;;;7654:18:1;;119940:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;119933:27;;;;118903:804;119041:12;119047:5;119041;:12::i;:::-;119036:664;;119570:49;119605:5;119613:2;119617:1;119570:26;:49::i;:::-;119634:54;119669:5;119677:2;119681:6;119634:26;:54::i;119987:191::-;120050:4;120075:39;;;;;:94;;-1:-1:-1;120131:38:0;;;116621:42;120131:38;120067:103;119987:191;-1:-1:-1;;119987:191:0:o;116673:524::-;116805:4;116826:6;116836:1;116826:11;116822:55;;-1:-1:-1;116861:4:0;116854:11;;116822:55;116893:12;116899:5;116893;:12::i;:::-;116889:301;;;116923:12;116965:2;116941:34;;117001:6;116941:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;116922:104:0;;-1:-1:-1;;117059:4:0;117048:15;;;;117041:23;;;;:::i;:::-;116907:169;116889:301;;;117097:55;117133:5;117141:2;117145:6;117097:27;:55::i;:::-;-1:-1:-1;117174:4:0;116889:301;116673:524;;;;;:::o;20172:200::-;20255:12;20287:77;20308:6;20316:4;20287:77;;;;;;;;;;;;;;;;;:20;:77::i;153537:1878::-;153689:33;153737:17;153769:21;153805:22;153842:17;153874:18;153907:24;153974:7;153945:308;;;;;;;;;;;;:::i;:::-;153674:579;;;;;;;;;;;;;;154290:6;154297:1;154290:9;;;;;;;;:::i;:::-;;;;;;;154268:32;;:10;:32;;;154264:61;;154309:16;;;;;;;;;;;;;;154264:61;154336:21;154368:13;154423:4;154415:18;;145483:10;154489:34;;154542:6;154567:7;154593:9;154621:5;154645:6;154670:4;154693:9;154448:269;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;154415:313;;;;154448:269;154415:313;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;154392:336:0;-1:-1:-1;154392:336:0;-1:-1:-1;154392:336:0;154741:89;;154771:47;154799:9;154810:7;154771:6;154778:1;154771:9;;;;;;;;:::i;:::-;;;;;;;:27;;;;:47;;;;;:::i;:::-;;154741:89;154846:13;154842:566;;;154876:19;154898:8;:81;;154972:7;154898:81;;;154934:17;154942:8;154934:17;:::i;:::-;154876:103;;154994:18;155015:8;:92;;155097:10;155015:92;;;155051:6;155074:1;155058:6;:13;:17;;;;:::i;:::-;155051:25;;;;;;;;:::i;:::-;;;;;;;155015:92;154994:113;;155145:9;:14;;155223:38;;;155284:10;155317:11;155351;155178:203;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;155145:251;;;;155178:203;155145:251;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;155122:274:0;-1:-1:-1;155122:274:0;-1:-1:-1;;;154842:566:0;153663:1752;;;;;;;;;153537:1878;;;:::o;124175:492::-;123415:4;123439:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;124259:401;;124452:28;124472:7;124452:19;:28::i;:::-;124553:38;124581:4;124588:2;124553:19;:38::i;:::-;124357:257;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;124303:345;;;;;;;;:::i;117205:978::-;117366:50;;117398:7;117366:50;117432:12;117438:5;117432;:12::i;:::-;117428:748;;;117487:18;;;117495:10;117487:18;:41;;;;;117522:6;117509:9;:19;;117487:41;117461:145;;;;;;;32335:2:1;117461:145:0;;;32317:21:1;32374:2;32354:18;;;32347:30;32413:34;32393:18;;;32386:62;32484:12;32464:18;;;32457:40;32514:19;;117461:145:0;32133:406:1;117461:145:0;117625:19;;;117639:4;117625:19;117621:214;;117666:12;117708:2;117684:34;;117748:6;117684:93;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;117665:112:0;;-1:-1:-1;;117814:4:0;117803:15;;;;117796:23;;;;:::i;:::-;117646:189;117621:214;117865:6;117853:9;:18;117849:218;;;117893:12;117919:10;117965:21;:9;117979:6;117965:13;:21::i;:::-;117911:98;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;117892:117:0;;-1:-1:-1;;118046:4:0;118035:15;;;;118028:23;;;;:::i;:::-;117873:194;117849:218;117428:748;;;118099:65;118139:5;118147:4;118153:2;118157:6;118099:31;:65::i;:::-;117205:978;;;;:::o;157411:429::-;157638:17;157683:149;157703:9;157727;157751:6;157772:9;157796:5;157816;157683;:149::i;:::-;157668:164;157411:429;-1:-1:-1;;;;;;;157411:429:0:o;806:435::-;1016:45;;;991:10;32736:55:1;;;1016:45:0;;;32718:74:1;32808:18;;;;32801:34;;;1016:45:0;;;;;;;;;;32691:18:1;;;;1016:45:0;;;;;;;;;;;;;991:81;;-1:-1:-1;;;;991:10:0;;;;:81;;1016:45;991:81;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;955:117;;;;1105:7;:57;;;;-1:-1:-1;1117:11:0;;:16;;:44;;;1148:4;1137:24;;;;;;;;;;;;:::i;:::-;1083:150;;;;;;;33298:2:1;1083:150:0;;;33280:21:1;33337:2;33317:18;;;33310:30;33376:34;33356:18;;;33349:62;33447:13;33427:18;;;33420:41;33478:19;;1083:150:0;33096:407:1;1083:150:0;878:363;;806:435;;;:::o;1249:439::-;1461:45;;;1436:10;32736:55:1;;;1461:45:0;;;32718:74:1;32808:18;;;;32801:34;;;1461:45:0;;;;;;;;;;32691:18:1;;;;1461:45:0;;;;;;;;;;;;;1436:81;;-1:-1:-1;;;;1436:10:0;;;;:81;;1461:45;1436:81;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1400:117;;;;1550:7;:57;;;;-1:-1:-1;1562:11:0;;:16;;:44;;;1593:4;1582:24;;;;;;;;;;;;:::i;:::-;1528:152;;;;;;;33710:2:1;1528:152:0;;;33692:21:1;33749:2;33729:18;;;33722:30;33788:34;33768:18;;;33761:62;33859:15;33839:18;;;33832:43;33892:19;;1528:152:0;33508:409:1;20566:332:0;20711:12;20737;20751:23;20778:6;:19;;20798:4;20778:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20736:67;;;;20821:69;20848:6;20856:7;20865:10;20877:12;20821:26;:69::i;:::-;20814:76;20566:332;-1:-1:-1;;;;;;20566:332:0:o;101725:151::-;101783:13;101816:52;101828:22;;;99600:2;101121:447;101196:13;101222:19;101254:10;101258:6;101254:1;:10;:::i;:::-;:14;;101267:1;101254:14;:::i;:::-;101244:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;101244:25:0;;101222:47;;101280:15;:6;101287:1;101280:9;;;;;;;;:::i;:::-;;;;:15;;;;;;;;;;;101306;:6;101313:1;101306:9;;;;;;;;:::i;:::-;;;;:15;;;;;;;;;;-1:-1:-1;101337:9:0;101349:10;101353:6;101349:1;:10;:::i;:::-;:14;;101362:1;101349:14;:::i;:::-;101337:26;;101332:131;101369:1;101365;:5;101332:131;;;101404:8;101413:5;101421:3;101413:11;101404:21;;;;;;;:::i;:::-;;;;101392:6;101399:1;101392:9;;;;;;;;:::i;:::-;;;;:33;;;;;;;;;;-1:-1:-1;101450:1:0;101440:11;;;;;101372:3;;;:::i;:::-;;;101332:131;;;-1:-1:-1;101481:10:0;;101473:55;;;;;;;34628:2:1;101473:55:0;;;34610:21:1;;;34647:18;;;34640:30;34706:34;34686:18;;;34679:62;34758:18;;101473:55:0;34426:356:1;77382:98:0;77440:7;77467:5;77471:1;77467;:5;:::i;1696:522::-;1981:51;;;1956:10;35068:15:1;;;1981:51:0;;;35050:34:1;35120:15;;;35100:18;;;35093:43;35152:18;;;;35145:34;;;1981:51:0;;;;;;;;;;34962:18:1;;;;1981:51:0;;;;;;;;;;;;;1956:87;;-1:-1:-1;;;;1956:10:0;;;;:87;;1981:51;1956:87;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1920:123;;;;2076:7;:57;;;;-1:-1:-1;2088:11:0;;:16;;:44;;;2119:4;2108:24;;;;;;;;;;;;:::i;:::-;2054:156;;;;;;;35392:2:1;2054:156:0;;;35374:21:1;35431:2;35411:18;;;35404:30;35470:34;35450:18;;;35443:62;35541:19;35521:18;;;35514:47;35578:19;;2054:156:0;35190:413:1;2054:156:0;1830:388;;1696:522;;;;:::o;157848:754::-;158070:20;158120:9;158107:22;;:9;:22;;;158103:68;;-1:-1:-1;158153:6:0;158146:13;;158103:68;158181:162;158346:26;158366:5;158346:19;:26::i;:::-;158181:191;-1:-1:-1;158385:23:0;158411:43;:28;;;158448:4;158411:28;:43::i;:::-;158385:69;;158465:60;158473:9;158484;158495:15;158512:5;158519;158465:7;:60;;:::i;:::-;158551:43;:28;;;158588:4;158551:28;:43::i;:::-;158536:58;157848:754;-1:-1:-1;;;;;;;;;157848:754:0:o;21194:644::-;21379:12;21408:7;21404:427;;;21436:10;:17;21457:1;21436:22;21432:290;;15075:19;;;;21646:60;;;;;;;35810:2:1;21646:60:0;;;35792:21:1;35849:2;35829:18;;;35822:30;35888:31;35868:18;;;35861:59;35937:18;;21646:60:0;35608:353:1;21646:60:0;-1:-1:-1;21743:10:0;21736:17;;21404:427;21786:33;21794:10;21806:12;21786:7;:33::i;:::-;21194:644;;;;;;:::o;158610:638::-;158733:189;158950:6;158943:4;:13;:31;;;;;158968:6;158960:4;:14;;158943:31;158939:259;;;-1:-1:-1;159023:16:0;;158610:638;-1:-1:-1;158610:638:0:o;158939:259::-;159061:4;159069:6;159061:14;159057:141;;-1:-1:-1;159099:15:0;;158610:638;-1:-1:-1;158610:638:0:o;159057:141::-;-1:-1:-1;159162:24:0;;158610:638;-1:-1:-1;158610:638:0:o;22380:552::-;22541:17;;:21;22537:388;;22773:10;22767:17;22830:15;22817:10;22813:2;22809:19;22802:44;22537:388;22900:12;22893:20;;;;;;;;;;;:::i;159256:275::-;159463:60;159487:9;159498;159509:6;159517:5;159463:23;:60::i;160504:980::-;160796:16;160815:23;;;:13;:23;;;;;;;;;160849:75;;160899:13;;;;;;;;;;;;;;160849:75;160940:17;:9;:15;;;:17::i;:::-;160936:89;;;160974:14;;;;;;;;;;;:22;;;161004:6;160974:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;160936:89;161035:31;161069:17;:9;:15;;;:17::i;:::-;:72;;161132:9;161069:72;;;161102:14;;;;161069:72;161035:106;;161154:127;161216:8;161199:48;;;:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;161154:30;;;;161264:6;161154:30;:127::i;:::-;161353:12;161379:8;161371:22;;161394:5;161371:29;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;161352:48;;;161416:7;161411:66;;161447:18;;;;;;;;;;;;;;161411:66;160702:782;;;160504:980;;;;;:::o;159539:957::-;159840:32;159875:23;;;:13;:23;;;;;;;;;159909:91;;159975:13;;;;;;;;;;;;;;159909:91;160014:17;:9;:15;;;:17::i;:::-;160010:89;;;160048:14;;;;;;;;;;;:22;;;160078:6;160048:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;160010:89;160111:31;160145:17;:9;:15;;;:17::i;:::-;:72;;160208:9;160145:72;;;160178:14;;;;160145:72;160111:106;-1:-1:-1;160230:73:0;:30;;;160269:24;160296:6;160230:30;:73::i;161492:1666::-;161678:20;161715:17;:9;:15;;;:17::i;:::-;161711:89;;;161749:14;;;;;;;;;;;:22;;;161779:6;161749:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;161711:89;161812:18;161833:23;;;:13;:23;;;;;;;;;161867:59;;;;;;;36168:2:1;161867:59:0;;;36150:21:1;36207:2;36187:18;;;36180:30;36246:24;36226:18;;;36219:52;36288:18;;161867:59:0;35966:346:1;161867:59:0;161991:10;161937:25;162050:17;:15;;;;:17::i;:::-;:72;;162113:9;162050:72;;;162083:14;;;;162050:72;162016:106;;162133:29;162165:17;:9;:15;;;:17::i;:::-;:72;;162228:9;162165:72;;;162198:14;;;;162165:72;162133:104;;162271:11;162254:28;;:13;:28;;;162250:74;;162306:6;162299:13;;;;;;;;162250:74;162360:43;;;;;:15;16978::1;;;162360:43:0;;;16960:34:1;17030:15;;;17010:18;;;17003:43;162334:23:0;;162360:15;;;;;;16872:18:1;;162360:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;162334:69;-1:-1:-1;162418:27:0;;;162414:53;;162454:13;;;;;;;;;;;;;;162414:53;162478:13;;162563:100;:14;;;162592:13;162620:11;162646:6;162563:14;:100::i;:::-;162526:137;;-1:-1:-1;162526:137:0;-1:-1:-1;162526:137:0;-1:-1:-1;162674:126:0;;;;162703:4;:9;;;:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;162674:126;;;162736:8;162732:68;;;162771:16;;162761:27;;;;;:9;162771:16;;;162761:27;;;7681:74:1;162761:9:0;;;;;;7654:18:1;;162761:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;162732:68;162812:54;:31;;;162852:4;162859:6;162812:31;:54::i;:::-;;162975:11;162951:38;;162919:13;162895:40;;:94;162877:274;;;163016:45;;;;;163026:1;163016:45;;;37515:25:1;;;37556:18;;;37549:34;;;163051:4:0;37599:18:1;;;37592:83;37711:3;37691:18;;;37684:31;37731:19;;;37724:30;163016:9:0;;;;;;37771:19:1;;163016:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;162877:274;;;163094:45;;;;;;;;37515:25:1;;;163118:1:0;37556:18:1;;;37549:34;;;163129:4:0;37599:18:1;;;37592:83;37711:3;37691:18;;;37684:31;37731:19;;;37724:30;163094:9:0;;;;;;37771:19:1;;163094:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;162877:274;161700:1458;;;;;;;161492:1666;;;;;;:::o;129385:1123::-;129575:14;;;;129652:47;:28;;;129689:8;129652:28;:47::i;:::-;129632:67;-1:-1:-1;129710:18:0;129731:47;:28;;;129768:8;129731:28;:47::i;:::-;129710:68;;129790:16;129808;129830:8;:20;;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;129789:63;;;;;129879:9;129867:21;;:9;:21;;;129863:97;;;129929:8;129863:97;129994:8;129982:20;;:9;:20;:45;;;;130019:8;130006:21;;:10;:21;129982:45;129970:58;;130051:8;130050:9;:60;;;;;130076:8;130064:20;;:9;:20;:45;;;;130101:8;130088:21;;:10;:21;130064:45;130039:71;-1:-1:-1;130123:23:0;130149:17;:8;130162:3;130149:12;:17::i;:::-;130123:43;;130177:17;130197:86;130231:41;130251:10;130263:8;130231:41;;:19;:41::i;:::-;130197:15;;:19;:86::i;:::-;130177:106;;130294:19;130316:113;130413:15;130316:78;130389:4;130316:54;130350:9;130361:8;130316:54;;:33;:54::i;:::-;:72;;:78::i;:::-;:96;;:113::i;:::-;130294:135;-1:-1:-1;130450:16:0;;130449:51;;130474:26;:9;130488:11;130474:13;:26::i;:::-;130449:51;;;130470:1;130449:51;130440:60;;129621:887;;;;;;;129385:1123;;;;;;;;:::o;77739:98::-;77797:7;77824:5;77828:1;77824;:5;:::i;61600:106::-;61658:7;61689:1;61685;:5;:13;;61697:1;61685:13;;;-1:-1:-1;61693:1:0;;61600:106;-1:-1:-1;61600:106:0:o;77001:98::-;77059:7;77086:5;77090:1;77086;:5;:::i;78138:98::-;78196:7;78223:5;78227:1;78223;:5;:::i;-1:-1:-1:-;;;:::i;:::-;:::o;14:332:1:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;725:154;811:42;804:5;800:54;793:5;790:65;780:93;;869:1;866;859:12;884:134;952:20;;981:31;952:20;981:31;:::i;:::-;884:134;;;:::o;1023:315::-;1091:6;1099;1152:2;1140:9;1131:7;1127:23;1123:32;1120:52;;;1168:1;1165;1158:12;1120:52;1204:9;1191:23;1181:33;;1264:2;1253:9;1249:18;1236:32;1277:31;1302:5;1277:31;:::i;:::-;1327:5;1317:15;;;1023:315;;;;;:::o;1343:247::-;1402:6;1455:2;1443:9;1434:7;1430:23;1426:32;1423:52;;;1471:1;1468;1461:12;1423:52;1510:9;1497:23;1529:31;1554:5;1529:31;:::i;1595:184::-;1647:77;1644:1;1637:88;1744:4;1741:1;1734:15;1768:4;1765:1;1758:15;1784:255;1856:2;1850:9;1898:6;1886:19;;1935:18;1920:34;;1956:22;;;1917:62;1914:88;;;1982:18;;:::i;:::-;2018:2;2011:22;1784:255;:::o;2044:334::-;2115:2;2109:9;2171:2;2161:13;;2176:66;2157:86;2145:99;;2274:18;2259:34;;2295:22;;;2256:62;2253:88;;;2321:18;;:::i;:::-;2357:2;2350:22;2044:334;;-1:-1:-1;2044:334:1:o;2383:202::-;2462:4;2495:18;2487:6;2484:30;2481:56;;;2517:18;;:::i;:::-;-1:-1:-1;2562:1:1;2558:14;2574:4;2554:25;;2383:202::o;2590:775::-;2663:5;2716:3;2709:4;2701:6;2697:17;2693:27;2683:55;;2734:1;2731;2724:12;2683:55;2770:6;2757:20;2796:4;2820:79;2836:62;2895:2;2836:62;:::i;:::-;2820:79;:::i;:::-;2933:15;;;3019:1;3015:10;;;;3003:23;;2999:32;;;2964:12;;;;3043:15;;;3040:35;;;3071:1;3068;3061:12;3040:35;3107:2;3099:6;3095:15;3119:217;3135:6;3130:3;3127:15;3119:217;;;3215:3;3202:17;3232:31;3257:5;3232:31;:::i;:::-;3276:18;;3314:12;;;;3152;;3119:217;;;-1:-1:-1;3354:5:1;2590:775;-1:-1:-1;;;;;;2590:775:1:o;3370:681::-;3424:5;3477:3;3470:4;3462:6;3458:17;3454:27;3444:55;;3495:1;3492;3485:12;3444:55;3531:6;3518:20;3557:4;3581:79;3597:62;3656:2;3597:62;:::i;3581:79::-;3694:15;;;3780:1;3776:10;;;;3764:23;;3760:32;;;3725:12;;;;3804:15;;;3801:35;;;3832:1;3829;3822:12;3801:35;3868:2;3860:6;3856:15;3880:142;3896:6;3891:3;3888:15;3880:142;;;3962:17;;3950:30;;4000:12;;;;3913;;3880:142;;4056:245;4104:4;4137:18;4129:6;4126:30;4123:56;;;4159:18;;:::i;:::-;-1:-1:-1;4216:2:1;4204:15;4221:66;4200:88;4290:4;4196:99;;4056:245::o;4306:462::-;4348:5;4401:3;4394:4;4386:6;4382:17;4378:27;4368:55;;4419:1;4416;4409:12;4368:55;4455:6;4442:20;4486:48;4502:31;4530:2;4502:31;:::i;4486:48::-;4559:2;4550:7;4543:19;4605:3;4598:4;4593:2;4585:6;4581:15;4577:26;4574:35;4571:55;;;4622:1;4619;4612:12;4571:55;4687:2;4680:4;4672:6;4668:17;4661:4;4652:7;4648:18;4635:55;4735:1;4710:16;;;4728:4;4706:27;4699:38;;;;4714:7;4306:462;-1:-1:-1;;;4306:462:1:o;4773:905::-;4825:5;4878:3;4871:4;4863:6;4859:17;4855:27;4845:55;;4896:1;4893;4886:12;4845:55;4932:6;4919:20;4958:4;4982:79;4998:62;5057:2;4998:62;:::i;4982:79::-;5095:15;;;5181:1;5177:10;;;;5165:23;;5161:32;;;5126:12;;;;5205:15;;;5202:35;;;5233:1;5230;5223:12;5202:35;5269:2;5261:6;5257:15;5281:368;5297:6;5292:3;5289:15;5281:368;;;5383:3;5370:17;5419:18;5406:11;5403:35;5400:125;;;5479:1;5508:2;5504;5497:14;5400:125;5550:56;5602:3;5597:2;5583:11;5575:6;5571:24;5567:33;5550:56;:::i;:::-;5538:69;;-1:-1:-1;5627:12:1;;;;5314;;5281:368;;5683:118;5769:5;5762:13;5755:21;5748:5;5745:32;5735:60;;5791:1;5788;5781:12;5806:128;5871:20;;5900:28;5871:20;5900:28;:::i;5939:1224::-;6168:6;6176;6184;6192;6200;6208;6216;6224;6277:3;6265:9;6256:7;6252:23;6248:33;6245:53;;;6294:1;6291;6284:12;6245:53;6334:9;6321:23;6363:18;6404:2;6396:6;6393:14;6390:34;;;6420:1;6417;6410:12;6390:34;6443:80;6515:7;6506:6;6495:9;6491:22;6443:80;:::i;:::-;6433:90;;6570:2;6559:9;6555:18;6542:32;6532:42;;6621:2;6610:9;6606:18;6593:32;6583:42;;6678:2;6667:9;6663:18;6650:32;6634:48;;6707:2;6697:8;6694:16;6691:36;;;6723:1;6720;6713:12;6691:36;6746:63;6801:7;6790:8;6779:9;6775:24;6746:63;:::i;:::-;6736:73;;6862:3;6851:9;6847:19;6834:33;6818:49;;6892:2;6882:8;6879:16;6876:36;;;6908:1;6905;6898:12;6876:36;;6931:61;6984:7;6973:8;6962:9;6958:24;6931:61;:::i;:::-;6921:71;;;7011:36;7042:3;7031:9;7027:19;7011:36;:::i;:::-;7001:46;;7066:39;7100:3;7089:9;7085:19;7066:39;:::i;:::-;7056:49;;7152:3;7141:9;7137:19;7124:33;7114:43;;5939:1224;;;;;;;;;;;:::o;7350:180::-;7409:6;7462:2;7450:9;7441:7;7437:23;7433:32;7430:52;;;7478:1;7475;7468:12;7430:52;-1:-1:-1;7501:23:1;;7350:180;-1:-1:-1;7350:180:1:o;8597:347::-;8648:8;8658:6;8712:3;8705:4;8697:6;8693:17;8689:27;8679:55;;8730:1;8727;8720:12;8679:55;-1:-1:-1;8753:20:1;;8796:18;8785:30;;8782:50;;;8828:1;8825;8818:12;8782:50;8865:4;8857:6;8853:17;8841:29;;8917:3;8910:4;8901:6;8893;8889:19;8885:30;8882:39;8879:59;;;8934:1;8931;8924:12;8879:59;8597:347;;;;;:::o;8949:156::-;9015:20;;9075:4;9064:16;;9054:27;;9044:55;;9095:1;9092;9085:12;9110:1333;9167:5;9215:6;9203:9;9198:3;9194:19;9190:32;9187:52;;;9235:1;9232;9225:12;9187:52;9257:22;;:::i;:::-;9248:31;;9315:9;9302:23;9344:18;9385:2;9377:6;9374:14;9371:34;;;9401:1;9398;9391:12;9371:34;9428:76;9500:3;9491:6;9480:9;9476:22;9428:76;:::i;:::-;9421:5;9414:91;9565:2;9554:9;9550:18;9537:32;9532:2;9525:5;9521:14;9514:56;9630:2;9619:9;9615:18;9602:32;9597:2;9590:5;9586:14;9579:56;9695:2;9684:9;9680:18;9667:32;9662:2;9655:5;9651:14;9644:56;9753:3;9742:9;9738:19;9725:33;9709:49;;9783:2;9773:8;9770:16;9767:36;;;9799:1;9796;9789:12;9767:36;9836:59;9891:3;9880:8;9869:9;9865:24;9836:59;:::i;:::-;9830:3;9823:5;9819:15;9812:84;9949:3;9938:9;9934:19;9921:33;9905:49;;9979:2;9969:8;9966:16;9963:36;;;9995:1;9992;9985:12;9963:36;10032:57;10085:3;10074:8;10063:9;10059:24;10032:57;:::i;:::-;10026:3;10019:5;10015:15;10008:82;10123:36;10154:3;10143:9;10139:19;10123:36;:::i;:::-;10117:3;10110:5;10106:15;10099:61;10193:39;10227:3;10216:9;10212:19;10193:39;:::i;:::-;10187:3;10180:5;10176:15;10169:64;10252:3;10242:13;;10308:2;10297:9;10293:18;10280:32;10337:2;10327:8;10324:16;10321:36;;;10353:1;10350;10343:12;10321:36;10389:47;10432:3;10421:8;10410:9;10406:24;10389:47;:::i;:::-;10384:2;10377:5;10373:14;10366:71;;;;9110:1333;;;;:::o;10448:1210::-;10616:6;10624;10632;10640;10648;10656;10664;10672;10680;10733:3;10721:9;10712:7;10708:23;10704:33;10701:53;;;10750:1;10747;10740:12;10701:53;10786:9;10773:23;10763:33;;10843:2;10832:9;10828:18;10815:32;10805:42;;10898:2;10887:9;10883:18;10870:32;10921:18;10962:2;10954:6;10951:14;10948:34;;;10978:1;10975;10968:12;10948:34;11017:58;11067:7;11058:6;11047:9;11043:22;11017:58;:::i;:::-;11094:8;;-1:-1:-1;10991:84:1;-1:-1:-1;10991:84:1;;-1:-1:-1;11148:36:1;11180:2;11165:18;;11148:36;:::i;:::-;11138:46;;11231:3;11220:9;11216:19;11203:33;11193:43;;11289:3;11278:9;11274:19;11261:33;11245:49;;11319:2;11309:8;11306:16;11303:36;;;11335:1;11332;11325:12;11303:36;11358:51;11401:7;11390:8;11379:9;11375:24;11358:51;:::i;:::-;11348:61;;11462:3;11451:9;11447:19;11434:33;11418:49;;11492:2;11482:8;11479:16;11476:36;;;11508:1;11505;11498:12;11476:36;;11531:63;11586:7;11575:8;11564:9;11560:24;11531:63;:::i;:::-;11521:73;;;11613:39;11647:3;11636:9;11632:19;11613:39;:::i;:::-;11603:49;;10448:1210;;;;;;;;;;;:::o;11663:626::-;11760:6;11768;11821:2;11809:9;11800:7;11796:23;11792:32;11789:52;;;11837:1;11834;11827:12;11789:52;11877:9;11864:23;11906:18;11947:2;11939:6;11936:14;11933:34;;;11963:1;11960;11953:12;11933:34;12001:6;11990:9;11986:22;11976:32;;12046:7;12039:4;12035:2;12031:13;12027:27;12017:55;;12068:1;12065;12058:12;12017:55;12108:2;12095:16;12134:2;12126:6;12123:14;12120:34;;;12150:1;12147;12140:12;12120:34;12203:7;12198:2;12188:6;12185:1;12181:14;12177:2;12173:23;12169:32;12166:45;12163:65;;;12224:1;12221;12214:12;12163:65;12255:2;12247:11;;;;;12277:6;;-1:-1:-1;11663:626:1;;-1:-1:-1;;;;11663:626:1:o;12294:250::-;12379:1;12389:113;12403:6;12400:1;12397:13;12389:113;;;12479:11;;;12473:18;12460:11;;;12453:39;12425:2;12418:10;12389:113;;;-1:-1:-1;;12536:1:1;12518:16;;12511:27;12294:250::o;12549:329::-;12590:3;12628:5;12622:12;12655:6;12650:3;12643:19;12671:76;12740:6;12733:4;12728:3;12724:14;12717:4;12710:5;12706:16;12671:76;:::i;:::-;12792:2;12780:15;12797:66;12776:88;12767:98;;;;12867:4;12763:109;;12549:329;-1:-1:-1;;12549:329:1:o;12883:614::-;12934:3;12972:5;12966:12;12999:6;12994:3;12987:19;13025:4;13066:2;13061:3;13057:12;13091:11;13118;13111:18;;13168:6;13165:1;13161:14;13154:5;13150:26;13138:38;;13210:2;13203:5;13199:14;13231:1;13241:230;13255:6;13252:1;13249:13;13241:230;;;13326:5;13320:4;13316:16;13311:3;13304:29;13354:37;13386:4;13377:6;13371:13;13354:37;:::i;:::-;13449:12;;;;13346:45;-1:-1:-1;13414:15:1;;;;13277:1;13270:9;13241:230;;;-1:-1:-1;13487:4:1;;12883:614;-1:-1:-1;;;;;;;12883:614:1:o;13502:277::-;13699:2;13688:9;13681:21;13662:4;13719:54;13769:2;13758:9;13754:18;13746:6;13719:54;:::i;13969:523::-;14055:6;14063;14071;14124:2;14112:9;14103:7;14099:23;14095:32;14092:52;;;14140:1;14137;14130:12;14092:52;14179:9;14166:23;14198:31;14223:5;14198:31;:::i;:::-;14248:5;-1:-1:-1;14300:2:1;14285:18;;14272:32;;-1:-1:-1;14355:2:1;14340:18;;14327:32;14382:18;14371:30;;14368:50;;;14414:1;14411;14404:12;14368:50;14437:49;14478:7;14469:6;14458:9;14454:22;14437:49;:::i;:::-;14427:59;;;13969:523;;;;;:::o;14497:388::-;14565:6;14573;14626:2;14614:9;14605:7;14601:23;14597:32;14594:52;;;14642:1;14639;14632:12;14594:52;14681:9;14668:23;14700:31;14725:5;14700:31;:::i;:::-;14750:5;-1:-1:-1;14807:2:1;14792:18;;14779:32;14820:33;14779:32;14820:33;:::i;15135:1283::-;15355:6;15363;15371;15379;15387;15395;15403;15456:3;15444:9;15435:7;15431:23;15427:33;15424:53;;;15473:1;15470;15463:12;15424:53;15513:9;15500:23;15542:18;15583:2;15575:6;15572:14;15569:34;;;15599:1;15596;15589:12;15569:34;15622:80;15694:7;15685:6;15674:9;15670:22;15622:80;:::i;:::-;15612:90;;15749:2;15738:9;15734:18;15721:32;15711:42;;15800:2;15789:9;15785:18;15772:32;15762:42;;15857:2;15846:9;15842:18;15829:32;15813:48;;15886:2;15876:8;15873:16;15870:36;;;15902:1;15899;15892:12;15870:36;15925:63;15980:7;15969:8;15958:9;15954:24;15925:63;:::i;:::-;15915:73;;16041:3;16030:9;16026:19;16013:33;15997:49;;16071:2;16061:8;16058:16;16055:36;;;16087:1;16084;16077:12;16055:36;;16110:61;16163:7;16152:8;16141:9;16137:24;16110:61;:::i;:::-;16100:71;;;16221:3;16210:9;16206:19;16193:33;16235:28;16257:5;16235:28;:::i;:::-;16282:5;-1:-1:-1;16339:3:1;16324:19;;16311:33;16353;16311;16353;:::i;:::-;16405:7;16395:17;;;15135:1283;;;;;;;;;;:::o;17328:503::-;17400:3;17438:5;17432:12;17465:6;17460:3;17453:19;17491:4;17520:2;17515:3;17511:12;17504:19;;17557:2;17550:5;17546:14;17578:1;17588:218;17602:6;17599:1;17596:13;17588:218;;;17667:13;;17682:42;17663:62;17651:75;;17746:12;;;;17781:15;;;;17624:1;17617:9;17588:218;;;-1:-1:-1;17822:3:1;;17328:503;-1:-1:-1;;;;;17328:503:1:o;17836:435::-;17889:3;17927:5;17921:12;17954:6;17949:3;17942:19;17980:4;18009:2;18004:3;18000:12;17993:19;;18046:2;18039:5;18035:14;18067:1;18077:169;18091:6;18088:1;18085:13;18077:169;;;18152:13;;18140:26;;18186:12;;;;18221:15;;;;18113:1;18106:9;18077:169;;18276:726;18643:3;18632:9;18625:22;18606:4;18670:76;18741:3;18730:9;18726:19;18718:6;18670:76;:::i;:::-;18782:6;18777:2;18766:9;18762:18;18755:34;18825:6;18820:2;18809:9;18805:18;18798:34;18880:9;18872:6;18868:22;18863:2;18852:9;18848:18;18841:50;18908:44;18945:6;18937;18908:44;:::i;:::-;18900:52;;;18989:6;18983:3;18972:9;18968:19;18961:35;18276:726;;;;;;;;:::o;19423:184::-;19475:77;19472:1;19465:88;19572:4;19569:1;19562:15;19596:4;19593:1;19586:15;19612:128;19679:9;;;19700:11;;;19697:37;;;19714:18;;:::i;19745:184::-;19797:77;19794:1;19787:88;19894:4;19891:1;19884:15;19918:4;19915:1;19908:15;20435:325;20523:6;20518:3;20511:19;20575:6;20568:5;20561:4;20556:3;20552:14;20539:43;;20627:1;20620:4;20611:6;20606:3;20602:16;20598:27;20591:38;20493:3;20749:4;20679:66;20674:2;20666:6;20662:15;20658:88;20653:3;20649:98;20645:109;20638:116;;20435:325;;;;:::o;20765:578::-;21015:4;21044:3;21056:48;21094:9;21086:6;20017:5;20011:12;20006:3;19999:25;20073:4;20066:5;20062:16;20056:23;20049:4;20044:3;20040:14;20033:47;20129:4;20122:5;20118:16;20112:23;20105:4;20100:3;20096:14;20089:47;20182:4;20175:5;20171:16;20165:23;20207:42;20299:2;20285:12;20281:21;20274:4;20269:3;20265:14;20258:45;20364:2;20356:4;20349:5;20345:16;20339:23;20335:32;20328:4;20323:3;20319:14;20312:56;;;20417:4;20410:5;20406:16;20400:23;20393:4;20388:3;20384:14;20377:47;19934:496;;;21056:48;21141:2;21135:3;21124:9;21120:19;21113:31;21167:44;21207:2;21196:9;21192:18;21184:6;21167:44;:::i;:::-;21153:58;;21260:9;21252:6;21248:22;21242:3;21231:9;21227:19;21220:51;21288:49;21330:6;21322;21314;21288:49;:::i;21348:739::-;21644:4;21673:3;21685:48;21723:9;21715:6;20017:5;20011:12;20006:3;19999:25;20073:4;20066:5;20062:16;20056:23;20049:4;20044:3;20040:14;20033:47;20129:4;20122:5;20118:16;20112:23;20105:4;20100:3;20096:14;20089:47;20182:4;20175:5;20171:16;20165:23;20207:42;20299:2;20285:12;20281:21;20274:4;20269:3;20265:14;20258:45;20364:2;20356:4;20349:5;20345:16;20339:23;20335:32;20328:4;20323:3;20319:14;20312:56;;;20417:4;20410:5;20406:16;20400:23;20393:4;20388:3;20384:14;20377:47;19934:496;;;21685:48;21770:2;21764:3;21753:9;21749:19;21742:31;21796:44;21836:2;21825:9;21821:18;21813:6;21796:44;:::i;:::-;21782:58;;21889:9;21881:6;21877:22;21871:3;21860:9;21856:19;21849:51;21923:49;21965:6;21957;21949;21923:49;:::i;:::-;21909:63;;22021:9;22013:6;22009:22;22003:3;21992:9;21988:19;21981:51;22049:32;22074:6;22066;22049:32;:::i;:::-;22041:40;21348:739;-1:-1:-1;;;;;;;;21348:739:1:o;22092:580::-;22169:4;22175:6;22235:11;22222:25;22325:66;22314:8;22298:14;22294:29;22290:102;22270:18;22266:127;22256:155;;22407:1;22404;22397:12;22256:155;22434:33;;22486:20;;;-1:-1:-1;22529:18:1;22518:30;;22515:50;;;22561:1;22558;22551:12;22515:50;22594:4;22582:17;;-1:-1:-1;22625:14:1;22621:27;;;22611:38;;22608:58;;;22662:1;22659;22652:12;22677:195;22716:3;22747:66;22740:5;22737:77;22734:103;;22817:18;;:::i;:::-;-1:-1:-1;22864:1:1;22853:13;;22677:195::o;23894:184::-;23964:6;24017:2;24005:9;23996:7;23992:23;23988:32;23985:52;;;24033:1;24030;24023:12;23985:52;-1:-1:-1;24056:16:1;;23894:184;-1:-1:-1;23894:184:1:o;24293:::-;24345:77;24342:1;24335:88;24442:4;24439:1;24432:15;24466:4;24463:1;24456:15;24482:772;24566:5;24619:3;24612:4;24604:6;24600:17;24596:27;24586:55;;24637:1;24634;24627:12;24586:55;24666:6;24660:13;24692:4;24716:79;24732:62;24791:2;24732:62;:::i;24716:79::-;24829:15;;;24915:1;24911:10;;;;24899:23;;24895:32;;;24860:12;;;;24939:15;;;24936:35;;;24967:1;24964;24957:12;24936:35;25003:2;24995:6;24991:15;25015:210;25031:6;25026:3;25023:15;25015:210;;;25104:3;25098:10;25121:31;25146:5;25121:31;:::i;:::-;25165:18;;25203:12;;;;25048;;25015:210;;25259:441;25312:5;25365:3;25358:4;25350:6;25346:17;25342:27;25332:55;;25383:1;25380;25373:12;25332:55;25412:6;25406:13;25443:48;25459:31;25487:2;25459:31;:::i;25443:48::-;25516:2;25507:7;25500:19;25562:3;25555:4;25550:2;25542:6;25538:15;25534:26;25531:35;25528:55;;;25579:1;25576;25569:12;25528:55;25592:77;25666:2;25659:4;25650:7;25646:18;25639:4;25631:6;25627:17;25592:77;:::i;25705:913::-;25768:5;25821:3;25814:4;25806:6;25802:17;25798:27;25788:55;;25839:1;25836;25829:12;25788:55;25868:6;25862:13;25894:4;25918:79;25934:62;25993:2;25934:62;:::i;25918:79::-;26031:15;;;26117:1;26113:10;;;;26101:23;;26097:32;;;26062:12;;;;26141:15;;;26138:35;;;26169:1;26166;26159:12;26138:35;26205:2;26197:6;26193:15;26217:372;26233:6;26228:3;26225:15;26217:372;;;26312:3;26306:10;26348:18;26335:11;26332:35;26329:125;;;26408:1;26437:2;26433;26426:14;26329:125;26479:67;26542:3;26537:2;26523:11;26515:6;26511:24;26507:33;26479:67;:::i;:::-;26467:80;;-1:-1:-1;26567:12:1;;;;26250;;26217:372;;26623:678;26688:5;26741:3;26734:4;26726:6;26722:17;26718:27;26708:55;;26759:1;26756;26749:12;26708:55;26788:6;26782:13;26814:4;26838:79;26854:62;26913:2;26854:62;:::i;26838:79::-;26951:15;;;27037:1;27033:10;;;;27021:23;;27017:32;;;26982:12;;;;27061:15;;;27058:35;;;27089:1;27086;27079:12;27058:35;27125:2;27117:6;27113:15;27137:135;27153:6;27148:3;27145:15;27137:135;;;27219:10;;27207:23;;27250:12;;;;27170;;27137:135;;27306:146;27393:13;;27415:31;27393:13;27415:31;:::i;27457:132::-;27533:13;;27555:28;27533:13;27555:28;:::i;27594:1343::-;27842:6;27850;27858;27866;27874;27882;27890;27943:3;27931:9;27922:7;27918:23;27914:33;27911:53;;;27960:1;27957;27950:12;27911:53;27993:9;27987:16;28022:18;28063:2;28055:6;28052:14;28049:34;;;28079:1;28076;28069:12;28049:34;28102:91;28185:7;28176:6;28165:9;28161:22;28102:91;:::i;:::-;28092:101;;28233:2;28222:9;28218:18;28212:25;28202:35;;28283:2;28272:9;28268:18;28262:25;28246:41;;28312:2;28302:8;28299:16;28296:36;;;28328:1;28325;28318:12;28296:36;28351:72;28415:7;28404:8;28393:9;28389:24;28351:72;:::i;:::-;28341:82;;28469:2;28458:9;28454:18;28448:25;28432:41;;28498:2;28488:8;28485:16;28482:36;;;28514:1;28511;28504:12;28482:36;28537:74;28603:7;28592:8;28581:9;28577:24;28537:74;:::i;:::-;28527:84;;28630:58;28683:3;28672:9;28668:19;28630:58;:::i;:::-;28620:68;;28707:47;28749:3;28738:9;28734:19;28707:47;:::i;:::-;28697:57;;28800:3;28789:9;28785:19;28779:26;28763:42;;28830:2;28820:8;28817:16;28814:36;;;28846:1;28843;28836:12;28814:36;;28869:62;28923:7;28912:8;28901:9;28897:24;28869:62;:::i;:::-;28859:72;;;27594:1343;;;;;;;;;;:::o;28942:1078::-;29427:3;29416:9;29409:22;29390:4;29454:76;29525:3;29514:9;29510:19;29502:6;29454:76;:::i;:::-;29566:6;29561:2;29550:9;29546:18;29539:34;29609:6;29604:2;29593:9;29589:18;29582:34;29664:9;29656:6;29652:22;29647:2;29636:9;29632:18;29625:50;29698:44;29735:6;29727;29698:44;:::i;:::-;29684:58;;29791:9;29783:6;29779:22;29773:3;29762:9;29758:19;29751:51;29819:42;29854:6;29846;29819:42;:::i;:::-;29905:14;;29898:22;29892:3;29877:19;;29870:51;-1:-1:-1;;29970:42:1;29958:55;;;;29952:3;29937:19;;;29930:84;29811:50;28942:1078;-1:-1:-1;;;;;28942:1078:1:o;30025:287::-;30154:3;30192:6;30186:13;30208:66;30267:6;30262:3;30255:4;30247:6;30243:17;30208:66;:::i;:::-;30290:16;;;;;30025:287;-1:-1:-1;;30025:287:1:o;30317:357::-;30435:12;;30482:4;30471:16;;;30465:23;;30435:12;30500:16;;30497:171;;;30590:66;30580:6;30574:4;30570:17;30567:1;30563:25;30559:98;30552:5;30548:110;30539:119;;30497:171;;30317:357;;;:::o;30679:408::-;30894:42;30886:6;30882:55;30871:9;30864:74;30974:6;30969:2;30958:9;30954:18;30947:34;31017:2;31012;31001:9;30997:18;30990:30;30845:4;31037:44;31077:2;31066:9;31062:18;31054:6;31037:44;:::i;:::-;31029:52;30679:408;-1:-1:-1;;;;;30679:408:1:o;31092:812::-;31503:25;31498:3;31491:38;31473:3;31558:6;31552:13;31574:75;31642:6;31637:2;31632:3;31628:12;31621:4;31613:6;31609:17;31574:75;:::i;:::-;31713:19;31708:2;31668:16;;;31700:11;;;31693:40;31758:13;;31780:76;31758:13;31842:2;31834:11;;31827:4;31815:17;;31780:76;:::i;:::-;31876:17;31895:2;31872:26;;31092:812;-1:-1:-1;;;;31092:812:1:o;31909:219::-;32058:2;32047:9;32040:21;32021:4;32078:44;32118:2;32107:9;32103:18;32095:6;32078:44;:::i;32846:245::-;32913:6;32966:2;32954:9;32945:7;32941:23;32937:32;32934:52;;;32982:1;32979;32972:12;32934:52;33014:9;33008:16;33033:28;33055:5;33033:28;:::i;33922:168::-;33995:9;;;34026;;34043:15;;;34037:22;;34023:37;34013:71;;34064:18;;:::i;34095:125::-;34160:9;;;34181:10;;;34178:36;;;34194:18;;:::i;34225:196::-;34264:3;34292:5;34282:39;;34301:18;;:::i;:::-;-1:-1:-1;34348:66:1;34337:78;;34225:196::o;36317:251::-;36387:6;36440:2;36428:9;36419:7;36415:23;36411:32;36408:52;;;36456:1;36453;36446:12;36408:52;36488:9;36482:16;36507:31;36532:5;36507:31;:::i;38362:188::-;38441:13;;38494:30;38483:42;;38473:53;;38463:81;;38540:1;38537;38530:12;38555:450;38642:6;38650;38658;38711:2;38699:9;38690:7;38686:23;38682:32;38679:52;;;38727:1;38724;38717:12;38679:52;38750:40;38780:9;38750:40;:::i;:::-;38740:50;;38809:49;38854:2;38843:9;38839:18;38809:49;:::i;:::-;38799:59;;38901:2;38890:9;38886:18;38880:25;38945:10;38938:5;38934:22;38927:5;38924:33;38914:61;;38971:1;38968;38961:12;38914:61;38994:5;38984:15;;;38555:450;;;;;:::o;39010:274::-;39050:1;39076;39066:189;;39111:77;39108:1;39101:88;39212:4;39209:1;39202:15;39240:4;39237:1;39230:15;39066:189;-1:-1:-1;39269:9:1;;39010:274::o;39289:184::-;39341:77;39338:1;39331:88;39438:4;39435:1;39428:15;39462:4;39459:1;39452:15
Swarm Source
ipfs://4f8bc88753261c0edad1003917da2a98ae0c20588845f73fe617d7b954cbe5cd
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
LINEA | 42.65% | $2,429.82 | 3.264 | $7,930.86 | |
LINEA | 9.38% | $0.998862 | 1,747.1856 | $1,745.2 | |
LINEA | 1.63% | $0.99989 | 302.779 | $302.75 | |
LINEA | <0.01% | $2,443.66 | 0.000000000761 | $0.000002 | |
AVAX | 37.66% | $0.999897 | 7,004.7146 | $7,003.99 | |
AVAX | 3.40% | $0.998943 | 632.0408 | $631.37 | |
ZKSYNC | 3.63% | $2,443.66 | 0.276 | $674.45 | |
SCROLL | 1.58% | $2,443.66 | 0.1206 | $294.7 | |
BASE | 0.07% | $2,447.24 | 0.005 | $12.24 | |
OP | <0.01% | $2,448.8 | 0.0005688 | $1.39 |
[ 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.