More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
Swap | 21998730 | 39 days ago | 0.005 ETH | ||||
Swap | 21998730 | 39 days ago | 0.005 ETH | ||||
Swap | 21908738 | 51 days ago | 0.00723276 ETH | ||||
Swap | 21908738 | 51 days ago | 0.00723276 ETH | ||||
Swap | 21908681 | 51 days ago | 0.01262785 ETH | ||||
Swap | 21908681 | 51 days ago | 0.01262785 ETH | ||||
Swap | 21908635 | 51 days ago | 0.01343368 ETH | ||||
Swap | 21908635 | 51 days ago | 0.01343368 ETH | ||||
Swap | 21908583 | 52 days ago | 0.00905828 ETH | ||||
Swap | 21908583 | 52 days ago | 0.00905828 ETH | ||||
Swap | 21908577 | 52 days ago | 0.01050679 ETH | ||||
Swap | 21908577 | 52 days ago | 0.01050679 ETH | ||||
Swap | 21904538 | 52 days ago | 0.00384004 ETH | ||||
Swap | 21904538 | 52 days ago | 0.00384004 ETH | ||||
Swap | 21904486 | 52 days ago | 0.00669931 ETH | ||||
Swap | 21904486 | 52 days ago | 0.00669931 ETH | ||||
Swap | 21904480 | 52 days ago | 0.00834804 ETH | ||||
Swap | 21904480 | 52 days ago | 0.00834804 ETH | ||||
Swap | 21904414 | 52 days ago | 0.00573054 ETH | ||||
Swap | 21904414 | 52 days ago | 0.00573054 ETH | ||||
Swap | 21904409 | 52 days ago | 0.0092057 ETH | ||||
Swap | 21904409 | 52 days ago | 0.0092057 ETH | ||||
Swap | 21904335 | 52 days ago | 0.008463 ETH | ||||
Swap | 21904335 | 52 days ago | 0.008463 ETH | ||||
Swap | 21904277 | 52 days ago | 0.0094299 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
PendleSwapL1
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import "../../core/libraries/TokenHelper.sol"; import "./IPSwapAggregator.sol"; import "./kyberswap/l1-contracts/InputScalingHelper.sol"; import "./kyberswap/l2-contracts/InputScalingHelperL2.sol"; import "./oneinch/OneInchAggregationRouterHelper.sol"; abstract contract PendleSwapBase is IPSwapAggregator, TokenHelper, OneInchAggregationRouterHelper { using Address for address; function swap(address tokenIn, uint256 amountIn, SwapData calldata data) external payable { _safeApproveInf(tokenIn, data.extRouter); data.extRouter.functionCallWithValue( data.needScale ? _getScaledInputData(data.swapType, data.extCalldata, amountIn) : data.extCalldata, tokenIn == NATIVE ? amountIn : 0 ); } function _getScaledInputData( SwapType swapType, bytes calldata rawCallData, uint256 amountIn ) internal pure returns (bytes memory scaledCallData) { if (swapType == SwapType.KYBERSWAP) { scaledCallData = _getKyberScaledInputData(rawCallData, amountIn); } else if (swapType == SwapType.ONE_INCH) { scaledCallData = _get1inchScaledInputData(rawCallData, amountIn); } else { assert(false); } } function _getKyberScaledInputData( bytes calldata rawCallData, uint256 amountIn ) internal pure virtual returns (bytes memory scaledCallData); receive() external payable {} } contract PendleSwapL1 is PendleSwapBase { function _getKyberScaledInputData( bytes calldata rawCallData, uint256 amountIn ) internal pure override returns (bytes memory) { return InputScalingHelper._getScaledInputData(rawCallData, amountIn); } } contract PendleSwapL2 is PendleSwapBase { function _getKyberScaledInputData( bytes calldata rawCallData, uint256 amountIn ) internal pure override returns (bytes memory) { return InputScalingHelperL2._getScaledInputData(rawCallData, amountIn); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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); } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; library Errors { // BulkSeller error BulkInsufficientSyForTrade(uint256 currentAmount, uint256 requiredAmount); error BulkInsufficientTokenForTrade(uint256 currentAmount, uint256 requiredAmount); error BulkInSufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut); error BulkInSufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut); error BulkInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance); error BulkNotMaintainer(); error BulkNotAdmin(); error BulkSellerAlreadyExisted(address token, address SY, address bulk); error BulkSellerInvalidToken(address token, address SY); error BulkBadRateTokenToSy(uint256 actualRate, uint256 currentRate, uint256 eps); error BulkBadRateSyToToken(uint256 actualRate, uint256 currentRate, uint256 eps); // APPROX error ApproxFail(); error ApproxParamsInvalid(uint256 guessMin, uint256 guessMax, uint256 eps); error ApproxBinarySearchInputInvalid( uint256 approxGuessMin, uint256 approxGuessMax, uint256 minGuessMin, uint256 maxGuessMax ); // MARKET + MARKET MATH CORE error MarketExpired(); error MarketZeroAmountsInput(); error MarketZeroAmountsOutput(); error MarketZeroLnImpliedRate(); error MarketInsufficientPtForTrade(int256 currentAmount, int256 requiredAmount); error MarketInsufficientPtReceived(uint256 actualBalance, uint256 requiredBalance); error MarketInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance); error MarketZeroTotalPtOrTotalAsset(int256 totalPt, int256 totalAsset); error MarketExchangeRateBelowOne(int256 exchangeRate); error MarketProportionMustNotEqualOne(); error MarketRateScalarBelowZero(int256 rateScalar); error MarketScalarRootBelowZero(int256 scalarRoot); error MarketProportionTooHigh(int256 proportion, int256 maxProportion); error OracleUninitialized(); error OracleTargetTooOld(uint32 target, uint32 oldest); error OracleZeroCardinality(); error MarketFactoryExpiredPt(); error MarketFactoryInvalidPt(); error MarketFactoryMarketExists(); error MarketFactoryLnFeeRateRootTooHigh(uint80 lnFeeRateRoot, uint256 maxLnFeeRateRoot); error MarketFactoryOverriddenFeeTooHigh(uint80 overriddenFee, uint256 marketLnFeeRateRoot); error MarketFactoryReserveFeePercentTooHigh(uint8 reserveFeePercent, uint8 maxReserveFeePercent); error MarketFactoryZeroTreasury(); error MarketFactoryInitialAnchorTooLow(int256 initialAnchor, int256 minInitialAnchor); error MFNotPendleMarket(address addr); // ROUTER error RouterInsufficientLpOut(uint256 actualLpOut, uint256 requiredLpOut); error RouterInsufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut); error RouterInsufficientPtOut(uint256 actualPtOut, uint256 requiredPtOut); error RouterInsufficientYtOut(uint256 actualYtOut, uint256 requiredYtOut); error RouterInsufficientPYOut(uint256 actualPYOut, uint256 requiredPYOut); error RouterInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut); error RouterInsufficientSyRepay(uint256 actualSyRepay, uint256 requiredSyRepay); error RouterInsufficientPtRepay(uint256 actualPtRepay, uint256 requiredPtRepay); error RouterNotAllSyUsed(uint256 netSyDesired, uint256 netSyUsed); error RouterTimeRangeZero(); error RouterCallbackNotPendleMarket(address caller); error RouterInvalidAction(bytes4 selector); error RouterInvalidFacet(address facet); error RouterKyberSwapDataZero(); error SimulationResults(bool success, bytes res); // YIELD CONTRACT error YCExpired(); error YCNotExpired(); error YieldContractInsufficientSy(uint256 actualSy, uint256 requiredSy); error YCNothingToRedeem(); error YCPostExpiryDataNotSet(); error YCNoFloatingSy(); // YieldFactory error YCFactoryInvalidExpiry(); error YCFactoryYieldContractExisted(); error YCFactoryZeroExpiryDivisor(); error YCFactoryZeroTreasury(); error YCFactoryInterestFeeRateTooHigh(uint256 interestFeeRate, uint256 maxInterestFeeRate); error YCFactoryRewardFeeRateTooHigh(uint256 newRewardFeeRate, uint256 maxRewardFeeRate); // SY error SYInvalidTokenIn(address token); error SYInvalidTokenOut(address token); error SYZeroDeposit(); error SYZeroRedeem(); error SYInsufficientSharesOut(uint256 actualSharesOut, uint256 requiredSharesOut); error SYInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut); // SY-specific error SYQiTokenMintFailed(uint256 errCode); error SYQiTokenRedeemFailed(uint256 errCode); error SYQiTokenRedeemRewardsFailed(uint256 rewardAccruedType0, uint256 rewardAccruedType1); error SYQiTokenBorrowRateTooHigh(uint256 borrowRate, uint256 borrowRateMax); error SYCurveInvalidPid(); error SYCurve3crvPoolNotFound(); error SYApeDepositAmountTooSmall(uint256 amountDeposited); error SYBalancerInvalidPid(); error SYInvalidRewardToken(address token); error SYStargateRedeemCapExceeded(uint256 amountLpDesired, uint256 amountLpRedeemable); error SYBalancerReentrancy(); error NotFromTrustedRemote(uint16 srcChainId, bytes path); error ApxETHNotEnoughBuffer(); // Liquidity Mining error VCInactivePool(address pool); error VCPoolAlreadyActive(address pool); error VCZeroVePendle(address user); error VCExceededMaxWeight(uint256 totalWeight, uint256 maxWeight); error VCEpochNotFinalized(uint256 wTime); error VCPoolAlreadyAddAndRemoved(address pool); error VEInvalidNewExpiry(uint256 newExpiry); error VEExceededMaxLockTime(); error VEInsufficientLockTime(); error VENotAllowedReduceExpiry(); error VEZeroAmountLocked(); error VEPositionNotExpired(); error VEZeroPosition(); error VEZeroSlope(uint128 bias, uint128 slope); error VEReceiveOldSupply(uint256 msgTime); error GCNotPendleMarket(address caller); error GCNotVotingController(address caller); error InvalidWTime(uint256 wTime); error ExpiryInThePast(uint256 expiry); error ChainNotSupported(uint256 chainId); error FDTotalAmountFundedNotMatch(uint256 actualTotalAmount, uint256 expectedTotalAmount); error FDEpochLengthMismatch(); error FDInvalidPool(address pool); error FDPoolAlreadyExists(address pool); error FDInvalidNewFinishedEpoch(uint256 oldFinishedEpoch, uint256 newFinishedEpoch); error FDInvalidStartEpoch(uint256 startEpoch); error FDInvalidWTimeFund(uint256 lastFunded, uint256 wTime); error FDFutureFunding(uint256 lastFunded, uint256 currentWTime); error BDInvalidEpoch(uint256 epoch, uint256 startTime); // Cross-Chain error MsgNotFromSendEndpoint(uint16 srcChainId, bytes path); error MsgNotFromReceiveEndpoint(address sender); error InsufficientFeeToSendMsg(uint256 currentFee, uint256 requiredFee); error ApproxDstExecutionGasNotSet(); error InvalidRetryData(); // GENERIC MSG error ArrayLengthMismatch(); error ArrayEmpty(); error ArrayOutOfBounds(); error ZeroAddress(); error FailedToSendEther(); error InvalidMerkleProof(); error OnlyLayerZeroEndpoint(); error OnlyYT(); error OnlyYCFactory(); error OnlyWhitelisted(); // Swap Aggregator error SAInsufficientTokenIn(address tokenIn, uint256 amountExpected, uint256 amountActual); error UnsupportedSelector(uint256 aggregatorType, bytes4 selector); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../../interfaces/IWETH.sol"; abstract contract TokenHelper { using SafeERC20 for IERC20; address internal constant NATIVE = address(0); uint256 internal constant LOWER_BOUND_APPROVAL = type(uint96).max / 2; // some tokens use 96 bits for approval function _transferIn(address token, address from, uint256 amount) internal { if (token == NATIVE) require(msg.value == amount, "eth mismatch"); else if (amount != 0) IERC20(token).safeTransferFrom(from, address(this), amount); } function _transferFrom(IERC20 token, address from, address to, uint256 amount) internal { if (amount != 0) token.safeTransferFrom(from, to, amount); } function _transferOut(address token, address to, uint256 amount) internal { if (amount == 0) return; if (token == NATIVE) { (bool success, ) = to.call{value: amount}(""); require(success, "eth send failed"); } else { IERC20(token).safeTransfer(to, amount); } } function _transferOut(address[] memory tokens, address to, uint256[] memory amounts) internal { uint256 numTokens = tokens.length; require(numTokens == amounts.length, "length mismatch"); for (uint256 i = 0; i < numTokens; ) { _transferOut(tokens[i], to, amounts[i]); unchecked { i++; } } } function _selfBalance(address token) internal view returns (uint256) { return (token == NATIVE) ? address(this).balance : IERC20(token).balanceOf(address(this)); } function _selfBalance(IERC20 token) internal view returns (uint256) { return token.balanceOf(address(this)); } /// @notice Approves the stipulated contract to spend the given allowance in the given token /// @dev PLS PAY ATTENTION to tokens that requires the approval to be set to 0 before changing it function _safeApprove(address token, address to, uint256 value) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "Safe Approve"); } function _safeApproveInf(address token, address to) internal { if (token == NATIVE) return; if (IERC20(token).allowance(address(this), to) < LOWER_BOUND_APPROVAL) { _safeApprove(token, to, 0); _safeApprove(token, to, type(uint256).max); } } function _wrap_unwrap_ETH(address tokenIn, address tokenOut, uint256 netTokenIn) internal { if (tokenIn == NATIVE) IWETH(tokenOut).deposit{value: netTokenIn}(); else IWETH(tokenIn).withdraw(netTokenIn); } }
// SPDX-License-Identifier: GPL-3.0-or-later /* * MIT License * =========== * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { event Deposit(address indexed dst, uint256 wad); event Withdrawal(address indexed src, uint256 wad); function deposit() external payable; function withdraw(uint256 wad) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; struct SwapData { SwapType swapType; address extRouter; bytes extCalldata; bool needScale; } enum SwapType { NONE, KYBERSWAP, ONE_INCH, // ETH_WETH not used in Aggregator ETH_WETH } interface IPSwapAggregator { function swap(address tokenIn, uint256 amountIn, SwapData calldata swapData) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12; interface IAggregationExecutor { function callBytes(bytes calldata data) external payable; // 0xd9c45357 // callbytes per swap sequence function swapSingleSequence(bytes calldata data) external; function finalTransactionProcessing( address tokenIn, address tokenOut, address to, bytes calldata destTokenFeeData ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12; interface IAggregationExecutorOptimistic { event Exchange(address pair, uint256 amountOut, address output); struct Swap { bytes data; bytes4 functionSelector; } struct SwapCallbackData { bytes path; address payer; } struct SwapCallbackDataPath { address pool; address tokenIn; address tokenOut; } struct PositiveSlippageFeeData { uint256 partnerPSInfor; // [partnerReceiver (160 bit) + partnerPercent(96bits)] uint256 expectedReturnAmount; // [minimumPSAmount (128 bits) + expectedReturnAmount (128 bits)] } struct SwapExecutorDescription { Swap[][] swapSequences; address tokenIn; address tokenOut; address to; uint256 deadline; bytes positiveSlippageData; } function rescueFunds(address token, uint256 amount) external; function callBytes(bytes calldata data) external payable; function swapSingleSequence(bytes calldata data) external; function multihopBatchSwapExactIn( Swap[][] memory swapSequences, address tokenIn, address tokenOut, address to, uint256 deadline, bytes memory positiveSlippageData ) external payable; function finalTransactionProcessing( address tokenIn, address tokenOut, address to, bytes calldata destTokenFeeData ) external; function updateExecutor(bytes4 functionSelector, address executor) external; function updateBatchExecutors(bytes4[] memory functionSelectors, address[] memory executors) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12; interface IExecutorHelper { struct Swap { bytes data; bytes32 selectorAndFlags; // [selector (32 bits) + flags (224 bits)]; selector is 4 most significant bytes; flags are stored in 4 least significant bytes. } struct SwapExecutorDescription { Swap[][] swapSequences; address tokenIn; address tokenOut; uint256 minTotalAmountOut; address to; uint256 deadline; bytes positiveSlippageData; } struct UniSwap { address pool; address tokenIn; address tokenOut; address recipient; uint256 collectAmount; // amount that should be transferred to the pool uint32 swapFee; uint32 feePrecision; uint32 tokenWeightInput; } struct StableSwap { address pool; address tokenFrom; address tokenTo; uint8 tokenIndexFrom; uint8 tokenIndexTo; uint256 dx; uint256 poolLength; address poolLp; bool isSaddle; // true: saddle, false: stable } struct CurveSwap { address pool; address tokenFrom; address tokenTo; int128 tokenIndexFrom; int128 tokenIndexTo; uint256 dx; bool usePoolUnderlying; bool useTriCrypto; } struct UniswapV3KSElastic { address recipient; address pool; address tokenIn; address tokenOut; uint256 swapAmount; uint160 sqrtPriceLimitX96; bool isUniV3; // true = UniV3, false = KSElastic } struct BalancerV2 { address vault; bytes32 poolId; address assetIn; address assetOut; uint256 amount; } struct DODO { address recipient; address pool; address tokenFrom; address tokenTo; uint256 amount; address sellHelper; bool isSellBase; bool isVersion2; } struct GMX { address vault; address tokenIn; address tokenOut; uint256 amount; address receiver; } struct Synthetix { address synthetixProxy; address tokenIn; address tokenOut; bytes32 sourceCurrencyKey; uint256 sourceAmount; bytes32 destinationCurrencyKey; bool useAtomicExchange; } struct Platypus { address pool; address tokenIn; address tokenOut; address recipient; uint256 collectAmount; // amount that should be transferred to the pool } struct PSM { address router; address tokenIn; address tokenOut; uint256 amountIn; address recipient; } struct WSTETH { address pool; uint256 amount; bool isWrapping; } struct Maverick { address pool; address tokenIn; address tokenOut; address recipient; uint256 swapAmount; uint256 sqrtPriceLimitD18; } struct SyncSwap { bytes _data; address vault; address tokenIn; address pool; uint256 collectAmount; } struct AlgebraV1 { address recipient; address pool; address tokenIn; address tokenOut; uint256 swapAmount; uint160 sqrtPriceLimitX96; uint256 senderFeeOnTransfer; // [ FoT_FLAG(1 bit) ... SENDER_ADDRESS(160 bits) ] } struct BalancerBatch { address vault; bytes32[] poolIds; address[] path; // swap path from assetIn to assetOut bytes[] userDatas; uint256 amountIn; // assetIn amount } struct Mantis { address pool; address tokenIn; address tokenOut; uint256 amount; address recipient; } struct IziSwap { address pool; address tokenIn; address tokenOut; address recipient; uint256 swapAmount; int24 limitPoint; } struct TraderJoeV2 { address recipient; address pool; address tokenIn; address tokenOut; uint256 collectAmount; // most significant 1 bit is to determine whether pool is v2.1, else v2.0 } struct LevelFiV2 { address pool; address fromToken; address toToken; uint256 amountIn; uint256 minAmountOut; address recipient; // receive token out } struct GMXGLP { address rewardRouter; address stakedGLP; address glpManager; address yearnVault; address tokenIn; address tokenOut; uint256 swapAmount; address recipient; } struct Vooi { address pool; address fromToken; address toToken; uint256 fromID; uint256 toID; uint256 fromAmount; address to; } struct VelocoreV2 { address vault; uint256 amount; address tokenIn; address tokenOut; address stablePool; // if not empty then use stable pool address wrapToken; bool isConvertFirst; } struct MaticMigrate { address pool; address tokenAddress; // should be POL uint256 amount; address recipient; // empty if migrate } struct Kokonut { address pool; uint256 dx; uint256 tokenIndexFrom; address fromToken; address toToken; } struct BalancerV1 { address pool; address tokenIn; address tokenOut; uint256 amount; } struct SwaapV2 { address router; uint256 amount; bytes data; address tokenIn; address tokenOut; address recipient; } struct ArbswapStable { address pool; uint256 dx; uint256 tokenIndexFrom; address tokenIn; address tokenOut; } struct BancorV2 { address pool; address[] swapPath; uint256 amount; address recipient; } struct Ambient { address pool; uint128 qty; address base; address quote; uint256 poolIdx; uint8 settleFlags; } struct UniV1 { address pool; uint256 amount; address tokenIn; address tokenOut; address recipient; } struct LighterV2 { address orderBook; uint256 amount; bool isAsk; // isAsk = orderBook.isAskOrder(orderId); address tokenIn; address tokenOut; address recipient; } struct EtherFiWeETH { uint256 amount; bool isWrapping; } struct Kelp { uint256 amount; address tokenIn; } struct EthenaSusde { uint256 amount; address recipient; } struct RocketPool { address pool; uint256 isDepositAndAmount; // 1 isDeposit + 127 empty + 128 amount token in } struct MakersDAI { uint256 isRedeemAndAmount; // 1 isRedeem + 127 empty + 128 amount token in address recipient; } struct Renzo { address pool; uint256 amount; address tokenIn; address tokenOut; } struct FrxETH { address pool; uint256 amount; address tokenOut; } struct SfrxETH { address pool; uint256 amount; address tokenOut; address recipient; } struct SfrxETHConvertor { address pool; uint256 isDepositAndAmount; // 1 isDeposit + 127 empty + 128 amount token in address tokenIn; address tokenOut; address recipient; } struct OriginETH { address pool; uint256 amount; } function executeUniswap(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeStableSwap(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeCurve(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeKSClassic(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeUniV3KSElastic(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeRfq(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeBalV2(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeDODO(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeVelodrome(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeGMX(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executePlatypus(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeWrappedstETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeStEth(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeSynthetix(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeHashflow(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executePSM(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeFrax(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeCamelot(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeKyberLimitOrder( bytes memory data, uint256 flagsAndPrevAmountOut ) external payable returns (uint256); function executeMaverick(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeSyncSwap(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeAlgebraV1(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeBalancerBatch(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeWombat(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeMantis(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeIziSwap(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeWooFiV2(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeTraderJoeV2(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executePancakeStableSwap( bytes memory data, uint256 flagsAndPrevAmountOut ) external payable returns (uint256); function executeLevelFiV2(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeGMXGLP(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeVooi(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeVelocoreV2(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeMaticMigrate(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeSmardex(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeSolidlyV2(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeKokonut(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeBalancerV1(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeSwaapV2(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeNomiswapStable(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeArbswapStable(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeBancorV2(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeBancorV3(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeAmbient(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeUniV1(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeNative(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeBebop(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeLighterV2(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeEtherFieETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeEtherFiWeETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeKelp(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeRocketPool(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeEthenaSusde(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeMakersDAI(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeRenzo(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeWBETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeMantleETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeFrxETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeSfrxETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeSfrxETHConvertor( bytes memory data, uint256 flagsAndPrevAmountOut ) external payable returns (uint256); function executeSwellETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeRswETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeStaderETHx(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeOriginETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executePrimeETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeMantleUsd(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeBedrockUniETH(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); function executeMaiPSM(bytes memory data, uint256 flagsAndPrevAmountOut) external payable returns (uint256); }
pragma solidity >=0.6.12; interface IExecutorHelperL2 { struct Swap { bytes data; bytes4 functionSelector; } struct SwapExecutorDescription { Swap[][] swapSequences; address tokenIn; address tokenOut; uint256 minTotalAmountOut; address to; uint256 deadline; bytes positiveSlippageData; } struct UniSwap { address pool; address tokenIn; address tokenOut; address recipient; uint256 collectAmount; // amount that should be transferred to the pool uint32 swapFee; uint32 feePrecision; uint32 tokenWeightInput; } struct StableSwap { address pool; address tokenFrom; address tokenTo; uint8 tokenIndexFrom; uint8 tokenIndexTo; uint256 dx; uint256 poolLength; address poolLp; bool isSaddle; // true: saddle, false: stable } struct CurveSwap { address pool; address tokenFrom; address tokenTo; int128 tokenIndexFrom; int128 tokenIndexTo; uint256 dx; bool usePoolUnderlying; bool useTriCrypto; } struct UniswapV3KSElastic { address recipient; address pool; address tokenIn; address tokenOut; uint256 swapAmount; uint160 sqrtPriceLimitX96; bool isUniV3; // true = UniV3, false = KSElastic } struct SwapCallbackData { bytes path; address payer; } struct SwapCallbackDataPath { address pool; address tokenIn; address tokenOut; } struct BalancerV2 { address vault; bytes32 poolId; address assetIn; address assetOut; uint256 amount; } struct DODO { address recipient; address pool; address tokenFrom; address tokenTo; uint256 amount; address sellHelper; bool isSellBase; bool isVersion2; } struct GMX { address vault; address tokenIn; address tokenOut; uint256 amount; address receiver; } struct Synthetix { address synthetixProxy; address tokenIn; address tokenOut; bytes32 sourceCurrencyKey; uint256 sourceAmount; bytes32 destinationCurrencyKey; bool useAtomicExchange; } struct WSTETH { address pool; uint256 amount; bool isWrapping; } struct Platypus { address pool; address tokenIn; address tokenOut; address recipient; uint256 collectAmount; // amount that should be transferred to the pool } struct PSM { address router; address tokenIn; address tokenOut; uint256 amountIn; address recipient; } struct Maverick { address pool; address tokenIn; address tokenOut; address recipient; uint256 swapAmount; uint256 sqrtPriceLimitD18; } /// @notice Struct for Sync Swap /// @param _data encode of (address, address, uint8) : (tokenIn, recipient, withdrawMode) /// Withdraw with mode. // 0 = DEFAULT // 1 = UNWRAPPED // 2 = WRAPPED /// @param vault vault contract /// @param tokenIn token input to swap /// @param pool pool of SyncSwap /// @param collectAmount amount that should be transferred to the pool struct SyncSwap { bytes _data; address vault; address tokenIn; address pool; uint256 collectAmount; } struct AlgebraV1 { address recipient; address pool; address tokenIn; address tokenOut; uint256 swapAmount; uint160 sqrtPriceLimitX96; uint256 senderFeeOnTransfer; // [ FoT_FLAG(1 bit) ... SENDER_ADDRESS(160 bits) ] } struct BalancerBatch { address vault; bytes32[] poolIds; address[] path; // swap path from assetIn to assetOut bytes[] userDatas; uint256 amountIn; // assetIn amount } struct Mantis { address pool; address tokenIn; address tokenOut; uint256 amount; address recipient; } struct IziSwap { address pool; address tokenIn; address tokenOut; address recipient; uint256 swapAmount; int24 limitPoint; } struct TraderJoeV2 { address recipient; address pool; address tokenIn; address tokenOut; uint256 collectAmount; // most significant 1 bit is to determine whether pool is v2.0, else v2.1 } struct LevelFiV2 { address pool; address fromToken; address toToken; uint256 amountIn; uint256 minAmountOut; address recipient; // receive token out } struct GMXGLP { address rewardRouter; address stakedGLP; address glpManager; address yearnVault; address tokenIn; address tokenOut; uint256 swapAmount; address recipient; } struct Vooi { address pool; address fromToken; address toToken; uint256 fromID; uint256 toID; uint256 fromAmount; address to; } struct VelocoreV2 { address vault; uint256 amount; address tokenIn; address tokenOut; address stablePool; // if not empty then use stable pool address wrapToken; bool isConvertFirst; } struct MaticMigrate { address pool; address tokenAddress; // should be POL uint256 amount; address recipient; // empty if migrate } struct Kokonut { address pool; uint256 dx; uint256 tokenIndexFrom; address fromToken; address toToken; } struct BalancerV1 { address pool; uint256 amount; address tokenIn; address tokenOut; } struct SwaapV2 { address router; uint256 amount; bytes data; address tokenIn; address tokenOut; address recipient; } struct ArbswapStable { address pool; uint256 dx; uint256 tokenIndexFrom; address tokenIn; address tokenOut; } struct BancorV2 { address pool; address[] swapPath; uint256 amount; address recipient; } struct Ambient { address pool; uint128 qty; address base; address quote; uint256 poolIdx; uint8 settleFlags; } struct LighterV2 { address orderBook; uint256 amount; bool isAsk; // isAsk = orderBook.isAskOrder(orderId); address tokenIn; address tokenOut; address recipient; } struct FrxETH { address pool; uint256 amount; address tokenOut; } function executeUniswap( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeKSClassic( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeVelodrome( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeFrax( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeCamelot( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeKyberLimitOrder( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeRfq( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeHashflow( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeStableSwap( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeCurve( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeUniV3KSElastic( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeBalV2( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeDODO( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeGMX( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeSynthetix( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeWrappedstETH( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeStEth( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executePlatypus( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executePSM( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeMaverick( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeSyncSwap( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeAlgebraV1( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeBalancerBatch( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeWombat( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeMantis( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeIziSwap( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeTraderJoeV2( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeLevelFiV2( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeGMXGLP( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeVooi( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeVelocoreV2( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeSmardex( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeSolidlyV2( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeKokonut( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeBalancerV1( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeSwaapV2( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeNomiswapStable( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeArbswapStable( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeBancorV2( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeBancorV3( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeAmbient( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeNative( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeLighterV2( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); function executeMaiPSM( uint256 index, bytes memory data, uint256 previousAmountOut, address tokenIn, bool getPoolOnly, address nextPool ) external payable returns (address tokenOut, uint256 tokenAmountOut, address pool); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IAggregationExecutor} from "./IAggregationExecutor.sol"; interface IMetaAggregationRouterV2 { struct SwapDescriptionV2 { IERC20 srcToken; IERC20 dstToken; address[] srcReceivers; // transfer src token to these addresses, default uint256[] srcAmounts; address[] feeReceivers; uint256[] feeAmounts; address dstReceiver; uint256 amount; uint256 minReturnAmount; uint256 flags; bytes permit; } /// @dev use for swapGeneric and swap to avoid stack too deep struct SwapExecutionParams { address callTarget; // call this address address approveTarget; // approve this address if _APPROVE_FUND set bytes targetData; SwapDescriptionV2 desc; bytes clientData; } struct SimpleSwapData { address[] firstPools; uint256[] firstSwapAmounts; bytes[] swapDatas; uint256 deadline; bytes positiveSlippageData; } function swap(SwapExecutionParams calldata execution) external payable returns (uint256, uint256); function swapSimpleMode( IAggregationExecutor caller, SwapDescriptionV2 memory desc, bytes calldata executorData, bytes calldata clientData ) external returns (uint256, uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IExecutorHelper} from "../interfaces/IExecutorHelper.sol"; import {IMetaAggregationRouterV2} from "../interfaces/IMetaAggregationRouterV2.sol"; import {ScalingDataLib} from "./ScalingDataLib.sol"; /* ---------------------------------------- .__ __. ______ .___________. _______ | \ | | / __ \ | || ____| | \| | | | | | `---| |----`| |__ | . ` | | | | | | | | __| | |\ | | `--' | | | | |____ |__| \__| \______/ |__| |_______| Please use InputScalingHelperL2 contract for scaling data on Arbitrum, Optimism, Base ---------------------------------------- */ library InputScalingHelper { uint256 private constant _PARTIAL_FILL = 0x01; uint256 private constant _REQUIRES_EXTRA_ETH = 0x02; uint256 private constant _SHOULD_CLAIM = 0x04; uint256 private constant _BURN_FROM_MSG_SENDER = 0x08; uint256 private constant _BURN_FROM_TX_ORIGIN = 0x10; uint256 private constant _SIMPLE_SWAP = 0x20; // fee data in case taking in dest token struct PositiveSlippageFeeData { uint256 partnerPSInfor; // [partnerReceiver (160 bit) + partnerPercent(96bits)] uint256 expectedReturnAmount; } struct Swap { bytes data; bytes32 selectorAndFlags; // [selector (32 bits) + flags (224 bits)]; selector is 4 most significant bytes; flags are stored in 4 least significant bytes. } struct SimpleSwapData { address[] firstPools; uint256[] firstSwapAmounts; bytes[] swapDatas; uint256 deadline; bytes positiveSlippageData; } struct SwapExecutorDescription { Swap[][] swapSequences; address tokenIn; address tokenOut; address to; uint256 deadline; bytes positiveSlippageData; } function _getScaledInputData(bytes calldata inputData, uint256 newAmount) internal pure returns (bytes memory) { bytes4 selector = bytes4(inputData[:4]); bytes calldata dataToDecode = inputData[4:]; if (selector == IMetaAggregationRouterV2.swap.selector) { IMetaAggregationRouterV2.SwapExecutionParams memory params = abi.decode( dataToDecode, (IMetaAggregationRouterV2.SwapExecutionParams) ); (params.desc, params.targetData) = _getScaledInputDataV2( params.desc, params.targetData, newAmount, _flagsChecked(params.desc.flags, _SIMPLE_SWAP) ); return abi.encodeWithSelector(selector, params); } else if (selector == IMetaAggregationRouterV2.swapSimpleMode.selector) { ( address callTarget, IMetaAggregationRouterV2.SwapDescriptionV2 memory desc, bytes memory targetData, bytes memory clientData ) = abi.decode(dataToDecode, (address, IMetaAggregationRouterV2.SwapDescriptionV2, bytes, bytes)); (desc, targetData) = _getScaledInputDataV2(desc, targetData, newAmount, true); return abi.encodeWithSelector(selector, callTarget, desc, targetData, clientData); } else { revert("InputScalingHelper: Invalid selector"); } } function _getScaledInputDataV2( IMetaAggregationRouterV2.SwapDescriptionV2 memory desc, bytes memory executorData, uint256 newAmount, bool isSimpleMode ) internal pure returns (IMetaAggregationRouterV2.SwapDescriptionV2 memory, bytes memory) { uint256 oldAmount = desc.amount; if (oldAmount == newAmount) { return (desc, executorData); } // simple mode swap if (isSimpleMode) { return ( _scaledSwapDescriptionV2(desc, oldAmount, newAmount), _scaledSimpleSwapData(executorData, oldAmount, newAmount) ); } //normal mode swap return ( _scaledSwapDescriptionV2(desc, oldAmount, newAmount), _scaledExecutorCallBytesData(executorData, oldAmount, newAmount) ); } /// @dev Scale the swap description function _scaledSwapDescriptionV2( IMetaAggregationRouterV2.SwapDescriptionV2 memory desc, uint256 oldAmount, uint256 newAmount ) internal pure returns (IMetaAggregationRouterV2.SwapDescriptionV2 memory) { desc.minReturnAmount = (desc.minReturnAmount * newAmount) / oldAmount; if (desc.minReturnAmount == 0) desc.minReturnAmount = 1; desc.amount = newAmount; uint256 nReceivers = desc.srcReceivers.length; for (uint256 i = 0; i < nReceivers; ) { desc.srcAmounts[i] = (desc.srcAmounts[i] * newAmount) / oldAmount; unchecked { ++i; } } return desc; } /// @dev Scale the executorData in case swapSimpleMode function _scaledSimpleSwapData( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { SimpleSwapData memory swapData = abi.decode(data, (SimpleSwapData)); uint256 nPools = swapData.firstPools.length; for (uint256 i = 0; i < nPools; ) { swapData.firstSwapAmounts[i] = (swapData.firstSwapAmounts[i] * newAmount) / oldAmount; unchecked { ++i; } } swapData.positiveSlippageData = _scaledPositiveSlippageFeeData( swapData.positiveSlippageData, oldAmount, newAmount ); return abi.encode(swapData); } /// @dev Scale the executorData in case normal swap function _scaledExecutorCallBytesData( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { SwapExecutorDescription memory executorDesc = abi.decode(data, (SwapExecutorDescription)); executorDesc.positiveSlippageData = _scaledPositiveSlippageFeeData( executorDesc.positiveSlippageData, oldAmount, newAmount ); uint256 nSequences = executorDesc.swapSequences.length; for (uint256 i = 0; i < nSequences; ) { Swap memory swap = executorDesc.swapSequences[i][0]; bytes4 functionSelector = bytes4(swap.selectorAndFlags); if (functionSelector == IExecutorHelper.executeUniswap.selector) { swap.data = ScalingDataLib.newUniSwap(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeStableSwap.selector) { swap.data = ScalingDataLib.newStableSwap(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeCurve.selector) { swap.data = ScalingDataLib.newCurveSwap(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeKSClassic.selector) { swap.data = ScalingDataLib.newKyberDMM(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeUniV3KSElastic.selector) { swap.data = ScalingDataLib.newUniV3ProMM(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeRfq.selector) { revert("InputScalingHelper: Can not scale RFQ swap"); } else if (functionSelector == IExecutorHelper.executeBalV2.selector) { swap.data = ScalingDataLib.newBalancerV2(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeWrappedstETH.selector) { swap.data = ScalingDataLib.newWrappedstETHSwap(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeStEth.selector) { swap.data = ScalingDataLib.newStETHSwap(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeDODO.selector) { swap.data = ScalingDataLib.newDODO(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeVelodrome.selector) { swap.data = ScalingDataLib.newVelodrome(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeGMX.selector) { swap.data = ScalingDataLib.newGMX(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeSynthetix.selector) { swap.data = ScalingDataLib.newSynthetix(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeHashflow.selector) { revert("InputScalingHelper: Can not scale Hasflow swap"); } else if (functionSelector == IExecutorHelper.executeCamelot.selector) { swap.data = ScalingDataLib.newCamelot(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeKyberLimitOrder.selector) { revert("InputScalingHelper: Can not scale KyberLO swap"); } else if (functionSelector == IExecutorHelper.executePSM.selector) { swap.data = ScalingDataLib.newPSM(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeFrax.selector) { swap.data = ScalingDataLib.newFrax(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executePlatypus.selector) { swap.data = ScalingDataLib.newPlatypus(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeMaverick.selector) { swap.data = ScalingDataLib.newMaverick(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeSyncSwap.selector) { swap.data = ScalingDataLib.newSyncSwap(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeAlgebraV1.selector) { swap.data = ScalingDataLib.newAlgebraV1(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeBalancerBatch.selector) { swap.data = ScalingDataLib.newBalancerBatch(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeWombat.selector) { swap.data = ScalingDataLib.newMantis(swap.data, oldAmount, newAmount); // @dev struct Mantis is used for both Wombat and Mantis because of same fields } else if (functionSelector == IExecutorHelper.executeMantis.selector) { swap.data = ScalingDataLib.newMantis(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeIziSwap.selector) { swap.data = ScalingDataLib.newIziSwap(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeWooFiV2.selector) { swap.data = ScalingDataLib.newMantis(swap.data, oldAmount, newAmount); // @dev using Mantis struct because WooFiV2 and Mantis have same fields } else if (functionSelector == IExecutorHelper.executeTraderJoeV2.selector) { swap.data = ScalingDataLib.newTraderJoeV2(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executePancakeStableSwap.selector) { swap.data = ScalingDataLib.newCurveSwap(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeLevelFiV2.selector) { swap.data = ScalingDataLib.newLevelFiV2(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeGMXGLP.selector) { swap.data = ScalingDataLib.newGMXGLP(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeVooi.selector) { swap.data = ScalingDataLib.newVooi(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeVelocoreV2.selector) { swap.data = ScalingDataLib.newVelocoreV2(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeMaticMigrate.selector) { swap.data = ScalingDataLib.newMaticMigrate(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeSmardex.selector) { swap.data = ScalingDataLib.newMantis(swap.data, oldAmount, newAmount); // @dev using Mantis struct because Smardex and Mantis have same fields } else if (functionSelector == IExecutorHelper.executeSolidlyV2.selector) { swap.data = ScalingDataLib.newMantis(swap.data, oldAmount, newAmount); // @dev using Mantis struct because Solidly V2 and Mantis have same fields } else if (functionSelector == IExecutorHelper.executeKokonut.selector) { swap.data = ScalingDataLib.newKokonut(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeBalancerV1.selector) { swap.data = ScalingDataLib.newBalancerV1(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeSwaapV2.selector) { revert("InputScalingHelper: Can not scale SwaapV2 swap"); } else if (functionSelector == IExecutorHelper.executeNomiswapStable.selector) { swap.data = ScalingDataLib.newMantis(swap.data, oldAmount, newAmount); // @dev using Mantis struct because NomiswapV2 and Mantis have same fields } else if (functionSelector == IExecutorHelper.executeArbswapStable.selector) { swap.data = ScalingDataLib.newArbswapStable(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeBancorV2.selector) { swap.data = ScalingDataLib.newBancorV2(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeBancorV3.selector) { swap.data = ScalingDataLib.newMantis(swap.data, oldAmount, newAmount); // @dev using Mantis struct because Bancor V3 and Mantis have same fields } else if (functionSelector == IExecutorHelper.executeAmbient.selector) { swap.data = ScalingDataLib.newAmbient(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeNative.selector) { revert("InputScalingHelper: Can not scale Native swap"); } else if (functionSelector == IExecutorHelper.executeLighterV2.selector) { swap.data = ScalingDataLib.newLighterV2(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeBebop.selector) { revert("InputScalingHelper: Can not scale Bebop swap"); } else if (functionSelector == IExecutorHelper.executeUniV1.selector) { swap.data = ScalingDataLib.newUniV1(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeEtherFieETH.selector) { swap.data = ScalingDataLib.newEtherFieETH(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeEtherFiWeETH.selector) { swap.data = ScalingDataLib.newEtherFiWeETH(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeKelp.selector) { swap.data = ScalingDataLib.newKelp(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeEthenaSusde.selector) { swap.data = ScalingDataLib.newEthenaSusde(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeRocketPool.selector) { swap.data = ScalingDataLib.newRocketPool(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeMakersDAI.selector) { swap.data = ScalingDataLib.newMakersDAI(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeRenzo.selector) { swap.data = ScalingDataLib.newRenzo(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeWBETH.selector) { swap.data = ScalingDataLib.newEtherFieETH(swap.data, oldAmount, newAmount); // same etherfi eETH } else if (functionSelector == IExecutorHelper.executeMantleETH.selector) { swap.data = ScalingDataLib.newEtherFieETH(swap.data, oldAmount, newAmount); // same etherfi eETH } else if (functionSelector == IExecutorHelper.executeFrxETH.selector) { swap.data = ScalingDataLib.newFrxETH(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeSfrxETH.selector) { swap.data = ScalingDataLib.newSfrxETH(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeSfrxETHConvertor.selector) { swap.data = ScalingDataLib.newSfrxETHConvertor(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeSwellETH.selector) { swap.data = ScalingDataLib.newEtherFieETH(swap.data, oldAmount, newAmount); // same etherfi eETH } else if (functionSelector == IExecutorHelper.executeRswETH.selector) { swap.data = ScalingDataLib.newEtherFieETH(swap.data, oldAmount, newAmount); // same etherfi eETH } else if (functionSelector == IExecutorHelper.executeStaderETHx.selector) { swap.data = ScalingDataLib.newEthenaSusde(swap.data, oldAmount, newAmount); // same ethena susde } else if (functionSelector == IExecutorHelper.executeOriginETH.selector) { swap.data = ScalingDataLib.newOriginETH(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executePrimeETH.selector) { swap.data = ScalingDataLib.newOriginETH(swap.data, oldAmount, newAmount); // same originETH } else if (functionSelector == IExecutorHelper.executeMantleUsd.selector) { swap.data = ScalingDataLib.newMantleUsd(swap.data, oldAmount, newAmount); } else if (functionSelector == IExecutorHelper.executeBedrockUniETH.selector) { swap.data = ScalingDataLib.newEtherFieETH(swap.data, oldAmount, newAmount); // same etherfi eETH } else if (functionSelector == IExecutorHelper.executeMaiPSM.selector) { swap.data = ScalingDataLib.newFrxETH(swap.data, oldAmount, newAmount); // same frxeth } else { revert("AggregationExecutor: Dex type not supported"); } unchecked { ++i; } } return abi.encode(executorDesc); } function _scaledPositiveSlippageFeeData( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory newData) { if (data.length > 32) { PositiveSlippageFeeData memory psData = abi.decode(data, (PositiveSlippageFeeData)); uint256 left = uint256(psData.expectedReturnAmount >> 128); uint256 right = (uint256(uint128(psData.expectedReturnAmount)) * newAmount) / oldAmount; require(right <= type(uint128).max, "Exceeded type range"); psData.expectedReturnAmount = right | (left << 128); data = abi.encode(psData); } else if (data.length == 32) { uint256 expectedReturnAmount = abi.decode(data, (uint256)); uint256 left = uint256(expectedReturnAmount >> 128); uint256 right = (uint256(uint128(expectedReturnAmount)) * newAmount) / oldAmount; require(right <= type(uint128).max, "Exceeded type range"); expectedReturnAmount = right | (left << 128); data = abi.encode(expectedReturnAmount); } return data; } function _flagsChecked(uint256 number, uint256 flag) internal pure returns (bool) { return number & flag != 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IExecutorHelper} from "../interfaces/IExecutorHelper.sol"; library ScalingDataLib { function newUniSwap(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.UniSwap memory uniSwap = abi.decode(data, (IExecutorHelper.UniSwap)); uniSwap.collectAmount = (uniSwap.collectAmount * newAmount) / oldAmount; return abi.encode(uniSwap); } function newStableSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.StableSwap memory stableSwap = abi.decode(data, (IExecutorHelper.StableSwap)); stableSwap.dx = (stableSwap.dx * newAmount) / oldAmount; return abi.encode(stableSwap); } function newCurveSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.CurveSwap memory curveSwap = abi.decode(data, (IExecutorHelper.CurveSwap)); curveSwap.dx = (curveSwap.dx * newAmount) / oldAmount; return abi.encode(curveSwap); } function newKyberDMM(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.UniSwap memory kyberDMMSwap = abi.decode(data, (IExecutorHelper.UniSwap)); kyberDMMSwap.collectAmount = (kyberDMMSwap.collectAmount * newAmount) / oldAmount; return abi.encode(kyberDMMSwap); } function newUniV3ProMM( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.UniswapV3KSElastic memory uniSwapV3ProMM = abi.decode( data, (IExecutorHelper.UniswapV3KSElastic) ); uniSwapV3ProMM.swapAmount = (uniSwapV3ProMM.swapAmount * newAmount) / oldAmount; return abi.encode(uniSwapV3ProMM); } function newBalancerV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.BalancerV2 memory balancerV2 = abi.decode(data, (IExecutorHelper.BalancerV2)); balancerV2.amount = (balancerV2.amount * newAmount) / oldAmount; return abi.encode(balancerV2); } function newDODO(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.DODO memory dodo = abi.decode(data, (IExecutorHelper.DODO)); dodo.amount = (dodo.amount * newAmount) / oldAmount; return abi.encode(dodo); } function newVelodrome( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.UniSwap memory velodrome = abi.decode(data, (IExecutorHelper.UniSwap)); velodrome.collectAmount = (velodrome.collectAmount * newAmount) / oldAmount; return abi.encode(velodrome); } function newGMX(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.GMX memory gmx = abi.decode(data, (IExecutorHelper.GMX)); gmx.amount = (gmx.amount * newAmount) / oldAmount; return abi.encode(gmx); } function newSynthetix( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.Synthetix memory synthetix = abi.decode(data, (IExecutorHelper.Synthetix)); synthetix.sourceAmount = (synthetix.sourceAmount * newAmount) / oldAmount; return abi.encode(synthetix); } function newCamelot(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.UniSwap memory camelot = abi.decode(data, (IExecutorHelper.UniSwap)); camelot.collectAmount = (camelot.collectAmount * newAmount) / oldAmount; return abi.encode(camelot); } function newPlatypus(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.Platypus memory platypus = abi.decode(data, (IExecutorHelper.Platypus)); platypus.collectAmount = (platypus.collectAmount * newAmount) / oldAmount; return abi.encode(platypus); } function newWrappedstETHSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.WSTETH memory wstEthData = abi.decode(data, (IExecutorHelper.WSTETH)); wstEthData.amount = (wstEthData.amount * newAmount) / oldAmount; return abi.encode(wstEthData); } function newPSM(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.PSM memory psm = abi.decode(data, (IExecutorHelper.PSM)); psm.amountIn = (psm.amountIn * newAmount) / oldAmount; return abi.encode(psm); } function newFrax(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.UniSwap memory frax = abi.decode(data, (IExecutorHelper.UniSwap)); frax.collectAmount = (frax.collectAmount * newAmount) / oldAmount; return abi.encode(frax); } function newStETHSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 amount = abi.decode(data, (uint256)); amount = (amount * newAmount) / oldAmount; return abi.encode(amount); } function newMaverick(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.Maverick memory maverick = abi.decode(data, (IExecutorHelper.Maverick)); maverick.swapAmount = (maverick.swapAmount * newAmount) / oldAmount; return abi.encode(maverick); } function newSyncSwap(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.SyncSwap memory syncSwap = abi.decode(data, (IExecutorHelper.SyncSwap)); syncSwap.collectAmount = (syncSwap.collectAmount * newAmount) / oldAmount; return abi.encode(syncSwap); } function newAlgebraV1( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.AlgebraV1 memory algebraV1Swap = abi.decode(data, (IExecutorHelper.AlgebraV1)); algebraV1Swap.swapAmount = (algebraV1Swap.swapAmount * newAmount) / oldAmount; return abi.encode(algebraV1Swap); } function newBalancerBatch( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.BalancerBatch memory balancerBatch = abi.decode(data, (IExecutorHelper.BalancerBatch)); balancerBatch.amountIn = (balancerBatch.amountIn * newAmount) / oldAmount; return abi.encode(balancerBatch); } function newMantis(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.Mantis memory mantis = abi.decode(data, (IExecutorHelper.Mantis)); mantis.amount = (mantis.amount * newAmount) / oldAmount; return abi.encode(mantis); } function newIziSwap(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.IziSwap memory iZi = abi.decode(data, (IExecutorHelper.IziSwap)); iZi.swapAmount = (iZi.swapAmount * newAmount) / oldAmount; return abi.encode(iZi); } function newTraderJoeV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.TraderJoeV2 memory traderJoe = abi.decode(data, (IExecutorHelper.TraderJoeV2)); // traderJoe.collectAmount; // most significant 1 bit is to determine whether pool is v2.1, else v2.0 traderJoe.collectAmount = (traderJoe.collectAmount & (1 << 255)) | ((uint256((traderJoe.collectAmount << 1) >> 1) * newAmount) / oldAmount); return abi.encode(traderJoe); } function newLevelFiV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.LevelFiV2 memory levelFiV2 = abi.decode(data, (IExecutorHelper.LevelFiV2)); levelFiV2.amountIn = (levelFiV2.amountIn * newAmount) / oldAmount; return abi.encode(levelFiV2); } function newGMXGLP(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.GMXGLP memory swapData = abi.decode(data, (IExecutorHelper.GMXGLP)); swapData.swapAmount = (swapData.swapAmount * newAmount) / oldAmount; return abi.encode(swapData); } function newVooi(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.Vooi memory vooi = abi.decode(data, (IExecutorHelper.Vooi)); vooi.fromAmount = (vooi.fromAmount * newAmount) / oldAmount; return abi.encode(vooi); } function newVelocoreV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.VelocoreV2 memory velocorev2 = abi.decode(data, (IExecutorHelper.VelocoreV2)); velocorev2.amount = (velocorev2.amount * newAmount) / oldAmount; return abi.encode(velocorev2); } function newMaticMigrate( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.MaticMigrate memory maticMigrate = abi.decode(data, (IExecutorHelper.MaticMigrate)); maticMigrate.amount = (maticMigrate.amount * newAmount) / oldAmount; return abi.encode(maticMigrate); } function newKokonut(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.Kokonut memory kokonut = abi.decode(data, (IExecutorHelper.Kokonut)); kokonut.dx = (kokonut.dx * newAmount) / oldAmount; return abi.encode(kokonut); } function newBalancerV1( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.BalancerV1 memory balancerV1 = abi.decode(data, (IExecutorHelper.BalancerV1)); balancerV1.amount = (balancerV1.amount * newAmount) / oldAmount; return abi.encode(balancerV1); } function newArbswapStable( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.ArbswapStable memory arbswapStable = abi.decode(data, (IExecutorHelper.ArbswapStable)); arbswapStable.dx = (arbswapStable.dx * newAmount) / oldAmount; return abi.encode(arbswapStable); } function newBancorV2(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.BancorV2 memory bancorV2 = abi.decode(data, (IExecutorHelper.BancorV2)); bancorV2.amount = (bancorV2.amount * newAmount) / oldAmount; return abi.encode(bancorV2); } function newAmbient(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.Ambient memory ambient = abi.decode(data, (IExecutorHelper.Ambient)); ambient.qty = uint128((uint256(ambient.qty) * newAmount) / oldAmount); return abi.encode(ambient); } function newLighterV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.LighterV2 memory structData = abi.decode(data, (IExecutorHelper.LighterV2)); structData.amount = uint128((uint256(structData.amount) * newAmount) / oldAmount); return abi.encode(structData); } function newUniV1(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.UniV1 memory structData = abi.decode(data, (IExecutorHelper.UniV1)); structData.amount = uint128((uint256(structData.amount) * newAmount) / oldAmount); return abi.encode(structData); } function newEtherFieETH( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 depositAmount = abi.decode(data, (uint256)); depositAmount = uint128((depositAmount * newAmount) / oldAmount); return abi.encode(depositAmount); } function newEtherFiWeETH( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.EtherFiWeETH memory structData = abi.decode(data, (IExecutorHelper.EtherFiWeETH)); structData.amount = uint128((uint256(structData.amount) * newAmount) / oldAmount); return abi.encode(structData); } function newKelp(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.Kelp memory structData = abi.decode(data, (IExecutorHelper.Kelp)); structData.amount = uint128((uint256(structData.amount) * newAmount) / oldAmount); return abi.encode(structData); } function newEthenaSusde( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.EthenaSusde memory structData = abi.decode(data, (IExecutorHelper.EthenaSusde)); structData.amount = uint128((uint256(structData.amount) * newAmount) / oldAmount); return abi.encode(structData); } function newRocketPool( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.RocketPool memory structData = abi.decode(data, (IExecutorHelper.RocketPool)); uint128 _amount = uint128((uint256(uint128(structData.isDepositAndAmount)) * newAmount) / oldAmount); bool _isDeposit = (structData.isDepositAndAmount >> 255) == 1; // reset and create new variable for isDeposit and amount structData.isDepositAndAmount = 0; structData.isDepositAndAmount |= uint256(uint128(_amount)); structData.isDepositAndAmount |= uint256(_isDeposit ? 1 : 0) << 255; return abi.encode(structData); } function newMakersDAI( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.MakersDAI memory structData = abi.decode(data, (IExecutorHelper.MakersDAI)); uint128 _amount = uint128((uint256(uint128(structData.isRedeemAndAmount)) * newAmount) / oldAmount); bool _isRedeem = (structData.isRedeemAndAmount >> 255) == 1; // reset and create new variable for isRedeem and amount structData.isRedeemAndAmount = 0; structData.isRedeemAndAmount |= uint256(uint128(_amount)); structData.isRedeemAndAmount |= uint256(_isRedeem ? 1 : 0) << 255; return abi.encode(structData); } function newRenzo(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.Renzo memory structData = abi.decode(data, (IExecutorHelper.Renzo)); structData.amount = uint128((uint256(structData.amount) * newAmount) / oldAmount); return abi.encode(structData); } function newFrxETH(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.FrxETH memory structData = abi.decode(data, (IExecutorHelper.FrxETH)); structData.amount = uint128((uint256(structData.amount) * newAmount) / oldAmount); return abi.encode(structData); } function newSfrxETH(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { IExecutorHelper.SfrxETH memory structData = abi.decode(data, (IExecutorHelper.SfrxETH)); structData.amount = uint128((uint256(structData.amount) * newAmount) / oldAmount); return abi.encode(structData); } function newSfrxETHConvertor( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.SfrxETHConvertor memory structData = abi.decode(data, (IExecutorHelper.SfrxETHConvertor)); uint128 _amount = uint128((uint256(uint128(structData.isDepositAndAmount)) * newAmount) / oldAmount); bool _isDeposit = (structData.isDepositAndAmount >> 255) == 1; // reset and create new variable for isDeposit and amount structData.isDepositAndAmount = 0; structData.isDepositAndAmount |= uint256(uint128(_amount)); structData.isDepositAndAmount |= uint256(_isDeposit ? 1 : 0) << 255; return abi.encode(structData); } function newOriginETH( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelper.OriginETH memory structData = abi.decode(data, (IExecutorHelper.OriginETH)); structData.amount = uint128((uint256(structData.amount) * newAmount) / oldAmount); return abi.encode(structData); } function newMantleUsd( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 isWrapAndAmount = abi.decode(data, (uint256)); uint128 _amount = uint128((uint256(uint128(isWrapAndAmount)) * newAmount) / oldAmount); bool _isWrap = (isWrapAndAmount >> 255) == 1; // reset and create new variable for isWrap and amount isWrapAndAmount = 0; isWrapAndAmount |= uint256(uint128(_amount)); isWrapAndAmount |= uint256(_isWrap ? 1 : 0) << 255; return abi.encode(isWrapAndAmount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library BytesHelper { function write16Bytes(bytes memory original, uint256 index, bytes16 value) internal pure returns (bytes memory) { assembly { let offset := add(original, add(index, 32)) let val := mload(offset) // read 32 bytes [index : index + 32] val := and(val, not(0xffffffffffffffffffffffffffffffff00000000000000000000000000000000)) // clear [index : index + 16] val := or(val, value) // set 16 bytes to val above mstore(offset, val) // store to [index : index + 32] } return original; } function write16Bytes(bytes memory original, uint256 index, uint128 value) internal pure returns (bytes memory) { return write16Bytes(original, index, bytes16(value)); } function write16Bytes( bytes memory original, uint256 index, uint256 value, string memory errorMsg ) internal pure returns (bytes memory) { require(value <= type(uint128).max, string(abi.encodePacked(errorMsg, "/Exceed compressed type range"))); return write16Bytes(original, index, uint128(value)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library CalldataReader { /// @notice read the bytes value of data from a starting position and length /// @param data bytes array of data /// @param startByte starting position to read /// @param length length from starting position /// @return retVal value of the bytes /// @return (the next position to read from) function _calldataVal( bytes memory data, uint256 startByte, uint256 length ) internal pure returns (bytes memory retVal, uint256) { require(length + startByte <= data.length, "calldataVal trying to read beyond data size"); uint256 loops = (length + 31) / 32; assembly { let m := mload(0x40) mstore(m, length) for { let i := 0 } lt(i, loops) { i := add(1, i) } { mstore(add(m, mul(32, add(1, i))), mload(add(data, add(mul(32, add(1, i)), startByte)))) } mstore(0x40, add(m, add(32, length))) retVal := m } return (retVal, length + startByte); } function _readBool(bytes memory data, uint256 startByte) internal pure returns (bool, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 1); return (bytes1(ret) > 0, startByte); } function _readUint8(bytes memory data, uint256 startByte) internal pure returns (uint8, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 1); return (uint8(bytes1(ret)), startByte); } function _readUint24(bytes memory data, uint256 startByte) internal pure returns (uint24, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 3); return (uint24(bytes3(ret)), startByte); } function _readUint32(bytes memory data, uint256 startByte) internal pure returns (uint32, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 4); return (uint32(bytes4(ret)), startByte); } function _readUint128(bytes memory data, uint256 startByte) internal pure returns (uint128, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 16); return (uint128(bytes16(ret)), startByte); } function _readUint160(bytes memory data, uint256 startByte) internal pure returns (uint160, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 20); return (uint160(bytes20(ret)), startByte); } /// @dev only when sure that the value of uint256 never exceed uint128 function _readUint128AsUint256(bytes memory data, uint256 startByte) internal pure returns (uint256, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 16); return (uint256(uint128(bytes16(ret))), startByte); } function _readAddress(bytes memory data, uint256 startByte) internal pure returns (address, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 20); return (address(bytes20(ret)), startByte); } function _readBytes1(bytes memory data, uint256 startByte) internal pure returns (bytes1, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 1); return (bytes1(ret), startByte); } function _readBytes4(bytes memory data, uint256 startByte) internal pure returns (bytes4, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 4); return (bytes4(ret), startByte); } function _readBytes32(bytes memory data, uint256 startByte) internal pure returns (bytes32, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 32); return (bytes32(ret), startByte); } /// @dev length of bytes is currently limited to uint32 function _readBytes(bytes memory data, uint256 startByte) internal pure returns (bytes memory b, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 4); uint256 length = uint256(uint32(bytes4(ret))); (b, startByte) = _calldataVal(data, startByte, length); return (b, startByte); } /// @dev length of bytes array is currently limited to uint8 function _readBytesArray( bytes memory data, uint256 startByte ) internal pure returns (bytes[] memory bytesArray, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 1); uint256 length = uint256(uint8(bytes1(ret))); bytesArray = new bytes[](length); for (uint8 i = 0; i < length; ++i) { (bytesArray[i], startByte) = _readBytes(data, startByte); } return (bytesArray, startByte); } /// @dev length of address array is currently limited to uint8 to save bytes function _readAddressArray( bytes memory data, uint256 startByte ) internal pure returns (address[] memory addrs, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 1); uint256 length = uint256(uint8(bytes1(ret))); addrs = new address[](length); for (uint8 i = 0; i < length; ++i) { (addrs[i], startByte) = _readAddress(data, startByte); } return (addrs, startByte); } /// @dev length of uint array is currently limited to uint8 to save bytes /// @dev same as _readUint128AsUint256, only use when sure that value never exceed uint128 function _readUint128ArrayAsUint256Array( bytes memory data, uint256 startByte ) internal pure returns (uint256[] memory, uint256) { bytes memory ret; (ret, startByte) = _calldataVal(data, startByte, 1); uint256 length = uint256(uint8(bytes1(ret))); uint256[] memory us = new uint256[](length); for (uint8 i = 0; i < length; ++i) { (us[i], startByte) = _readUint128AsUint256(data, startByte); } return (us, startByte); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IMetaAggregationRouterV2} from "../interfaces/IMetaAggregationRouterV2.sol"; import {IAggregationExecutorOptimistic as IExecutorHelperL2} from "../interfaces/IAggregationExecutorOptimistic.sol"; import {IExecutorHelper as IExecutorHelperL1} from "../interfaces/IExecutorHelper.sol"; library CalldataWriter { function writeSimpleSwapData( IMetaAggregationRouterV2.SimpleSwapData memory simpleSwapData ) internal pure returns (bytes memory shortData) { shortData = bytes.concat(shortData, _writeAddressArray(simpleSwapData.firstPools)); shortData = bytes.concat(shortData, _writeUint256ArrayAsUint128Array(simpleSwapData.firstSwapAmounts)); shortData = bytes.concat(shortData, _writeBytesArray(simpleSwapData.swapDatas)); shortData = bytes.concat(shortData, bytes16(uint128(simpleSwapData.deadline))); shortData = bytes.concat(shortData, _writeBytes(simpleSwapData.positiveSlippageData)); } /* ************************ AggregationExecutor ************************ */ function writeSwapExecutorDescription( IExecutorHelperL2.SwapExecutorDescription memory desc ) internal pure returns (bytes memory shortData) { // write Swap array uint8 lX = uint8(desc.swapSequences.length); shortData = bytes.concat(shortData, bytes1(lX)); for (uint8 i = 0; i < lX; ++i) { uint8 lY = uint8(desc.swapSequences[i].length); shortData = bytes.concat(shortData, bytes1(lY)); for (uint8 j = 0; j < lY; ++j) { shortData = bytes.concat(shortData, _writeSwap(desc.swapSequences[i][j])); } } // basic members shortData = bytes.concat(shortData, bytes20(desc.tokenIn)); shortData = bytes.concat(shortData, bytes20(desc.tokenOut)); shortData = bytes.concat(shortData, bytes20(desc.to)); shortData = bytes.concat(shortData, bytes16(uint128(desc.deadline))); shortData = bytes.concat(shortData, _writeBytes(desc.positiveSlippageData)); } function writeSimpleModeSwapDatas( bytes[] memory swapDatas, address tokenIn ) internal pure returns (bytes[] memory shortData) { uint8 len = uint8(swapDatas.length); for (uint8 i = 0; i < len; ++i) { swapDatas[i] = _writeSwapSingleSequence(swapDatas[i], tokenIn); } return (swapDatas); } function _writeSwapSingleSequence( bytes memory data, address tokenIn ) internal pure returns (bytes memory shortData) { IExecutorHelperL2.Swap[] memory swaps = abi.decode(data, (IExecutorHelperL2.Swap[])); uint8 len = uint8(swaps.length); shortData = bytes.concat(shortData, bytes1(len)); for (uint8 i = 0; i < len; ++i) { shortData = bytes.concat(shortData, _writeSwap(swaps[i])); } shortData = bytes.concat(shortData, bytes20(tokenIn)); } function _writeAddressArray(address[] memory addrs) internal pure returns (bytes memory data) { uint8 length = uint8(addrs.length); data = bytes.concat(data, bytes1(length)); for (uint8 i = 0; i < length; ++i) { data = bytes.concat(data, bytes20(addrs[i])); } return data; } function _writeUint256ArrayAsUint128Array(uint256[] memory us) internal pure returns (bytes memory data) { uint8 length = uint8(us.length); data = bytes.concat(data, bytes1(length)); for (uint8 i = 0; i < length; ++i) { data = bytes.concat(data, bytes16(uint128(us[i]))); } return data; } function _writeBytes(bytes memory b) internal pure returns (bytes memory data) { uint32 length = uint32(b.length); data = bytes.concat(data, bytes4(length)); data = bytes.concat(data, b); return data; } function _writeBytesArray(bytes[] memory bytesArray) internal pure returns (bytes memory data) { uint8 x = uint8(bytesArray.length); data = bytes.concat(data, bytes1(x)); for (uint8 i; i < x; ++i) { uint32 length = uint32(bytesArray[i].length); data = bytes.concat(data, bytes4(length)); data = bytes.concat(data, bytesArray[i]); } return data; } function _writeBytes32Array(bytes32[] memory bytesArray) internal pure returns (bytes memory data) { uint8 x = uint8(bytesArray.length); data = bytes.concat(data, bytes1(x)); for (uint8 i; i < x; ++i) { data = bytes.concat(data, bytesArray[i]); } return data; } function _writeSwap(IExecutorHelperL2.Swap memory swap) internal pure returns (bytes memory shortData) { shortData = bytes.concat(shortData, _writeBytes(swap.data)); shortData = bytes.concat(shortData, bytes1(uint8(uint32(swap.functionSelector)))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./CalldataReader.sol"; library Common { using CalldataReader for bytes; function _readPool(bytes memory data, uint256 startByte) internal pure returns (address, uint256) { uint24 poolId; address poolAddress; (poolId, startByte) = data._readUint24(startByte); if (poolId == 0) { (poolAddress, startByte) = data._readAddress(startByte); } return (poolAddress, startByte); } function _readRecipient(bytes memory data, uint256 startByte) internal pure returns (address, uint256) { uint8 recipientFlag; address recipient; (recipientFlag, startByte) = data._readUint8(startByte); if (recipientFlag != 2 && recipientFlag != 1) { (recipient, startByte) = data._readAddress(startByte); } return (recipient, startByte); } function _readBytes32Array( bytes memory data, uint256 startByte ) internal pure returns (bytes32[] memory bytesArray, uint256) { bytes memory ret; (ret, startByte) = data._calldataVal(startByte, 1); uint256 length = uint256(uint8(bytes1(ret))); bytesArray = new bytes32[](length); for (uint8 i = 0; i < length; ++i) { (bytesArray[i], startByte) = data._readBytes32(startByte); } return (bytesArray, startByte); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./CalldataReader.sol"; import "../interfaces/IExecutorHelperL2.sol"; import {BytesHelper} from "./BytesHelper.sol"; import {Common} from "./Common.sol"; /// @title DexScaler /// @notice Contain functions to scale DEX structs /// @dev For this repo's scope, we only care about swap amounts, so we just need to decode until we get swap amounts library DexScaler { using BytesHelper for bytes; using CalldataReader for bytes; using Common for bytes; function scaleUniSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; // decode (, startByte) = data._readPool(startByte); (, startByte) = data._readRecipient(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleUniSwap"); } function scaleStableSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); (, startByte) = data._readUint8(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleStableSwap"); } function scaleCurveSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; bool canGetIndex; (canGetIndex, startByte) = data._readBool(0); (, startByte) = data._readPool(startByte); if (!canGetIndex) { (, startByte) = data._readAddress(startByte); (, startByte) = data._readUint8(startByte); } (, startByte) = data._readUint8(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleCurveSwap"); } function scaleUniswapV3KSElastic( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readRecipient(startByte); (, startByte) = data._readPool(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes( startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleUniswapV3KSElastic" ); } function scaleBalancerV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); (, startByte) = data._readBytes32(startByte); (, startByte) = data._readUint8(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleBalancerV2"); } function scaleDODO(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readRecipient(startByte); (, startByte) = data._readPool(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleDODO"); } function scaleGMX(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { uint256 startByte; // decode (, startByte) = data._readPool(startByte); (, startByte) = data._readAddress(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleGMX"); } function scaleSynthetix( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; // decode (, startByte) = data._readPool(startByte); (, startByte) = data._readAddress(startByte); (, startByte) = data._readBytes32(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleSynthetix"); } function scaleWrappedstETH( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; // decode (, startByte) = data._readPool(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes( startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleWrappedstETH" ); } function scaleStETH(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { (uint256 swapAmount, ) = data._readUint128AsUint256(0); return data.write16Bytes(0, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleStETH"); } function scalePlatypus( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; // decode (, startByte) = data._readPool(startByte); (, startByte) = data._readAddress(startByte); (, startByte) = data._readRecipient(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scalePlatypus"); } function scalePSM(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { uint256 startByte; // decode (, startByte) = data._readPool(startByte); (, startByte) = data._readAddress(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scalePSM"); } function scaleMaverick( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; // decode (, startByte) = data._readPool(startByte); (, startByte) = data._readAddress(startByte); (, startByte) = data._readRecipient(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleMaverick"); } function scaleSyncSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; // decode (, startByte) = data._readBytes(startByte); (, startByte) = data._readPool(startByte); (, startByte) = data._readAddress(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleSyncSwap"); } function scaleAlgebraV1( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readRecipient(startByte); (, startByte) = data._readPool(startByte); (, startByte) = data._readAddress(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleAlgebraV1"); } function scaleBalancerBatch( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; // decode (, startByte) = data._readPool(startByte); (, startByte) = data._readBytes32Array(startByte); (, startByte) = data._readAddressArray(startByte); (, startByte) = data._readBytesArray(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); return data.write16Bytes( startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleBalancerBatch" ); } function scaleMantis(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (, startByte) = data._readAddress(startByte); // tokenOut (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleMantis"); } function scaleIziSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (, startByte) = data._readAddress(startByte); // tokenOut // recipient (, startByte) = data._readRecipient(startByte); (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleIziSwap"); } function scaleTraderJoeV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; // recipient (, startByte) = data._readRecipient(startByte); (, startByte) = data._readPool(startByte); // pool (, startByte) = data._readAddress(startByte); // tokenOut (, startByte) = data._readBool(startByte); // isV2 (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleTraderJoeV2"); } function scaleLevelFiV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (, startByte) = data._readAddress(startByte); // tokenOut (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleLevelFiV2"); } function scaleGMXGLP(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (, startByte) = data._readAddress(startByte); // yearnVault uint8 directionFlag; (directionFlag, startByte) = data._readUint8(startByte); if (directionFlag == 1) (, startByte) = data._readAddress(startByte); // tokenOut (uint256 swapAmount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (swapAmount * newAmount) / oldAmount, "scaleGMXGLP"); } function scaleVooi(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (, startByte) = data._readUint8(startByte); // toId (uint256 fromAmount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (fromAmount * newAmount) / oldAmount, "scaleVooi"); } function scaleVelocoreV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (uint256 amount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (amount * newAmount) / oldAmount, "scaleVelocoreV2"); } function scaleKokonut( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (uint256 amount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (amount * newAmount) / oldAmount, "scaleKokonut"); } function scaleBalancerV1( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (uint256 amount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (amount * newAmount) / oldAmount, "scaleBalancerV1"); } function scaleArbswapStable( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (uint256 dx, ) = data._readUint128AsUint256(startByte); // dx return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (dx * newAmount) / oldAmount, "scaleArbswapStable"); } function scaleBancorV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (, startByte) = data._readAddressArray(startByte); // swapPath (uint256 amount, ) = data._readUint128AsUint256(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (amount * newAmount) / oldAmount, "scaleBancorV2"); } function scaleAmbient( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // pool (uint128 qty, ) = data._readUint128(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (qty * newAmount) / oldAmount, "scaleAmbient"); } function scaleLighterV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { uint256 startByte; (, startByte) = data._readPool(startByte); // orderbook (uint128 amount, ) = data._readUint128(startByte); // amount return data.write16Bytes(startByte, oldAmount == 0 ? 0 : (amount * newAmount) / oldAmount, "scaleLighterV2"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./CalldataReader.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../interfaces/IAggregationExecutorOptimistic.sol"; library ExecutorReader { function readSwapExecutorDescription(bytes memory data) internal pure returns (bytes memory) { uint256 startByte = 0; IAggregationExecutorOptimistic.SwapExecutorDescription memory desc; // Swap array bytes memory ret; (ret, startByte) = CalldataReader._calldataVal(data, startByte, 1); uint256 lX = uint256(uint8(bytes1(ret))); desc.swapSequences = new IAggregationExecutorOptimistic.Swap[][](lX); for (uint8 i = 0; i < lX; ++i) { (ret, startByte) = CalldataReader._calldataVal(data, startByte, 1); uint256 lY = uint256(uint8(bytes1(ret))); desc.swapSequences[i] = new IAggregationExecutorOptimistic.Swap[](lY); for (uint8 j = 0; j < lY; ++j) { (desc.swapSequences[i][j], startByte) = _readSwap(data, startByte); } } // basic members (desc.tokenIn, startByte) = CalldataReader._readAddress(data, startByte); (desc.tokenOut, startByte) = CalldataReader._readAddress(data, startByte); (desc.to, startByte) = CalldataReader._readAddress(data, startByte); (desc.deadline, startByte) = CalldataReader._readUint128AsUint256(data, startByte); (desc.positiveSlippageData, startByte) = CalldataReader._readBytes(data, startByte); return abi.encode(desc); } function readSwapSingleSequence( bytes memory data ) internal pure returns (IAggregationExecutorOptimistic.Swap[] memory swaps, address tokenIn) { uint256 startByte = 0; bytes memory ret; (ret, startByte) = CalldataReader._calldataVal(data, startByte, 1); uint256 len = uint256(uint8(bytes1(ret))); swaps = new IAggregationExecutorOptimistic.Swap[](len); for (uint8 i = 0; i < len; ++i) { (swaps[i], startByte) = _readSwap(data, startByte); } (tokenIn, startByte) = CalldataReader._readAddress(data, startByte); } function _readSwap( bytes memory data, uint256 startByte ) internal pure returns (IAggregationExecutorOptimistic.Swap memory swap, uint256) { (swap.data, startByte) = CalldataReader._readBytes(data, startByte); bytes1 t; (t, startByte) = CalldataReader._readBytes1(data, startByte); swap.functionSelector = bytes4(uint32(uint8(t))); return (swap, startByte); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IAggregationExecutorOptimistic as IExecutorHelperL2} from "../interfaces/IAggregationExecutorOptimistic.sol"; import {IExecutorHelper as IExecutorHelperL1} from "../interfaces/IExecutorHelper.sol"; import {IMetaAggregationRouterV2} from "../interfaces/IMetaAggregationRouterV2.sol"; import {ScalingDataL2Lib} from "./ScalingDataL2Lib.sol"; import {ExecutorReader} from "./ExecutorReader.sol"; import {CalldataWriter} from "./CalldataWriter.sol"; library InputScalingHelperL2 { using ExecutorReader for bytes; using ScalingDataL2Lib for bytes; uint256 private constant _PARTIAL_FILL = 0x01; uint256 private constant _REQUIRES_EXTRA_ETH = 0x02; uint256 private constant _SHOULD_CLAIM = 0x04; uint256 private constant _BURN_FROM_MSG_SENDER = 0x08; uint256 private constant _BURN_FROM_TX_ORIGIN = 0x10; uint256 private constant _SIMPLE_SWAP = 0x20; struct PositiveSlippageFeeData { uint256 partnerPSInfor; uint256 expectedReturnAmount; } enum DexIndex { UNI, KyberDMM, Velodrome, Fraxswap, Camelot, KyberLO, RFQ, Hashflow, StableSwap, Curve, UniswapV3KSElastic, BalancerV2, DODO, GMX, Synthetix, wstETH, stETH, Platypus, PSM, Maverick, SyncSwap, AlgebraV1, BalancerBatch, Mantis, Wombat, WooFiV2, iZiSwap, TraderJoeV2, KyberDSLO, LevelFiV2, GMXGLP, PancakeStableSwap, Vooi, VelocoreV2, Smardex, SolidlyV2, Kokonut, BalancerV1, SwaapV2, NomiswapStable, ArbswapStable, BancorV3, BancorV2, Ambient, Native, LighterV2, Bebop } function _getScaledInputData(bytes calldata inputData, uint256 newAmount) internal pure returns (bytes memory) { bytes4 selector = bytes4(inputData[:4]); bytes calldata dataToDecode = inputData[4:]; if (selector == IMetaAggregationRouterV2.swap.selector) { IMetaAggregationRouterV2.SwapExecutionParams memory params = abi.decode( dataToDecode, (IMetaAggregationRouterV2.SwapExecutionParams) ); (params.desc, params.targetData) = _getScaledInputDataV2( params.desc, params.targetData, newAmount, _flagsChecked(params.desc.flags, _SIMPLE_SWAP) ); return abi.encodeWithSelector(selector, params); } else if (selector == IMetaAggregationRouterV2.swapSimpleMode.selector) { ( address callTarget, IMetaAggregationRouterV2.SwapDescriptionV2 memory desc, bytes memory targetData, bytes memory clientData ) = abi.decode(dataToDecode, (address, IMetaAggregationRouterV2.SwapDescriptionV2, bytes, bytes)); (desc, targetData) = _getScaledInputDataV2(desc, targetData, newAmount, true); return abi.encodeWithSelector(selector, callTarget, desc, targetData, clientData); } else { revert("InputScalingHelper: Invalid selector"); } } function _getScaledInputDataV2( IMetaAggregationRouterV2.SwapDescriptionV2 memory desc, bytes memory executorData, uint256 newAmount, bool isSimpleMode ) internal pure returns (IMetaAggregationRouterV2.SwapDescriptionV2 memory, bytes memory) { uint256 oldAmount = desc.amount; if (oldAmount == newAmount) { return (desc, executorData); } // simple mode swap if (isSimpleMode) { return ( _scaledSwapDescriptionV2(desc, oldAmount, newAmount), _scaledSimpleSwapData(executorData, oldAmount, newAmount) ); } //normal mode swap return ( _scaledSwapDescriptionV2(desc, oldAmount, newAmount), _scaledExecutorCallBytesData(executorData, oldAmount, newAmount) ); } /// @dev Scale the swap description function _scaledSwapDescriptionV2( IMetaAggregationRouterV2.SwapDescriptionV2 memory desc, uint256 oldAmount, uint256 newAmount ) internal pure returns (IMetaAggregationRouterV2.SwapDescriptionV2 memory) { desc.minReturnAmount = (desc.minReturnAmount * newAmount) / oldAmount; if (desc.minReturnAmount == 0) desc.minReturnAmount = 1; desc.amount = (desc.amount * newAmount) / oldAmount; uint256 nReceivers = desc.srcReceivers.length; for (uint256 i = 0; i < nReceivers; ) { desc.srcAmounts[i] = (desc.srcAmounts[i] * newAmount) / oldAmount; unchecked { ++i; } } return desc; } /// @dev Scale the executorData in case swapSimpleMode function _scaledSimpleSwapData( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IMetaAggregationRouterV2.SimpleSwapData memory simpleSwapData = abi.decode( data, (IMetaAggregationRouterV2.SimpleSwapData) ); uint256 nPools = simpleSwapData.firstPools.length; address tokenIn; for (uint256 i = 0; i < nPools; ) { simpleSwapData.firstSwapAmounts[i] = (simpleSwapData.firstSwapAmounts[i] * newAmount) / oldAmount; IExecutorHelperL2.Swap[] memory dexData; (dexData, tokenIn) = simpleSwapData.swapDatas[i].readSwapSingleSequence(); // only need to scale the first dex in each sequence if (dexData.length > 0) { dexData[0] = _scaleDexData(dexData[0], oldAmount, newAmount); } simpleSwapData.swapDatas[i] = CalldataWriter._writeSwapSingleSequence(abi.encode(dexData), tokenIn); unchecked { ++i; } } simpleSwapData.positiveSlippageData = _scaledPositiveSlippageFeeData( simpleSwapData.positiveSlippageData, oldAmount, newAmount ); return abi.encode(simpleSwapData); } /// @dev Scale the executorData in case normal swap function _scaledExecutorCallBytesData( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { IExecutorHelperL2.SwapExecutorDescription memory executorDesc = abi.decode( data.readSwapExecutorDescription(), (IExecutorHelperL2.SwapExecutorDescription) ); executorDesc.positiveSlippageData = _scaledPositiveSlippageFeeData( executorDesc.positiveSlippageData, oldAmount, newAmount ); uint256 nSequences = executorDesc.swapSequences.length; for (uint256 i = 0; i < nSequences; ) { // only need to scale the first dex in each sequence IExecutorHelperL2.Swap memory swap = executorDesc.swapSequences[i][0]; executorDesc.swapSequences[i][0] = _scaleDexData(swap, oldAmount, newAmount); unchecked { ++i; } } return CalldataWriter.writeSwapExecutorDescription(executorDesc); } function _scaledPositiveSlippageFeeData( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory newData) { if (data.length > 32) { PositiveSlippageFeeData memory psData = abi.decode(data, (PositiveSlippageFeeData)); uint256 left = uint256(psData.expectedReturnAmount >> 128); uint256 right = (uint256(uint128(psData.expectedReturnAmount)) * newAmount) / oldAmount; require(right <= type(uint128).max, "_scaledPositiveSlippageFeeData/Exceeded type range"); psData.expectedReturnAmount = right | (left << 128); data = abi.encode(psData); } else if (data.length == 32) { uint256 expectedReturnAmount = abi.decode(data, (uint256)); uint256 left = uint256(expectedReturnAmount >> 128); uint256 right = (uint256(uint128(expectedReturnAmount)) * newAmount) / oldAmount; require(right <= type(uint128).max, "_scaledPositiveSlippageFeeData/Exceeded type range"); expectedReturnAmount = right | (left << 128); data = abi.encode(expectedReturnAmount); } return data; } function _scaleDexData( IExecutorHelperL2.Swap memory swap, uint256 oldAmount, uint256 newAmount ) internal pure returns (IExecutorHelperL2.Swap memory) { uint8 functionSelectorIndex = uint8(uint32(swap.functionSelector)); if (DexIndex(functionSelectorIndex) == DexIndex.UNI) { swap.data = swap.data.newUniSwap(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.StableSwap) { swap.data = swap.data.newStableSwap(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Curve) { swap.data = swap.data.newCurveSwap(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.KyberDMM) { swap.data = swap.data.newKyberDMM(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.UniswapV3KSElastic) { swap.data = swap.data.newUniswapV3KSElastic(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.RFQ) { revert("InputScalingHelper: Can not scale RFQ swap"); } else if (DexIndex(functionSelectorIndex) == DexIndex.BalancerV2) { swap.data = swap.data.newBalancerV2(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.wstETH) { swap.data = swap.data.newWrappedstETHSwap(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.stETH) { swap.data = swap.data.newStETHSwap(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.DODO) { swap.data = swap.data.newDODO(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Velodrome) { swap.data = swap.data.newVelodrome(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.GMX) { swap.data = swap.data.newGMX(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Synthetix) { swap.data = swap.data.newSynthetix(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Hashflow) { revert("InputScalingHelper: Can not scale Hashflow swap"); } else if (DexIndex(functionSelectorIndex) == DexIndex.Camelot) { swap.data = swap.data.newCamelot(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.KyberLO) { revert("InputScalingHelper: Can not scale KyberLO swap"); } else if (DexIndex(functionSelectorIndex) == DexIndex.PSM) { swap.data = swap.data.newPSM(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Fraxswap) { swap.data = swap.data.newFrax(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Platypus) { swap.data = swap.data.newPlatypus(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Maverick) { swap.data = swap.data.newMaverick(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.SyncSwap) { swap.data = swap.data.newSyncSwap(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.AlgebraV1) { swap.data = swap.data.newAlgebraV1(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.BalancerBatch) { swap.data = swap.data.newBalancerBatch(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Mantis) { swap.data = swap.data.newMantis(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Wombat) { swap.data = swap.data.newMantis(oldAmount, newAmount); // @dev use identical calldata structure as Mantis } else if (DexIndex(functionSelectorIndex) == DexIndex.iZiSwap) { swap.data = swap.data.newIziSwap(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.TraderJoeV2) { swap.data = swap.data.newTraderJoeV2(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.WooFiV2) { swap.data = swap.data.newMantis(oldAmount, newAmount); // @dev use identical calldata structure as Mantis } else if (DexIndex(functionSelectorIndex) == DexIndex.KyberDSLO) { revert("InputScalingHelper: Can not scale KyberDSLO swap"); } else if (DexIndex(functionSelectorIndex) == DexIndex.LevelFiV2) { swap.data = swap.data.newLevelFiV2(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.PancakeStableSwap) { swap.data = swap.data.newCurveSwap(oldAmount, newAmount); // @dev same encoded data as Curve } else if (DexIndex(functionSelectorIndex) == DexIndex.GMXGLP) { swap.data = swap.data.newGMXGLP(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Vooi) { swap.data = swap.data.newVooi(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.VelocoreV2) { swap.data = swap.data.newVelocoreV2(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Smardex) { swap.data = swap.data.newMantis(oldAmount, newAmount); // @dev use identical calldata structure as Mantis } else if (DexIndex(functionSelectorIndex) == DexIndex.SolidlyV2) { swap.data = swap.data.newMantis(oldAmount, newAmount); // @dev use identical calldata structure as Mantis } else if (DexIndex(functionSelectorIndex) == DexIndex.Kokonut) { swap.data = swap.data.newKokonut(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.BalancerV1) { swap.data = swap.data.newBalancerV1(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.SwaapV2) { revert("InputScalingHelper: Can not scale SwaapV2 swap"); } else if (DexIndex(functionSelectorIndex) == DexIndex.NomiswapStable) { swap.data = swap.data.newMantis(oldAmount, newAmount); // @dev use identical calldata structure as Mantis } else if (DexIndex(functionSelectorIndex) == DexIndex.ArbswapStable) { swap.data = swap.data.newArbswapStable(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.BancorV2) { swap.data = swap.data.newBancorV2(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.BancorV3) { swap.data = swap.data.newMantis(oldAmount, newAmount); // @dev use identical calldata structure as Mantis } else if (DexIndex(functionSelectorIndex) == DexIndex.Ambient) { swap.data = swap.data.newAmbient(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Native) { revert("InputScalingHelper: Can not scale Native swap"); } else if (DexIndex(functionSelectorIndex) == DexIndex.LighterV2) { swap.data = swap.data.newLighterV2(oldAmount, newAmount); } else if (DexIndex(functionSelectorIndex) == DexIndex.Bebop) { revert("InputScalingHelper: Can not scale Bebop swap"); } else { revert("InputScaleHelper: Dex type not supported"); } return swap; } function _flagsChecked(uint256 number, uint256 flag) internal pure returns (bool) { return number & flag != 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IExecutorHelper} from "../interfaces/IExecutorHelper.sol"; import {DexScaler} from "./DexScaler.sol"; library ScalingDataL2Lib { using DexScaler for bytes; function newUniSwap(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleUniSwap(oldAmount, newAmount); } function newStableSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleStableSwap(oldAmount, newAmount); } function newCurveSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleCurveSwap(oldAmount, newAmount); } function newKyberDMM(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleUniSwap(oldAmount, newAmount); } function newUniswapV3KSElastic( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleUniswapV3KSElastic(oldAmount, newAmount); } function newBalancerV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleBalancerV2(oldAmount, newAmount); } function newDODO(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleDODO(oldAmount, newAmount); } function newVelodrome( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleUniSwap(oldAmount, newAmount); } function newGMX(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleGMX(oldAmount, newAmount); } function newSynthetix( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleSynthetix(oldAmount, newAmount); } function newCamelot(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleUniSwap(oldAmount, newAmount); } function newPlatypus(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scalePlatypus(oldAmount, newAmount); } function newWrappedstETHSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleWrappedstETH(oldAmount, newAmount); } function newPSM(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scalePSM(oldAmount, newAmount); } function newFrax(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleUniSwap(oldAmount, newAmount); } function newStETHSwap( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleStETH(oldAmount, newAmount); } function newMaverick(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleMaverick(oldAmount, newAmount); } function newSyncSwap(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleSyncSwap(oldAmount, newAmount); } function newAlgebraV1( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleAlgebraV1(oldAmount, newAmount); } function newBalancerBatch( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleBalancerBatch(oldAmount, newAmount); } function newMantis(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleMantis(oldAmount, newAmount); } function newIziSwap(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleIziSwap(oldAmount, newAmount); } function newTraderJoeV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleTraderJoeV2(oldAmount, newAmount); } function newLevelFiV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleLevelFiV2(oldAmount, newAmount); } function newGMXGLP(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleGMXGLP(oldAmount, newAmount); } function newVooi(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleVooi(oldAmount, newAmount); } function newVelocoreV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleVelocoreV2(oldAmount, newAmount); } function newKokonut(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleKokonut(oldAmount, newAmount); } function newBalancerV1( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleBalancerV1(oldAmount, newAmount); } function newArbswapStable( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleArbswapStable(oldAmount, newAmount); } function newBancorV2(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleBancorV2(oldAmount, newAmount); } function newAmbient(bytes memory data, uint256 oldAmount, uint256 newAmount) internal pure returns (bytes memory) { return data.scaleAmbient(oldAmount, newAmount); } function newLighterV2( bytes memory data, uint256 oldAmount, uint256 newAmount ) internal pure returns (bytes memory) { return data.scaleLighterV2(oldAmount, newAmount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; interface I1inchAggregationRouterV5 { struct SwapDescription { IERC20 srcToken; IERC20 dstToken; address payable srcReceiver; address payable dstReceiver; uint256 amount; uint256 minReturnAmount; uint256 flags; } function uniswapV3SwapTo( address payable recipient, uint256 amount, uint256 minReturn, uint256[] calldata pools ) external payable returns (uint256 returnAmount); function swap( address executor, SwapDescription calldata desc, bytes calldata permit, bytes calldata data ) external payable returns (uint256 returnAmount, uint256 spentAmount); function unoswapTo( address payable recipient, address srcToken, uint256 amount, uint256 minReturn, uint256[] calldata pools ) external payable returns (uint256 returnAmount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./I1inchAggregationRouterV5.sol"; import "../../../core/libraries/Errors.sol"; abstract contract OneInchAggregationRouterHelper { function _rescaleMinAmount( uint256 minAmount, uint256 oldAmount, uint256 newAmount ) internal pure returns (uint256) { return (minAmount * newAmount) / oldAmount; } function _get1inchScaledInputData( bytes calldata rawCallData, uint256 newAmount ) internal pure returns (bytes memory) { bytes4 selector = bytes4(rawCallData[:4]); bytes memory args = rawCallData[4:]; if (selector == I1inchAggregationRouterV5.uniswapV3SwapTo.selector) { (address payable recipient, uint256 amount, uint256 minReturn, uint256[] memory pools) = abi.decode( args, (address, uint256, uint256, uint256[]) ); amount = newAmount; return abi.encodeWithSelector(selector, recipient, amount, minReturn, pools); } if (selector == I1inchAggregationRouterV5.swap.selector) { ( address executor, I1inchAggregationRouterV5.SwapDescription memory desc, bytes memory permit, bytes memory data ) = abi.decode(args, (address, I1inchAggregationRouterV5.SwapDescription, bytes, bytes)); desc.amount = newAmount; return abi.encodeWithSelector(selector, executor, desc, permit, data); } if (selector == I1inchAggregationRouterV5.unoswapTo.selector) { ( address payable recipient, address srcToken, uint256 amount, uint256 minReturn, uint256[] memory pools ) = abi.decode(args, (address, address, uint256, uint256, uint256[])); amount = newAmount; return abi.encodeWithSelector(selector, recipient, srcToken, amount, minReturn, pools); } revert Errors.UnsupportedSelector(2, selector); } }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "viaIR": true, "evmVersion": "shanghai", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"aggregatorType","type":"uint256"},{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"UnsupportedSelector","type":"error"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"components":[{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"extRouter","type":"address"},{"internalType":"bytes","name":"extCalldata","type":"bytes"},{"internalType":"bool","name":"needScale","type":"bool"}],"internalType":"struct SwapData","name":"data","type":"tuple"}],"name":"swap","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608080604052346100175761582d90816200001c8239f35b5f80fdfe608060405260048036101561001c575b50361561001a575f80fd5b005b5f3560e01c632bdb823c0361000f577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9060608236011261025d5780359173ffffffffffffffffffffffffffffffffffffffff83169283810361025d57602435906044359067ffffffffffffffff821161025d57608082860194833603011261025d576100bf906100ba60248401916100b4836102a0565b906104ef565b6102a0565b926064820135801515810361025d5715610261578035918583101561025d57839160446100ed9201906102c1565b9260018103610217575091610101926111e5565b935b610210575b6040519261011584610405565b602984527f416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c60208501527f7565206661696c65640000000000000000000000000000000000000000000000604085015281471061018c57505f848192602061001a9751920190855af16101866107b3565b916115ac565b6084906020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152fd5b505f610108565b9091506002036102315761022c918391610965565b610101565b6001857f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b5f80fd5b6102729060446102799301906102c1565b36916104b9565b93610103565b359073ffffffffffffffffffffffffffffffffffffffff8216820361025d57565b3573ffffffffffffffffffffffffffffffffffffffff8116810361025d5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561025d570180359067ffffffffffffffff821161025d5760200191813603831361025d57565b60e0810190811067ffffffffffffffff82111761032e57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610160810190811067ffffffffffffffff82111761032e57604052565b60a0810190811067ffffffffffffffff82111761032e57604052565b60c0810190811067ffffffffffffffff82111761032e57604052565b6040810190811067ffffffffffffffff82111761032e57604052565b6080810190811067ffffffffffffffff82111761032e57604052565b610100810190811067ffffffffffffffff82111761032e57604052565b6060810190811067ffffffffffffffff82111761032e57604052565b610120810190811067ffffffffffffffff82111761032e57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761032e57604052565b67ffffffffffffffff811161032e57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926104c58261047f565b916104d3604051938461043e565b82948184528183011161025d578281602093845f960137010152565b9073ffffffffffffffffffffffffffffffffffffffff918281169081156107ad576040918251809581957fdd62ed3e0000000000000000000000000000000000000000000000000000000083523060048401521691826024830152602096879160449788915afa80156107a3575f9061076a575b6b7fffffffffffffffffffffff91501061057f575b5050505050565b8251905f808784017f095ea7b3000000000000000000000000000000000000000000000000000000009485825284602482015282898201528881526105c3816103cc565b519082875af16105d16107b3565b81610732575b50156106d657915f929183809386519089820193845260248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff88820152878152610623816103cc565b51925af161062f6107b3565b8161069e575b5015610642578080610578565b606492917f5361666520417070726f766500000000000000000000000000000000000000009151927f08c379a00000000000000000000000000000000000000000000000000000000084526004840152600c6024840152820152fd5b809150518481159182156106b7575b505090505f610635565b838092935001031261025d57836106ce91016107e2565b80845f6106ad565b6064867f5361666520417070726f76650000000000000000000000000000000000000000878751927f08c379a00000000000000000000000000000000000000000000000000000000084526004840152600c6024840152820152fd5b8091505187811591821561074b575b505090505f6105d7565b838092935001031261025d578661076291016107e2565b80875f610741565b508581813d831161079c575b610780818361043e565b8101031261025d576b7fffffffffffffffffffffff9051610563565b503d610776565b84513d5f823e3d90fd5b50505050565b3d156107dd573d906107c48261047f565b916107d2604051938461043e565b82523d5f602084013e565b606090565b5190811515820361025d57565b519073ffffffffffffffffffffffffffffffffffffffff8216820361025d57565b67ffffffffffffffff811161032e5760051b60200190565b9080601f8301121561025d5781519060209161084381610810565b93610851604051958661043e565b81855260208086019260051b82010192831161025d57602001905b82821061087a575050505090565b8151815290830190830161086c565b9081518082526020808093019301915f5b8281106108a8575050505090565b83518552938101939281019260010161089a565b5f5b8381106108cd5750505f910152565b81810151838201526020016108be565b81601f8201121561025d5780516108f38161047f565b92610901604051948561043e565b8184526020828401011161025d5761091f91602080850191016108bc565b90565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209361095e815180928187528780880191016108bc565b0116010190565b91908060041161025d576109a0907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc369101600485016104b9565b7fbc80f1a8000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084351614610e08577f12aa3caf000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084351614610bcf577ff78dc253000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084351614610ad9576044837fffffffff00000000000000000000000000000000000000000000000000000000604051917fa7dd6a950000000000000000000000000000000000000000000000000000000083526002600484015235166024820152fd5b90918151820160a08382031261025d57610af5602084016107ef565b93610b02604085016107ef565b9060808501519060a08601519667ffffffffffffffff881161025d57610b5761091f9760207fffffffff000000000000000000000000000000000000000000000000000000009a81610ba39901920101610828565b9373ffffffffffffffffffffffffffffffffffffffff80926040519a8b99351660208a01521660248801521660448601526064850152608484015260a060a484015260c4830190610889565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261043e565b909181518201928260208501940390610140821261025d5760e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610c16602087016107ef565b93011261025d5760405194610c2a86610312565b610c36604086016107ef565b8652610c44606086016107ef565b6020870152610c55608086016107ef565b6040870152610c6660a086016107ef565b606087015260c0850151608087015260e085015160a087015261010085015160c08701526101208501519067ffffffffffffffff9182811161025d57816020610cb1928901016108dd565b9061014087015192831161025d577fffffffff000000000000000000000000000000000000000000000000000000009773ffffffffffffffffffffffffffffffffffffffff610ba396610d1160c0946020610dd79861091f9d01016108dd565b9660808401526040519a8b99351660208a015216602488015273ffffffffffffffffffffffffffffffffffffffff815116604488015273ffffffffffffffffffffffffffffffffffffffff602082015116606488015273ffffffffffffffffffffffffffffffffffffffff604082015116608488015273ffffffffffffffffffffffffffffffffffffffff60608201511660a4880152608081015160c488015260a081015160e48801520151610104860152610140610124860152610164850190610922565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc84830301610144850152610922565b91825183019260808185031261025d57610e24602082016107ef565b606082015160808301519467ffffffffffffffff861161025d5773ffffffffffffffffffffffffffffffffffffffff610e8c610ba395602061091f99817fffffffff000000000000000000000000000000000000000000000000000000009c01920101610828565b9360405198899735166020880152166024860152604485015260648401526080608484015260a4830190610889565b9080601f8301121561025d576020908235610ed581610810565b93610ee3604051958661043e565b81855260208086019260051b82010192831161025d57602001905b828210610f0c575050505090565b838091610f188461027f565b815201910190610efe565b9080601f8301121561025d576020908235610f3d81610810565b93610f4b604051958661043e565b81855260208086019260051b82010192831161025d57602001905b828210610f74575050505090565b81358152908301908301610f66565b9080601f8301121561025d5781602061091f933591016104b9565b91906101608382031261025d5760405190610fb88261035b565b8193610fc38161027f565b8352610fd16020820161027f565b602084015267ffffffffffffffff91604082013583811161025d5781610ff8918401610ebb565b6040850152606082013583811161025d5781611015918401610f23565b6060850152608082013583811161025d5781611032918401610ebb565b608085015260a082013583811161025d578161104f918401610f23565b60a085015261106060c0830161027f565b60c085015260e082013560e085015261010080830135908501526101208083013590850152610140928383013590811161025d5761109e9201610f83565b910152565b9081518082526020808093019301915f5b8281106110c2575050505090565b835173ffffffffffffffffffffffffffffffffffffffff16855293810193928101926001016110b4565b9081518082526020808093019301915f5b82811061110b575050505090565b8351855293810193928101926001016110fd565b9061091f91610160916111a661119461118261117073ffffffffffffffffffffffffffffffffffffffff968787511686528760208801511660208701526040870151908060408801528601906110a3565b606086015185820360608701526110ec565b608085015184820360808601526110a3565b60a084015183820360a08501526110ec565b9260c08301511660c082015260e082015160e0820152610100808301519082015261012080830151908201526101408092015191818403910152610922565b909160049280841161025d5782357fffffffff000000000000000000000000000000000000000000000000000000001691848401917fe21fd0e90000000000000000000000000000000000000000000000000000000084036113dc5784017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc92602084878403011261025d57359467ffffffffffffffff9586811161025d5760a0910193848303011261025d576040519061129f82610378565b6112aa87850161027f565b82526112b86024850161027f565b9660208301978852604485013587811161025d5782826112da92880101610f83565b60408401908152606486013588811161025d5783836112fb92890101610f9e565b9360608101948552608487013598891161025d5761134a61132c6113cb956113979561091f9c610ba39b0101610f83565b966080830197885286519084516020610120840151161515926118d5565b83528552604051998a9860208a0152602060248a015273ffffffffffffffffffffffffffffffffffffffff8092511660448a0152511660648801525160a0608488015260e4870190610922565b9151917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc92838783030160a488015261111f565b9151908483030160c4850152610922565b909391907f8af033fb0000000000000000000000000000000000000000000000000000000084036115295782019060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc848403011261025d57359473ffffffffffffffffffffffffffffffffffffffff861680960361025d5767ffffffffffffffff90602484013582811161025d57838261147a92870101610f9e565b91604485013581811161025d57848361149592880101610f83565b96606486013591821161025d5761091f976114c06114e99661151a956114c695610ba39a0101610f83565b946116ce565b9390604051988997602089015260248801526080604488015260a487019061111f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc9384878303016064880152610922565b91848303016084850152610922565b6084866020604051917f08c379a00000000000000000000000000000000000000000000000000000000083528201526024808201527f496e7075745363616c696e6748656c7065723a20496e76616c69642073656c6560448201527f63746f72000000000000000000000000000000000000000000000000000000006064820152fd5b9192901561162757508151156115c0575090565b3b156115c95790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b82519091501561163a5750805190602001fd5b611678906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190610922565b0390fd5b604051906116898261035b565b815f81525f602082015261014060609182604082015282808201528260808201528260a08201525f60c08201525f60e08201525f6101008201525f6101208201520152565b909291926116da61167c565b5060e0820151918483146118ce5784836116f392614d71565b91815191602092810191838301848385031261025d57848301519267ffffffffffffffff9384811161025d5760a091018095031261025d576040519761173889610378565b8585015184811161025d57828761175192880101614dec565b8952604085015184811161025d57828761176d92880101610828565b93868a01948552606086015181811161025d57838861178e92890101614e55565b9260408b0193845260808701519660608c0197885260a081015192831161025d576117bb920188016108dd565b9260808a019384528951515f5b81811061189b57505061186b94926117eb8593611854936118979a999751614fb4565b835261184361180f6040519c898e9a8b01525160a060408b015260e08a01906110a3565b9451947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc095868a83030160608b01526110ec565b905184888303016080890152614ed5565b925160a086015251908483030160c0850152610922565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810185528461043e565b9190565b806118bc846118b7876118b16001968d51614d5d565b51614ce6565b614d26565b6118c7828a51614d5d565b52016117c8565b9350919050565b939290936118e161167c565b5060e081015191838314614cde57614baf5782826118fe92614d71565b91845194602081878101031261025d5760208101519567ffffffffffffffff871161025d5760c0878301828401031261025d576040519661193e88610394565b6020818401015167ffffffffffffffff811161025d57602083850101603f828487010101121561025d576020818386010101519061197b82610810565b91611989604051938461043e565b808352602083019160208688010160408360051b83888b010101011161025d576040818689010101925b60408360051b83888b010101018410614a69575050505088526119da6040828501016107ef565b60208901526119ed6060828501016107ef565b6040890152611a006080828501016107ef565b606089015282810160a081015160808a015260c001519067ffffffffffffffff821161025d578360208793611a4193828997611a4c990101930101016108dd565b8060a08a0152614fb4565b60a0860152845151905f5b828110611be75750505050604051926020808501528381519160c06040830152825180610100840152610120906020828501928260051b8601019501915f905b828210611b1f57505050506118979260a082602061186b94015173ffffffffffffffffffffffffffffffffffffffff809116606087015280604083015116608087015260608201511682860152608081015160c086015201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08483030160e0850152610922565b9193947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee0908792949703018252855190815180825260208201906020808260051b8501019401925f5b828110611b8a5750505050506020806001929701920192018894939192611a97565b9091929394602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600195030188528851908280611bd48451604085526040850190610922565b9301519101529701950193929101611b68565b611bf2818851614d5d565b51805115614a3c5760200151907fffffffff000000000000000000000000000000000000000000000000000000006020830151167f593611990000000000000000000000000000000000000000000000000000000081145f14611c68575081611c5f8487600195516156ce565b90525b01611a57565b7fa8d2cb11000000000000000000000000000000000000000000000000000000008103611e4b575081516101208180518101031261025d57604051908161012081011067ffffffffffffffff6101208401111761032e57866118b786611d61936101208601604052611cdc602082016107ef565b8652611cea604082016107ef565b6020870152611cfb606082016107ef565b6040870152611d0c608082016153d8565b6060870152611d1d60a082016153d8565b6080870152611d5661012060c0830151928360a08a015260e081015160c08a0152611d4b61010082016107ef565b60e08a0152016107e2565b610100870152614ce6565b60a08201526101006040519173ffffffffffffffffffffffffffffffffffffffff815116602084015273ffffffffffffffffffffffffffffffffffffffff602082015116604084015273ffffffffffffffffffffffffffffffffffffffff6040820151166060840152606081015160ff809116608085015260808201511660a084015260a081015160c084015260c081015160e084015273ffffffffffffffffffffffffffffffffffffffff60e0820151168284015201511515610120820152610120815261014081019281841067ffffffffffffffff85111761032e5760019360405252611c62565b7fd90ce491000000000000000000000000000000000000000000000000000000008103611e89575081611e82848760019551615535565b9052611c62565b7fa3722546000000000000000000000000000000000000000000000000000000008103611ec0575081611e828487600195516156ce565b7f63407a49000000000000000000000000000000000000000000000000000000008103611fff5750815160e08180518101031261025d57600192611f82876118b78760405195611f0f87610312565b611f1b602082016107ef565b8752611f29604082016107ef565b6020880152611f3a606082016107ef565b6040880152611f4b608082016107ef565b6060880152611f7860e060a0830151928360808b0152611f6d60c082016107ef565b60a08b0152016107e2565b60c0880152614ce6565b608083015260c06040519273ffffffffffffffffffffffffffffffffffffffff808251166020860152806020830151166040860152806040830151166060860152806060830151166080860152608082015160a086015260a082015116828501520151151560e083015260e08252611ff9826103e8565b52611c62565b7fca6182da0000000000000000000000000000000000000000000000000000000081036120aa5760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65205246512073776170000000000000000000000000000000000000000000006064820152fd5b7f8cc7a56b0000000000000000000000000000000000000000000000000000000081036121995750815160a08180518101031261025d576001926040516120f081610378565b6120fc602084016107ef565b8152604083015160208201908152612116606085016107ef565b936040830194855260a061212c608083016107ef565b916060850192835201519261214c8b6118b78b6080850197808952614ce6565b84526040519573ffffffffffffffffffffffffffffffffffffffff938480935116602089015251604088015251166060860152511660808401525160a083015260a08252611ff982610394565b7f0ca8ebf10000000000000000000000000000000000000000000000000000000081036122595750815160608180518101031261025d57600192604051916121e083610405565b6121ec602082016107ef565b835260408101519061221c896118b78961220f606060208a0196888852016107e2565b9560408901968752614ce6565b815273ffffffffffffffffffffffffffffffffffffffff6040519451166020850152516040840152511515606083015260608252611ff9826103cc565b7feeb543140000000000000000000000000000000000000000000000000000000081036122bc575081519160208380518101031261025d576122a5866118b78660206001970151614ce6565b9060405191602083015260208252611ff9826103b0565b7f7b797563000000000000000000000000000000000000000000000000000000008103612416575081516101008180518101031261025d57600192612391876118b7876040519561230c876103e8565b612318602082016107ef565b8752612326604082016107ef565b6020880152612337606082016107ef565b6040880152612348608082016107ef565b606088015261238761010060a0830151928360808b015261236b60c082016107ef565b60a08b015261237c60e082016107e2565b60c08b0152016107e2565b60e0880152614ce6565b608083015260e06040519273ffffffffffffffffffffffffffffffffffffffff808251166020860152806020830151166040860152806040830151166060860152806060830151166080860152608082015160a086015260a08201511660c085015260c0810151151582850152015115156101008301526101008252611ff982610421565b7f55fad2fb00000000000000000000000000000000000000000000000000000000810361244d575081611e828487600195516156ce565b7f3b284cfe00000000000000000000000000000000000000000000000000000000810361251157508151918251830160a08482031261025d57600193602080612498930191016153e6565b90606082016124ac886118b7888451614ce6565b90526125046040519260208401906080908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015260608101516060860152015116910152565b60a08252611ff982610394565b7f74836acb0000000000000000000000000000000000000000000000000000000081036126375750815160e08180518101031261025d576001926040519161255883610312565b612564602082016107ef565b8352612572604082016107ef565b6020840152612583606082016107ef565b6040840152608081015160608401526125c8886118b7886125bb60e060a0870151968760808b015260c081015160a08b0152016107e2565b9460c08801958652614ce6565b608084015260a06040519373ffffffffffffffffffffffffffffffffffffffff808251166020870152806020830151166040870152604082015116606086015260608101516080860152608081015182860152015160c084015251151560e083015260e08252611ff9826103e8565b7f800023a10000000000000000000000000000000000000000000000000000000081036126e25760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f6520486173666c6f7720737761700000000000000000000000000000000000006064820152fd5b7f8df4a16b000000000000000000000000000000000000000000000000000000008103612719575081611e828487600195516156ce565b7fd6984a6d0000000000000000000000000000000000000000000000000000000081036127c45760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65204b796265724c4f20737761700000000000000000000000000000000000006064820152fd5b7f8f07985400000000000000000000000000000000000000000000000000000000810361280f57508151918251830160a08482031261025d57600193602080612498930191016153e6565b7fa9b3e398000000000000000000000000000000000000000000000000000000008103612846575081611e828487600195516156ce565b7f92749fe10000000000000000000000000000000000000000000000000000000081036128fc57508151918251830160a08482031261025d576001936020806128919301910161565b565b90608082016128a5886118b7888451614ce6565b90526125046040519260208401906080809173ffffffffffffffffffffffffffffffffffffffff80825116855280602083015116602086015280604083015116604086015260608201511660608501520151910152565b7f27c0cd18000000000000000000000000000000000000000000000000000000008103612a075750815160c08180518101031261025d5760019260405161294281610394565b61294e602084016107ef565b815261295c604084016107ef565b9260208201938452612970606082016107ef565b9360408301948552612984608083016107ef565b6060840190815260a0830151936129b28c6118b78c60c060808601988a8a5201519860a08601998a52614ce6565b84526040519673ffffffffffffffffffffffffffffffffffffffff8094818094511660208b01525116604089015251166060870152511660808501525160a08401525160c083015260c08252611ff982610312565b7fe756cac1000000000000000000000000000000000000000000000000000000008103612b815750815191825183019060208483031261025d57602084015167ffffffffffffffff811161025d5760a081860184031261025d57604051612a6d81610378565b602082870101519167ffffffffffffffff831161025d57600196612aa1611ff994602080612b2099019185850101016108dd565b8352612ab16040838301016107ef565b916020840192835260a0612ac96060838501016107ef565b9160408601928352612adf6080828601016107ef565b936060870194855201015191612b008d6118b78d6080890196808852614ce6565b83526040519788956020808801525160a0604088015260e0870190610922565b935173ffffffffffffffffffffffffffffffffffffffff9283809216606088015251166080860152511660a08401525160c0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810184528361043e565b7f48d31802000000000000000000000000000000000000000000000000000000008103612cb15750815160e08180518101031261025d57600192612c3c876118b78760405195612bd087610312565b612bdc602082016107ef565b8752612bea604082016107ef565b6020880152612bfb606082016107ef565b6040880152612c0c608082016107ef565b606088015260e060a0820151918260808a0152612c2b60c082016107ef565b60a08a0152015160c0880152614ce6565b608083015260c06040519273ffffffffffffffffffffffffffffffffffffffff808251166020860152806020830151166040860152806040830151166060860152806060830151166080860152608082015160a086015260a08201511682850152015160e083015260e08252611ff9826103e8565b7f04cca9f7000000000000000000000000000000000000000000000000000000008103612f405750908051908151820160208382031261025d57602083015167ffffffffffffffff811161025d5760a081850183031261025d5760405193612d1885610378565b612d266020838301016107ef565b85526040828201015167ffffffffffffffff811161025d5760208401603f828585010101121561025d57602081848401010151612d6281610810565b91612d70604051938461043e565b81835260208301906020870160408460051b838989010101011161025d576040818787010101915b60408460051b838989010101018310612f30575050505060208601526060828201015167ffffffffffffffff811161025d57612dde906020808601918585010101614dec565b6040860152608082820101519267ffffffffffffffff841161025d5760a08a936118b793612e1a612e2d976020808e9701918585010101614e55565b60608a0152010151806080880152614ce6565b60808301526040519160208084015260e0830173ffffffffffffffffffffffffffffffffffffffff825116604085015260208201519060a060608601528151809152602061010086019201905f905b808210612f185750505083826080612ee4611ff994612ecf604060019b9a99980151917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0928388830301868901526110a3565b906060850151908683030160a0870152614ed5565b91015160c0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810184528361043e565b90919260208060019286518152019401920190612e7c565b8251815260209283019201612d98565b7faa293da2000000000000000000000000000000000000000000000000000000008103612f77575081611e82848760019551615443565b7f517e7ca1000000000000000000000000000000000000000000000000000000008103612fae575081611e82848760019551615443565b7f1b96cfd40000000000000000000000000000000000000000000000000000000081036130cd575081519160c08380518101031261025d5760405190612ff382610394565b612fff602085016107ef565b825261300d604085016107ef565b602083015261301e606085016107ef565b604083015261302f608085016107ef565b606083015260c060a08501519485608085015201518060020b810361025d57613065886118b78860019860a08801958652614ce6565b608084015260806040519373ffffffffffffffffffffffffffffffffffffffff80825116602087015280602083015116604087015280604083015116606087015260608201511682860152015160a08401525160020b60c083015260c08252611ff982610312565b7f5987cf43000000000000000000000000000000000000000000000000000000008103613104575081611e82848760019551615443565b7fc43025bd00000000000000000000000000000000000000000000000000000000810361320157508151918251830160a08482031261025d5760019360208061314f9301910161565b565b906080820180517f80000000000000000000000000000000000000000000000000000000000000006131a78a6118b78a7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616614ce6565b91161790526125046040519260208401906080809173ffffffffffffffffffffffffffffffffffffffff80825116855280602083015116602086015280604083015116604086015260608201511660608501520151910152565b7f63d71df3000000000000000000000000000000000000000000000000000000008103613238575081611e82848760019551615535565b7fe7e1b5cb0000000000000000000000000000000000000000000000000000000081036133445750815160c08180518101031261025d5760019260405161327e81610394565b61328a602084016107ef565b8152613298604084016107ef565b90602081019182526132ac606085016107ef565b936040820194855260808101519160608101908382526132ef8c6118b78c6132e260c060a08901519860808801998a52016107ef565b9760a08601988952614ce6565b82526040519673ffffffffffffffffffffffffffffffffffffffff8096818094511660208b015251166040890152511660608701525160808601525160a0850152511660c083015260c08252611ff982610312565b7f3ac19910000000000000000000000000000000000000000000000000000000008103613494575081516101008180518101031261025d5760019261340f876118b78760405195613394876103e8565b6133a0602082016107ef565b87526133ae604082016107ef565b60208801526133bf606082016107ef565b60408801526133d0608082016107ef565b60608801526133e160a082016107ef565b60808801526133f260c082016107ef565b60a088015261238761010060e0830151928360c08b0152016107ef565b60c083015273ffffffffffffffffffffffffffffffffffffffff60e0604051938281511660208601528260208201511660408601528260408201511660608601528260608201511660808601528260808201511660a08601528260a08201511660c086015260c0810151828601520151166101008301526101008252611ff982610421565b7f37e96a470000000000000000000000000000000000000000000000000000000081036135b25750815160e08180518101031261025d576001926040516134da81610312565b6134e6602084016107ef565b81526134f4604084016107ef565b9060208101918252613508606085016107ef565b936040820194855260808101516060830190815260a0820151906080840191825260c0830151936135578d6118b78d61354a60e060a08701998b8b52016107ef565b9860c08601998a52614ce6565b84526040519773ffffffffffffffffffffffffffffffffffffffff8097818094511660208c0152511660408a0152511660608801525160808701525160a08601525160c0850152511660e083015260e08252611ff9826103e8565b7f4a8ac7610000000000000000000000000000000000000000000000000000000081036136e55750815160e08180518101031261025d57600192604051916135f983610312565b613605602082016107ef565b83526040810151906020840190828252613621606082016107ef565b9160408601928352613635608083016107ef565b956060810196875261364960a084016107ef565b90608081019182526136858d6118b78d61367860e061366a60c08b016107ef565b9960a088019a8b52016107e2565b9960c086019a8b52614ce6565b83526040519773ffffffffffffffffffffffffffffffffffffffff80968195828095511660208d01525160408c0152511660608a015251166080880152511660a0860152511660c084015251151560e083015260e08252611ff9826103e8565b7fc8e128e40000000000000000000000000000000000000000000000000000000081036137c35750815160808180518101031261025d576001926040519161372c836103cc565b613738602082016107ef565b8352613746604082016107ef565b906020840191825260608101519061377c8a6118b78a61376f608060408b0196888852016107ef565b9560608a01968752614ce6565b81526040519473ffffffffffffffffffffffffffffffffffffffff9384809251166020880152511660408601525160608501525116608083015260808252611ff982610378565b7ffac08e6f0000000000000000000000000000000000000000000000000000000081036137fa575081611e82848760019551615443565b7fe445a7ec000000000000000000000000000000000000000000000000000000008103613831575081611e82848760019551615443565b7f944432e00000000000000000000000000000000000000000000000000000000081036138e657508151918251830160a08482031261025d5760019360208061387c930191016154dc565b9060208201613890886118b7888451614ce6565b90526125046040519260208401906080908173ffffffffffffffffffffffffffffffffffffffff918281511685526020810151602086015260408101516040860152826060820151166060860152015116910152565b7f0e00deaa0000000000000000000000000000000000000000000000000000000081036139c35750815160808180518101031261025d576001926040519161392d836103cc565b613939602082016107ef565b8352613947604082016107ef565b60208401908152608061395c606084016107ef565b926040860193845201519161397c8a6118b78a6060890196808852614ce6565b83526040519473ffffffffffffffffffffffffffffffffffffffff9283809251166020880152511660408601525116606084015251608083015260808252611ff982610378565b7f67f2255d000000000000000000000000000000000000000000000000000000008103613a6e5760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65205377616170563220737761700000000000000000000000000000000000006064820152fd5b7f48bad50c000000000000000000000000000000000000000000000000000000008103613aa5575081611e82848760019551615443565b7fb1f7d82d000000000000000000000000000000000000000000000000000000008103613af057508151918251830160a08482031261025d5760019360208061387c930191016154dc565b7f68abdc71000000000000000000000000000000000000000000000000000000008103613c4d5750815191825183019060208483031261025d5760208401519367ffffffffffffffff851161025d57608085820184031261025d5760405194613b58866103cc565b613b666020828401016107ef565b8652604081830101519167ffffffffffffffff831161025d57600196613b9c611ff994602080613c139901918686010101614dec565b9260208201938452613bd58c6118b78c613bc860806060878a010151966040890199888b5201016107ef565b9460608701958652614ce6565b835260405196879460208087015273ffffffffffffffffffffffffffffffffffffffff809451166040870152516080606087015260c08601906110a3565b92516080850152511660a0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810184528361043e565b7f152dc1cf000000000000000000000000000000000000000000000000000000008103613c84575081611e82848760019551615443565b7f98923834000000000000000000000000000000000000000000000000000000008103613dd8575081519160c08380518101031261025d5760405190613cc982610394565b613cd5602085016107ef565b825260408401516fffffffffffffffffffffffffffffffff8116810361025d57613d5b886118b7886fffffffffffffffffffffffffffffffff85613d5060c060019c849960208d0152613d2a606082016107ef565b60408d0152613d3b608082016107ef565b60608d015260a081015160808d0152016153d8565b60a08a015216614ce6565b16602083015260ff60a06040519373ffffffffffffffffffffffffffffffffffffffff8082511660208701526fffffffffffffffffffffffffffffffff6020830151166040870152806040830151166060870152606082015116608086015260808101518286015201511660c083015260c08252611ff982610312565b7e3c5f89000000000000000000000000000000000000000000000000000000008103613e825760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65204e61746976652073776170000000000000000000000000000000000000006064820152fd5b7fddfb5cb6000000000000000000000000000000000000000000000000000000008103613fa95750815160c08180518101031261025d5760019260405191613ec983610394565b613ed5602082016107ef565b8352604081015160208401818152613eef606084016107e2565b9260408601938452613f03608082016107ef565b95606081019687526fffffffffffffffffffffffffffffffff613f508d6118b78d613f4360c0613f3560a08a016107ef565b9860808901998a52016107ef565b9860a08701998a52614ce6565b1683526040519673ffffffffffffffffffffffffffffffffffffffff958694858094511660208b01525160408a0152511515606089015251166080870152511660a0850152511660c083015260c08252611ff982610312565b7f3bbc6abf0000000000000000000000000000000000000000000000000000000081036140545760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65204265626f70207377617000000000000000000000000000000000000000006064820152fd5b7f180a5b7600000000000000000000000000000000000000000000000000000000810361411d57508151918251830160a08482031261025d5760019360208061409f9301910161532f565b90602082016fffffffffffffffffffffffffffffffff6140c4896118b7898551614ce6565b1690526125046040519260208401906080908173ffffffffffffffffffffffffffffffffffffffff9182815116855260208101516020860152826040820151166040860152826060820151166060860152015116910152565b7f63123dbb000000000000000000000000000000000000000000000000000000008103614154575081611e82848760019551615194565b7ff9c357e00000000000000000000000000000000000000000000000000000000081036141f75750815160408180518101031261025d576001926040519161419b836103b0565b6fffffffffffffffffffffffffffffffff6141d5896118b7896141c86040602088015197888b52016107e2565b9560208901968752614ce6565b16809352604051926020840152511515604083015260408252611ff982610405565b7fd883ad9f0000000000000000000000000000000000000000000000000000000081036142a457508151918251830160408482031261025d5760019360208061424293019101615292565b906fffffffffffffffffffffffffffffffff614263886118b7888651614ce6565b16825261429760405192602084019073ffffffffffffffffffffffffffffffffffffffff6020809280518552015116910152565b60408252611ff982610405565b7f0343ecaf0000000000000000000000000000000000000000000000000000000081036142db575081611e828487600195516152bc565b7f020918a10000000000000000000000000000000000000000000000000000000081036143c057508151918251830160408482031261025d57600193602080614326930191016151dc565b90602082016fffffffffffffffffffffffffffffffff61434d896118b78984865116614ce6565b167f8000000000000000000000000000000000000000000000000000000000000000868351908060ff92831c145f146143b857905b1b161790526142976040519260208401906020809173ffffffffffffffffffffffffffffffffffffffff81511684520151910152565b505f90614382565b7f95d02f7d0000000000000000000000000000000000000000000000000000000081036144a157508151918251830160408482031261025d5760019360208061440b93019101615292565b906fffffffffffffffffffffffffffffffff61442e886118b78884875116614ce6565b167f8000000000000000000000000000000000000000000000000000000000000000858451908060ff92831c145f1461449957905b1b1617825261429760405192602084019073ffffffffffffffffffffffffffffffffffffffff6020809280518552015116910152565b505f90614463565b7fc390adea00000000000000000000000000000000000000000000000000000000810361456b57508151918251830160808482031261025d576001936020806144ec9301910161538c565b90602082016fffffffffffffffffffffffffffffffff614511896118b7898551614ce6565b16905261455e6040519260208401906060908173ffffffffffffffffffffffffffffffffffffffff9182815116855260208101516020860152826040820151166040860152015116910152565b60808252611ff982610378565b7fc9989fac0000000000000000000000000000000000000000000000000000000081036145a2575081611e82848760019551615194565b7f5829bd520000000000000000000000000000000000000000000000000000000081036145d9575081611e82848760019551615194565b7f87ab3c27000000000000000000000000000000000000000000000000000000008103614610575081611e828487600195516150ef565b7fba176e5c00000000000000000000000000000000000000000000000000000000810361465b57508151918251830160808482031261025d576001936020806144ec9301910161538c565b7fe937b9a900000000000000000000000000000000000000000000000000000000810361476557508151918251830160a08482031261025d576001936020806146a69301910161532f565b90602082016fffffffffffffffffffffffffffffffff6146cd896118b78984865116614ce6565b167f8000000000000000000000000000000000000000000000000000000000000000868351908060ff92831c145f1461475d57905b1b161790526125046040519260208401906080908173ffffffffffffffffffffffffffffffffffffffff9182815116855260208101516020860152826040820151166040860152826060820151166060860152015116910152565b505f90614702565b7f323b615300000000000000000000000000000000000000000000000000000000810361479c575081611e82848760019551615194565b7ff17912eb0000000000000000000000000000000000000000000000000000000081036147d3575081611e82848760019551615194565b7fcebf718d00000000000000000000000000000000000000000000000000000000810361480a575081611e828487600195516152bc565b7fa8e60da0000000000000000000000000000000000000000000000000000000008103614841575081611e8284876001955161520b565b7fd5c275ad000000000000000000000000000000000000000000000000000000008103614878575081611e8284876001955161520b565b7fac40622c00000000000000000000000000000000000000000000000000000000810361494c575081519160208380518101031261025d5760206001930151906fffffffffffffffffffffffffffffffff6148d9886118b788848716614ce6565b16848060ff94851c145f14614924577f8000000000000000000000000000000000000000000000000000000000000000905b604051941b1617602083015260208252611ff9826103b0565b507f80000000000000000000000000000000000000000000000000000000000000005f61490b565b7fe93d0ac7000000000000000000000000000000000000000000000000000000008103614983575081611e82848760019551615194565b7fd1019fd000000000000000000000000000000000000000000000000000000000036149b85781611e828487600195516150ef565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4167677265676174696f6e4578656375746f723a204465782074797065206e6f60448201527f7420737570706f727465640000000000000000000000000000000000000000006064820152fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b835167ffffffffffffffff811161025d576020888a0101605f82858a8d01010101121561025d5760408184898c010101015188614aa582610810565b92614ab3604051948561043e565b8284526020808501928d01018c8b0187018201600585901b016060011161025d578960608d8389838282878601010101945b8860051b9301010101018110614b085750505090825250602093840193016119b3565b80519267ffffffffffffffff841161025d5760407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08f8f968f8c889184010101019687910103011261025d5760405193614b61856103b0565b60608101519467ffffffffffffffff861161025d578f918f8f97606095889460808f95614b9b602096958b8880988d0101918401016108dd565b835201518382015281520195019496614ae5565b8282614bbe9296939496614d71565b91815191602092810191838301848385031261025d57848301519267ffffffffffffffff9384811161025d5760a091018095031261025d5760405197614c0389610378565b8585015184811161025d578287614c1c92880101614dec565b8952604085015184811161025d578287614c3892880101610828565b93868a01948552606086015181811161025d578388614c5992890101614e55565b9260408b0193845260808701519660608c0197885260a081015192831161025d57614c86920188016108dd565b9260808a019384528951515f5b818110614cb657505061186b94926117eb8593611854936118979a999751614fb4565b80614ccc846118b7876118b16001968d51614d5d565b614cd7828a51614d5d565b5201614c93565b509150509190565b81810292918115918404141715614cf957565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8115614d30570490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b8051821015614a3c5760209160051b010190565b91614d7a61167c565b506101008301614d8f836118b7848451614ce6565b80825215614de2575b508060e0840152604083015151915f5b838110614db6575050505090565b60019060608601614ddb82614dd4866118b7896118b1858851614d5d565b9251614d5d565b5201614da8565b600190525f614d98565b9080601f8301121561025d57815190602091614e0781610810565b93614e15604051958661043e565b81855260208086019260051b82010192831161025d57602001905b828210614e3e575050505090565b838091614e4a846107ef565b815201910190614e30565b81601f8201121561025d57805191602091614e6f84610810565b93614e7d604051958661043e565b808552838086019160051b8301019280841161025d57848301915b848310614ea85750505050505090565b825167ffffffffffffffff811161025d578691614eca848480948901016108dd565b815201920191614e98565b90808251908181526020809101926020808460051b8301019501935f915b848310614f035750505050505090565b9091929394958480614f3f837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a51610922565b9801930193019194939290614ef3565b15614f5657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f457863656564656420747970652072616e6765000000000000000000000000006044820152fd5b919082918251906020918281115f1461505c5750835160409485918101031261025d577fffffffffffffffffffffffffffffffff0000000000000000000000000000000084805196615005886103b0565b8481015188520151615040615037858901968388526118b76fffffffffffffffffffffffffffffffff96878616614ce6565b93841115614f4f565b1617825282519351908401525181830152815261091f81610405565b9091809394508114615070575b5050505090565b918480929382959601031261025d576150a7836150b0920151946118b76fffffffffffffffffffffffffffffffff94858816614ce6565b91821115614f4f565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000006040519316178183015281526150e6816103b0565b5f808080615069565b9160608380518101031261025d576fffffffffffffffffffffffffffffffff6151556040519361511e85610405565b61512a602087016107ef565b85526118b760408701519461514860606020890199888b52016107ef565b9560408801968752614ce6565b1683526040519273ffffffffffffffffffffffffffffffffffffffff809351166020850152516040840152511660608201526060815261091f816103cc565b919060208380518101031261025d576118b76151c59260206fffffffffffffffffffffffffffffffff950151614ce6565b166040519060208201526020815261091f816103b0565b919082604091031261025d576040516151f4816103b0565b6020808294615202816107ef565b84520151910152565b919091805181019060408183031261025d57615241615251916020806fffffffffffffffffffffffffffffffff950191016151dc565b936118b760208601948551614ce6565b1690526152856040519160208301906020809173ffffffffffffffffffffffffffffffffffffffff81511684520151910152565b6040815261091f81610405565b919082604091031261025d576040516152aa816103b0565b602061109e81839580518552016107ef565b90815182019060408383031261025d576118b76152f36fffffffffffffffffffffffffffffffff946020806152fb96019101615292565b948551614ce6565b16815261528560405191602083019073ffffffffffffffffffffffffffffffffffffffff6020809280518552015116910152565b91908260a091031261025d5760405161534781610378565b608061109e818395615358816107ef565b855260208101516020860152615370604082016107ef565b6040860152615381606082016107ef565b6060860152016107ef565b919082608091031261025d576040516153a4816103cc565b606061109e8183956153b5816107ef565b8552602081015160208601526153cd604082016107ef565b6040860152016107ef565b519060ff8216820361025d57565b91908260a091031261025d576040516153fe81610378565b608061109e81839561540f816107ef565b855261541d602082016107ef565b602086015261542e604082016107ef565b604086015260608101516060860152016107ef565b9190918051810160a08282031261025d5761547791602080615467930191016153e6565b926118b760608501938451614ce6565b90526154cf6040519160208301906080908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015260608101516060860152015116910152565b60a0815261091f81610394565b91908260a091031261025d576040516154f481610378565b608061109e818395615505816107ef565b85526020810151602086015260408101516040860152615381606082016107ef565b519081600f0b820361025d57565b9190829182516101009485918101031261025d5760a08493604051958694859461555e866103e8565b61556a602085016107ef565b86526155f561557b604086016107ef565b92602088019384526118b7615592606088016107ef565b9360408a019485528960e06155eb6155ac60808c01615527565b99606084019a8b526155bf8d8d01615527565b9b608085019c8d5260c08101519d8e95019d8e5260c06155e08583016107e2565b9f019e8f52016107e2565b9c019b8c52614ce6565b85526040519873ffffffffffffffffffffffffffffffffffffffff92838092511660208c0152511660408a01525116606088015251600f0b608087015251600f0b60a08601525160c085015251151560e084015251151581830152815261091f81610421565b91908260a091031261025d5760405161567381610378565b6080808294615681816107ef565b845261568f602082016107ef565b60208501526156a0604082016107ef565b60408501526156b1606082016107ef565b60608501520151910152565b519063ffffffff8216820361025d57565b80919281516101009384918101031261025d57818060c092604051906156f3826103e8565b6156ff602084016107ef565b825261570d604084016107ef565b916020810192835261578d615724606086016107ef565b99604083019a8b526118b761573b608088016107ef565b94606085019586526157808c61577260e061576460a08d01519e8f9d60808c019e8f52016156bd565b9c60a08a019d8e52016156bd565b9c60c088019d8e52016156bd565b9960e086019a8b52614ce6565b84526040519873ffffffffffffffffffffffffffffffffffffffff8094818094511660208d0152511660408b015251166060890152511660808701525160a08601525163ffffffff928380921660c0870152511660e0850152511681830152815261091f8161042156fea2646970667358221220d0795bdc5bd2dd32e5c1d0a36090ad6cd21b3d392ef24a8e99c59565c715baa464736f6c63430008180033
Deployed Bytecode
0x608060405260048036101561001c575b50361561001a575f80fd5b005b5f3560e01c632bdb823c0361000f577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9060608236011261025d5780359173ffffffffffffffffffffffffffffffffffffffff83169283810361025d57602435906044359067ffffffffffffffff821161025d57608082860194833603011261025d576100bf906100ba60248401916100b4836102a0565b906104ef565b6102a0565b926064820135801515810361025d5715610261578035918583101561025d57839160446100ed9201906102c1565b9260018103610217575091610101926111e5565b935b610210575b6040519261011584610405565b602984527f416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c60208501527f7565206661696c65640000000000000000000000000000000000000000000000604085015281471061018c57505f848192602061001a9751920190855af16101866107b3565b916115ac565b6084906020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152fd5b505f610108565b9091506002036102315761022c918391610965565b610101565b6001857f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b5f80fd5b6102729060446102799301906102c1565b36916104b9565b93610103565b359073ffffffffffffffffffffffffffffffffffffffff8216820361025d57565b3573ffffffffffffffffffffffffffffffffffffffff8116810361025d5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561025d570180359067ffffffffffffffff821161025d5760200191813603831361025d57565b60e0810190811067ffffffffffffffff82111761032e57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610160810190811067ffffffffffffffff82111761032e57604052565b60a0810190811067ffffffffffffffff82111761032e57604052565b60c0810190811067ffffffffffffffff82111761032e57604052565b6040810190811067ffffffffffffffff82111761032e57604052565b6080810190811067ffffffffffffffff82111761032e57604052565b610100810190811067ffffffffffffffff82111761032e57604052565b6060810190811067ffffffffffffffff82111761032e57604052565b610120810190811067ffffffffffffffff82111761032e57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761032e57604052565b67ffffffffffffffff811161032e57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926104c58261047f565b916104d3604051938461043e565b82948184528183011161025d578281602093845f960137010152565b9073ffffffffffffffffffffffffffffffffffffffff918281169081156107ad576040918251809581957fdd62ed3e0000000000000000000000000000000000000000000000000000000083523060048401521691826024830152602096879160449788915afa80156107a3575f9061076a575b6b7fffffffffffffffffffffff91501061057f575b5050505050565b8251905f808784017f095ea7b3000000000000000000000000000000000000000000000000000000009485825284602482015282898201528881526105c3816103cc565b519082875af16105d16107b3565b81610732575b50156106d657915f929183809386519089820193845260248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff88820152878152610623816103cc565b51925af161062f6107b3565b8161069e575b5015610642578080610578565b606492917f5361666520417070726f766500000000000000000000000000000000000000009151927f08c379a00000000000000000000000000000000000000000000000000000000084526004840152600c6024840152820152fd5b809150518481159182156106b7575b505090505f610635565b838092935001031261025d57836106ce91016107e2565b80845f6106ad565b6064867f5361666520417070726f76650000000000000000000000000000000000000000878751927f08c379a00000000000000000000000000000000000000000000000000000000084526004840152600c6024840152820152fd5b8091505187811591821561074b575b505090505f6105d7565b838092935001031261025d578661076291016107e2565b80875f610741565b508581813d831161079c575b610780818361043e565b8101031261025d576b7fffffffffffffffffffffff9051610563565b503d610776565b84513d5f823e3d90fd5b50505050565b3d156107dd573d906107c48261047f565b916107d2604051938461043e565b82523d5f602084013e565b606090565b5190811515820361025d57565b519073ffffffffffffffffffffffffffffffffffffffff8216820361025d57565b67ffffffffffffffff811161032e5760051b60200190565b9080601f8301121561025d5781519060209161084381610810565b93610851604051958661043e565b81855260208086019260051b82010192831161025d57602001905b82821061087a575050505090565b8151815290830190830161086c565b9081518082526020808093019301915f5b8281106108a8575050505090565b83518552938101939281019260010161089a565b5f5b8381106108cd5750505f910152565b81810151838201526020016108be565b81601f8201121561025d5780516108f38161047f565b92610901604051948561043e565b8184526020828401011161025d5761091f91602080850191016108bc565b90565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209361095e815180928187528780880191016108bc565b0116010190565b91908060041161025d576109a0907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc369101600485016104b9565b7fbc80f1a8000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084351614610e08577f12aa3caf000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084351614610bcf577ff78dc253000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084351614610ad9576044837fffffffff00000000000000000000000000000000000000000000000000000000604051917fa7dd6a950000000000000000000000000000000000000000000000000000000083526002600484015235166024820152fd5b90918151820160a08382031261025d57610af5602084016107ef565b93610b02604085016107ef565b9060808501519060a08601519667ffffffffffffffff881161025d57610b5761091f9760207fffffffff000000000000000000000000000000000000000000000000000000009a81610ba39901920101610828565b9373ffffffffffffffffffffffffffffffffffffffff80926040519a8b99351660208a01521660248801521660448601526064850152608484015260a060a484015260c4830190610889565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261043e565b909181518201928260208501940390610140821261025d5760e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610c16602087016107ef565b93011261025d5760405194610c2a86610312565b610c36604086016107ef565b8652610c44606086016107ef565b6020870152610c55608086016107ef565b6040870152610c6660a086016107ef565b606087015260c0850151608087015260e085015160a087015261010085015160c08701526101208501519067ffffffffffffffff9182811161025d57816020610cb1928901016108dd565b9061014087015192831161025d577fffffffff000000000000000000000000000000000000000000000000000000009773ffffffffffffffffffffffffffffffffffffffff610ba396610d1160c0946020610dd79861091f9d01016108dd565b9660808401526040519a8b99351660208a015216602488015273ffffffffffffffffffffffffffffffffffffffff815116604488015273ffffffffffffffffffffffffffffffffffffffff602082015116606488015273ffffffffffffffffffffffffffffffffffffffff604082015116608488015273ffffffffffffffffffffffffffffffffffffffff60608201511660a4880152608081015160c488015260a081015160e48801520151610104860152610140610124860152610164850190610922565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc84830301610144850152610922565b91825183019260808185031261025d57610e24602082016107ef565b606082015160808301519467ffffffffffffffff861161025d5773ffffffffffffffffffffffffffffffffffffffff610e8c610ba395602061091f99817fffffffff000000000000000000000000000000000000000000000000000000009c01920101610828565b9360405198899735166020880152166024860152604485015260648401526080608484015260a4830190610889565b9080601f8301121561025d576020908235610ed581610810565b93610ee3604051958661043e565b81855260208086019260051b82010192831161025d57602001905b828210610f0c575050505090565b838091610f188461027f565b815201910190610efe565b9080601f8301121561025d576020908235610f3d81610810565b93610f4b604051958661043e565b81855260208086019260051b82010192831161025d57602001905b828210610f74575050505090565b81358152908301908301610f66565b9080601f8301121561025d5781602061091f933591016104b9565b91906101608382031261025d5760405190610fb88261035b565b8193610fc38161027f565b8352610fd16020820161027f565b602084015267ffffffffffffffff91604082013583811161025d5781610ff8918401610ebb565b6040850152606082013583811161025d5781611015918401610f23565b6060850152608082013583811161025d5781611032918401610ebb565b608085015260a082013583811161025d578161104f918401610f23565b60a085015261106060c0830161027f565b60c085015260e082013560e085015261010080830135908501526101208083013590850152610140928383013590811161025d5761109e9201610f83565b910152565b9081518082526020808093019301915f5b8281106110c2575050505090565b835173ffffffffffffffffffffffffffffffffffffffff16855293810193928101926001016110b4565b9081518082526020808093019301915f5b82811061110b575050505090565b8351855293810193928101926001016110fd565b9061091f91610160916111a661119461118261117073ffffffffffffffffffffffffffffffffffffffff968787511686528760208801511660208701526040870151908060408801528601906110a3565b606086015185820360608701526110ec565b608085015184820360808601526110a3565b60a084015183820360a08501526110ec565b9260c08301511660c082015260e082015160e0820152610100808301519082015261012080830151908201526101408092015191818403910152610922565b909160049280841161025d5782357fffffffff000000000000000000000000000000000000000000000000000000001691848401917fe21fd0e90000000000000000000000000000000000000000000000000000000084036113dc5784017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc92602084878403011261025d57359467ffffffffffffffff9586811161025d5760a0910193848303011261025d576040519061129f82610378565b6112aa87850161027f565b82526112b86024850161027f565b9660208301978852604485013587811161025d5782826112da92880101610f83565b60408401908152606486013588811161025d5783836112fb92890101610f9e565b9360608101948552608487013598891161025d5761134a61132c6113cb956113979561091f9c610ba39b0101610f83565b966080830197885286519084516020610120840151161515926118d5565b83528552604051998a9860208a0152602060248a015273ffffffffffffffffffffffffffffffffffffffff8092511660448a0152511660648801525160a0608488015260e4870190610922565b9151917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc92838783030160a488015261111f565b9151908483030160c4850152610922565b909391907f8af033fb0000000000000000000000000000000000000000000000000000000084036115295782019060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc848403011261025d57359473ffffffffffffffffffffffffffffffffffffffff861680960361025d5767ffffffffffffffff90602484013582811161025d57838261147a92870101610f9e565b91604485013581811161025d57848361149592880101610f83565b96606486013591821161025d5761091f976114c06114e99661151a956114c695610ba39a0101610f83565b946116ce565b9390604051988997602089015260248801526080604488015260a487019061111f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc9384878303016064880152610922565b91848303016084850152610922565b6084866020604051917f08c379a00000000000000000000000000000000000000000000000000000000083528201526024808201527f496e7075745363616c696e6748656c7065723a20496e76616c69642073656c6560448201527f63746f72000000000000000000000000000000000000000000000000000000006064820152fd5b9192901561162757508151156115c0575090565b3b156115c95790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b82519091501561163a5750805190602001fd5b611678906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190610922565b0390fd5b604051906116898261035b565b815f81525f602082015261014060609182604082015282808201528260808201528260a08201525f60c08201525f60e08201525f6101008201525f6101208201520152565b909291926116da61167c565b5060e0820151918483146118ce5784836116f392614d71565b91815191602092810191838301848385031261025d57848301519267ffffffffffffffff9384811161025d5760a091018095031261025d576040519761173889610378565b8585015184811161025d57828761175192880101614dec565b8952604085015184811161025d57828761176d92880101610828565b93868a01948552606086015181811161025d57838861178e92890101614e55565b9260408b0193845260808701519660608c0197885260a081015192831161025d576117bb920188016108dd565b9260808a019384528951515f5b81811061189b57505061186b94926117eb8593611854936118979a999751614fb4565b835261184361180f6040519c898e9a8b01525160a060408b015260e08a01906110a3565b9451947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc095868a83030160608b01526110ec565b905184888303016080890152614ed5565b925160a086015251908483030160c0850152610922565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810185528461043e565b9190565b806118bc846118b7876118b16001968d51614d5d565b51614ce6565b614d26565b6118c7828a51614d5d565b52016117c8565b9350919050565b939290936118e161167c565b5060e081015191838314614cde57614baf5782826118fe92614d71565b91845194602081878101031261025d5760208101519567ffffffffffffffff871161025d5760c0878301828401031261025d576040519661193e88610394565b6020818401015167ffffffffffffffff811161025d57602083850101603f828487010101121561025d576020818386010101519061197b82610810565b91611989604051938461043e565b808352602083019160208688010160408360051b83888b010101011161025d576040818689010101925b60408360051b83888b010101018410614a69575050505088526119da6040828501016107ef565b60208901526119ed6060828501016107ef565b6040890152611a006080828501016107ef565b606089015282810160a081015160808a015260c001519067ffffffffffffffff821161025d578360208793611a4193828997611a4c990101930101016108dd565b8060a08a0152614fb4565b60a0860152845151905f5b828110611be75750505050604051926020808501528381519160c06040830152825180610100840152610120906020828501928260051b8601019501915f905b828210611b1f57505050506118979260a082602061186b94015173ffffffffffffffffffffffffffffffffffffffff809116606087015280604083015116608087015260608201511682860152608081015160c086015201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08483030160e0850152610922565b9193947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee0908792949703018252855190815180825260208201906020808260051b8501019401925f5b828110611b8a5750505050506020806001929701920192018894939192611a97565b9091929394602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600195030188528851908280611bd48451604085526040850190610922565b9301519101529701950193929101611b68565b611bf2818851614d5d565b51805115614a3c5760200151907fffffffff000000000000000000000000000000000000000000000000000000006020830151167f593611990000000000000000000000000000000000000000000000000000000081145f14611c68575081611c5f8487600195516156ce565b90525b01611a57565b7fa8d2cb11000000000000000000000000000000000000000000000000000000008103611e4b575081516101208180518101031261025d57604051908161012081011067ffffffffffffffff6101208401111761032e57866118b786611d61936101208601604052611cdc602082016107ef565b8652611cea604082016107ef565b6020870152611cfb606082016107ef565b6040870152611d0c608082016153d8565b6060870152611d1d60a082016153d8565b6080870152611d5661012060c0830151928360a08a015260e081015160c08a0152611d4b61010082016107ef565b60e08a0152016107e2565b610100870152614ce6565b60a08201526101006040519173ffffffffffffffffffffffffffffffffffffffff815116602084015273ffffffffffffffffffffffffffffffffffffffff602082015116604084015273ffffffffffffffffffffffffffffffffffffffff6040820151166060840152606081015160ff809116608085015260808201511660a084015260a081015160c084015260c081015160e084015273ffffffffffffffffffffffffffffffffffffffff60e0820151168284015201511515610120820152610120815261014081019281841067ffffffffffffffff85111761032e5760019360405252611c62565b7fd90ce491000000000000000000000000000000000000000000000000000000008103611e89575081611e82848760019551615535565b9052611c62565b7fa3722546000000000000000000000000000000000000000000000000000000008103611ec0575081611e828487600195516156ce565b7f63407a49000000000000000000000000000000000000000000000000000000008103611fff5750815160e08180518101031261025d57600192611f82876118b78760405195611f0f87610312565b611f1b602082016107ef565b8752611f29604082016107ef565b6020880152611f3a606082016107ef565b6040880152611f4b608082016107ef565b6060880152611f7860e060a0830151928360808b0152611f6d60c082016107ef565b60a08b0152016107e2565b60c0880152614ce6565b608083015260c06040519273ffffffffffffffffffffffffffffffffffffffff808251166020860152806020830151166040860152806040830151166060860152806060830151166080860152608082015160a086015260a082015116828501520151151560e083015260e08252611ff9826103e8565b52611c62565b7fca6182da0000000000000000000000000000000000000000000000000000000081036120aa5760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65205246512073776170000000000000000000000000000000000000000000006064820152fd5b7f8cc7a56b0000000000000000000000000000000000000000000000000000000081036121995750815160a08180518101031261025d576001926040516120f081610378565b6120fc602084016107ef565b8152604083015160208201908152612116606085016107ef565b936040830194855260a061212c608083016107ef565b916060850192835201519261214c8b6118b78b6080850197808952614ce6565b84526040519573ffffffffffffffffffffffffffffffffffffffff938480935116602089015251604088015251166060860152511660808401525160a083015260a08252611ff982610394565b7f0ca8ebf10000000000000000000000000000000000000000000000000000000081036122595750815160608180518101031261025d57600192604051916121e083610405565b6121ec602082016107ef565b835260408101519061221c896118b78961220f606060208a0196888852016107e2565b9560408901968752614ce6565b815273ffffffffffffffffffffffffffffffffffffffff6040519451166020850152516040840152511515606083015260608252611ff9826103cc565b7feeb543140000000000000000000000000000000000000000000000000000000081036122bc575081519160208380518101031261025d576122a5866118b78660206001970151614ce6565b9060405191602083015260208252611ff9826103b0565b7f7b797563000000000000000000000000000000000000000000000000000000008103612416575081516101008180518101031261025d57600192612391876118b7876040519561230c876103e8565b612318602082016107ef565b8752612326604082016107ef565b6020880152612337606082016107ef565b6040880152612348608082016107ef565b606088015261238761010060a0830151928360808b015261236b60c082016107ef565b60a08b015261237c60e082016107e2565b60c08b0152016107e2565b60e0880152614ce6565b608083015260e06040519273ffffffffffffffffffffffffffffffffffffffff808251166020860152806020830151166040860152806040830151166060860152806060830151166080860152608082015160a086015260a08201511660c085015260c0810151151582850152015115156101008301526101008252611ff982610421565b7f55fad2fb00000000000000000000000000000000000000000000000000000000810361244d575081611e828487600195516156ce565b7f3b284cfe00000000000000000000000000000000000000000000000000000000810361251157508151918251830160a08482031261025d57600193602080612498930191016153e6565b90606082016124ac886118b7888451614ce6565b90526125046040519260208401906080908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015260608101516060860152015116910152565b60a08252611ff982610394565b7f74836acb0000000000000000000000000000000000000000000000000000000081036126375750815160e08180518101031261025d576001926040519161255883610312565b612564602082016107ef565b8352612572604082016107ef565b6020840152612583606082016107ef565b6040840152608081015160608401526125c8886118b7886125bb60e060a0870151968760808b015260c081015160a08b0152016107e2565b9460c08801958652614ce6565b608084015260a06040519373ffffffffffffffffffffffffffffffffffffffff808251166020870152806020830151166040870152604082015116606086015260608101516080860152608081015182860152015160c084015251151560e083015260e08252611ff9826103e8565b7f800023a10000000000000000000000000000000000000000000000000000000081036126e25760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f6520486173666c6f7720737761700000000000000000000000000000000000006064820152fd5b7f8df4a16b000000000000000000000000000000000000000000000000000000008103612719575081611e828487600195516156ce565b7fd6984a6d0000000000000000000000000000000000000000000000000000000081036127c45760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65204b796265724c4f20737761700000000000000000000000000000000000006064820152fd5b7f8f07985400000000000000000000000000000000000000000000000000000000810361280f57508151918251830160a08482031261025d57600193602080612498930191016153e6565b7fa9b3e398000000000000000000000000000000000000000000000000000000008103612846575081611e828487600195516156ce565b7f92749fe10000000000000000000000000000000000000000000000000000000081036128fc57508151918251830160a08482031261025d576001936020806128919301910161565b565b90608082016128a5886118b7888451614ce6565b90526125046040519260208401906080809173ffffffffffffffffffffffffffffffffffffffff80825116855280602083015116602086015280604083015116604086015260608201511660608501520151910152565b7f27c0cd18000000000000000000000000000000000000000000000000000000008103612a075750815160c08180518101031261025d5760019260405161294281610394565b61294e602084016107ef565b815261295c604084016107ef565b9260208201938452612970606082016107ef565b9360408301948552612984608083016107ef565b6060840190815260a0830151936129b28c6118b78c60c060808601988a8a5201519860a08601998a52614ce6565b84526040519673ffffffffffffffffffffffffffffffffffffffff8094818094511660208b01525116604089015251166060870152511660808501525160a08401525160c083015260c08252611ff982610312565b7fe756cac1000000000000000000000000000000000000000000000000000000008103612b815750815191825183019060208483031261025d57602084015167ffffffffffffffff811161025d5760a081860184031261025d57604051612a6d81610378565b602082870101519167ffffffffffffffff831161025d57600196612aa1611ff994602080612b2099019185850101016108dd565b8352612ab16040838301016107ef565b916020840192835260a0612ac96060838501016107ef565b9160408601928352612adf6080828601016107ef565b936060870194855201015191612b008d6118b78d6080890196808852614ce6565b83526040519788956020808801525160a0604088015260e0870190610922565b935173ffffffffffffffffffffffffffffffffffffffff9283809216606088015251166080860152511660a08401525160c0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810184528361043e565b7f48d31802000000000000000000000000000000000000000000000000000000008103612cb15750815160e08180518101031261025d57600192612c3c876118b78760405195612bd087610312565b612bdc602082016107ef565b8752612bea604082016107ef565b6020880152612bfb606082016107ef565b6040880152612c0c608082016107ef565b606088015260e060a0820151918260808a0152612c2b60c082016107ef565b60a08a0152015160c0880152614ce6565b608083015260c06040519273ffffffffffffffffffffffffffffffffffffffff808251166020860152806020830151166040860152806040830151166060860152806060830151166080860152608082015160a086015260a08201511682850152015160e083015260e08252611ff9826103e8565b7f04cca9f7000000000000000000000000000000000000000000000000000000008103612f405750908051908151820160208382031261025d57602083015167ffffffffffffffff811161025d5760a081850183031261025d5760405193612d1885610378565b612d266020838301016107ef565b85526040828201015167ffffffffffffffff811161025d5760208401603f828585010101121561025d57602081848401010151612d6281610810565b91612d70604051938461043e565b81835260208301906020870160408460051b838989010101011161025d576040818787010101915b60408460051b838989010101018310612f30575050505060208601526060828201015167ffffffffffffffff811161025d57612dde906020808601918585010101614dec565b6040860152608082820101519267ffffffffffffffff841161025d5760a08a936118b793612e1a612e2d976020808e9701918585010101614e55565b60608a0152010151806080880152614ce6565b60808301526040519160208084015260e0830173ffffffffffffffffffffffffffffffffffffffff825116604085015260208201519060a060608601528151809152602061010086019201905f905b808210612f185750505083826080612ee4611ff994612ecf604060019b9a99980151917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0928388830301868901526110a3565b906060850151908683030160a0870152614ed5565b91015160c0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810184528361043e565b90919260208060019286518152019401920190612e7c565b8251815260209283019201612d98565b7faa293da2000000000000000000000000000000000000000000000000000000008103612f77575081611e82848760019551615443565b7f517e7ca1000000000000000000000000000000000000000000000000000000008103612fae575081611e82848760019551615443565b7f1b96cfd40000000000000000000000000000000000000000000000000000000081036130cd575081519160c08380518101031261025d5760405190612ff382610394565b612fff602085016107ef565b825261300d604085016107ef565b602083015261301e606085016107ef565b604083015261302f608085016107ef565b606083015260c060a08501519485608085015201518060020b810361025d57613065886118b78860019860a08801958652614ce6565b608084015260806040519373ffffffffffffffffffffffffffffffffffffffff80825116602087015280602083015116604087015280604083015116606087015260608201511682860152015160a08401525160020b60c083015260c08252611ff982610312565b7f5987cf43000000000000000000000000000000000000000000000000000000008103613104575081611e82848760019551615443565b7fc43025bd00000000000000000000000000000000000000000000000000000000810361320157508151918251830160a08482031261025d5760019360208061314f9301910161565b565b906080820180517f80000000000000000000000000000000000000000000000000000000000000006131a78a6118b78a7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616614ce6565b91161790526125046040519260208401906080809173ffffffffffffffffffffffffffffffffffffffff80825116855280602083015116602086015280604083015116604086015260608201511660608501520151910152565b7f63d71df3000000000000000000000000000000000000000000000000000000008103613238575081611e82848760019551615535565b7fe7e1b5cb0000000000000000000000000000000000000000000000000000000081036133445750815160c08180518101031261025d5760019260405161327e81610394565b61328a602084016107ef565b8152613298604084016107ef565b90602081019182526132ac606085016107ef565b936040820194855260808101519160608101908382526132ef8c6118b78c6132e260c060a08901519860808801998a52016107ef565b9760a08601988952614ce6565b82526040519673ffffffffffffffffffffffffffffffffffffffff8096818094511660208b015251166040890152511660608701525160808601525160a0850152511660c083015260c08252611ff982610312565b7f3ac19910000000000000000000000000000000000000000000000000000000008103613494575081516101008180518101031261025d5760019261340f876118b78760405195613394876103e8565b6133a0602082016107ef565b87526133ae604082016107ef565b60208801526133bf606082016107ef565b60408801526133d0608082016107ef565b60608801526133e160a082016107ef565b60808801526133f260c082016107ef565b60a088015261238761010060e0830151928360c08b0152016107ef565b60c083015273ffffffffffffffffffffffffffffffffffffffff60e0604051938281511660208601528260208201511660408601528260408201511660608601528260608201511660808601528260808201511660a08601528260a08201511660c086015260c0810151828601520151166101008301526101008252611ff982610421565b7f37e96a470000000000000000000000000000000000000000000000000000000081036135b25750815160e08180518101031261025d576001926040516134da81610312565b6134e6602084016107ef565b81526134f4604084016107ef565b9060208101918252613508606085016107ef565b936040820194855260808101516060830190815260a0820151906080840191825260c0830151936135578d6118b78d61354a60e060a08701998b8b52016107ef565b9860c08601998a52614ce6565b84526040519773ffffffffffffffffffffffffffffffffffffffff8097818094511660208c0152511660408a0152511660608801525160808701525160a08601525160c0850152511660e083015260e08252611ff9826103e8565b7f4a8ac7610000000000000000000000000000000000000000000000000000000081036136e55750815160e08180518101031261025d57600192604051916135f983610312565b613605602082016107ef565b83526040810151906020840190828252613621606082016107ef565b9160408601928352613635608083016107ef565b956060810196875261364960a084016107ef565b90608081019182526136858d6118b78d61367860e061366a60c08b016107ef565b9960a088019a8b52016107e2565b9960c086019a8b52614ce6565b83526040519773ffffffffffffffffffffffffffffffffffffffff80968195828095511660208d01525160408c0152511660608a015251166080880152511660a0860152511660c084015251151560e083015260e08252611ff9826103e8565b7fc8e128e40000000000000000000000000000000000000000000000000000000081036137c35750815160808180518101031261025d576001926040519161372c836103cc565b613738602082016107ef565b8352613746604082016107ef565b906020840191825260608101519061377c8a6118b78a61376f608060408b0196888852016107ef565b9560608a01968752614ce6565b81526040519473ffffffffffffffffffffffffffffffffffffffff9384809251166020880152511660408601525160608501525116608083015260808252611ff982610378565b7ffac08e6f0000000000000000000000000000000000000000000000000000000081036137fa575081611e82848760019551615443565b7fe445a7ec000000000000000000000000000000000000000000000000000000008103613831575081611e82848760019551615443565b7f944432e00000000000000000000000000000000000000000000000000000000081036138e657508151918251830160a08482031261025d5760019360208061387c930191016154dc565b9060208201613890886118b7888451614ce6565b90526125046040519260208401906080908173ffffffffffffffffffffffffffffffffffffffff918281511685526020810151602086015260408101516040860152826060820151166060860152015116910152565b7f0e00deaa0000000000000000000000000000000000000000000000000000000081036139c35750815160808180518101031261025d576001926040519161392d836103cc565b613939602082016107ef565b8352613947604082016107ef565b60208401908152608061395c606084016107ef565b926040860193845201519161397c8a6118b78a6060890196808852614ce6565b83526040519473ffffffffffffffffffffffffffffffffffffffff9283809251166020880152511660408601525116606084015251608083015260808252611ff982610378565b7f67f2255d000000000000000000000000000000000000000000000000000000008103613a6e5760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65205377616170563220737761700000000000000000000000000000000000006064820152fd5b7f48bad50c000000000000000000000000000000000000000000000000000000008103613aa5575081611e82848760019551615443565b7fb1f7d82d000000000000000000000000000000000000000000000000000000008103613af057508151918251830160a08482031261025d5760019360208061387c930191016154dc565b7f68abdc71000000000000000000000000000000000000000000000000000000008103613c4d5750815191825183019060208483031261025d5760208401519367ffffffffffffffff851161025d57608085820184031261025d5760405194613b58866103cc565b613b666020828401016107ef565b8652604081830101519167ffffffffffffffff831161025d57600196613b9c611ff994602080613c139901918686010101614dec565b9260208201938452613bd58c6118b78c613bc860806060878a010151966040890199888b5201016107ef565b9460608701958652614ce6565b835260405196879460208087015273ffffffffffffffffffffffffffffffffffffffff809451166040870152516080606087015260c08601906110a3565b92516080850152511660a0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810184528361043e565b7f152dc1cf000000000000000000000000000000000000000000000000000000008103613c84575081611e82848760019551615443565b7f98923834000000000000000000000000000000000000000000000000000000008103613dd8575081519160c08380518101031261025d5760405190613cc982610394565b613cd5602085016107ef565b825260408401516fffffffffffffffffffffffffffffffff8116810361025d57613d5b886118b7886fffffffffffffffffffffffffffffffff85613d5060c060019c849960208d0152613d2a606082016107ef565b60408d0152613d3b608082016107ef565b60608d015260a081015160808d0152016153d8565b60a08a015216614ce6565b16602083015260ff60a06040519373ffffffffffffffffffffffffffffffffffffffff8082511660208701526fffffffffffffffffffffffffffffffff6020830151166040870152806040830151166060870152606082015116608086015260808101518286015201511660c083015260c08252611ff982610312565b7e3c5f89000000000000000000000000000000000000000000000000000000008103613e825760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65204e61746976652073776170000000000000000000000000000000000000006064820152fd5b7fddfb5cb6000000000000000000000000000000000000000000000000000000008103613fa95750815160c08180518101031261025d5760019260405191613ec983610394565b613ed5602082016107ef565b8352604081015160208401818152613eef606084016107e2565b9260408601938452613f03608082016107ef565b95606081019687526fffffffffffffffffffffffffffffffff613f508d6118b78d613f4360c0613f3560a08a016107ef565b9860808901998a52016107ef565b9860a08701998a52614ce6565b1683526040519673ffffffffffffffffffffffffffffffffffffffff958694858094511660208b01525160408a0152511515606089015251166080870152511660a0850152511660c083015260c08252611ff982610312565b7f3bbc6abf0000000000000000000000000000000000000000000000000000000081036140545760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f496e7075745363616c696e6748656c7065723a2043616e206e6f74207363616c60448201527f65204265626f70207377617000000000000000000000000000000000000000006064820152fd5b7f180a5b7600000000000000000000000000000000000000000000000000000000810361411d57508151918251830160a08482031261025d5760019360208061409f9301910161532f565b90602082016fffffffffffffffffffffffffffffffff6140c4896118b7898551614ce6565b1690526125046040519260208401906080908173ffffffffffffffffffffffffffffffffffffffff9182815116855260208101516020860152826040820151166040860152826060820151166060860152015116910152565b7f63123dbb000000000000000000000000000000000000000000000000000000008103614154575081611e82848760019551615194565b7ff9c357e00000000000000000000000000000000000000000000000000000000081036141f75750815160408180518101031261025d576001926040519161419b836103b0565b6fffffffffffffffffffffffffffffffff6141d5896118b7896141c86040602088015197888b52016107e2565b9560208901968752614ce6565b16809352604051926020840152511515604083015260408252611ff982610405565b7fd883ad9f0000000000000000000000000000000000000000000000000000000081036142a457508151918251830160408482031261025d5760019360208061424293019101615292565b906fffffffffffffffffffffffffffffffff614263886118b7888651614ce6565b16825261429760405192602084019073ffffffffffffffffffffffffffffffffffffffff6020809280518552015116910152565b60408252611ff982610405565b7f0343ecaf0000000000000000000000000000000000000000000000000000000081036142db575081611e828487600195516152bc565b7f020918a10000000000000000000000000000000000000000000000000000000081036143c057508151918251830160408482031261025d57600193602080614326930191016151dc565b90602082016fffffffffffffffffffffffffffffffff61434d896118b78984865116614ce6565b167f8000000000000000000000000000000000000000000000000000000000000000868351908060ff92831c145f146143b857905b1b161790526142976040519260208401906020809173ffffffffffffffffffffffffffffffffffffffff81511684520151910152565b505f90614382565b7f95d02f7d0000000000000000000000000000000000000000000000000000000081036144a157508151918251830160408482031261025d5760019360208061440b93019101615292565b906fffffffffffffffffffffffffffffffff61442e886118b78884875116614ce6565b167f8000000000000000000000000000000000000000000000000000000000000000858451908060ff92831c145f1461449957905b1b1617825261429760405192602084019073ffffffffffffffffffffffffffffffffffffffff6020809280518552015116910152565b505f90614463565b7fc390adea00000000000000000000000000000000000000000000000000000000810361456b57508151918251830160808482031261025d576001936020806144ec9301910161538c565b90602082016fffffffffffffffffffffffffffffffff614511896118b7898551614ce6565b16905261455e6040519260208401906060908173ffffffffffffffffffffffffffffffffffffffff9182815116855260208101516020860152826040820151166040860152015116910152565b60808252611ff982610378565b7fc9989fac0000000000000000000000000000000000000000000000000000000081036145a2575081611e82848760019551615194565b7f5829bd520000000000000000000000000000000000000000000000000000000081036145d9575081611e82848760019551615194565b7f87ab3c27000000000000000000000000000000000000000000000000000000008103614610575081611e828487600195516150ef565b7fba176e5c00000000000000000000000000000000000000000000000000000000810361465b57508151918251830160808482031261025d576001936020806144ec9301910161538c565b7fe937b9a900000000000000000000000000000000000000000000000000000000810361476557508151918251830160a08482031261025d576001936020806146a69301910161532f565b90602082016fffffffffffffffffffffffffffffffff6146cd896118b78984865116614ce6565b167f8000000000000000000000000000000000000000000000000000000000000000868351908060ff92831c145f1461475d57905b1b161790526125046040519260208401906080908173ffffffffffffffffffffffffffffffffffffffff9182815116855260208101516020860152826040820151166040860152826060820151166060860152015116910152565b505f90614702565b7f323b615300000000000000000000000000000000000000000000000000000000810361479c575081611e82848760019551615194565b7ff17912eb0000000000000000000000000000000000000000000000000000000081036147d3575081611e82848760019551615194565b7fcebf718d00000000000000000000000000000000000000000000000000000000810361480a575081611e828487600195516152bc565b7fa8e60da0000000000000000000000000000000000000000000000000000000008103614841575081611e8284876001955161520b565b7fd5c275ad000000000000000000000000000000000000000000000000000000008103614878575081611e8284876001955161520b565b7fac40622c00000000000000000000000000000000000000000000000000000000810361494c575081519160208380518101031261025d5760206001930151906fffffffffffffffffffffffffffffffff6148d9886118b788848716614ce6565b16848060ff94851c145f14614924577f8000000000000000000000000000000000000000000000000000000000000000905b604051941b1617602083015260208252611ff9826103b0565b507f80000000000000000000000000000000000000000000000000000000000000005f61490b565b7fe93d0ac7000000000000000000000000000000000000000000000000000000008103614983575081611e82848760019551615194565b7fd1019fd000000000000000000000000000000000000000000000000000000000036149b85781611e828487600195516150ef565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4167677265676174696f6e4578656375746f723a204465782074797065206e6f60448201527f7420737570706f727465640000000000000000000000000000000000000000006064820152fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b835167ffffffffffffffff811161025d576020888a0101605f82858a8d01010101121561025d5760408184898c010101015188614aa582610810565b92614ab3604051948561043e565b8284526020808501928d01018c8b0187018201600585901b016060011161025d578960608d8389838282878601010101945b8860051b9301010101018110614b085750505090825250602093840193016119b3565b80519267ffffffffffffffff841161025d5760407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08f8f968f8c889184010101019687910103011261025d5760405193614b61856103b0565b60608101519467ffffffffffffffff861161025d578f918f8f97606095889460808f95614b9b602096958b8880988d0101918401016108dd565b835201518382015281520195019496614ae5565b8282614bbe9296939496614d71565b91815191602092810191838301848385031261025d57848301519267ffffffffffffffff9384811161025d5760a091018095031261025d5760405197614c0389610378565b8585015184811161025d578287614c1c92880101614dec565b8952604085015184811161025d578287614c3892880101610828565b93868a01948552606086015181811161025d578388614c5992890101614e55565b9260408b0193845260808701519660608c0197885260a081015192831161025d57614c86920188016108dd565b9260808a019384528951515f5b818110614cb657505061186b94926117eb8593611854936118979a999751614fb4565b80614ccc846118b7876118b16001968d51614d5d565b614cd7828a51614d5d565b5201614c93565b509150509190565b81810292918115918404141715614cf957565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8115614d30570490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b8051821015614a3c5760209160051b010190565b91614d7a61167c565b506101008301614d8f836118b7848451614ce6565b80825215614de2575b508060e0840152604083015151915f5b838110614db6575050505090565b60019060608601614ddb82614dd4866118b7896118b1858851614d5d565b9251614d5d565b5201614da8565b600190525f614d98565b9080601f8301121561025d57815190602091614e0781610810565b93614e15604051958661043e565b81855260208086019260051b82010192831161025d57602001905b828210614e3e575050505090565b838091614e4a846107ef565b815201910190614e30565b81601f8201121561025d57805191602091614e6f84610810565b93614e7d604051958661043e565b808552838086019160051b8301019280841161025d57848301915b848310614ea85750505050505090565b825167ffffffffffffffff811161025d578691614eca848480948901016108dd565b815201920191614e98565b90808251908181526020809101926020808460051b8301019501935f915b848310614f035750505050505090565b9091929394958480614f3f837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a51610922565b9801930193019194939290614ef3565b15614f5657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f457863656564656420747970652072616e6765000000000000000000000000006044820152fd5b919082918251906020918281115f1461505c5750835160409485918101031261025d577fffffffffffffffffffffffffffffffff0000000000000000000000000000000084805196615005886103b0565b8481015188520151615040615037858901968388526118b76fffffffffffffffffffffffffffffffff96878616614ce6565b93841115614f4f565b1617825282519351908401525181830152815261091f81610405565b9091809394508114615070575b5050505090565b918480929382959601031261025d576150a7836150b0920151946118b76fffffffffffffffffffffffffffffffff94858816614ce6565b91821115614f4f565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000006040519316178183015281526150e6816103b0565b5f808080615069565b9160608380518101031261025d576fffffffffffffffffffffffffffffffff6151556040519361511e85610405565b61512a602087016107ef565b85526118b760408701519461514860606020890199888b52016107ef565b9560408801968752614ce6565b1683526040519273ffffffffffffffffffffffffffffffffffffffff809351166020850152516040840152511660608201526060815261091f816103cc565b919060208380518101031261025d576118b76151c59260206fffffffffffffffffffffffffffffffff950151614ce6565b166040519060208201526020815261091f816103b0565b919082604091031261025d576040516151f4816103b0565b6020808294615202816107ef565b84520151910152565b919091805181019060408183031261025d57615241615251916020806fffffffffffffffffffffffffffffffff950191016151dc565b936118b760208601948551614ce6565b1690526152856040519160208301906020809173ffffffffffffffffffffffffffffffffffffffff81511684520151910152565b6040815261091f81610405565b919082604091031261025d576040516152aa816103b0565b602061109e81839580518552016107ef565b90815182019060408383031261025d576118b76152f36fffffffffffffffffffffffffffffffff946020806152fb96019101615292565b948551614ce6565b16815261528560405191602083019073ffffffffffffffffffffffffffffffffffffffff6020809280518552015116910152565b91908260a091031261025d5760405161534781610378565b608061109e818395615358816107ef565b855260208101516020860152615370604082016107ef565b6040860152615381606082016107ef565b6060860152016107ef565b919082608091031261025d576040516153a4816103cc565b606061109e8183956153b5816107ef565b8552602081015160208601526153cd604082016107ef565b6040860152016107ef565b519060ff8216820361025d57565b91908260a091031261025d576040516153fe81610378565b608061109e81839561540f816107ef565b855261541d602082016107ef565b602086015261542e604082016107ef565b604086015260608101516060860152016107ef565b9190918051810160a08282031261025d5761547791602080615467930191016153e6565b926118b760608501938451614ce6565b90526154cf6040519160208301906080908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015260608101516060860152015116910152565b60a0815261091f81610394565b91908260a091031261025d576040516154f481610378565b608061109e818395615505816107ef565b85526020810151602086015260408101516040860152615381606082016107ef565b519081600f0b820361025d57565b9190829182516101009485918101031261025d5760a08493604051958694859461555e866103e8565b61556a602085016107ef565b86526155f561557b604086016107ef565b92602088019384526118b7615592606088016107ef565b9360408a019485528960e06155eb6155ac60808c01615527565b99606084019a8b526155bf8d8d01615527565b9b608085019c8d5260c08101519d8e95019d8e5260c06155e08583016107e2565b9f019e8f52016107e2565b9c019b8c52614ce6565b85526040519873ffffffffffffffffffffffffffffffffffffffff92838092511660208c0152511660408a01525116606088015251600f0b608087015251600f0b60a08601525160c085015251151560e084015251151581830152815261091f81610421565b91908260a091031261025d5760405161567381610378565b6080808294615681816107ef565b845261568f602082016107ef565b60208501526156a0604082016107ef565b60408501526156b1606082016107ef565b60608501520151910152565b519063ffffffff8216820361025d57565b80919281516101009384918101031261025d57818060c092604051906156f3826103e8565b6156ff602084016107ef565b825261570d604084016107ef565b916020810192835261578d615724606086016107ef565b99604083019a8b526118b761573b608088016107ef565b94606085019586526157808c61577260e061576460a08d01519e8f9d60808c019e8f52016156bd565b9c60a08a019d8e52016156bd565b9c60c088019d8e52016156bd565b9960e086019a8b52614ce6565b84526040519873ffffffffffffffffffffffffffffffffffffffff8094818094511660208d0152511660408b015251166060890152511660808701525160a08601525163ffffffff928380921660c0870152511660e0850152511681830152815261091f8161042156fea2646970667358221220d0795bdc5bd2dd32e5c1d0a36090ad6cd21b3d392ef24a8e99c59565c715baa464736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.