Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 265 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Swap In Same Cha... | 19474809 | 131 days ago | IN | 0.1069 ETH | 0.00634415 | ||||
Swap And Deposit | 19474552 | 131 days ago | IN | 0 ETH | 0.00998702 | ||||
Swap In Same Cha... | 19471764 | 131 days ago | IN | 0.16 ETH | 0.01122403 | ||||
Swap And Deposit | 19469470 | 132 days ago | IN | 0.3 ETH | 0.01552308 | ||||
Swap In Same Cha... | 19468916 | 132 days ago | IN | 0.107 ETH | 0.00916243 | ||||
Swap And Deposit | 19468634 | 132 days ago | IN | 0.7685 ETH | 0.01812681 | ||||
Swap And Deposit | 19464944 | 132 days ago | IN | 0 ETH | 0.0089283 | ||||
Swap And Deposit | 19464129 | 133 days ago | IN | 0 ETH | 0.01596182 | ||||
Swap And Deposit | 19462737 | 133 days ago | IN | 0 ETH | 0.01872357 | ||||
Swap And Deposit | 19462734 | 133 days ago | IN | 1 ETH | 0.01528326 | ||||
Swap And Deposit | 19462731 | 133 days ago | IN | 0 ETH | 0.01779848 | ||||
Swap In Same Cha... | 19460042 | 133 days ago | IN | 0 ETH | 0.00094814 | ||||
Swap In Same Cha... | 19460040 | 133 days ago | IN | 0 ETH | 0.0045923 | ||||
Swap And Deposit | 19459472 | 133 days ago | IN | 0 ETH | 0.00530546 | ||||
Swap In Same Cha... | 19453754 | 134 days ago | IN | 0 ETH | 0.00493744 | ||||
Swap And Deposit | 19453710 | 134 days ago | IN | 0.01 ETH | 0.01066284 | ||||
Swap In Same Cha... | 19453464 | 134 days ago | IN | 0 ETH | 0.01705225 | ||||
Swap In Same Cha... | 19453457 | 134 days ago | IN | 0 ETH | 0.01886286 | ||||
Swap In Same Cha... | 19453453 | 134 days ago | IN | 0 ETH | 0.0187155 | ||||
Swap In Same Cha... | 19453390 | 134 days ago | IN | 0.1061 ETH | 0.00785177 | ||||
Swap And Deposit | 19451691 | 134 days ago | IN | 0 ETH | 0.00496823 | ||||
Swap And Deposit | 19450007 | 135 days ago | IN | 2.04 ETH | 0.01301346 | ||||
Swap And Deposit | 19448785 | 135 days ago | IN | 0.61 ETH | 0.01090842 | ||||
Swap And Deposit | 19446324 | 135 days ago | IN | 0 ETH | 0.00577938 | ||||
Swap And Deposit | 19446317 | 135 days ago | IN | 0 ETH | 0.00602881 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
19474809 | 131 days ago | 0.1069 ETH | ||||
19471764 | 131 days ago | 0.16 ETH | ||||
19469470 | 132 days ago | 0.3 ETH | ||||
19468916 | 132 days ago | 0.107 ETH | ||||
19468634 | 132 days ago | 0.7685 ETH | ||||
19467263 | 132 days ago | 23.367436 ETH | ||||
19467263 | 132 days ago | 23.367436 ETH | ||||
19467246 | 132 days ago | 50.9583089 ETH | ||||
19467246 | 132 days ago | 50.9583089 ETH | ||||
19467222 | 132 days ago | 10.18395828 ETH | ||||
19467222 | 132 days ago | 10.18395828 ETH | ||||
19462734 | 133 days ago | 1 ETH | ||||
19461112 | 133 days ago | 0.05956565 ETH | ||||
19461112 | 133 days ago | 0.05956565 ETH | ||||
19460423 | 133 days ago | 0.82305548 ETH | ||||
19460423 | 133 days ago | 0.82305548 ETH | ||||
19458567 | 133 days ago | 0.03033892 ETH | ||||
19458567 | 133 days ago | 0.03033892 ETH | ||||
19453754 | 134 days ago | 0.04216092 ETH | ||||
19453754 | 134 days ago | 0.04216092 ETH | ||||
19453710 | 134 days ago | 0.01 ETH | ||||
19453390 | 134 days ago | 0.1061 ETH | ||||
19450007 | 135 days ago | 2.04 ETH | ||||
19448785 | 135 days ago | 0.61 ETH | ||||
19441670 | 136 days ago | 1.1 ETH |
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.18+commit.87f61d96
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-01-25 */ // SPDX-License-Identifier: MIT pragma solidity 0.8.18; // 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; } } } // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.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); } // 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); } // 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); } } } /** * @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)); } } // 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); } // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.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; } } /** * @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); } } // OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.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; } // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.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); } } } // 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); } } } /** * @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)); } } // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.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); } /** * @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; } } /** * @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()); } } } // 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 { /** * @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; } } 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); } interface IUniswapFactory { function getExchange( IERC20Upgradeable token ) external view returns (IUniswapExchange exchange); } // 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); } } } // 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; } } } // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.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); } // 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); } } } /** * @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)); } } // 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" ); } } 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)) { payable(address(uint160(to))).transfer(amount); } 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)) { payable(address(uint160(to))).transfer(amount); } if (msg.value > amount) { payable(msg.sender).transfer(msg.value.sub(amount)); } } 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 payable(msg.sender).transfer(msg.value.sub(amount)); } } 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)); } } 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); } } interface IUniswapV2Factory { function getPair( IERC20Upgradeable tokenA, IERC20Upgradeable tokenB ) external view returns (IUniswapV2Exchange pair); } interface IHandlerReserve { function _lpToContract(address token) external returns (address); function _contractToLP(address token) external returns (address); } interface IEthHandler { function withdraw(address WETH, uint256) external; } 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); } abstract contract IWETH is IERC20Upgradeable { function deposit() external payable virtual; function withdraw(uint256 amount) external virtual; } // import "./libraries/Multicall.sol"; interface IAugustusSwapper { function getTokenTransferProxy() external view returns (address); } /// @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 iUSDCDeposited( uint256 partnerId, uint256 amount, bytes32 destChainIdBytes, uint256 usdcNonce, address srcToken, bytes32 recipient, address depositor ); 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 DestDetails { uint32 domainId; uint256 fee; bool isSet; } 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 iDepositUSDC( uint256 partnerId, bytes32 destChainIdBytes, bytes32 recipient, uint256 amount ) external payable; 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; } /// @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; } 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 ); } 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 internal 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]; } } contract DexSpan is DexSpanFlags, DexSpanRoot, AccessControl, Multicall { 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 InavlidPool(); error InavlidCaller(); error ZeroAddress(); error ZeroFlag(); error InvalidCaller(); error RestrictNativeToken(); error WrongTokenSent(); error WrongDataLength(); error AmountTooLow(); error ExcecutionFailed(); error AlreadyFactorySetter(); struct DexesArgs { IERC20Upgradeable factoryAddress; uint256 _exchangeCode; } struct SwapParams { IERC20Upgradeable[] tokens; uint256 amount; uint256 minReturn; 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 InavlidCaller(); } _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, uint256 feeAmount, bytes memory message, bool isMessage, 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 ]; uint256 amount = reserveToken.universalBalanceOf(address(this)); if (isMessage) { reserveToken.universalApprove( address(assetForwarder), swapData.minReturn ); assetForwarder.iDepositMessage{ value: reserveToken.isETH() ? amount : 0 }( IAssetForwarder.DepositData( partnerId, swapData.minReturn, swapData.minReturn - feeAmount, address(reserveToken), refundRecipient, destChainIdBytes ), swapData.destToken, recipient, message ); // In case of confusion please connect with Developers if (amount > swapData.minReturn) { reserveToken.universalTransfer( refundRecipient, amount - swapData.minReturn ); } } else { 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 ); } } 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 if (flag == 0x03EA) { return _swapOnOneInch; // 1002 } else if (flag == 0x0FA2) { return _swapOnOpenocean; // 4002 } else if (flag == 0x0BBA) { return _swapOnUniswapV3; // 3002 } 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 _swapOnUniswapV3( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, bytes memory _data, uint256 flagCode ) internal { if (_data.length < 0) { revert WrongDataLength(); } address uniswapv3router = flagToAddress[flagCode]; if (uniswapv3router == address(0)) { revert ZeroAddress(); } if (fromToken.isETH()) { wnativeAddress.deposit{value: amount}(); } IERC20Upgradeable fromTokenReal = fromToken.isETH() ? wnativeAddress : fromToken; fromTokenReal.universalApprove(address(uniswapv3router), amount); // solhint-disable-next-line avoid-low-level-calls (bool success, ) = address(uniswapv3router).call(_data); if (!success) revert ExcecutionFailed(); } function _swapOnOpenocean( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, bytes memory _data, uint256 flagCode ) internal { if (_data.length < 0) { revert WrongDataLength(); } address openoceanSwap = flagToAddress[flagCode]; if (openoceanSwap == address(0)) { revert ZeroAddress(); } if (fromToken.isETH()) { wnativeAddress.deposit{value: amount}(); } IERC20Upgradeable fromTokenReal = fromToken.isETH() ? wnativeAddress : fromToken; fromTokenReal.universalApprove(address(openoceanSwap), amount); // solhint-disable-next-line avoid-low-level-calls (bool success, ) = address(openoceanSwap).call(_data); if (!success) { revert ExcecutionFailed(); } } function _swapOnOneInch( IERC20Upgradeable fromToken, IERC20Upgradeable destToken, uint256 amount, bytes memory _data, uint256 flagCode ) internal { if (_data.length < 0) { revert WrongDataLength(); } address oneInchSwap = flagToAddress[flagCode]; if (oneInchSwap == address(0)) { revert ZeroAddress(); } if (fromToken.isETH()) { wnativeAddress.deposit{value: amount}(); } IERC20Upgradeable fromTokenReal = fromToken.isETH() ? wnativeAddress : fromToken; fromTokenReal.universalApprove(address(oneInchSwap), amount); // solhint-disable-next-line avoid-low-level-calls (bool success, ) = address(oneInchSwap).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 InavlidPool(); 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":"InavlidCaller","type":"error"},{"inputs":[],"name":"InavlidPool","type":"error"},{"inputs":[],"name":"InvalidCaller","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":"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":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"bool","name":"isMessage","type":"bool"},{"components":[{"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":"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
60806040523480156200001157600080fd5b5060405162004d9338038062004d93833981016040819052620000349162000206565b6001600160a01b0384166200005c5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038316620000845760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038216620000ac5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038116620000d45760405163d92e233d60e01b815260040160405180910390fd5b620000e160003362000135565b600480546001600160a01b039586166001600160a01b031991821617909155600280549486169482169490941790935560018054928516928416929092179091556006805491909316911617905562000263565b62000141828262000145565b5050565b60008281526003602090815260408083206001600160a01b038516845290915290205460ff16620001415760008281526003602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620001a53390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b80516001600160a01b03811681146200020157600080fd5b919050565b600080600080608085870312156200021d57600080fd5b6200022885620001e9565b93506200023860208601620001e9565b92506200024860408601620001e9565b91506200025860608601620001e9565b905092959194509250565b614b2080620002736000396000f3fe6080604052600436106101b05760003560e01c806391d14854116100ec578063d00a2d5f1161008a578063da6689f011610064578063da6689f01461057e578063e2a4ac2d1461059e578063e738aa8d146105cb578063f2fde38b146105de57600080fd5b8063d00a2d5f14610511578063d4ee1d9014610531578063d547741f1461055e57600080fd5b8063a2625efc116100c6578063a2625efc14610454578063ac9650d814610481578063adb88982146104ae578063c75a57e4146104ce57600080fd5b806391d14854146103cc5780639e99ec391461041f578063a217fddf1461043f57600080fd5b8063285f94a01161015957806336568abe1161013357806336568abe146103575780634e71e0c8146103775780637fe689171461038c57806387b47f11146103b957600080fd5b8063285f94a0146102b85780632e4763371461030a5780632f2ff15d1461033757600080fd5b806318137a411161018a57806318137a4114610255578063183d9c9514610275578063248a9ca31461028857600080fd5b806301ffc9a7146101bc578063086efdc4146101f1578063169651601461023357600080fd5b366101b757005b600080fd5b3480156101c857600080fd5b506101dc6101d73660046138cc565b6105fe565b60405190151581526020015b60405180910390f35b3480156101fd57600080fd5b506102257fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee097581565b6040519081526020016101e8565b34801561023f57600080fd5b5061025361024e366004613940565b610697565b005b34801561026157600080fd5b50610253610270366004613970565b6107d5565b610225610283366004613c58565b6108ad565b34801561029457600080fd5b506102256102a3366004613d1f565b60009081526003602052604090206001015490565b3480156102c457600080fd5b506005546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e8565b34801561031657600080fd5b506002546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561034357600080fd5b50610253610352366004613940565b610957565b34801561036357600080fd5b50610253610372366004613940565b610981565b34801561038357600080fd5b50610253610a39565b34801561039857600080fd5b506004546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b6102536103c7366004613e71565b610aca565b3480156103d857600080fd5b506101dc6103e7366004613940565b600091825260036020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561042b57600080fd5b5061025361043a366004613970565b610df0565b34801561044b57600080fd5b50610225600081565b34801561046057600080fd5b506006546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561048d57600080fd5b506104a161049c366004613f3d565b610ec0565b6040516101e89190614075565b3480156104ba57600080fd5b506102536104c9366004613970565b610fb5565b3480156104da57600080fd5b506102e56104e9366004613d1f565b60086020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b34801561051d57600080fd5b5061025361052c366004614088565b6110fc565b34801561053d57600080fd5b506007546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561056a57600080fd5b50610253610579366004613940565b61117e565b34801561058a57600080fd5b506102536105993660046140e1565b6111a3565b3480156105aa57600080fd5b506001546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b6102256105d936600461410f565b6112cb565b3480156105ea57600080fd5b506102536105f9366004613970565b611375565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061069157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b7fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee09756106c181611440565b826000036106fb576040517f196de28b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216610748576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526008602090815260409182902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86169081179091558251868152918201527f11f5b5361c420666dc3452b8107601e1702f94b951f15bd93c26262c8147874e91015b60405180910390a1505050565b60006107e081611440565b73ffffffffffffffffffffffffffffffffffffffff821661082d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155604080519182523360208301527f61b6fe2922f0180b98d305419bf3dcf432f5d8df894388c61c1f599c2194ec1d91015b60405180910390a15050565b60006108be898989898989896112cb565b6040517f73776170496e53616d65436861696e0000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8416903390600f0160405180910390207fe3716b48e7d01d727d68472c873c69c2c4407365e4f68b2b6c8dd4569cd16dc78c8c868c89604051610943959493929190614253565b60405180910390a498975050505050505050565b60008281526003602052604090206001015461097281611440565b61097c838361144d565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610a2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610a358282611541565b5050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610a8a576040517f821de23100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a956000336115fc565b6040513381527f85a8c8100c1d48466310240af79644f50cdae7d09cb4820d60dfc5b2462f0fd09060200160405180910390a1565b610af1826000015183602001518460400151856060015186608001518760a0015130611606565b508151805160009190610b06906001906142c6565b81518110610b1657610b166142d9565b602002602001015190506000610b4b308373ffffffffffffffffffffffffffffffffffffffff16611b1c90919063ffffffff16565b90508415610cc5576004546040850151610b809173ffffffffffffffffffffffffffffffffffffffff85811692911690611be1565b60045473ffffffffffffffffffffffffffffffffffffffff90811690630421caf090610bad908516611c05565b610bb8576000610bba565b825b6040518060c001604052808f8152602001886040015181526020018b8960400151610be591906142c6565b81526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508760e001518d8d8c6040518763ffffffff1660e01b8152600401610c4e959493929190614351565b6000604051808303818588803b158015610c6757600080fd5b505af1158015610c7b573d6000803e3d6000fd5b50505050508360400151811115610cc057610cbe83856040015183610ca091906142c6565b73ffffffffffffffffffffffffffffffffffffffff85169190611c58565b505b610de3565b600454610cec9073ffffffffffffffffffffffffffffffffffffffff848116911683611be1565b60045473ffffffffffffffffffffffffffffffffffffffff9081169063f452ed4d90610d19908516611c05565b610d24576000610d26565b825b6040518060c001604052808f81526020018581526020018b86610d4991906142c6565b81526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508760e001518d8d6040518663ffffffff1660e01b8152600401610db094939291906143f9565b6000604051808303818588803b158015610dc957600080fd5b505af1158015610ddd573d6000803e3d6000fd5b50505050505b5050505050505050505050565b6000610dfb81611440565b73ffffffffffffffffffffffffffffffffffffffff8216610e48576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155604080519182523360208301527f45085069ced50a4d2e82656a82ba8f5a1a28694489d8ea262252e40899a930a291016108a1565b60608167ffffffffffffffff811115610edb57610edb61398d565b604051908082528060200260200182016040528015610f0e57816020015b6060815260200190600190039081610ef95790505b50905060005b82811015610fae57610f7e30858584818110610f3257610f326142d9565b9050602002810190610f449190614480565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611cd792505050565b828281518110610f9057610f906142d9565b60200260200101819052508080610fa6906144e5565b915050610f14565b5092915050565b6000610fc081611440565b73ffffffffffffffffffffffffffffffffffffffff821661100d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081527f3ab9add546f7e3b43565da9bc7e65e47b969d3856bb01a7dcac7bc8ff5080cbd602052604090205460ff161561108c576040517fe4e970d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110b67fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee0975836115fc565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fd2b69bde5a989d23ef605a0dd4e0edf7662105058ab69f2559e482857b599ed8906020016108a1565b60045473ffffffffffffffffffffffffffffffffffffffff16331480159061113c575060055473ffffffffffffffffffffffffffffffffffffffff163314155b15611173576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097c838383611cfc565b60008281526003602052604090206001015461119981611440565b61097c8383611541565b60006111ae81611440565b73ffffffffffffffffffffffffffffffffffffffff83166111fb576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611248576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556001805492851692909116821790556040519081527fcc4166d40cf68104cdf710f65ce022efd296742868a22b42e4695f89b8863636906020016107c8565b60006112dc88888888888888611606565b6040517f737761704d756c746957697468526563697069656e7400000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff831690339060160160405180910390207fc40fae9d5f584875c393ac222c6f88b6c9dced1e9cc6251483648ac2e902c8b08b8b868b6000604051611362959493929190614253565b60405180910390a4979650505050505050565b600061138081611440565b73ffffffffffffffffffffffffffffffffffffffff82166113cd576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527fcfaaa26691e16e66e73290fc725eee1a6b4e0e693a1640484937aac25ffb55a4906020016108a1565b61144a813361206f565b50565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a3557600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556114e33390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1615610a3557600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b610a35828261144d565b600073ffffffffffffffffffffffffffffffffffffffff8216611655576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516001895161166591906142c6565b1461169c576040517fcc513c7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82611764576116da886000815181106116b7576116b76142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611c05565b1580156116e657503415155b1561171d576040517f694b150300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117643330898b600081518110611736576117366142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16612129909392919063ffffffff16565b6117a7308960008151811061177b5761177b6142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611b1c90919063ffffffff16565b905060008860018a516117ba91906142c6565b815181106117ca576117ca6142d9565b602002602001015190506000600190505b8951811015611900578981815181106117f6576117f66142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168a60018361182291906142c6565b81518110611832576118326142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603156118ee576118eb8a6118656001846142c6565b81518110611875576118756142d9565b60200260200101518b838151811061188f5761188f6142d9565b60200260200101518560008b6001876118a891906142c6565b815181106118b8576118b86142d9565b60200260200101518b6001886118ce91906142c6565b815181106118de576118de6142d9565b60200260200101516122a7565b92505b806118f8816144e5565b9150506117db565b506119208173ffffffffffffffffffffffffffffffffffffffff16611c05565b15611a3d576001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015611993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b7919061451d565b6001546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905291935073ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff83163014611b10576000611a7c73ffffffffffffffffffffffffffffffffffffffff831685611b1c565b9050611a9f73ffffffffffffffffffffffffffffffffffffffff83168585611c58565b506000611ac273ffffffffffffffffffffffffffffffffffffffff841686611b1c565b90506000611ad083836142c6565b9050898111611b0b576040517f1fbaba3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b935050505b50979650505050505050565b6000611b2783611c05565b15611b4a575073ffffffffffffffffffffffffffffffffffffffff811631610691565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015611bb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bda919061451d565b9050610691565b611bea83611c05565b61097c57611bfa838360006122c2565b61097c8383836122c2565b600073ffffffffffffffffffffffffffffffffffffffff82161580610691575073ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b600081600003611c6a57506001611cd0565b611c7384611c05565b15611cc15760405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc029084906000818181858888f19350505050158015611cbb573d6000803e3d6000fd5b50611cd0565b611ccc848484612458565b5060015b9392505050565b6060611cd08383604051806060016040528060278152602001614ac4602791396125e7565b600080600080600080600087806020019051810190611d1b91906146d0565b965096509650965096509650965086600081518110611d3c57611d3c6142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff1614611da8576040517f198b098900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606060003073ffffffffffffffffffffffffffffffffffffffff1663e738aa8d60e01b8a8d8b8a8c60018c604051602401611de997969594939291906147a8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611e72919061481f565b6000604051808303816000865af19150503d8060008114611eaf576040519150601f19603f3d011682016040523d82523d6000602084013e611eb4565b606091505b509250905080611f0557611f03858c8b600081518110611ed657611ed66142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611c589092919063ffffffff16565b505b831561206157600081611f18578b611f21565b611f218361483b565b9050600082611f30578d611f58565b8a60018c51611f3f91906142c6565b81518110611f4f57611f4f6142d9565b60200260200101515b90508673ffffffffffffffffffffffffffffffffffffffff1663d00a2d5f60e01b828488604051602401611f8e93929190614880565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612017919061481f565b6000604051808303816000865af19150503d8060008114612054576040519150601f19603f3d011682016040523d82523d6000602084013e612059565b606091505b509450925050505b505050505050505050505050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a35576120af8161266c565b6120ba83602061268b565b6040516020016120cb9291906148be565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a0000000000000000000000000000000000000000000000000000000008252610a229160040161493f565b80156122a15761213884611c05565b156122955773ffffffffffffffffffffffffffffffffffffffff8316331480156121625750803410155b6121ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f57726f6e67207573616765206f66204554482e756e6976657273616c5472616e60448201527f7366657246726f6d2829000000000000000000000000000000000000000000006064820152608401610a22565b73ffffffffffffffffffffffffffffffffffffffff821630146122505760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f1935050505015801561224e573d6000803e3d6000fd5b505b8034111561229057336108fc61226634846128ce565b6040518115909202916000818181858888f1935050505015801561228e573d6000803e3d6000fd5b505b6122a1565b6122a1848484846128da565b50505050565b60006122b7878787878787612a79565b979650505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839290871691612359919061481f565b6000604051808303816000865af19150503d8060008114612396576040519150601f19603f3d011682016040523d82523d6000602084013e61239b565b606091505b50915091508180156123c55750805115806123c55750808060200190518101906123c59190614952565b612451576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5472616e7366657248656c7065723a3a73616665417070726f76653a2061707060448201527f726f7665206661696c65640000000000000000000000000000000000000000006064820152608401610a22565b5050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916124ef919061481f565b6000604051808303816000865af19150503d806000811461252c576040519150601f19603f3d011682016040523d82523d6000602084013e612531565b606091505b509150915081801561255b57508051158061255b57508080602001905181019061255b9190614952565b612451576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201527f616e73666572206661696c6564000000000000000000000000000000000000006064820152608401610a22565b60606000808573ffffffffffffffffffffffffffffffffffffffff1685604051612611919061481f565b600060405180830381855af49150503d806000811461264c576040519150601f19603f3d011682016040523d82523d6000602084013e612651565b606091505b509150915061266286838387612b25565b9695505050505050565b606061069173ffffffffffffffffffffffffffffffffffffffff831660145b6060600061269a83600261496f565b6126a5906002614986565b67ffffffffffffffff8111156126bd576126bd61398d565b6040519080825280601f01601f1916602001820160405280156126e7576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061271e5761271e6142d9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612781576127816142d9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006127bd84600261496f565b6127c8906001614986565b90505b6001811115612865577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110612809576128096142d9565b1a60f81b82828151811061281f5761281f6142d9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361285e81614999565b90506127cb565b508315611cd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a22565b6000611cd082846142c6565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691612979919061481f565b6000604051808303816000865af19150503d80600081146129b6576040519150601f19603f3d011682016040523d82523d6000602084013e6129bb565b606091505b50915091508180156129e55750805115806129e55750808060200190518101906129e59190614952565b612a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c65640000000000000000000000000000006064820152608401610a22565b505050505050565b60008573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603612ab5575083612662565b6138c2612ac184612bcd565b90506000612ae573ffffffffffffffffffffffffffffffffffffffff8a1630611b1c565b9050612af889898387898763ffffffff16565b612b1873ffffffffffffffffffffffffffffffffffffffff891630611b1c565b9998505050505050505050565b60608315612bbb578251600003612bb45773ffffffffffffffffffffffffffffffffffffffff85163b612bb4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a22565b5081612bc5565b612bc58383612c9a565b949350505050565b6138c26103e982108015612be2575060018210155b15612bf05750612cde919050565b816107d203612c025750612cea919050565b816103ea03612c145750612f73919050565b81610fa203612c265750612f73919050565b81610bba03612c385750612f73919050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52413a2045786368616e6765206e6f7420666f756e64000000000000000000006044820152606401610a22565b815115612caa5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a22919061493f565b612a71858585846130df565b60008181526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680612d46576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612d658673ffffffffffffffffffffffffffffffffffffffff16611c05565b15612dee57600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015612dd457600080fd5b505af1158015612de8573d6000803e3d6000fd5b50505050505b6000612e0f8773ffffffffffffffffffffffffffffffffffffffff16611c05565b612e195786612e33565b60015473ffffffffffffffffffffffffffffffffffffffff165b9050612ec58273ffffffffffffffffffffffffffffffffffffffff1663d2c4b5986040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea791906149ce565b73ffffffffffffffffffffffffffffffffffffffff83169087611be1565b60008273ffffffffffffffffffffffffffffffffffffffff1685604051612eec919061481f565b6000604051808303816000865af19150503d8060008114612f29576040519150601f19603f3d011682016040523d82523d6000602084013e612f2e565b606091505b5050905080612f69576040517f5987947500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b60008181526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680612fcf576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fee8673ffffffffffffffffffffffffffffffffffffffff16611c05565b1561307757600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561305d57600080fd5b505af1158015613071573d6000803e3d6000fd5b50505050505b60006130988773ffffffffffffffffffffffffffffffffffffffff16611c05565b6130a257866130bc565b60015473ffffffffffffffffffffffffffffffffffffffff165b9050612ec573ffffffffffffffffffffffffffffffffffffffff82168387611be1565b60006131008573ffffffffffffffffffffffffffffffffffffffff16611c05565b1561318957600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b15801561316f57600080fd5b505af1158015613183573d6000803e3d6000fd5b50505050505b60008281526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680613215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52413a2045786368616e6765206e6f7420666f756e64000000000000000000006044820152606401610a22565b80600061323773ffffffffffffffffffffffffffffffffffffffff8916611c05565b613241578761325b565b60015473ffffffffffffffffffffffffffffffffffffffff165b9050600061327e8873ffffffffffffffffffffffffffffffffffffffff16611c05565b61328857876132a2565b60015473ffffffffffffffffffffffffffffffffffffffff165b90508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036132e35786945050505050612bc5565b6040517fe6a4390500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282811660248301526000919085169063e6a4390590604401602060405180830381865afa15801561335b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061337f91906149ce565b905073ffffffffffffffffffffffffffffffffffffffff81166133ce576040517f1fcdbb0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806133f373ffffffffffffffffffffffffffffffffffffffff841686868d613692565b919950925090508115613465578273ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561344857600080fd5b505af115801561345c573d6000803e3d6000fd5b505050506134f1565b80156134f1576006546040517fbc25cf7700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201529084169063bc25cf7790602401600060405180830381600087803b1580156134d857600080fd5b505af11580156134ec573d6000803e3d6000fd5b505050505b61351273ffffffffffffffffffffffffffffffffffffffff8616848c611c58565b508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610156135e7576040517f022c0d9f000000000000000000000000000000000000000000000000000000008152600060048201819052602482018a905230604483015260806064830152608482015273ffffffffffffffffffffffffffffffffffffffff84169063022c0d9f9060a401600060405180830381600087803b1580156135ca57600080fd5b505af11580156135de573d6000803e3d6000fd5b50505050613683565b6040517f022c0d9f0000000000000000000000000000000000000000000000000000000081526004810189905260006024820181905230604483015260806064830152608482015273ffffffffffffffffffffffffffffffffffffffff84169063022c0d9f9060a401600060405180830381600087803b15801561366a57600080fd5b505af115801561367e573d6000803e3d6000fd5b505050505b50505050505050949350505050565b60008080806136b773ffffffffffffffffffffffffffffffffffffffff881689611b1c565b905060006136db73ffffffffffffffffffffffffffffffffffffffff88168a611b1c565b90506000808a73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561372b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374f9190614a09565b50915091508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16111561378a57905b816dffffffffffffffffffffffffffff168410806137b75750806dffffffffffffffffffffffffffff1683105b9550851580156137ef5750816dffffffffffffffffffffffffffff168411806137ef5750806dffffffffffffffffffffffffffff1683115b945060006137ff896103e5613888565b9050600061382761382086856dffffffffffffffffffffffffffff16613894565b8390613888565b9050600061385b836138556103e861384f8b8a6dffffffffffffffffffffffffffff16613894565b90613888565b906138aa565b905080156138725761386d82826138b6565b613875565b60005b9950505050505050509450945094915050565b6000611cd0828461496f565b60008183106138a35781611cd0565b5090919050565b6000611cd08284614986565b6000611cd08284614a59565b6138ca614a94565b565b6000602082840312156138de57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611cd057600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461144a57600080fd5b803561393b8161390e565b919050565b6000806040838503121561395357600080fd5b8235915060208301356139658161390e565b809150509250929050565b60006020828403121561398257600080fd5b8135611cd08161390e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156139e0576139e061398d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613a2d57613a2d61398d565b604052919050565b600067ffffffffffffffff821115613a4f57613a4f61398d565b5060051b60200190565b600082601f830112613a6a57600080fd5b81356020613a7f613a7a83613a35565b6139e6565b82815260059290921b84018101918181019086841115613a9e57600080fd5b8286015b84811015613ac2578035613ab58161390e565b8352918301918301613aa2565b509695505050505050565b600082601f830112613ade57600080fd5b81356020613aee613a7a83613a35565b82815260059290921b84018101918181019086841115613b0d57600080fd5b8286015b84811015613ac25780358352918301918301613b11565b600067ffffffffffffffff821115613b4257613b4261398d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613b7f57600080fd5b8135613b8d613a7a82613b28565b818152846020838601011115613ba257600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112613bd057600080fd5b81356020613be0613a7a83613a35565b82815260059290921b84018101918181019086841115613bff57600080fd5b8286015b84811015613ac257803567ffffffffffffffff811115613c235760008081fd5b613c318986838b0101613b6e565b845250918301918301613c03565b801515811461144a57600080fd5b803561393b81613c3f565b600080600080600080600080610100898b031215613c7557600080fd5b883567ffffffffffffffff80821115613c8d57600080fd5b613c998c838d01613a59565b995060208b0135985060408b0135975060608b0135915080821115613cbd57600080fd5b613cc98c838d01613acd565b965060808b0135915080821115613cdf57600080fd5b50613cec8b828c01613bbf565b945050613cfb60a08a01613c4d565b9250613d0960c08a01613930565b915060e089013590509295985092959890939650565b600060208284031215613d3157600080fd5b5035919050565b60008083601f840112613d4a57600080fd5b50813567ffffffffffffffff811115613d6257600080fd5b602083019150836020828501011115613d7a57600080fd5b9250929050565b60006101008284031215613d9457600080fd5b613d9c6139bc565b9050813567ffffffffffffffff80821115613db657600080fd5b613dc285838601613a59565b835260208401356020840152604084013560408401526060840135915080821115613dec57600080fd5b613df885838601613acd565b60608401526080840135915080821115613e1157600080fd5b613e1d85838601613bbf565b6080840152613e2e60a08501613c4d565b60a0840152613e3f60c08501613930565b60c084015260e0840135915080821115613e5857600080fd5b50613e6584828501613b6e565b60e08301525092915050565b60008060008060008060008060006101008a8c031215613e9057600080fd5b8935985060208a0135975060408a013567ffffffffffffffff80821115613eb657600080fd5b613ec28d838e01613d38565b909950975060608c0135965060808c0135915080821115613ee257600080fd5b613eee8d838e01613b6e565b9550613efc60a08d01613c4d565b945060c08c0135915080821115613f1257600080fd5b50613f1f8c828d01613d81565b925050613f2e60e08b01613930565b90509295985092959850929598565b60008060208385031215613f5057600080fd5b823567ffffffffffffffff80821115613f6857600080fd5b818501915085601f830112613f7c57600080fd5b813581811115613f8b57600080fd5b8660208260051b8501011115613fa057600080fd5b60209290920196919550909350505050565b60005b83811015613fcd578181015183820152602001613fb5565b50506000910152565b60008151808452613fee816020860160208601613fb2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015614068578284038952614056848351613fd6565b9885019893509084019060010161403e565b5091979650505050505050565b602081526000611cd06020830184614020565b60008060006060848603121561409d57600080fd5b83356140a88161390e565b925060208401359150604084013567ffffffffffffffff8111156140cb57600080fd5b6140d786828701613b6e565b9150509250925092565b600080604083850312156140f457600080fd5b82356140ff8161390e565b915060208301356139658161390e565b600080600080600080600060e0888a03121561412a57600080fd5b873567ffffffffffffffff8082111561414257600080fd5b61414e8b838c01613a59565b985060208a0135975060408a0135965060608a013591508082111561417257600080fd5b61417e8b838c01613acd565b955060808a013591508082111561419457600080fd5b506141a18a828b01613bbf565b93505060a08801356141b281613c3f565b915060c08801356141c28161390e565b8091505092959891949750929550565b600081518084526020808501945080840160005b8381101561421857815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016141e6565b509495945050505050565b600081518084526020808501945080840160005b8381101561421857815187529582019590820190600101614237565b60a08152600061426660a08301886141d2565b86602084015285604084015282810360608401526142848186614223565b9150508260808301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561069157610691614297565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60006101206143b18389805182526020810151602083015260408101516040830152606081015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080840151166080850152505060a081015160a08301525050565b8060c08401526143c381840188613fd6565b905082810360e08401526143d8818688614308565b90508281036101008401526143ed8185613fd6565b98975050505050505050565b60006101006144598388805182526020810151602083015260408101516040830152606081015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080840151166080850152505060a081015160a08301525050565b8060c084015261446b81840187613fd6565b905082810360e08401526122b7818587614308565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126144b557600080fd5b83018035915067ffffffffffffffff8211156144d057600080fd5b602001915036819003821315613d7a57600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361451657614516614297565b5060010190565b60006020828403121561452f57600080fd5b5051919050565b600082601f83011261454757600080fd5b81516020614557613a7a83613a35565b82815260059290921b8401810191818101908684111561457657600080fd5b8286015b84811015613ac257805161458d8161390e565b835291830191830161457a565b600082601f8301126145ab57600080fd5b81516145b9613a7a82613b28565b8181528460208386010111156145ce57600080fd5b612bc5826020830160208701613fb2565b600082601f8301126145f057600080fd5b81516020614600613a7a83613a35565b82815260059290921b8401810191818101908684111561461f57600080fd5b8286015b84811015613ac257805167ffffffffffffffff8111156146435760008081fd5b6146518986838b010161459a565b845250918301918301614623565b600082601f83011261467057600080fd5b81516020614680613a7a83613a35565b82815260059290921b8401810191818101908684111561469f57600080fd5b8286015b84811015613ac257805183529183019183016146a3565b805161393b8161390e565b805161393b81613c3f565b600080600080600080600060e0888a0312156146eb57600080fd5b875167ffffffffffffffff8082111561470357600080fd5b61470f8b838c01614536565b985060208a0151975060408a015191508082111561472c57600080fd5b6147388b838c016145df565b965060608a015191508082111561474e57600080fd5b61475a8b838c0161465f565b955061476860808b016146ba565b945061477660a08b016146c5565b935060c08a015191508082111561478c57600080fd5b506147998a828b0161459a565b91505092959891949750929550565b60e0815260006147bb60e083018a6141d2565b88602084015287604084015282810360608401526147d98188614223565b905082810360808401526147ed8187614020565b94151560a0840152505073ffffffffffffffffffffffffffffffffffffffff9190911660c09091015295945050505050565b60008251614831818460208701613fb2565b9190910192915050565b8051602080830151919081101561487a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b73ffffffffffffffffffffffffffffffffffffffff841681528260208201526060604082015260006148b56060830184613fd6565b95945050505050565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516148f6816017850160208801613fb2565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614933816028840160208801613fb2565b01602801949350505050565b602081526000611cd06020830184613fd6565b60006020828403121561496457600080fd5b8151611cd081613c3f565b808202811582820484141761069157610691614297565b8082018082111561069157610691614297565b6000816149a8576149a8614297565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b6000602082840312156149e057600080fd5b8151611cd08161390e565b80516dffffffffffffffffffffffffffff8116811461393b57600080fd5b600080600060608486031215614a1e57600080fd5b614a27846149eb565b9250614a35602085016149eb565b9150604084015163ffffffff81168114614a4e57600080fd5b809150509250925092565b600082614a8f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d77c836f50e8fca127bdf0b20c6376c023ebbdd9466658211512cde84958cda364736f6c63430008120033000000000000000000000000c21e4ebd1d92036cb467b53fe3258f219d909eb9000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000b1b64005b11350a94c4d069eff4215592d98f2e2
Deployed Bytecode
0x6080604052600436106101b05760003560e01c806391d14854116100ec578063d00a2d5f1161008a578063da6689f011610064578063da6689f01461057e578063e2a4ac2d1461059e578063e738aa8d146105cb578063f2fde38b146105de57600080fd5b8063d00a2d5f14610511578063d4ee1d9014610531578063d547741f1461055e57600080fd5b8063a2625efc116100c6578063a2625efc14610454578063ac9650d814610481578063adb88982146104ae578063c75a57e4146104ce57600080fd5b806391d14854146103cc5780639e99ec391461041f578063a217fddf1461043f57600080fd5b8063285f94a01161015957806336568abe1161013357806336568abe146103575780634e71e0c8146103775780637fe689171461038c57806387b47f11146103b957600080fd5b8063285f94a0146102b85780632e4763371461030a5780632f2ff15d1461033757600080fd5b806318137a411161018a57806318137a4114610255578063183d9c9514610275578063248a9ca31461028857600080fd5b806301ffc9a7146101bc578063086efdc4146101f1578063169651601461023357600080fd5b366101b757005b600080fd5b3480156101c857600080fd5b506101dc6101d73660046138cc565b6105fe565b60405190151581526020015b60405180910390f35b3480156101fd57600080fd5b506102257fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee097581565b6040519081526020016101e8565b34801561023f57600080fd5b5061025361024e366004613940565b610697565b005b34801561026157600080fd5b50610253610270366004613970565b6107d5565b610225610283366004613c58565b6108ad565b34801561029457600080fd5b506102256102a3366004613d1f565b60009081526003602052604090206001015490565b3480156102c457600080fd5b506005546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e8565b34801561031657600080fd5b506002546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561034357600080fd5b50610253610352366004613940565b610957565b34801561036357600080fd5b50610253610372366004613940565b610981565b34801561038357600080fd5b50610253610a39565b34801561039857600080fd5b506004546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b6102536103c7366004613e71565b610aca565b3480156103d857600080fd5b506101dc6103e7366004613940565b600091825260036020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561042b57600080fd5b5061025361043a366004613970565b610df0565b34801561044b57600080fd5b50610225600081565b34801561046057600080fd5b506006546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561048d57600080fd5b506104a161049c366004613f3d565b610ec0565b6040516101e89190614075565b3480156104ba57600080fd5b506102536104c9366004613970565b610fb5565b3480156104da57600080fd5b506102e56104e9366004613d1f565b60086020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b34801561051d57600080fd5b5061025361052c366004614088565b6110fc565b34801561053d57600080fd5b506007546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561056a57600080fd5b50610253610579366004613940565b61117e565b34801561058a57600080fd5b506102536105993660046140e1565b6111a3565b3480156105aa57600080fd5b506001546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b6102256105d936600461410f565b6112cb565b3480156105ea57600080fd5b506102536105f9366004613970565b611375565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061069157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b7fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee09756106c181611440565b826000036106fb576040517f196de28b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216610748576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526008602090815260409182902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86169081179091558251868152918201527f11f5b5361c420666dc3452b8107601e1702f94b951f15bd93c26262c8147874e91015b60405180910390a1505050565b60006107e081611440565b73ffffffffffffffffffffffffffffffffffffffff821661082d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155604080519182523360208301527f61b6fe2922f0180b98d305419bf3dcf432f5d8df894388c61c1f599c2194ec1d91015b60405180910390a15050565b60006108be898989898989896112cb565b6040517f73776170496e53616d65436861696e0000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8416903390600f0160405180910390207fe3716b48e7d01d727d68472c873c69c2c4407365e4f68b2b6c8dd4569cd16dc78c8c868c89604051610943959493929190614253565b60405180910390a498975050505050505050565b60008281526003602052604090206001015461097281611440565b61097c838361144d565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610a2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610a358282611541565b5050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610a8a576040517f821de23100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a956000336115fc565b6040513381527f85a8c8100c1d48466310240af79644f50cdae7d09cb4820d60dfc5b2462f0fd09060200160405180910390a1565b610af1826000015183602001518460400151856060015186608001518760a0015130611606565b508151805160009190610b06906001906142c6565b81518110610b1657610b166142d9565b602002602001015190506000610b4b308373ffffffffffffffffffffffffffffffffffffffff16611b1c90919063ffffffff16565b90508415610cc5576004546040850151610b809173ffffffffffffffffffffffffffffffffffffffff85811692911690611be1565b60045473ffffffffffffffffffffffffffffffffffffffff90811690630421caf090610bad908516611c05565b610bb8576000610bba565b825b6040518060c001604052808f8152602001886040015181526020018b8960400151610be591906142c6565b81526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508760e001518d8d8c6040518763ffffffff1660e01b8152600401610c4e959493929190614351565b6000604051808303818588803b158015610c6757600080fd5b505af1158015610c7b573d6000803e3d6000fd5b50505050508360400151811115610cc057610cbe83856040015183610ca091906142c6565b73ffffffffffffffffffffffffffffffffffffffff85169190611c58565b505b610de3565b600454610cec9073ffffffffffffffffffffffffffffffffffffffff848116911683611be1565b60045473ffffffffffffffffffffffffffffffffffffffff9081169063f452ed4d90610d19908516611c05565b610d24576000610d26565b825b6040518060c001604052808f81526020018581526020018b86610d4991906142c6565b81526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018e8152508760e001518d8d6040518663ffffffff1660e01b8152600401610db094939291906143f9565b6000604051808303818588803b158015610dc957600080fd5b505af1158015610ddd573d6000803e3d6000fd5b50505050505b5050505050505050505050565b6000610dfb81611440565b73ffffffffffffffffffffffffffffffffffffffff8216610e48576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155604080519182523360208301527f45085069ced50a4d2e82656a82ba8f5a1a28694489d8ea262252e40899a930a291016108a1565b60608167ffffffffffffffff811115610edb57610edb61398d565b604051908082528060200260200182016040528015610f0e57816020015b6060815260200190600190039081610ef95790505b50905060005b82811015610fae57610f7e30858584818110610f3257610f326142d9565b9050602002810190610f449190614480565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611cd792505050565b828281518110610f9057610f906142d9565b60200260200101819052508080610fa6906144e5565b915050610f14565b5092915050565b6000610fc081611440565b73ffffffffffffffffffffffffffffffffffffffff821661100d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081527f3ab9add546f7e3b43565da9bc7e65e47b969d3856bb01a7dcac7bc8ff5080cbd602052604090205460ff161561108c576040517fe4e970d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110b67fafffb39e42e2a1496bc4305c8783f904fa76641e3895205b6002a03336ee0975836115fc565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fd2b69bde5a989d23ef605a0dd4e0edf7662105058ab69f2559e482857b599ed8906020016108a1565b60045473ffffffffffffffffffffffffffffffffffffffff16331480159061113c575060055473ffffffffffffffffffffffffffffffffffffffff163314155b15611173576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097c838383611cfc565b60008281526003602052604090206001015461119981611440565b61097c8383611541565b60006111ae81611440565b73ffffffffffffffffffffffffffffffffffffffff83166111fb576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611248576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556001805492851692909116821790556040519081527fcc4166d40cf68104cdf710f65ce022efd296742868a22b42e4695f89b8863636906020016107c8565b60006112dc88888888888888611606565b6040517f737761704d756c746957697468526563697069656e7400000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff831690339060160160405180910390207fc40fae9d5f584875c393ac222c6f88b6c9dced1e9cc6251483648ac2e902c8b08b8b868b6000604051611362959493929190614253565b60405180910390a4979650505050505050565b600061138081611440565b73ffffffffffffffffffffffffffffffffffffffff82166113cd576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527fcfaaa26691e16e66e73290fc725eee1a6b4e0e693a1640484937aac25ffb55a4906020016108a1565b61144a813361206f565b50565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a3557600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556114e33390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1615610a3557600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b610a35828261144d565b600073ffffffffffffffffffffffffffffffffffffffff8216611655576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516001895161166591906142c6565b1461169c576040517fcc513c7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82611764576116da886000815181106116b7576116b76142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611c05565b1580156116e657503415155b1561171d576040517f694b150300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117643330898b600081518110611736576117366142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16612129909392919063ffffffff16565b6117a7308960008151811061177b5761177b6142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611b1c90919063ffffffff16565b905060008860018a516117ba91906142c6565b815181106117ca576117ca6142d9565b602002602001015190506000600190505b8951811015611900578981815181106117f6576117f66142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168a60018361182291906142c6565b81518110611832576118326142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603156118ee576118eb8a6118656001846142c6565b81518110611875576118756142d9565b60200260200101518b838151811061188f5761188f6142d9565b60200260200101518560008b6001876118a891906142c6565b815181106118b8576118b86142d9565b60200260200101518b6001886118ce91906142c6565b815181106118de576118de6142d9565b60200260200101516122a7565b92505b806118f8816144e5565b9150506117db565b506119208173ffffffffffffffffffffffffffffffffffffffff16611c05565b15611a3d576001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015611993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b7919061451d565b6001546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905291935073ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff83163014611b10576000611a7c73ffffffffffffffffffffffffffffffffffffffff831685611b1c565b9050611a9f73ffffffffffffffffffffffffffffffffffffffff83168585611c58565b506000611ac273ffffffffffffffffffffffffffffffffffffffff841686611b1c565b90506000611ad083836142c6565b9050898111611b0b576040517f1fbaba3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b935050505b50979650505050505050565b6000611b2783611c05565b15611b4a575073ffffffffffffffffffffffffffffffffffffffff811631610691565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015611bb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bda919061451d565b9050610691565b611bea83611c05565b61097c57611bfa838360006122c2565b61097c8383836122c2565b600073ffffffffffffffffffffffffffffffffffffffff82161580610691575073ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b600081600003611c6a57506001611cd0565b611c7384611c05565b15611cc15760405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc029084906000818181858888f19350505050158015611cbb573d6000803e3d6000fd5b50611cd0565b611ccc848484612458565b5060015b9392505050565b6060611cd08383604051806060016040528060278152602001614ac4602791396125e7565b600080600080600080600087806020019051810190611d1b91906146d0565b965096509650965096509650965086600081518110611d3c57611d3c6142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff1614611da8576040517f198b098900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606060003073ffffffffffffffffffffffffffffffffffffffff1663e738aa8d60e01b8a8d8b8a8c60018c604051602401611de997969594939291906147a8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611e72919061481f565b6000604051808303816000865af19150503d8060008114611eaf576040519150601f19603f3d011682016040523d82523d6000602084013e611eb4565b606091505b509250905080611f0557611f03858c8b600081518110611ed657611ed66142d9565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16611c589092919063ffffffff16565b505b831561206157600081611f18578b611f21565b611f218361483b565b9050600082611f30578d611f58565b8a60018c51611f3f91906142c6565b81518110611f4f57611f4f6142d9565b60200260200101515b90508673ffffffffffffffffffffffffffffffffffffffff1663d00a2d5f60e01b828488604051602401611f8e93929190614880565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612017919061481f565b6000604051808303816000865af19150503d8060008114612054576040519150601f19603f3d011682016040523d82523d6000602084013e612059565b606091505b509450925050505b505050505050505050505050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a35576120af8161266c565b6120ba83602061268b565b6040516020016120cb9291906148be565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a0000000000000000000000000000000000000000000000000000000008252610a229160040161493f565b80156122a15761213884611c05565b156122955773ffffffffffffffffffffffffffffffffffffffff8316331480156121625750803410155b6121ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f57726f6e67207573616765206f66204554482e756e6976657273616c5472616e60448201527f7366657246726f6d2829000000000000000000000000000000000000000000006064820152608401610a22565b73ffffffffffffffffffffffffffffffffffffffff821630146122505760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f1935050505015801561224e573d6000803e3d6000fd5b505b8034111561229057336108fc61226634846128ce565b6040518115909202916000818181858888f1935050505015801561228e573d6000803e3d6000fd5b505b6122a1565b6122a1848484846128da565b50505050565b60006122b7878787878787612a79565b979650505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839290871691612359919061481f565b6000604051808303816000865af19150503d8060008114612396576040519150601f19603f3d011682016040523d82523d6000602084013e61239b565b606091505b50915091508180156123c55750805115806123c55750808060200190518101906123c59190614952565b612451576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5472616e7366657248656c7065723a3a73616665417070726f76653a2061707060448201527f726f7665206661696c65640000000000000000000000000000000000000000006064820152608401610a22565b5050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916124ef919061481f565b6000604051808303816000865af19150503d806000811461252c576040519150601f19603f3d011682016040523d82523d6000602084013e612531565b606091505b509150915081801561255b57508051158061255b57508080602001905181019061255b9190614952565b612451576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201527f616e73666572206661696c6564000000000000000000000000000000000000006064820152608401610a22565b60606000808573ffffffffffffffffffffffffffffffffffffffff1685604051612611919061481f565b600060405180830381855af49150503d806000811461264c576040519150601f19603f3d011682016040523d82523d6000602084013e612651565b606091505b509150915061266286838387612b25565b9695505050505050565b606061069173ffffffffffffffffffffffffffffffffffffffff831660145b6060600061269a83600261496f565b6126a5906002614986565b67ffffffffffffffff8111156126bd576126bd61398d565b6040519080825280601f01601f1916602001820160405280156126e7576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061271e5761271e6142d9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612781576127816142d9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006127bd84600261496f565b6127c8906001614986565b90505b6001811115612865577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110612809576128096142d9565b1a60f81b82828151811061281f5761281f6142d9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361285e81614999565b90506127cb565b508315611cd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a22565b6000611cd082846142c6565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691612979919061481f565b6000604051808303816000865af19150503d80600081146129b6576040519150601f19603f3d011682016040523d82523d6000602084013e6129bb565b606091505b50915091508180156129e55750805115806129e55750808060200190518101906129e59190614952565b612a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c65640000000000000000000000000000006064820152608401610a22565b505050505050565b60008573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603612ab5575083612662565b6138c2612ac184612bcd565b90506000612ae573ffffffffffffffffffffffffffffffffffffffff8a1630611b1c565b9050612af889898387898763ffffffff16565b612b1873ffffffffffffffffffffffffffffffffffffffff891630611b1c565b9998505050505050505050565b60608315612bbb578251600003612bb45773ffffffffffffffffffffffffffffffffffffffff85163b612bb4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a22565b5081612bc5565b612bc58383612c9a565b949350505050565b6138c26103e982108015612be2575060018210155b15612bf05750612cde919050565b816107d203612c025750612cea919050565b816103ea03612c145750612f73919050565b81610fa203612c265750612f73919050565b81610bba03612c385750612f73919050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52413a2045786368616e6765206e6f7420666f756e64000000000000000000006044820152606401610a22565b815115612caa5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a22919061493f565b612a71858585846130df565b60008181526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680612d46576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612d658673ffffffffffffffffffffffffffffffffffffffff16611c05565b15612dee57600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015612dd457600080fd5b505af1158015612de8573d6000803e3d6000fd5b50505050505b6000612e0f8773ffffffffffffffffffffffffffffffffffffffff16611c05565b612e195786612e33565b60015473ffffffffffffffffffffffffffffffffffffffff165b9050612ec58273ffffffffffffffffffffffffffffffffffffffff1663d2c4b5986040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea791906149ce565b73ffffffffffffffffffffffffffffffffffffffff83169087611be1565b60008273ffffffffffffffffffffffffffffffffffffffff1685604051612eec919061481f565b6000604051808303816000865af19150503d8060008114612f29576040519150601f19603f3d011682016040523d82523d6000602084013e612f2e565b606091505b5050905080612f69576040517f5987947500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b60008181526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680612fcf576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fee8673ffffffffffffffffffffffffffffffffffffffff16611c05565b1561307757600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561305d57600080fd5b505af1158015613071573d6000803e3d6000fd5b50505050505b60006130988773ffffffffffffffffffffffffffffffffffffffff16611c05565b6130a257866130bc565b60015473ffffffffffffffffffffffffffffffffffffffff165b9050612ec573ffffffffffffffffffffffffffffffffffffffff82168387611be1565b60006131008573ffffffffffffffffffffffffffffffffffffffff16611c05565b1561318957600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b15801561316f57600080fd5b505af1158015613183573d6000803e3d6000fd5b50505050505b60008281526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1680613215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52413a2045786368616e6765206e6f7420666f756e64000000000000000000006044820152606401610a22565b80600061323773ffffffffffffffffffffffffffffffffffffffff8916611c05565b613241578761325b565b60015473ffffffffffffffffffffffffffffffffffffffff165b9050600061327e8873ffffffffffffffffffffffffffffffffffffffff16611c05565b61328857876132a2565b60015473ffffffffffffffffffffffffffffffffffffffff165b90508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036132e35786945050505050612bc5565b6040517fe6a4390500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282811660248301526000919085169063e6a4390590604401602060405180830381865afa15801561335b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061337f91906149ce565b905073ffffffffffffffffffffffffffffffffffffffff81166133ce576040517f1fcdbb0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806133f373ffffffffffffffffffffffffffffffffffffffff841686868d613692565b919950925090508115613465578273ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561344857600080fd5b505af115801561345c573d6000803e3d6000fd5b505050506134f1565b80156134f1576006546040517fbc25cf7700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201529084169063bc25cf7790602401600060405180830381600087803b1580156134d857600080fd5b505af11580156134ec573d6000803e3d6000fd5b505050505b61351273ffffffffffffffffffffffffffffffffffffffff8616848c611c58565b508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610156135e7576040517f022c0d9f000000000000000000000000000000000000000000000000000000008152600060048201819052602482018a905230604483015260806064830152608482015273ffffffffffffffffffffffffffffffffffffffff84169063022c0d9f9060a401600060405180830381600087803b1580156135ca57600080fd5b505af11580156135de573d6000803e3d6000fd5b50505050613683565b6040517f022c0d9f0000000000000000000000000000000000000000000000000000000081526004810189905260006024820181905230604483015260806064830152608482015273ffffffffffffffffffffffffffffffffffffffff84169063022c0d9f9060a401600060405180830381600087803b15801561366a57600080fd5b505af115801561367e573d6000803e3d6000fd5b505050505b50505050505050949350505050565b60008080806136b773ffffffffffffffffffffffffffffffffffffffff881689611b1c565b905060006136db73ffffffffffffffffffffffffffffffffffffffff88168a611b1c565b90506000808a73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561372b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374f9190614a09565b50915091508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16111561378a57905b816dffffffffffffffffffffffffffff168410806137b75750806dffffffffffffffffffffffffffff1683105b9550851580156137ef5750816dffffffffffffffffffffffffffff168411806137ef5750806dffffffffffffffffffffffffffff1683115b945060006137ff896103e5613888565b9050600061382761382086856dffffffffffffffffffffffffffff16613894565b8390613888565b9050600061385b836138556103e861384f8b8a6dffffffffffffffffffffffffffff16613894565b90613888565b906138aa565b905080156138725761386d82826138b6565b613875565b60005b9950505050505050509450945094915050565b6000611cd0828461496f565b60008183106138a35781611cd0565b5090919050565b6000611cd08284614986565b6000611cd08284614a59565b6138ca614a94565b565b6000602082840312156138de57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611cd057600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461144a57600080fd5b803561393b8161390e565b919050565b6000806040838503121561395357600080fd5b8235915060208301356139658161390e565b809150509250929050565b60006020828403121561398257600080fd5b8135611cd08161390e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156139e0576139e061398d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613a2d57613a2d61398d565b604052919050565b600067ffffffffffffffff821115613a4f57613a4f61398d565b5060051b60200190565b600082601f830112613a6a57600080fd5b81356020613a7f613a7a83613a35565b6139e6565b82815260059290921b84018101918181019086841115613a9e57600080fd5b8286015b84811015613ac2578035613ab58161390e565b8352918301918301613aa2565b509695505050505050565b600082601f830112613ade57600080fd5b81356020613aee613a7a83613a35565b82815260059290921b84018101918181019086841115613b0d57600080fd5b8286015b84811015613ac25780358352918301918301613b11565b600067ffffffffffffffff821115613b4257613b4261398d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613b7f57600080fd5b8135613b8d613a7a82613b28565b818152846020838601011115613ba257600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112613bd057600080fd5b81356020613be0613a7a83613a35565b82815260059290921b84018101918181019086841115613bff57600080fd5b8286015b84811015613ac257803567ffffffffffffffff811115613c235760008081fd5b613c318986838b0101613b6e565b845250918301918301613c03565b801515811461144a57600080fd5b803561393b81613c3f565b600080600080600080600080610100898b031215613c7557600080fd5b883567ffffffffffffffff80821115613c8d57600080fd5b613c998c838d01613a59565b995060208b0135985060408b0135975060608b0135915080821115613cbd57600080fd5b613cc98c838d01613acd565b965060808b0135915080821115613cdf57600080fd5b50613cec8b828c01613bbf565b945050613cfb60a08a01613c4d565b9250613d0960c08a01613930565b915060e089013590509295985092959890939650565b600060208284031215613d3157600080fd5b5035919050565b60008083601f840112613d4a57600080fd5b50813567ffffffffffffffff811115613d6257600080fd5b602083019150836020828501011115613d7a57600080fd5b9250929050565b60006101008284031215613d9457600080fd5b613d9c6139bc565b9050813567ffffffffffffffff80821115613db657600080fd5b613dc285838601613a59565b835260208401356020840152604084013560408401526060840135915080821115613dec57600080fd5b613df885838601613acd565b60608401526080840135915080821115613e1157600080fd5b613e1d85838601613bbf565b6080840152613e2e60a08501613c4d565b60a0840152613e3f60c08501613930565b60c084015260e0840135915080821115613e5857600080fd5b50613e6584828501613b6e565b60e08301525092915050565b60008060008060008060008060006101008a8c031215613e9057600080fd5b8935985060208a0135975060408a013567ffffffffffffffff80821115613eb657600080fd5b613ec28d838e01613d38565b909950975060608c0135965060808c0135915080821115613ee257600080fd5b613eee8d838e01613b6e565b9550613efc60a08d01613c4d565b945060c08c0135915080821115613f1257600080fd5b50613f1f8c828d01613d81565b925050613f2e60e08b01613930565b90509295985092959850929598565b60008060208385031215613f5057600080fd5b823567ffffffffffffffff80821115613f6857600080fd5b818501915085601f830112613f7c57600080fd5b813581811115613f8b57600080fd5b8660208260051b8501011115613fa057600080fd5b60209290920196919550909350505050565b60005b83811015613fcd578181015183820152602001613fb5565b50506000910152565b60008151808452613fee816020860160208601613fb2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015614068578284038952614056848351613fd6565b9885019893509084019060010161403e565b5091979650505050505050565b602081526000611cd06020830184614020565b60008060006060848603121561409d57600080fd5b83356140a88161390e565b925060208401359150604084013567ffffffffffffffff8111156140cb57600080fd5b6140d786828701613b6e565b9150509250925092565b600080604083850312156140f457600080fd5b82356140ff8161390e565b915060208301356139658161390e565b600080600080600080600060e0888a03121561412a57600080fd5b873567ffffffffffffffff8082111561414257600080fd5b61414e8b838c01613a59565b985060208a0135975060408a0135965060608a013591508082111561417257600080fd5b61417e8b838c01613acd565b955060808a013591508082111561419457600080fd5b506141a18a828b01613bbf565b93505060a08801356141b281613c3f565b915060c08801356141c28161390e565b8091505092959891949750929550565b600081518084526020808501945080840160005b8381101561421857815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016141e6565b509495945050505050565b600081518084526020808501945080840160005b8381101561421857815187529582019590820190600101614237565b60a08152600061426660a08301886141d2565b86602084015285604084015282810360608401526142848186614223565b9150508260808301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561069157610691614297565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60006101206143b18389805182526020810151602083015260408101516040830152606081015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080840151166080850152505060a081015160a08301525050565b8060c08401526143c381840188613fd6565b905082810360e08401526143d8818688614308565b90508281036101008401526143ed8185613fd6565b98975050505050505050565b60006101006144598388805182526020810151602083015260408101516040830152606081015173ffffffffffffffffffffffffffffffffffffffff8082166060850152806080840151166080850152505060a081015160a08301525050565b8060c084015261446b81840187613fd6565b905082810360e08401526122b7818587614308565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126144b557600080fd5b83018035915067ffffffffffffffff8211156144d057600080fd5b602001915036819003821315613d7a57600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361451657614516614297565b5060010190565b60006020828403121561452f57600080fd5b5051919050565b600082601f83011261454757600080fd5b81516020614557613a7a83613a35565b82815260059290921b8401810191818101908684111561457657600080fd5b8286015b84811015613ac257805161458d8161390e565b835291830191830161457a565b600082601f8301126145ab57600080fd5b81516145b9613a7a82613b28565b8181528460208386010111156145ce57600080fd5b612bc5826020830160208701613fb2565b600082601f8301126145f057600080fd5b81516020614600613a7a83613a35565b82815260059290921b8401810191818101908684111561461f57600080fd5b8286015b84811015613ac257805167ffffffffffffffff8111156146435760008081fd5b6146518986838b010161459a565b845250918301918301614623565b600082601f83011261467057600080fd5b81516020614680613a7a83613a35565b82815260059290921b8401810191818101908684111561469f57600080fd5b8286015b84811015613ac257805183529183019183016146a3565b805161393b8161390e565b805161393b81613c3f565b600080600080600080600060e0888a0312156146eb57600080fd5b875167ffffffffffffffff8082111561470357600080fd5b61470f8b838c01614536565b985060208a0151975060408a015191508082111561472c57600080fd5b6147388b838c016145df565b965060608a015191508082111561474e57600080fd5b61475a8b838c0161465f565b955061476860808b016146ba565b945061477660a08b016146c5565b935060c08a015191508082111561478c57600080fd5b506147998a828b0161459a565b91505092959891949750929550565b60e0815260006147bb60e083018a6141d2565b88602084015287604084015282810360608401526147d98188614223565b905082810360808401526147ed8187614020565b94151560a0840152505073ffffffffffffffffffffffffffffffffffffffff9190911660c09091015295945050505050565b60008251614831818460208701613fb2565b9190910192915050565b8051602080830151919081101561487a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b73ffffffffffffffffffffffffffffffffffffffff841681528260208201526060604082015260006148b56060830184613fd6565b95945050505050565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516148f6816017850160208801613fb2565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614933816028840160208801613fb2565b01602801949350505050565b602081526000611cd06020830184613fd6565b60006020828403121561496457600080fd5b8151611cd081613c3f565b808202811582820484141761069157610691614297565b8082018082111561069157610691614297565b6000816149a8576149a8614297565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b6000602082840312156149e057600080fd5b8151611cd08161390e565b80516dffffffffffffffffffffffffffff8116811461393b57600080fd5b600080600060608486031215614a1e57600080fd5b614a27846149eb565b9250614a35602085016149eb565b9150604084015163ffffffff81168114614a4e57600080fd5b809150509250925092565b600082614a8f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d77c836f50e8fca127bdf0b20c6376c023ebbdd9466658211512cde84958cda364736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c21e4ebd1d92036cb467b53fe3258f219d909eb9000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000b1b64005b11350a94c4d069eff4215592d98f2e2
-----Decoded View---------------
Arg [0] : _assetForwarderAddress (address): 0xC21e4ebD1d92036Cb467b53fE3258F219d909Eb9
Arg [1] : _native (address): 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Arg [2] : _wrappedNative (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [3] : _univ2SkimAddress (address): 0xB1b64005B11350a94c4D069eff4215592d98F2E2
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000c21e4ebd1d92036cb467b53fe3258f219d909eb9
Arg [1] : 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
Arg [2] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [3] : 000000000000000000000000b1b64005b11350a94c4d069eff4215592d98f2e2
Deployed Bytecode Sourcemap
123477:21291:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58945:204;;;;;;;;;;-1:-1:-1;58945:204:0;;;;;:::i;:::-;;:::i;:::-;;;516:14:1;;509:22;491:41;;479:2;464:18;58945:204:0;;;;;;;;125785:87;;;;;;;;;;;;125840:32;125785:87;;;;;689:25:1;;;677:2;662:18;125785:87:0;543:177:1;127747:385:0;;;;;;;;;;-1:-1:-1;127747:385:0;;;;;:::i;:::-;;:::i;:::-;;127185:282;;;;;;;;;;-1:-1:-1;127185:282:0;;;;;:::i;:::-;;:::i;129306:766::-;;;;;;:::i;:::-;;:::i;60768:131::-;;;;;;;;;;-1:-1:-1;60768:131:0;;;;;:::i;:::-;60842:7;60869:12;;;:6;:12;;;;;:22;;;;60768:131;123775:26;;;;;;;;;;-1:-1:-1;123775:26:0;;;;;;;;;;;7711:42:1;7699:55;;;7681:74;;7669:2;7654:18;123775:26:0;7535:226:1;121646:38:0;;;;;;;;;;-1:-1:-1;121646:38:0;;;;;;;;61209:147;;;;;;;;;;-1:-1:-1;61209:147:0;;;;;:::i;:::-;;:::i;62353:218::-;;;;;;;;;;-1:-1:-1;62353:218:0;;;;;:::i;:::-;;:::i;126952:225::-;;;;;;;;;;;;;:::i;123731:37::-;;;;;;;;;;-1:-1:-1;123731:37:0;;;;;;;;130843:2287;;;;;;:::i;:::-;;:::i;59241:147::-;;;;;;;;;;-1:-1:-1;59241:147:0;;;;;:::i;:::-;59327:4;59351:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;;;;59241:147;127475:264;;;;;;;;;;-1:-1:-1;127475:264:0;;;;;:::i;:::-;;:::i;58346:49::-;;;;;;;;;;-1:-1:-1;58346:49:0;58391:4;58346:49;;123808:31;;;;;;;;;;-1:-1:-1;123808:31:0;;;;;;;;65014:314;;;;;;;;;;-1:-1:-1;65014:314:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;128140:386::-;;;;;;;;;;-1:-1:-1;128140:386:0;;;;;:::i;:::-;;:::i;123917:48::-;;;;;;;;;;-1:-1:-1;123917:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;128959:339;;;;;;;;;;-1:-1:-1;128959:339:0;;;;;:::i;:::-;;:::i;123846:23::-;;;;;;;;;;-1:-1:-1;123846:23:0;;;;;;;;61649:149;;;;;;;;;;-1:-1:-1;61649:149:0;;;;;:::i;:::-;;:::i;128534:417::-;;;;;;;;;;-1:-1:-1;128534:417:0;;;;;:::i;:::-;;:::i;121612:27::-;;;;;;;;;;-1:-1:-1;121612:27:0;;;;;;;;130080:755;;;;;;:::i;:::-;;:::i;126701:243::-;;;;;;;;;;-1:-1:-1;126701:243:0;;;;;:::i;:::-;;:::i;58945:204::-;59030:4;59054:47;;;59069:32;59054:47;;:87;;-1:-1:-1;56377:25:0;56362:40;;;;59105:36;59047:94;58945:204;-1:-1:-1;;58945:204:0:o;127747:385::-;125840:32;58837:16;58848:4;58837:10;:16::i;:::-;127903:9:::1;127916:1;127903:14:::0;127899:37:::1;;127926:10;;;;;;;;;;;;;;127899:37;127951:29;::::0;::::1;127947:55;;127989:13;;;;;;;;;;;;;;127947:55;128013:24;::::0;;;:13:::1;:24;::::0;;;;;;;;:51;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;128080:44;;16348:25:1;;;16389:18;;;16382:83;128080:44:0::1;::::0;16321:18:1;128080:44:0::1;;;;;;;;127747:385:::0;;;:::o;127185:282::-;58391:4;58837:16;58391:4;58837:10;:16::i;:::-;127301:24:::1;::::0;::::1;127297:50;;127334:13;;;;;;;;;;;;;;127297:50;127358:14;:44:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;127418:41:::1;::::0;;16711:34:1;;;127448:10:0::1;16776:2:1::0;16761:18;;16754:43;127418:41:0::1;::::0;16623:18:1;127418:41:0::1;;;;;;;;127185:282:::0;;:::o;129306:766::-;129604:20;129652:188;129689:6;129710;129731:9;129755:5;129775:6;129796:9;129820;129652:22;:188::i;:::-;129856:208;;17022:17:1;17010:30;;129637:203:0;;-1:-1:-1;129856:208:0;;;;129949:10;;17065:2:1;17056:12;129856:208:0;;;;;;;;129907:6;129928;129998:12;130025:5;130045:8;129856:208;;;;;;;;;;:::i;:::-;;;;;;;;129306:766;;;;;;;;;;:::o;61209:147::-;60842:7;60869:12;;;:6;:12;;;;;:22;;;58837:16;58848:4;58837:10;:16::i;:::-;61323:25:::1;61334:4;61340:7;61323:10;:25::i;:::-;61209:147:::0;;;:::o;62353:218::-;62449:23;;;31910:10;62449:23;62441:83;;;;;;;18960:2:1;62441:83:0;;;18942:21:1;18999:2;18979:18;;;18972:30;19038:34;19018:18;;;19011:62;19109:17;19089:18;;;19082:45;19144:19;;62441:83:0;;;;;;;;;62537:26;62549:4;62555:7;62537:11;:26::i;:::-;62353:218;;:::o;126952:225::-;127002:8;;:22;:8;127014:10;127002:22;126998:77;;127048:15;;;;;;;;;;;;;;126998:77;127085:42;58391:4;127116:10;127085;:42::i;:::-;127143:26;;127158:10;7681:74:1;;127143:26:0;;7669:2:1;7654:18;127143:26:0;;;;;;;126952:225::o;130843:2287::-;131153:242;131186:8;:15;;;131216:8;:15;;;131246:8;:18;;;131279:8;:14;;;131308:8;:15;;;131338:8;:18;;;131379:4;131153:18;:242::i;:::-;-1:-1:-1;131439:15:0;;131469:22;;131406:30;;131439:15;131469:26;;131494:1;;131469:26;:::i;:::-;131439:67;;;;;;;;:::i;:::-;;;;;;;131406:100;;131517:14;131534:46;131574:4;131534:12;:31;;;;:46;;;;:::i;:::-;131517:63;;131595:9;131591:1532;;;131677:14;;131711:18;;;;131621:123;;131677:14;131621:29;;;;131677:14;;;131621:29;:123::i;:::-;131759:14;;;;;;;:30;;131815:20;;:18;;;:20::i;:::-;:33;;131847:1;131815:33;;;131838:6;131815:33;131882:293;;;;;;;;131932:9;131882:293;;;;131964:8;:18;;;131882:293;;;;132026:9;132005:8;:18;;;:30;;;;:::i;:::-;131882:293;;;;132066:12;131882:293;;;;;;132102:15;131882:293;;;;;;132140:16;131882:293;;;132194:8;:18;;;132231:9;;132259:7;131759:522;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132377:8;:18;;;132368:6;:27;132364:205;;;132416:137;132469:15;132516:8;:18;;;132507:6;:27;;;;:::i;:::-;132416:30;;;;:137;:30;:137::i;:::-;;132364:205;131591:1532;;;132639:14;;132601:62;;132639:14;132601:29;;;;132639:14;132656:6;132601:29;:62::i;:::-;132678:14;;;;;;;:23;;132709:20;;:18;;;:20::i;:::-;:33;;132741:1;132709:33;;;132732:6;132709:33;132762:269;;;;;;;;132812:9;132762:269;;;;132844:6;132762:269;;;;132882:9;132873:6;:18;;;;:::i;:::-;132762:269;;;;132922:12;132762:269;;;;;;132958:15;132762:269;;;;;;132996:16;132762:269;;;133050:8;:18;;;133087:9;;132678:433;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131591:1532;131142:1988;;130843:2287;;;;;;;;;:::o;127475:264::-;58391:4;58837:16;58391:4;58837:10;:16::i;:::-;127590:26:::1;::::0;::::1;127586:52;;127625:13;;;;;;;;;;;;;;127586:52;127649:11;:26:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;127691:40:::1;::::0;;16711:34:1;;;127720:10:0::1;16776:2:1::0;16761:18;;16754:43;127691:40:0::1;::::0;16623:18:1;127691:40:0::1;16476:327:1::0;65014:314:0;65082:22;65139:4;65127:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65117:34;;65167:9;65162:134;65182:15;;;65162:134;;;65232:52;65269:4;65276;;65281:1;65276:7;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;65232:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;65232:28:0;;-1:-1:-1;;;65232:52:0:i;:::-;65219:7;65227:1;65219:10;;;;;;;;:::i;:::-;;;;;;:65;;;;65199:3;;;;;:::i;:::-;;;;65162:134;;;;65014:314;;;;:::o;128140:386::-;58391:4;58837:16;58391:4;58837:10;:16::i;:::-;128259:28:::1;::::0;::::1;128255:54;;128296:13;;;;;;;;;;;;;;128255:54;59351:29:::0;;;59327:4;59351:29;;;:12;;:29;:12;:29;;;;;128320:92:::1;;;128390:22;;;;;;;;;;;;;;128320:92;128423:47;125840:32;128455:14;128423:10;:47::i;:::-;128486:32;::::0;7711:42:1;7699:55;;7681:74;;128486:32:0::1;::::0;7669:2:1;7654:18;128486:32:0::1;7535:226:1::0;128959:339:0;129135:14;;;;129113:10;:37;;;;:88;;-1:-1:-1;129189:11:0;;;;129167:10;:34;;129113:88;129095:140;;;129220:15;;;;;;;;;;;;;;129095:140;129246:44;129261:10;129273:7;129282;129246:14;:44::i;61649:149::-;60842:7;60869:12;;;:6;:12;;;;;:22;;;58837:16;58848:4;58837:10;:16::i;:::-;61764:26:::1;61776:4;61782:7;61764:11;:26::i;128534:417::-:0;58391:4;58837:16;58391:4;58837:10;:16::i;:::-;128682:21:::1;::::0;::::1;128678:47;;128712:13;;;;;;;;;;;;;;128678:47;128740:28;::::0;::::1;128736:54;;128777:13;;;;;;;;;;;;;;128736:54;128801:13;:42:::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;-1:-1:-1;128854:38:0;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;128908:35:::1;::::0;7681:74:1;;;128908:35:0::1;::::0;7669:2:1;7654:18;128908:35:0::1;7535:226:1::0;130080:755:0;130358:20;130406:184;130439:6;130460;130481:9;130505:5;130525:6;130546:9;130570;130406:18;:184::i;:::-;130606:221;;22846:24:1;22834:37;;130391:199:0;;-1:-1:-1;130606:221:0;;;;130719:10;;22896:2:1;22887:12;130606:221:0;;;;;;;;130677:6;130698;130768:12;130795:5;130815:1;130606:221;;;;;;;;;;:::i;:::-;;;;;;;;130080:755;;;;;;;;;:::o;126701:243::-;58391:4;58837:16;58391:4;58837:10;:16::i;:::-;126816:23:::1;::::0;::::1;126812:49;;126848:13;;;;;;;;;;;;;;126812:49;126872:8;:20:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;126908:28:::1;::::0;7681:74:1;;;126908:28:0::1;::::0;7669:2:1;7654:18;126908:28:0::1;7535:226:1::0;59692:105:0;59759:30;59770:4;31910:10;59759;:30::i;:::-;59692:105;:::o;63950:238::-;59327:4;59351:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;64029:152;;64073:12;;;;:6;:12;;;;;;;;:29;;;;;;;;;;:36;;;;64105:4;64073:36;;;64156:12;31910:10;;31830:98;64156:12;64129:40;;64147:7;64129:40;;64141:4;64129:40;;;;;;;;;;63950:238;;:::o;64368:239::-;59327:4;59351:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;64448:152;;;64523:5;64491:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;:37;;;;;;64548:40;31910:10;;64491:12;;64548:40;;64523:5;64548:40;64368:239;;:::o;63278:112::-;63357:25;63368:4;63374:7;63357:10;:25::i;135024:1980::-;135292:20;135329:23;;;135325:49;;135361:13;;;;;;;;;;;;;;135325:49;135410:5;:12;135405:1;135389:6;:13;:17;;;;:::i;:::-;:33;135385:90;;135446:17;;;;;;;;;;;;;;135385:90;135490:9;135485:228;;135521:17;:6;135528:1;135521:9;;;;;;;;:::i;:::-;;;;;;;:15;;;:17::i;:::-;135520:18;:36;;;;-1:-1:-1;135542:9:0;:14;;135520:36;135516:105;;;135584:21;;;;;;;;;;;;;;135516:105;135635:66;135667:10;135687:4;135694:6;135635;135642:1;135635:9;;;;;;;;:::i;:::-;;;;;;;:31;;;;:66;;;;;;:::i;:::-;135738:43;135775:4;135738:6;135745:1;135738:9;;;;;;;;:::i;:::-;;;;;;;:28;;;;:43;;;;:::i;:::-;135723:58;;135792:34;135829:6;135852:1;135836:6;:13;:17;;;;:::i;:::-;135829:25;;;;;;;;:::i;:::-;;;;;;;135792:62;;135870:9;135882:1;135870:13;;135865:374;135889:6;:13;135885:1;:17;135865:374;;;135945:6;135952:1;135945:9;;;;;;;;:::i;:::-;;;;;;;135928:26;;:6;135939:1;135935;:5;;;;:::i;:::-;135928:13;;;;;;;;:::i;:::-;;;;;;;:26;;;135924:75;135975:8;135924:75;136028:199;136057:6;136064:5;136068:1;136064;:5;:::i;:::-;136057:13;;;;;;;;:::i;:::-;;;;;;;136089:6;136096:1;136089:9;;;;;;;;:::i;:::-;;;;;;;136117:12;136148:1;136168:5;136178:1;136174;:5;;;;:::i;:::-;136168:12;;;;;;;;:::i;:::-;;;;;;;136199:6;136210:1;136206;:5;;;;:::i;:::-;136199:13;;;;;;;;:::i;:::-;;;;;;;136028:10;:199::i;:::-;136013:214;;135865:374;135904:3;;;;:::i;:::-;;;;135865:374;;;;136255:24;:16;:22;;;:24::i;:::-;136251:163;;;136311:14;;:39;;;;;136344:4;136311:39;;;7681:74:1;136311:14:0;;;;;:24;;7654:18:1;;136311:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;136365:14;;:37;;;;;;;;689:25:1;;;136296:54:0;;-1:-1:-1;136365:14:0;;;:23;;662:18:1;;136365:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136251:163;136430:26;;;136451:4;136430:26;136426:571;;136473:22;136498:78;:35;;;136552:9;136498:35;:78::i;:::-;136473:103;-1:-1:-1;136591:59:0;:34;;;136626:9;136637:12;136591:34;:59::i;:::-;-1:-1:-1;136665:22:0;136690:78;:35;;;136744:9;136690:35;:78::i;:::-;136665:103;-1:-1:-1;136785:19:0;136807:31;136824:14;136665:103;136807:31;:::i;:::-;136785:53;;136875:9;136857:14;:27;136853:89;;136912:14;;;;;;;;;;;;;;136853:89;136971:14;-1:-1:-1;;;136426:571:0;135314:1690;135024:1980;;;;;;;;;:::o;109690:264::-;109804:7;109828:12;109834:5;109828;:12::i;:::-;109824:123;;;-1:-1:-1;109864:11:0;;;;109857:18;;109824:123;109915:20;;;;;:15;7699:55:1;;;109915:20:0;;;7681:74:1;109915:15:0;;;;;7654:18:1;;109915:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;109908:27;;;;108878:804;109016:12;109022:5;109016;:12::i;:::-;109011:664;;109545:49;109580:5;109588:2;109592:1;109545:26;:49::i;:::-;109609:54;109644:5;109652:2;109656:6;109609:26;:54::i;109962:191::-;110025:4;110050:39;;;;;:94;;-1:-1:-1;110106:38:0;;;107016:42;110106:38;110042:103;109962:191;-1:-1:-1;;109962:191:0:o;107068:428::-;107200:4;107221:6;107231:1;107221:11;107217:55;;-1:-1:-1;107256:4:0;107249:11;;107217:55;107288:12;107294:5;107288;:12::i;:::-;107284:205;;;107317:46;;:38;;;;:46;;;;;107356:6;;107317:46;;;;107356:6;107317:38;:46;;;;;;;;;;;;;;;;;;;;;107284:205;;;107396:55;107432:5;107440:2;107444:6;107396:27;:55::i;:::-;-1:-1:-1;107473:4:0;107284:205;107068:428;;;;;:::o;18798:200::-;18881:12;18913:77;18934:6;18942:4;18913:77;;;;;;;;;;;;;;;;;:20;:77::i;133138:1878::-;133290:33;133338:17;133370:21;133406:22;133443:17;133475:18;133508:24;133575:7;133546:308;;;;;;;;;;;;:::i;:::-;133275:579;;;;;;;;;;;;;;133891:6;133898:1;133891:9;;;;;;;;:::i;:::-;;;;;;;133869:32;;:10;:32;;;133865:61;;133910:16;;;;;;;;;;;;;;133865:61;133937:21;133969:13;134024:4;134016:18;;125941:10;134090:34;;134143:6;134168:7;134194:9;134222:5;134246:6;134271:4;134294:9;134049:269;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134016:313;;;;134049:269;134016:313;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;133993:336:0;-1:-1:-1;133993:336:0;-1:-1:-1;133993:336:0;134342:89;;134372:47;134400:9;134411:7;134372:6;134379:1;134372:9;;;;;;;;:::i;:::-;;;;;;;:27;;;;:47;;;;;:::i;:::-;;134342:89;134447:13;134443:566;;;134477:19;134499:8;:81;;134573:7;134499:81;;;134535:17;134543:8;134535:17;:::i;:::-;134477:103;;134595:18;134616:8;:92;;134698:10;134616:92;;;134652:6;134675:1;134659:6;:13;:17;;;;:::i;:::-;134652:25;;;;;;;;:::i;:::-;;;;;;;134616:92;134595:113;;134746:9;:14;;134824:38;;;134885:10;134918:11;134952;134779:203;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134746:251;;;;134779:203;134746:251;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;134723:274:0;-1:-1:-1;134723:274:0;-1:-1:-1;;;134443:566:0;133264:1752;;;;;;;;;133138:1878;;;:::o;60087:492::-;59327:4;59351:12;;;:6;:12;;;;;;;;:29;;;;;;;;;;;;;60171:401;;60364:28;60384:7;60364:19;:28::i;:::-;60465:38;60493:4;60500:2;60465:19;:38::i;:::-;60269:257;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;60215:345;;;;;;;;:::i;107504:762::-;107665:50;;107697:7;107665:50;107731:12;107737:5;107731;:12::i;:::-;107727:532;;;107786:18;;;107794:10;107786:18;:41;;;;;107821:6;107808:9;:19;;107786:41;107760:145;;;;;;;31691:2:1;107760:145:0;;;31673:21:1;31730:2;31710:18;;;31703:30;31769:34;31749:18;;;31742:62;31840:12;31820:18;;;31813:40;31870:19;;107760:145:0;31489:406:1;107760:145:0;107924:19;;;107938:4;107924:19;107920:106;;107964:46;;:38;;;;:46;;;;;108003:6;;107964:46;;;;108003:6;107964:38;:46;;;;;;;;;;;;;;;;;;;;;107920:106;108056:6;108044:9;:18;108040:110;;;108091:10;108083:51;108112:21;:9;108126:6;108112:13;:21::i;:::-;108083:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108040:110;107727:532;;;108182:65;108222:5;108230:4;108236:2;108240:6;108182:31;:65::i;:::-;107504:762;;;;:::o;137012:429::-;137239:17;137284:149;137304:9;137328;137352:6;137373:9;137397:5;137417;137284;:149::i;:::-;137269:164;137012:429;-1:-1:-1;;;;;;;137012:429:0:o;105263:435::-;105473:45;;;105448:10;32092:55:1;;;105473:45:0;;;32074:74:1;32164:18;;;;32157:34;;;105473:45:0;;;;;;;;;;32047:18:1;;;;105473:45:0;;;;;;;;;;;;;105448:81;;-1:-1:-1;;;;105448:10:0;;;;:81;;105473:45;105448:81;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105412:117;;;;105562:7;:57;;;;-1:-1:-1;105574:11:0;;:16;;:44;;;105605:4;105594:24;;;;;;;;;;;;:::i;:::-;105540:150;;;;;;;32654:2:1;105540:150:0;;;32636:21:1;32693:2;32673:18;;;32666:30;32732:34;32712:18;;;32705:62;32803:13;32783:18;;;32776:41;32834:19;;105540:150:0;32452:407:1;105540:150:0;105335:363;;105263:435;;;:::o;105706:439::-;105918:45;;;105893:10;32092:55:1;;;105918:45:0;;;32074:74:1;32164:18;;;;32157:34;;;105918:45:0;;;;;;;;;;32047:18:1;;;;105918:45:0;;;;;;;;;;;;;105893:81;;-1:-1:-1;;;;105893:10:0;;;;:81;;105918:45;105893:81;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105857:117;;;;106007:7;:57;;;;-1:-1:-1;106019:11:0;;:16;;:44;;;106050:4;106039:24;;;;;;;;;;;;:::i;:::-;105985:152;;;;;;;33066:2:1;105985:152:0;;;33048:21:1;33105:2;33085:18;;;33078:30;33144:34;33124:18;;;33117:62;33215:15;33195:18;;;33188:43;33248:19;;105985:152:0;32864:409:1;19192:332:0;19337:12;19363;19377:23;19404:6;:19;;19424:4;19404:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19362:67;;;;19447:69;19474:6;19482:7;19491:10;19503:12;19447:26;:69::i;:::-;19440:76;19192:332;-1:-1:-1;;;;;;19192:332:0:o;54280:151::-;54338:13;54371:52;54383:22;;;52155:2;53676:447;53751:13;53777:19;53809:10;53813:6;53809:1;:10;:::i;:::-;:14;;53822:1;53809:14;:::i;:::-;53799:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;53799:25:0;;53777:47;;53835:15;:6;53842:1;53835:9;;;;;;;;:::i;:::-;;;;:15;;;;;;;;;;;53861;:6;53868:1;53861:9;;;;;;;;:::i;:::-;;;;:15;;;;;;;;;;-1:-1:-1;53892:9:0;53904:10;53908:6;53904:1;:10;:::i;:::-;:14;;53917:1;53904:14;:::i;:::-;53892:26;;53887:131;53924:1;53920;:5;53887:131;;;53959:8;53968:5;53976:3;53968:11;53959:21;;;;;;;:::i;:::-;;;;53947:6;53954:1;53947:9;;;;;;;;:::i;:::-;;;;:33;;;;;;;;;;-1:-1:-1;54005:1:0;53995:11;;;;;53927:3;;;:::i;:::-;;;53887:131;;;-1:-1:-1;54036:10:0;;54028:55;;;;;;;33984:2:1;54028:55:0;;;33966:21:1;;;34003:18;;;33996:30;34062:34;34042:18;;;34035:62;34114:18;;54028:55:0;33782:356:1;82558:98:0;82616:7;82643:5;82647:1;82643;:5;:::i;106153:522::-;106438:51;;;106413:10;34424:15:1;;;106438:51:0;;;34406:34:1;34476:15;;;34456:18;;;34449:43;34508:18;;;;34501:34;;;106438:51:0;;;;;;;;;;34318:18:1;;;;106438:51:0;;;;;;;;;;;;;106413:87;;-1:-1:-1;;;;106413:10:0;;;;:87;;106438:51;106413:87;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106377:123;;;;106533:7;:57;;;;-1:-1:-1;106545:11:0;;:16;;:44;;;106576:4;106565:24;;;;;;;;;;;;:::i;:::-;106511:156;;;;;;;34748:2:1;106511:156:0;;;34730:21:1;34787:2;34767:18;;;34760:30;34826:34;34806:18;;;34799:62;34897:19;34877:18;;;34870:47;34934:19;;106511:156:0;34546:413:1;106511:156:0;106287:388;;106153:522;;;;:::o;137449:754::-;137671:20;137721:9;137708:22;;:9;:22;;;137704:68;;-1:-1:-1;137754:6:0;137747:13;;137704:68;137782:162;137947:26;137967:5;137947:19;:26::i;:::-;137782:191;-1:-1:-1;137986:23:0;138012:43;:28;;;138049:4;138012:28;:43::i;:::-;137986:69;;138066:60;138074:9;138085;138096:15;138113:5;138120;138066:7;:60;;:::i;:::-;138152:43;:28;;;138189:4;138152:28;:43::i;:::-;138137:58;137449:754;-1:-1:-1;;;;;;;;;137449:754:0:o;19820:644::-;20005:12;20034:7;20030:427;;;20062:10;:17;20083:1;20062:22;20058:290;;13701:19;;;;20272:60;;;;;;;35166:2:1;20272:60:0;;;35148:21:1;35205:2;35185:18;;;35178:30;35244:31;35224:18;;;35217:59;35293:18;;20272:60:0;34964:353:1;20272:60:0;-1:-1:-1;20369:10:0;20362:17;;20030:427;20412:33;20420:10;20432:12;20412:7;:33::i;:::-;19820:644;;;;;;:::o;138211:824::-;138334:189;138551:6;138544:4;:13;:31;;;;;138569:6;138561:4;:14;;138544:31;138540:445;;;-1:-1:-1;138624:16:0;;138211:824;-1:-1:-1;138211:824:0:o;138540:445::-;138662:4;138670:6;138662:14;138658:327;;-1:-1:-1;138700:15:0;;138211:824;-1:-1:-1;138211:824:0:o;138658:327::-;138745:4;138753:6;138745:14;138741:244;;-1:-1:-1;138783:14:0;;138211:824;-1:-1:-1;138211:824:0:o;138741:244::-;138827:4;138835:6;138827:14;138823:162;;-1:-1:-1;138865:16:0;;138211:824;-1:-1:-1;138211:824:0:o;138823:162::-;138911:4;138919:6;138911:14;138907:78;;-1:-1:-1;138949:16:0;;138211:824;-1:-1:-1;138211:824:0:o;138907:78::-;138995:32;;;;;35524:2:1;138995:32:0;;;35506:21:1;35563:2;35543:18;;;35536:30;35602:24;35582:18;;;35575:52;35644:18;;138995:32:0;35322:346:1;21006:552:0;21167:17;;:21;21163:388;;21399:10;21393:17;21456:15;21443:10;21439:2;21435:19;21428:44;21163:388;21526:12;21519:20;;;;;;;;;;;:::i;139043:275::-;139250:60;139274:9;139285;139296:6;139304:5;139250:23;:60::i;142111:980::-;142403:16;142422:23;;;:13;:23;;;;;;;;;142456:75;;142506:13;;;;;;;;;;;;;;142456:75;142547:17;:9;:15;;;:17::i;:::-;142543:89;;;142581:14;;;;;;;;;;;:22;;;142611:6;142581:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;142543:89;142642:31;142676:17;:9;:15;;;:17::i;:::-;:72;;142739:9;142676:72;;;142709:14;;;;142676:72;142642:106;;142761:127;142823:8;142806:48;;;:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;142761:30;;;;142871:6;142761:30;:127::i;:::-;142960:12;142986:8;142978:22;;143001:5;142978:29;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;142959:48;;;143023:7;143018:66;;143054:18;;;;;;;;;;;;;;143018:66;142309:782;;;142111:980;;;;;:::o;141184:919::-;141475:19;141497:23;;;:13;:23;;;;;;;;;141531:78;;141584:13;;;;;;;;;;;;;;141531:78;141625:17;:9;:15;;;:17::i;:::-;141621:89;;;141659:14;;;;;;;;;;;:22;;;141689:6;141659:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;141621:89;141720:31;141754:17;:9;:15;;;:17::i;:::-;:72;;141817:9;141754:72;;;141787:14;;;;141754:72;141720:106;-1:-1:-1;141837:60:0;:30;;;141876:11;141890:6;141837:30;:60::i;143099:1666::-;143285:20;143322:17;:9;:15;;;:17::i;:::-;143318:89;;;143356:14;;;;;;;;;;;:22;;;143386:6;143356:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;143318:89;143419:18;143440:23;;;:13;:23;;;;;;;;;143474:59;;;;;;;35524:2:1;143474:59:0;;;35506:21:1;35563:2;35543:18;;;35536:30;35602:24;35582:18;;;35575:52;35644:18;;143474:59:0;35322:346:1;143474:59:0;143598:10;143544:25;143657:17;:15;;;;:17::i;:::-;:72;;143720:9;143657:72;;;143690:14;;;;143657:72;143623:106;;143740:29;143772:17;:9;:15;;;:17::i;:::-;:72;;143835:9;143772:72;;;143805:14;;;;143772:72;143740:104;;143878:11;143861:28;;:13;:28;;;143857:74;;143913:6;143906:13;;;;;;;;143857:74;143967:43;;;;;:15;16729::1;;;143967:43:0;;;16711:34:1;16781:15;;;16761:18;;;16754:43;143941:23:0;;143967:15;;;;;;16623:18:1;;143967:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;143941:69;-1:-1:-1;144025:27:0;;;144021:53;;144061:13;;;;;;;;;;;;;;144021:53;144085:13;;144170:100;:14;;;144199:13;144227:11;144253:6;144170:14;:100::i;:::-;144133:137;;-1:-1:-1;144133:137:0;-1:-1:-1;144133:137:0;-1:-1:-1;144281:126:0;;;;144310:4;:9;;;:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;144281:126;;;144343:8;144339:68;;;144378:16;;144368:27;;;;;:9;144378:16;;;144368:27;;;7681:74:1;144368:9:0;;;;;;7654:18:1;;144368:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;144339:68;144419:54;:31;;;144459:4;144466:6;144419:31;:54::i;:::-;;144582:11;144558:38;;144526:13;144502:40;;:94;144484:274;;;144623:45;;;;;144633:1;144623:45;;;36871:25:1;;;36912:18;;;36905:34;;;144658:4:0;36955:18:1;;;36948:83;37067:3;37047:18;;;37040:31;37087:19;;;37080:30;144623:9:0;;;;;;37127:19:1;;144623:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;144484:274;;;144701:45;;;;;;;;36871:25:1;;;144725:1:0;36912:18:1;;;36905:34;;;144736:4:0;36955:18:1;;;36948:83;37067:3;37047:18;;;37040:31;37087:19;;;37080:30;144701:9:0;;;;;;37127:19:1;;144701:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;144484:274;143307:1458;;;;;;;143099:1666;;;;;;:::o;110960:1123::-;111150:14;;;;111227:47;:28;;;111264:8;111227:28;:47::i;:::-;111207:67;-1:-1:-1;111285:18:0;111306:47;:28;;;111343:8;111306:28;:47::i;:::-;111285:68;;111365:16;111383;111405:8;:20;;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111364:63;;;;;111454:9;111442:21;;:9;:21;;;111438:97;;;111504:8;111438:97;111569:8;111557:20;;:9;:20;:45;;;;111594:8;111581:21;;:10;:21;111557:45;111545:58;;111626:8;111625:9;:60;;;;;111651:8;111639:20;;:9;:20;:45;;;;111676:8;111663:21;;:10;:21;111639:45;111614:71;-1:-1:-1;111698:23:0;111724:17;:8;111737:3;111724:12;:17::i;:::-;111698:43;;111752:17;111772:86;111806:41;111826:10;111838:8;111806:41;;:19;:41::i;:::-;111772:15;;:19;:86::i;:::-;111752:106;;111869:19;111891:113;111988:15;111891:78;111964:4;111891:54;111925:9;111936:8;111891:54;;:33;:54::i;:::-;:72;;:78::i;:::-;:96;;:113::i;:::-;111869:135;-1:-1:-1;112025:16:0;;112024:51;;112049:26;:9;112063:11;112049:13;:26::i;:::-;112024:51;;;112045:1;112024:51;112015:60;;111196:887;;;;;;;110960:1123;;;;;;;;:::o;82915:98::-;82973:7;83000:5;83004:1;83000;:5;:::i;66866:106::-;66924:7;66955:1;66951;:5;:13;;66963:1;66951:13;;;-1:-1:-1;66959:1:0;;66866:106;-1:-1:-1;66866:106:0:o;82177:98::-;82235:7;82262:5;82266:1;82262;:5;:::i;83314:98::-;83372:7;83399:5;83403:1;83399;: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;8598:347::-;8649:8;8659:6;8713:3;8706:4;8698:6;8694:17;8690:27;8680:55;;8731:1;8728;8721:12;8680:55;-1:-1:-1;8754:20:1;;8797:18;8786:30;;8783:50;;;8829:1;8826;8819:12;8783:50;8866:4;8858:6;8854:17;8842:29;;8918:3;8911:4;8902:6;8894;8890:19;8886:30;8883:39;8880:59;;;8935:1;8932;8925:12;8880:59;8598:347;;;;;:::o;8950:1246::-;9007:5;9055:6;9043:9;9038:3;9034:19;9030:32;9027:52;;;9075:1;9072;9065:12;9027:52;9097:22;;:::i;:::-;9088:31;;9155:9;9142:23;9184:18;9225:2;9217:6;9214:14;9211:34;;;9241:1;9238;9231:12;9211:34;9268:76;9340:3;9331:6;9320:9;9316:22;9268:76;:::i;:::-;9261:5;9254:91;9405:2;9394:9;9390:18;9377:32;9372:2;9365:5;9361:14;9354:56;9470:2;9459:9;9455:18;9442:32;9437:2;9430:5;9426:14;9419:56;9528:2;9517:9;9513:18;9500:32;9484:48;;9557:2;9547:8;9544:16;9541:36;;;9573:1;9570;9563:12;9541:36;9609:59;9664:3;9653:8;9642:9;9638:24;9609:59;:::i;:::-;9604:2;9597:5;9593:14;9586:83;9722:3;9711:9;9707:19;9694:33;9678:49;;9752:2;9742:8;9739:16;9736:36;;;9768:1;9765;9758:12;9736:36;9805:57;9858:3;9847:8;9836:9;9832:24;9805:57;:::i;:::-;9799:3;9792:5;9788:15;9781:82;9896:36;9927:3;9916:9;9912:19;9896:36;:::i;:::-;9890:3;9883:5;9879:15;9872:61;9966:39;10000:3;9989:9;9985:19;9966:39;:::i;:::-;9960:3;9953:5;9949:15;9942:64;10059:3;10048:9;10044:19;10031:33;10015:49;;10089:2;10079:8;10076:16;10073:36;;;10105:1;10102;10095:12;10073:36;;10142:47;10185:3;10174:8;10163:9;10159:24;10142:47;:::i;:::-;10136:3;10129:5;10125:15;10118:72;;8950:1246;;;;:::o;10201:1208::-;10368:6;10376;10384;10392;10400;10408;10416;10424;10432;10485:3;10473:9;10464:7;10460:23;10456:33;10453:53;;;10502:1;10499;10492:12;10453:53;10538:9;10525:23;10515:33;;10595:2;10584:9;10580:18;10567:32;10557:42;;10650:2;10639:9;10635:18;10622:32;10673:18;10714:2;10706:6;10703:14;10700:34;;;10730:1;10727;10720:12;10700:34;10769:58;10819:7;10810:6;10799:9;10795:22;10769:58;:::i;:::-;10846:8;;-1:-1:-1;10743:84:1;-1:-1:-1;10928:2:1;10913:18;;10900:32;;-1:-1:-1;10985:3:1;10970:19;;10957:33;;-1:-1:-1;11002:16:1;;;10999:36;;;11031:1;11028;11021:12;10999:36;11054:51;11097:7;11086:8;11075:9;11071:24;11054:51;:::i;:::-;11044:61;;11124:36;11155:3;11144:9;11140:19;11124:36;:::i;:::-;11114:46;;11213:3;11202:9;11198:19;11185:33;11169:49;;11243:2;11233:8;11230:16;11227:36;;;11259:1;11256;11249:12;11227:36;;11282:63;11337:7;11326:8;11315:9;11311:24;11282:63;:::i;:::-;11272:73;;;11364:39;11398:3;11387:9;11383:19;11364:39;:::i;:::-;11354:49;;10201:1208;;;;;;;;;;;:::o;11414:626::-;11511:6;11519;11572:2;11560:9;11551:7;11547:23;11543:32;11540:52;;;11588:1;11585;11578:12;11540:52;11628:9;11615:23;11657:18;11698:2;11690:6;11687:14;11684:34;;;11714:1;11711;11704:12;11684:34;11752:6;11741:9;11737:22;11727:32;;11797:7;11790:4;11786:2;11782:13;11778:27;11768:55;;11819:1;11816;11809:12;11768:55;11859:2;11846:16;11885:2;11877:6;11874:14;11871:34;;;11901:1;11898;11891:12;11871:34;11954:7;11949:2;11939:6;11936:1;11932:14;11928:2;11924:23;11920:32;11917:45;11914:65;;;11975:1;11972;11965:12;11914:65;12006:2;11998:11;;;;;12028:6;;-1:-1:-1;11414:626:1;;-1:-1:-1;;;;11414:626:1:o;12045:250::-;12130:1;12140:113;12154:6;12151:1;12148:13;12140:113;;;12230:11;;;12224:18;12211:11;;;12204:39;12176:2;12169:10;12140:113;;;-1:-1:-1;;12287:1:1;12269:16;;12262:27;12045:250::o;12300:329::-;12341:3;12379:5;12373:12;12406:6;12401:3;12394:19;12422:76;12491:6;12484:4;12479:3;12475:14;12468:4;12461:5;12457:16;12422:76;:::i;:::-;12543:2;12531:15;12548:66;12527:88;12518:98;;;;12618:4;12514:109;;12300:329;-1:-1:-1;;12300:329:1:o;12634:614::-;12685:3;12723:5;12717:12;12750:6;12745:3;12738:19;12776:4;12817:2;12812:3;12808:12;12842:11;12869;12862:18;;12919:6;12916:1;12912:14;12905:5;12901:26;12889:38;;12961:2;12954:5;12950:14;12982:1;12992:230;13006:6;13003:1;13000:13;12992:230;;;13077:5;13071:4;13067:16;13062:3;13055:29;13105:37;13137:4;13128:6;13122:13;13105:37;:::i;:::-;13200:12;;;;13097:45;-1:-1:-1;13165:15:1;;;;13028:1;13021:9;12992:230;;;-1:-1:-1;13238:4:1;;12634:614;-1:-1:-1;;;;;;;12634:614:1:o;13253:277::-;13450:2;13439:9;13432:21;13413:4;13470:54;13520:2;13509:9;13505:18;13497:6;13470:54;:::i;13720:523::-;13806:6;13814;13822;13875:2;13863:9;13854:7;13850:23;13846:32;13843:52;;;13891:1;13888;13881:12;13843:52;13930:9;13917:23;13949:31;13974:5;13949:31;:::i;:::-;13999:5;-1:-1:-1;14051:2:1;14036:18;;14023:32;;-1:-1:-1;14106:2:1;14091:18;;14078:32;14133:18;14122:30;;14119:50;;;14165:1;14162;14155:12;14119:50;14188:49;14229:7;14220:6;14209:9;14205:22;14188:49;:::i;:::-;14178:59;;;13720:523;;;;;:::o;14248:388::-;14316:6;14324;14377:2;14365:9;14356:7;14352:23;14348:32;14345:52;;;14393:1;14390;14383:12;14345:52;14432:9;14419:23;14451:31;14476:5;14451:31;:::i;:::-;14501:5;-1:-1:-1;14558:2:1;14543:18;;14530:32;14571:33;14530:32;14571:33;:::i;14886:1283::-;15106:6;15114;15122;15130;15138;15146;15154;15207:3;15195:9;15186:7;15182:23;15178:33;15175:53;;;15224:1;15221;15214:12;15175:53;15264:9;15251:23;15293:18;15334:2;15326:6;15323:14;15320:34;;;15350:1;15347;15340:12;15320:34;15373:80;15445:7;15436:6;15425:9;15421:22;15373:80;:::i;:::-;15363:90;;15500:2;15489:9;15485:18;15472:32;15462:42;;15551:2;15540:9;15536:18;15523:32;15513:42;;15608:2;15597:9;15593:18;15580:32;15564:48;;15637:2;15627:8;15624:16;15621:36;;;15653:1;15650;15643:12;15621:36;15676:63;15731:7;15720:8;15709:9;15705:24;15676:63;:::i;:::-;15666:73;;15792:3;15781:9;15777:19;15764:33;15748:49;;15822:2;15812:8;15809:16;15806:36;;;15838:1;15835;15828:12;15806:36;;15861:61;15914:7;15903:8;15892:9;15888:24;15861:61;:::i;:::-;15851:71;;;15972:3;15961:9;15957:19;15944:33;15986:28;16008:5;15986:28;:::i;:::-;16033:5;-1:-1:-1;16090:3:1;16075:19;;16062:33;16104;16062;16104;:::i;:::-;16156:7;16146:17;;;14886:1283;;;;;;;;;;:::o;17079:503::-;17151:3;17189:5;17183:12;17216:6;17211:3;17204:19;17242:4;17271:2;17266:3;17262:12;17255:19;;17308:2;17301:5;17297:14;17329:1;17339:218;17353:6;17350:1;17347:13;17339:218;;;17418:13;;17433:42;17414:62;17402:75;;17497:12;;;;17532:15;;;;17375:1;17368:9;17339:218;;;-1:-1:-1;17573:3:1;;17079:503;-1:-1:-1;;;;;17079:503:1:o;17587:435::-;17640:3;17678:5;17672:12;17705:6;17700:3;17693:19;17731:4;17760:2;17755:3;17751:12;17744:19;;17797:2;17790:5;17786:14;17818:1;17828:169;17842:6;17839:1;17836:13;17828:169;;;17903:13;;17891:26;;17937:12;;;;17972:15;;;;17864:1;17857:9;17828:169;;18027:726;18394:3;18383:9;18376:22;18357:4;18421:76;18492:3;18481:9;18477:19;18469:6;18421:76;:::i;:::-;18533:6;18528:2;18517:9;18513:18;18506:34;18576:6;18571:2;18560:9;18556:18;18549:34;18631:9;18623:6;18619:22;18614:2;18603:9;18599:18;18592:50;18659:44;18696:6;18688;18659:44;:::i;:::-;18651:52;;;18740:6;18734:3;18723:9;18719:19;18712:35;18027:726;;;;;;;;:::o;19174:184::-;19226:77;19223:1;19216:88;19323:4;19320:1;19313:15;19347:4;19344:1;19337:15;19363:128;19430:9;;;19451:11;;;19448:37;;;19465:18;;:::i;19496:184::-;19548:77;19545:1;19538:88;19645:4;19642:1;19635:15;19669:4;19666:1;19659:15;20186:325;20274:6;20269:3;20262:19;20326:6;20319:5;20312:4;20307:3;20303:14;20290:43;;20378:1;20371:4;20362:6;20357:3;20353:16;20349:27;20342:38;20244:3;20500:4;20430:66;20425:2;20417:6;20413:15;20409:88;20404:3;20400:98;20396:109;20389:116;;20186:325;;;;:::o;20516:741::-;20814:4;20843:3;20855:48;20893:9;20885:6;19768:5;19762:12;19757:3;19750:25;19824:4;19817:5;19813:16;19807:23;19800:4;19795:3;19791:14;19784:47;19880:4;19873:5;19869:16;19863:23;19856:4;19851:3;19847:14;19840:47;19933:4;19926:5;19922:16;19916:23;19958:42;20050:2;20036:12;20032:21;20025:4;20020:3;20016:14;20009:45;20115:2;20107:4;20100:5;20096:16;20090:23;20086:32;20079:4;20074:3;20070:14;20063:56;;;20168:4;20161:5;20157:16;20151:23;20144:4;20139:3;20135:14;20128:47;19685:496;;;20855:48;20940:2;20934:3;20923:9;20919:19;20912:31;20966:44;21006:2;20995:9;20991:18;20983:6;20966:44;:::i;:::-;20952:58;;21059:9;21051:6;21047:22;21041:3;21030:9;21026:19;21019:51;21093:49;21135:6;21127;21119;21093:49;:::i;:::-;21079:63;;21191:9;21183:6;21179:22;21173:3;21162:9;21158:19;21151:51;21219:32;21244:6;21236;21219:32;:::i;:::-;21211:40;20516:741;-1:-1:-1;;;;;;;;20516:741:1:o;21262:580::-;21514:4;21543:3;21555:48;21593:9;21585:6;19768:5;19762:12;19757:3;19750:25;19824:4;19817:5;19813:16;19807:23;19800:4;19795:3;19791:14;19784:47;19880:4;19873:5;19869:16;19863:23;19856:4;19851:3;19847:14;19840:47;19933:4;19926:5;19922:16;19916:23;19958:42;20050:2;20036:12;20032:21;20025:4;20020:3;20016:14;20009:45;20115:2;20107:4;20100:5;20096:16;20090:23;20086:32;20079:4;20074:3;20070:14;20063:56;;;20168:4;20161:5;20157:16;20151:23;20144:4;20139:3;20135:14;20128:47;19685:496;;;21555:48;21640:2;21634:3;21623:9;21619:19;21612:31;21666:44;21706:2;21695:9;21691:18;21683:6;21666:44;:::i;:::-;21652:58;;21759:9;21751:6;21747:22;21741:3;21730:9;21726:19;21719:51;21787:49;21829:6;21821;21813;21787:49;:::i;21847:580::-;21924:4;21930:6;21990:11;21977:25;22080:66;22069:8;22053:14;22049:29;22045:102;22025:18;22021:127;22011:155;;22162:1;22159;22152:12;22011:155;22189:33;;22241:20;;;-1:-1:-1;22284:18:1;22273:30;;22270:50;;;22316:1;22313;22306:12;22270:50;22349:4;22337:17;;-1:-1:-1;22380:14:1;22376:27;;;22366:38;;22363:58;;;22417:1;22414;22407:12;22432:195;22471:3;22502:66;22495:5;22492:77;22489:103;;22572:18;;:::i;:::-;-1:-1:-1;22619:1:1;22608:13;;22432:195::o;23649:184::-;23719:6;23772:2;23760:9;23751:7;23747:23;23743:32;23740:52;;;23788:1;23785;23778:12;23740:52;-1:-1:-1;23811:16:1;;23649:184;-1:-1:-1;23649:184:1:o;23838:772::-;23922:5;23975:3;23968:4;23960:6;23956:17;23952:27;23942:55;;23993:1;23990;23983:12;23942:55;24022:6;24016:13;24048:4;24072:79;24088:62;24147:2;24088:62;:::i;24072:79::-;24185:15;;;24271:1;24267:10;;;;24255:23;;24251:32;;;24216:12;;;;24295:15;;;24292:35;;;24323:1;24320;24313:12;24292:35;24359:2;24351:6;24347:15;24371:210;24387:6;24382:3;24379:15;24371:210;;;24460:3;24454:10;24477:31;24502:5;24477:31;:::i;:::-;24521:18;;24559:12;;;;24404;;24371:210;;24615:441;24668:5;24721:3;24714:4;24706:6;24702:17;24698:27;24688:55;;24739:1;24736;24729:12;24688:55;24768:6;24762:13;24799:48;24815:31;24843:2;24815:31;:::i;24799:48::-;24872:2;24863:7;24856:19;24918:3;24911:4;24906:2;24898:6;24894:15;24890:26;24887:35;24884:55;;;24935:1;24932;24925:12;24884:55;24948:77;25022:2;25015:4;25006:7;25002:18;24995:4;24987:6;24983:17;24948:77;:::i;25061:913::-;25124:5;25177:3;25170:4;25162:6;25158:17;25154:27;25144:55;;25195:1;25192;25185:12;25144:55;25224:6;25218:13;25250:4;25274:79;25290:62;25349:2;25290:62;:::i;25274:79::-;25387:15;;;25473:1;25469:10;;;;25457:23;;25453:32;;;25418:12;;;;25497:15;;;25494:35;;;25525:1;25522;25515:12;25494:35;25561:2;25553:6;25549:15;25573:372;25589:6;25584:3;25581:15;25573:372;;;25668:3;25662:10;25704:18;25691:11;25688:35;25685:125;;;25764:1;25793:2;25789;25782:14;25685:125;25835:67;25898:3;25893:2;25879:11;25871:6;25867:24;25863:33;25835:67;:::i;:::-;25823:80;;-1:-1:-1;25923:12:1;;;;25606;;25573:372;;25979:678;26044:5;26097:3;26090:4;26082:6;26078:17;26074:27;26064:55;;26115:1;26112;26105:12;26064:55;26144:6;26138:13;26170:4;26194:79;26210:62;26269:2;26210:62;:::i;26194:79::-;26307:15;;;26393:1;26389:10;;;;26377:23;;26373:32;;;26338:12;;;;26417:15;;;26414:35;;;26445:1;26442;26435:12;26414:35;26481:2;26473:6;26469:15;26493:135;26509:6;26504:3;26501:15;26493:135;;;26575:10;;26563:23;;26606:12;;;;26526;;26493:135;;26662:146;26749:13;;26771:31;26749:13;26771:31;:::i;26813:132::-;26889:13;;26911:28;26889:13;26911:28;:::i;26950:1343::-;27198:6;27206;27214;27222;27230;27238;27246;27299:3;27287:9;27278:7;27274:23;27270:33;27267:53;;;27316:1;27313;27306:12;27267:53;27349:9;27343:16;27378:18;27419:2;27411:6;27408:14;27405:34;;;27435:1;27432;27425:12;27405:34;27458:91;27541:7;27532:6;27521:9;27517:22;27458:91;:::i;:::-;27448:101;;27589:2;27578:9;27574:18;27568:25;27558:35;;27639:2;27628:9;27624:18;27618:25;27602:41;;27668:2;27658:8;27655:16;27652:36;;;27684:1;27681;27674:12;27652:36;27707:72;27771:7;27760:8;27749:9;27745:24;27707:72;:::i;:::-;27697:82;;27825:2;27814:9;27810:18;27804:25;27788:41;;27854:2;27844:8;27841:16;27838:36;;;27870:1;27867;27860:12;27838:36;27893:74;27959:7;27948:8;27937:9;27933:24;27893:74;:::i;:::-;27883:84;;27986:58;28039:3;28028:9;28024:19;27986:58;:::i;:::-;27976:68;;28063:47;28105:3;28094:9;28090:19;28063:47;:::i;:::-;28053:57;;28156:3;28145:9;28141:19;28135:26;28119:42;;28186:2;28176:8;28173:16;28170:36;;;28202:1;28199;28192:12;28170:36;;28225:62;28279:7;28268:8;28257:9;28253:24;28225:62;:::i;:::-;28215:72;;;26950:1343;;;;;;;;;;:::o;28298:1078::-;28783:3;28772:9;28765:22;28746:4;28810:76;28881:3;28870:9;28866:19;28858:6;28810:76;:::i;:::-;28922:6;28917:2;28906:9;28902:18;28895:34;28965:6;28960:2;28949:9;28945:18;28938:34;29020:9;29012:6;29008:22;29003:2;28992:9;28988:18;28981:50;29054:44;29091:6;29083;29054:44;:::i;:::-;29040:58;;29147:9;29139:6;29135:22;29129:3;29118:9;29114:19;29107:51;29175:42;29210:6;29202;29175:42;:::i;:::-;29261:14;;29254:22;29248:3;29233:19;;29226:51;-1:-1:-1;;29326:42:1;29314:55;;;;29308:3;29293:19;;;29286:84;29167:50;28298:1078;-1:-1:-1;;;;;28298:1078:1:o;29381:287::-;29510:3;29548:6;29542:13;29564:66;29623:6;29618:3;29611:4;29603:6;29599:17;29564:66;:::i;:::-;29646:16;;;;;29381:287;-1:-1:-1;;29381:287:1:o;29673:357::-;29791:12;;29838:4;29827:16;;;29821:23;;29791:12;29856:16;;29853:171;;;29946:66;29936:6;29930:4;29926:17;29923:1;29919:25;29915:98;29908:5;29904:110;29895:119;;29853:171;;29673:357;;;:::o;30035:408::-;30250:42;30242:6;30238:55;30227:9;30220:74;30330:6;30325:2;30314:9;30310:18;30303:34;30373:2;30368;30357:9;30353:18;30346:30;30201:4;30393:44;30433:2;30422:9;30418:18;30410:6;30393:44;:::i;:::-;30385:52;30035:408;-1:-1:-1;;;;;30035:408:1:o;30448:812::-;30859:25;30854:3;30847:38;30829:3;30914:6;30908:13;30930:75;30998:6;30993:2;30988:3;30984:12;30977:4;30969:6;30965:17;30930:75;:::i;:::-;31069:19;31064:2;31024:16;;;31056:11;;;31049:40;31114:13;;31136:76;31114:13;31198:2;31190:11;;31183:4;31171:17;;31136:76;:::i;:::-;31232:17;31251:2;31228:26;;30448:812;-1:-1:-1;;;;30448:812:1:o;31265:219::-;31414:2;31403:9;31396:21;31377:4;31434:44;31474:2;31463:9;31459:18;31451:6;31434:44;:::i;32202:245::-;32269:6;32322:2;32310:9;32301:7;32297:23;32293:32;32290:52;;;32338:1;32335;32328:12;32290:52;32370:9;32364:16;32389:28;32411:5;32389:28;:::i;33278:168::-;33351:9;;;33382;;33399:15;;;33393:22;;33379:37;33369:71;;33420:18;;:::i;33451:125::-;33516:9;;;33537:10;;;33534:36;;;33550:18;;:::i;33581:196::-;33620:3;33648:5;33638:39;;33657:18;;:::i;:::-;-1:-1:-1;33704:66:1;33693:78;;33581:196::o;35673:251::-;35743:6;35796:2;35784:9;35775:7;35771:23;35767:32;35764:52;;;35812:1;35809;35802:12;35764:52;35844:9;35838:16;35863:31;35888:5;35863:31;:::i;37718:188::-;37797:13;;37850:30;37839:42;;37829:53;;37819:81;;37896:1;37893;37886:12;37911:450;37998:6;38006;38014;38067:2;38055:9;38046:7;38042:23;38038:32;38035:52;;;38083:1;38080;38073:12;38035:52;38106:40;38136:9;38106:40;:::i;:::-;38096:50;;38165:49;38210:2;38199:9;38195:18;38165:49;:::i;:::-;38155:59;;38257:2;38246:9;38242:18;38236:25;38301:10;38294:5;38290:22;38283:5;38280:33;38270:61;;38327:1;38324;38317:12;38270:61;38350:5;38340:15;;;37911:450;;;;;:::o;38366:274::-;38406:1;38432;38422:189;;38467:77;38464:1;38457:88;38568:4;38565:1;38558:15;38596:4;38593:1;38586:15;38422:189;-1:-1:-1;38625:9:1;;38366:274::o;38645:184::-;38697:77;38694:1;38687:88;38794:4;38791:1;38784:15;38818:4;38815:1;38808:15
Swarm Source
ipfs://d77c836f50e8fca127bdf0b20c6376c023ebbdd9466658211512cde84958cda3
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.