Overview
S Balance
0 S
S Value
-More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
434347 | 15 days ago | Contract Creation | 0 S |
Loading...
Loading
Contract Name:
FluidVaultLiquidationResolver
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 10000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { Variables } from "./variables.sol"; import { Structs } from "./structs.sol"; import { FluidProtocolTypes } from "../../../libraries/fluidProtocolTypes.sol"; import { Structs as VaultResolverStructs } from "../vault/structs.sol"; import { IFluidVaultResolver } from "../vault/iVaultResolver.sol"; import { IFluidVaultT1 } from "../../../protocols/vault/interfaces/iVaultT1.sol"; /// @notice Resolver contract that helps in finding available token (liquidation) swaps available in Fluid VaultT1s. /// @dev Note that on the same protocol, if "withAbsorb = true" is executed, this also consumes the swap /// that would be on the same protocol with "withAbsorb = false". So the total available swap amount /// at a protocol if both a swap with and without absorb is available is not `with inAmt + without inAmt` /// but rather `with inAmt`. /// Sometimes with absorb can provide better swaps, sometimes without absorb can provide better swaps. /// But available liquidity for "withAbsorb" amounts will always be >= without absorb amounts. /// @dev The "Raw" methods return both the with and without absorb swaps for the same Fluid Vault, the non-"Raw" /// methods automatically filter by the better ratio swap. For same cases a better optimization of ratios /// is possible with custom logic based on the "Raw" methods, see details in comments. /// @dev for native token, send 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE. /// @dev returned swaps Struct can be fed into `getSwapTx` to prepare the tx that executes the swaps. /// @dev non-view methods in this contract are expected to be called with callStatic, /// although they would anyway not do any actual state changes. contract FluidVaultLiquidationResolver is Variables, Structs { /// @notice thrown if an input param address is zero error FluidVaultLiquidationsResolver__AddressZero(); /// @notice thrown if an invalid param is given to a method error FluidVaultLiquidationsResolver__InvalidParams(); /// @notice constructor sets the immutable vault resolver address constructor(IFluidVaultResolver vaultResolver_) Variables(vaultResolver_) { if (address(vaultResolver_) == address(0)) { revert FluidVaultLiquidationsResolver__AddressZero(); } } /// @notice returns all available token swap paths function getAllSwapPaths() public view returns (SwapPath[] memory paths_) { address[] memory vaultAddresses_ = _getVaultT1s(); paths_ = new SwapPath[](vaultAddresses_.length); address borrowToken_; address supplyToken_; for (uint256 i; i < vaultAddresses_.length; ++i) { (borrowToken_, supplyToken_) = _getVaultTokens(vaultAddresses_[i]); paths_[i] = SwapPath({ protocol: vaultAddresses_[i], tokenIn: borrowToken_, tokenOut: supplyToken_ }); } } /// @notice returns all swap paths for a certain `tokenIn_` swapped to a `tokenOut_`. /// returns empty array if no swap path is available for a given pair. function getSwapPaths(address tokenIn_, address tokenOut_) public view returns (SwapPath[] memory paths_) { address[] memory vaultAddresses_ = _getVaultT1s(); uint256 foundVaultsCount_; address[] memory foundVaults_ = new address[](vaultAddresses_.length); address borrowToken_; address supplyToken_; for (uint256 i; i < vaultAddresses_.length; ++i) { (borrowToken_, supplyToken_) = _getVaultTokens(vaultAddresses_[i]); if (borrowToken_ == tokenIn_ && supplyToken_ == tokenOut_) { foundVaults_[foundVaultsCount_] = vaultAddresses_[i]; ++foundVaultsCount_; } } paths_ = new SwapPath[](foundVaultsCount_); for (uint256 i; i < foundVaultsCount_; ++i) { paths_[i] = SwapPath({ protocol: foundVaults_[i], tokenIn: tokenIn_, tokenOut: tokenOut_ }); } } /// @notice returns all available swap paths for any `tokensIn_` to any `tokensOut_`. function getAnySwapPaths( address[] calldata tokensIn_, address[] calldata tokensOut_ ) public view returns (SwapPath[] memory paths_) { SwapPath[] memory maxPaths_ = new SwapPath[](tokensIn_.length * tokensOut_.length); address[] memory vaultAddresses_ = _getVaultT1s(); uint256 matches_; address borrowToken_; address supplyToken_; unchecked { for (uint256 vi; vi < vaultAddresses_.length; ++vi) { (borrowToken_, supplyToken_) = _getVaultTokens(vaultAddresses_[vi]); // for each vault, iterate over all possible input params token combinations for (uint256 i; i < tokensIn_.length; ++i) { for (uint256 j; j < tokensOut_.length; ++j) { if (borrowToken_ == tokensIn_[i] && supplyToken_ == tokensOut_[j]) { maxPaths_[matches_] = SwapPath({ protocol: vaultAddresses_[vi], tokenIn: borrowToken_, tokenOut: supplyToken_ }); ++matches_; } } } } paths_ = new SwapPath[](matches_); for (uint256 i; i < matches_; ++i) { paths_[i] = maxPaths_[i]; } } } /// @notice returns the swap data for with and without absorb for a Fluid `vault_`. function getVaultSwapData( address vault_ ) public returns (SwapData memory withoutAbsorb_, SwapData memory withAbsorb_) { VaultResolverStructs.LiquidationStruct memory liquidationData_ = VAULT_RESOLVER.getVaultLiquidation(vault_, 0); withoutAbsorb_ = SwapData({ inAmt: liquidationData_.inAmt, outAmt: liquidationData_.outAmt, withAbsorb: false, ratio: _calcRatio(liquidationData_.inAmt, liquidationData_.outAmt) }); withAbsorb_ = SwapData({ inAmt: liquidationData_.inAmtWithAbsorb, outAmt: liquidationData_.outAmtWithAbsorb, withAbsorb: true, ratio: _calcRatio(liquidationData_.inAmtWithAbsorb, liquidationData_.outAmtWithAbsorb) }); } /// @notice returns the swap data for with and without absorb for multiple Fluid `vaults_`. function getVaultsSwapData( address[] memory vaults_ ) public returns (SwapData[] memory withoutAbsorb_, SwapData[] memory withAbsorb_) { withoutAbsorb_ = new SwapData[](vaults_.length); withAbsorb_ = new SwapData[](vaults_.length); for (uint256 i; i < vaults_.length; ++i) { (withoutAbsorb_[i], withAbsorb_[i]) = getVaultSwapData(vaults_[i]); } } /// @notice returns the swap data for with and without absorb for all Fluid vaults. function getAllVaultsSwapData() public returns (SwapData[] memory withoutAbsorb_, SwapData[] memory withAbsorb_) { return getVaultsSwapData(_getVaultT1s()); } /// @notice returns the available swap amounts at a certain `protocol_`. Only returns non-zero swaps. /// For vault protocol considering both a swap that uses liquidation with absorb and without absorb. function getSwapForProtocol(address protocol_) public returns (Swap memory swap_) { if (protocol_ == address(0)) { return swap_; } (address borrowToken_, address supplyToken_) = _getVaultTokens(protocol_); (SwapData memory withoutAbsorb_, SwapData memory withAbsorb_) = getVaultSwapData(protocol_); return Swap({ path: SwapPath({ protocol: protocol_, tokenIn: borrowToken_, tokenOut: supplyToken_ }), data: _getBetterRatioSwapData(withoutAbsorb_, withAbsorb_) }); } /// @notice returns all available `swaps_` for multiple Fluid `vaults_` raw. Only returns non-zero swaps. /// includes all swaps unfiltered, e.g. with absorb and without absorb swaps are present for the same vault. function getVaultsSwapRaw(address[] memory vaults_) public returns (Swap[] memory swaps_) { unchecked { uint256 nonZeroSwaps_; Swap[] memory allSwaps_ = new Swap[](vaults_.length * 2); SwapData memory withoutAbsorb_; SwapData memory withAbsorb_; address borrowToken_; address supplyToken_; for (uint256 i; i < vaults_.length; ++i) { (withoutAbsorb_, withAbsorb_) = getVaultSwapData(vaults_[i]); if (withAbsorb_.inAmt == 0) { // if with absorb is 0, then without absorb can only be 0 too continue; } ++nonZeroSwaps_; if (withAbsorb_.inAmt == withoutAbsorb_.inAmt) { // with absorb has the same liquidity as without absorb. // running liquidate() with absorb in that case only costs extra gas. return only without absorb swap withAbsorb_.inAmt = 0; } else if (withoutAbsorb_.inAmt > 0) { // both with and without absorb swaps ++nonZeroSwaps_; } (borrowToken_, supplyToken_) = _getVaultTokens(vaults_[i]); allSwaps_[i * 2] = Swap({ path: SwapPath({ protocol: vaults_[i], tokenIn: borrowToken_, tokenOut: supplyToken_ }), data: withoutAbsorb_ }); allSwaps_[i * 2 + 1] = Swap({ path: SwapPath({ protocol: vaults_[i], tokenIn: borrowToken_, tokenOut: supplyToken_ }), data: withAbsorb_ }); } return _getNonZeroSwaps(allSwaps_, nonZeroSwaps_); } } /// @notice returns all available `swaps_` for all Fluid vaults raw. Only returns non-zero swaps. /// includes all swaps unfiltered, e.g. with absorb and without absorb swaps are present for the same vault. function getAllVaultsSwapRaw() public returns (Swap[] memory swaps_) { return getVaultsSwapRaw(_getVaultT1s()); } /// @notice returns all the available `swaps_` for certain swap `paths_`. Only returns non-zero swaps. /// includes all swaps unfiltered, e.g. with absorb and without absorb swaps are present for the same vault. function getSwapsForPathsRaw(SwapPath[] memory paths_) public returns (Swap[] memory swaps_) { unchecked { Swap[] memory allSwaps_ = new Swap[](paths_.length * 2); uint256 nonZeroSwaps_; SwapData memory withoutAbsorb_; SwapData memory withAbsorb_; for (uint256 i; i < paths_.length; ++i) { (withoutAbsorb_, withAbsorb_) = getVaultSwapData(paths_[i].protocol); if (withAbsorb_.inAmt == 0) { // if with absorb is 0, then without absorb can only be 0 too continue; } ++nonZeroSwaps_; if (withAbsorb_.inAmt == withoutAbsorb_.inAmt) { // with absorb has the same liquidity as without absorb. // running liquidate() with absorb in that case only costs extra gas. return only without absorb swap withAbsorb_.inAmt = 0; } else if (withoutAbsorb_.inAmt > 0) { // both with and without absorb swaps ++nonZeroSwaps_; } allSwaps_[i * 2] = Swap({ path: paths_[i], data: withoutAbsorb_ }); allSwaps_[i * 2 + 1] = Swap({ path: paths_[i], data: withAbsorb_ }); } swaps_ = new Swap[](nonZeroSwaps_); uint256 index_; for (uint256 i; i < allSwaps_.length; ++i) { if (allSwaps_[i].data.inAmt > 0) { swaps_[index_] = allSwaps_[i]; ++index_; } } } } /// @notice finds all available `swaps_` for `tokenIn_` to `tokenOut_`. /// includes all swaps unfiltered, e.g. with absorb and without absorb swaps are present for the same vault. function getSwapsRaw(address tokenIn_, address tokenOut_) public returns (Swap[] memory swaps_) { return getSwapsForPathsRaw(getSwapPaths(tokenIn_, tokenOut_)); } /// @notice finds all available `swaps_` for any `tokensIn_` to any `tokesnOut_`. /// Token pairs that are not available or where available swap amounts are zero /// will not be present in the returned `swaps_` array. /// includes all swaps unfiltered, e.g. with absorb and without absorb swaps are present for the same vault. function getAnySwapsRaw( address[] calldata tokensIn_, address[] calldata tokensOut_ ) public returns (Swap[] memory swaps_) { return getSwapsForPathsRaw(getAnySwapPaths(tokensIn_, tokensOut_)); } /// @notice returns all available `swaps_` for multiple Fluid `vaults_`. Only returns non-zero swaps. /// returns only either the with absorb swap or without absorb swap for each vault, whichever has the /// better ratio. function getVaultsSwap(address[] memory vaults_) public returns (Swap[] memory swaps_) { unchecked { uint256 nonZeroSwaps_; Swap[] memory allSwaps_ = new Swap[](vaults_.length); SwapData memory withoutAbsorb_; SwapData memory withAbsorb_; Swap memory swap_; for (uint256 i; i < vaults_.length; ++i) { (withoutAbsorb_, withAbsorb_) = getVaultSwapData(vaults_[i]); swap_ = Swap({ path: SwapPath({ protocol: vaults_[i], tokenIn: address(0), tokenOut: address(0) }), data: _getBetterRatioSwapData(withoutAbsorb_, withAbsorb_) }); if (swap_.data.inAmt == 0) { // no swap available on this vault continue; } ++nonZeroSwaps_; (swap_.path.tokenIn, swap_.path.tokenOut) = _getVaultTokens(vaults_[i]); allSwaps_[i] = swap_; } return _getNonZeroSwaps(allSwaps_, nonZeroSwaps_); } } /// @notice returns all available `swaps_` for all Fluid vaults. Only returns non-zero swaps. /// returns only either the with absorb swap or without absorb swap for each vault, whichever has the /// better ratio. function getAllVaultsSwap() public returns (Swap[] memory swaps_) { return getVaultsSwap(_getVaultT1s()); } /// @notice returns all the available `swaps_` for certain swap `paths_`. Only returns non-zero swaps. /// returns only either the with absorb swap or without absorb swap for each vault, whichever has the /// better ratio. function getSwapsForPaths(SwapPath[] memory paths_) public returns (Swap[] memory swaps_) { unchecked { Swap[] memory allSwaps_ = new Swap[](paths_.length); uint256 nonZeroSwaps_; Swap memory swap_; SwapData memory withoutAbsorb_; SwapData memory withAbsorb_; for (uint256 i; i < paths_.length; ++i) { (withoutAbsorb_, withAbsorb_) = getVaultSwapData(paths_[i].protocol); swap_ = Swap({ path: paths_[i], data: _getBetterRatioSwapData(withoutAbsorb_, withAbsorb_) }); if (swap_.data.inAmt == 0) { // no swap available on this vault continue; } ++nonZeroSwaps_; allSwaps_[i] = swap_; } return _getNonZeroSwaps(allSwaps_, nonZeroSwaps_); } } /// @notice finds all available `swaps_` for `tokenIn_` to `tokenOut_`. /// returns only either the with absorb swap or without absorb swap for each vault, whichever has the /// better ratio. function getSwaps(address tokenIn_, address tokenOut_) public returns (Swap[] memory swaps_) { return getSwapsForPaths(getSwapPaths(tokenIn_, tokenOut_)); } /// @notice finds all available `swaps_` for any `tokensIn_` to any `tokesnOut_`. /// Token pairs that are not available or where available swap amounts are zero /// will not be present in the returned `swaps_` array. /// returns only either the with absorb swap or without absorb swap for each vault, whichever has the /// better ratio. function getAnySwaps( address[] calldata tokensIn_, address[] calldata tokensOut_ ) public returns (Swap[] memory swaps_) { return getSwapsForPaths(getAnySwapPaths(tokensIn_, tokensOut_)); } /// @notice returns the calldata to execute a swap as returned by the other methods in this contract. /// `swap_.data.inAmt` must come from msg.sender, `swap_.data.outAmt` goes to `receiver_`. If the input token /// is the native token, msg.value must be sent along when triggering the actual call with the returned calldata /// which should be `swap_.data.inAmt`. /// @param swap_ Swap struct as returned by other methods /// @param receiver_ receiver address that the output token is sent to /// @param slippage_ maximum allowed slippage for the expected output token amount. Reverts iIf received token out /// amount is lower than this. in 1e4 percentage, e.g. 1% = 10000, 0.3% = 3000, 0.01% = 100, 0.0001% = 1. /// @return target_ target address where `calldata_` must be executed /// @return calldata_ the calldata that can be used to trigger the liquidation call, resulting in the desired swap. function getSwapTx( Swap calldata swap_, address receiver_, uint256 slippage_ ) public pure returns (address target_, bytes memory calldata_) { if (swap_.path.protocol == address(0) || receiver_ == address(0)) { revert FluidVaultLiquidationsResolver__AddressZero(); } if (slippage_ >= 1e6 || swap_.data.inAmt == 0 || swap_.data.outAmt == 0) { revert FluidVaultLiquidationsResolver__InvalidParams(); } uint256 colPerUnitDebt_ = (swap_.data.outAmt * 1e18) / swap_.data.inAmt; colPerUnitDebt_ = (colPerUnitDebt_ * (1e6 - slippage_)) / 1e6; // e.g. 50 * 99% / 100% = 49.5 calldata_ = abi.encodeWithSelector( IFluidVaultT1(swap_.path.protocol).liquidate.selector, swap_.data.inAmt, colPerUnitDebt_, receiver_, swap_.data.withAbsorb ); target_ = swap_.path.protocol; } /// @notice returns the same data as `getSwapTx` for an array of input `swaps_` at once. function getSwapTxs( Swap[] calldata swaps_, address receiver_, uint256 slippage_ ) public pure returns (address[] memory targets_, bytes[] memory calldatas_) { targets_ = new address[](swaps_.length); calldatas_ = new bytes[](swaps_.length); for (uint256 i; i < swaps_.length; ++i) { (targets_[i], calldatas_[i]) = getSwapTx(swaps_[i], receiver_, slippage_); } } /// @notice finds all swaps from `tokenIn_` to `tokenOut_` for an exact input amount `inAmt_`. /// filters the available swaps and sorts them by ratio, so the returned swaps are the best available /// swaps to reach the target `inAmt_`. /// If the full available amount is less than the target `inAmt_`, the available amount is returned as `actualInAmt_`. /// @dev The only cases that are currently not best possible optimized for are when the ratio for withoutAbsorb is better /// but the target swap amount is more than the available without absorb liquidity. For this, currently the available /// withAbsorb liquidity is consumed first before tapping into the better ratio withoutAbsorb liquidity. /// The optimized version would be to split the tx into two swaps, first executing liquidate() with absorb = false /// to fully swap all the withoutAbsorb liquidity, and then in the second tx run with absorb = true to fill the missing /// amount up to the target amount with the worse ratio with absorb liquidity. /// @param tokenIn_ input token /// @param tokenOut_ output token /// @param inAmt_ exact input token amount that should be swapped to output token /// @return swaps_ swaps to reach the target amount, sorted by ratio in descending order /// (higher ratio = better rate). Best ratio swap will be at pos 0, second best at pos 1 and so on. /// @return actualInAmt_ actual input token amount. Can be less than inAmt_ if all available swaps can not cover /// the target amount. /// @return outAmt_ output token amount received for `actualInAmt_` function exactInput( address tokenIn_, address tokenOut_, uint256 inAmt_ ) public returns (Swap[] memory swaps_, uint256 actualInAmt_, uint256 outAmt_) { return filterToTargetInAmt(getSwapsRaw(tokenIn_, tokenOut_), inAmt_); } /// @notice finds all swaps from `tokenIn_` to `tokenOut_` for an APPROXIMATE output amount `outAmt_`. /// filters the available swaps and sorts them by ratio, so the returned swaps are the best available /// swaps to reach the target `outAmt_`. /// If the full available amount is less than the target `outAmt_`, the available amount is returned as `actualOutAmt_`. /// IMPORTANT: guaranteed exact output swaps are not possible with Fluid, this method only aims to /// approximately estimate the required input amounts to reach a certain output amount. This /// will change until execution and should be controlled with a maximum slippage. /// Recommended to use exact input methods instead. /// @dev The only cases that are currently not best possible optimized for are when the ratio for withoutAbsorb is better /// but the target swap amount is more than the available without absorb liquidity. For this currently the available /// withAbsorb liquidity is consumed first before tapping into the better ratio withoutAbsorb liquidity. /// The optimized version would be to split the tx into two swaps, first executing liquidate() with absorb = false /// to fully swap all the withoutAbsorb liquidity, and then in the second tx run with absorb = true to fill the missing /// amount up to the target amount with the worse ratio with absorb liquidity. /// @param tokenIn_ input token /// @param tokenOut_ output token /// @param outAmt_ exact output token amount that should be swapped to from input token /// @return swaps_ swaps to reach the target amount, sorted by ratio in descending order /// (higher ratio = better rate). Best ratio swap will be at pos 0, second best at pos 1 and so on. /// @return inAmt_ input token amount needed to receive `actualOutAmt_` /// @return approxOutAmt_ approximate output token amount. Can be less than `outAmt_` if all available swaps can not cover /// the target amount. function approxOutput( address tokenIn_, address tokenOut_, uint256 outAmt_ ) public returns (Swap[] memory swaps_, uint256 inAmt_, uint256 approxOutAmt_) { return filterToApproxOutAmt(getSwapsRaw(tokenIn_, tokenOut_), outAmt_); } /// @notice filters the `swaps_` to the point where `targetInAmt_` is reached. /// This is best used in combination with the "Raw" methods, as the `targetInAmt_` allows for more optimized /// filtering than otherwise done with the non-"Raw" methods. /// @return filteredSwaps_ swaps to reach the target amount, sorted by ratio in descending order /// (higher ratio = better rate). Best ratio swap will be at pos 0, second best at pos 1 and so on. /// @return actualInAmt_ actual input amount. Can be less than targetInAmt_ if all available swaps can not cover /// the target amount. /// @return approxOutAmt_ actual estimated output amount. function filterToTargetInAmt( Swap[] memory swaps_, uint256 targetInAmt_ ) public returns (Swap[] memory filteredSwaps_, uint256 actualInAmt_, uint256 approxOutAmt_) { return _filterToTarget(swaps_, targetInAmt_, type(uint256).max); } /// @notice filters the `swaps_` to the point where APPROXIMATELY `targetOutAmt_` is reached. /// IMPORTANT: guaranteed exact output swaps are not possible with Fluid, this method only aims to /// approximately estimate the required input amounts to reach a certain output amount. This /// will change until execution and should be controlled with a maximum slippage. /// Recommended to use exact input methods instead. /// This is best used in combination with the "Raw" methods, as the `targetInAmt_` allows for more optimized /// filtering than otherwise done with the non-"Raw" methods. /// @return filteredSwaps_ swaps to reach the target amount, sorted by ratio in descending order /// (higher ratio = better rate). Best ratio swap will be at pos 0, second best at pos 1 and so on. /// @return actualInAmt_ actual input amount. /// @return approxOutAmt_ APPROXIMATE actual output amount. Can be less than targetOutAmt_ if all available swaps /// can not cover the target amount. function filterToApproxOutAmt( Swap[] memory swaps_, uint256 targetApproxOutAmt_ ) public returns (Swap[] memory filteredSwaps_, uint256 actualInAmt_, uint256 approxOutAmt_) { return _filterToTarget(swaps_, type(uint256).max, targetApproxOutAmt_); } /// @dev filters the `swaps_` to the point where either `targetInAmt_` or `targetOutAmt_` is reached. /// To filter only by in or only by out amount, send `type(uint256).max` for the other param. /// @return filteredSwaps_ swaps to reach the target amount, sorted by ratio in descending order /// (higher ratio = better rate). Best ratio swap will be at pos 0, second best at pos 1 and so on. /// @return actualInAmt_ actual input amount. Can be less than targetInAmt_ if all available swaps can not cover /// the target amount. /// @return actualOutAmt_ actual output amount. Can be less than targetOutAmt_ if all available swaps can not cover /// the target amount. function _filterToTarget( Swap[] memory swaps_, uint256 targetInAmt_, uint256 targetOutAmt_ ) internal returns (Swap[] memory filteredSwaps_, uint256 actualInAmt_, uint256 actualOutAmt_) { swaps_ = _sortByRatio(swaps_); (filteredSwaps_, actualInAmt_, actualOutAmt_) = _filterSwapsUntilTarget(swaps_, targetInAmt_, targetOutAmt_); if (actualInAmt_ > targetInAmt_ || actualOutAmt_ > targetOutAmt_) { // reduce last swap in amt to match target in amt uint256 lastSwapIndex_ = filteredSwaps_.length - 1; uint256 missingInAmt_; if (actualInAmt_ > targetInAmt_) { // swaps_[i].data.inAmt is causing that we over reach targetInAmt_ // so to get missing account from here until targetInAmt_, we only want // swaps_[i].data.inAmt minus whatever is too much (actualInAmt_ - targetInAmt_) missingInAmt_ = filteredSwaps_[lastSwapIndex_].data.inAmt + 1 - (actualInAmt_ - targetInAmt_); } else { // get missing in amt to use for liquidation call input param based on missing out amt and ratio uint256 missingOutAmt_ = filteredSwaps_[lastSwapIndex_].data.outAmt - (actualOutAmt_ - targetOutAmt_); // get total available liquidation and the ratios for with absorb vs without absorb VaultResolverStructs.LiquidationStruct memory liquidationDataAvailable_ = VAULT_RESOLVER .getVaultLiquidation(filteredSwaps_[lastSwapIndex_].path.protocol, 0); uint256 withoutAbsorbRatio_ = _calcRatio( liquidationDataAvailable_.inAmt, liquidationDataAvailable_.outAmt ); // calculate the ratio of the absorb only liquidity part uint256 absorbOnlyRatio_ = _calcRatio( liquidationDataAvailable_.inAmtWithAbsorb - liquidationDataAvailable_.inAmt, liquidationDataAvailable_.outAmtWithAbsorb - liquidationDataAvailable_.outAmt ); if (absorbOnlyRatio_ > withoutAbsorbRatio_ || liquidationDataAvailable_.outAmt < missingOutAmt_) { // with absorb has the better ratio than without absorb or without absorb can not fully cover // the missing out amount. So with absorb has to be run. // Note for the case liquidationDataAvailable_.outAmt < missingOutAmt_: // missing in amt would ideally be a combination of the whole without absorb liquidity + // some left over which has the different (worse) with absorb ratio. // when running withAbsorb = true, always the whole with absorb liquidity is taken first. // so to profit of the better without absorb liquidity, this would have to be turned into 2 swaps. // but this might not always be better because of gas usage etc., so for simplicity we just // take the whole absorb liquidity first. // check if absorb only liquidity covers the missing out amount, if so then the swap ratio is already known // as absorbOnlyRatio_ which can be used to derive the required inAmt uint256 asborbOnlyLiquidity_ = liquidationDataAvailable_.outAmtWithAbsorb - liquidationDataAvailable_.outAmt; if (asborbOnlyLiquidity_ >= missingOutAmt_) { missingInAmt_ = (missingOutAmt_ * 1e27) / absorbOnlyRatio_ + 1; } else { // missing in amt is a combination of the whole absorb liquidity + some left over // which has the different without absorb ratio missingInAmt_ = (asborbOnlyLiquidity_ * 1e27) / absorbOnlyRatio_ + 1; missingInAmt_ += ((missingOutAmt_ - asborbOnlyLiquidity_) * 1e27) / withoutAbsorbRatio_ + 1; } } else { // without absorb has the better ratio AND missing out amount can be covered by without absorb liquidity missingInAmt_ = (missingOutAmt_ * 1e27) / withoutAbsorbRatio_ + 1; } } VaultResolverStructs.LiquidationStruct memory liquidationData_ = VAULT_RESOLVER.getVaultLiquidation( filteredSwaps_[lastSwapIndex_].path.protocol, missingInAmt_ ); actualInAmt_ -= filteredSwaps_[lastSwapIndex_].data.inAmt; actualOutAmt_ -= filteredSwaps_[lastSwapIndex_].data.outAmt; if (filteredSwaps_[lastSwapIndex_].data.withAbsorb) { filteredSwaps_[lastSwapIndex_].data.inAmt = liquidationData_.inAmtWithAbsorb; filteredSwaps_[lastSwapIndex_].data.outAmt = liquidationData_.outAmtWithAbsorb; filteredSwaps_[lastSwapIndex_].data.ratio = _calcRatio( liquidationData_.inAmtWithAbsorb, liquidationData_.outAmtWithAbsorb ); } else { filteredSwaps_[lastSwapIndex_].data.inAmt = liquidationData_.inAmt; filteredSwaps_[lastSwapIndex_].data.outAmt = liquidationData_.outAmt; filteredSwaps_[lastSwapIndex_].data.ratio = _calcRatio(liquidationData_.inAmt, liquidationData_.outAmt); } actualInAmt_ += filteredSwaps_[lastSwapIndex_].data.inAmt; actualOutAmt_ += filteredSwaps_[lastSwapIndex_].data.outAmt; } } /// @dev sorts `swaps_` by ratio descending. Higher ratio is better (getting more output for input). /// Best ratio swap will be at pos 0, second best at pos 1 and so on function _sortByRatio(Swap[] memory swaps_) internal pure returns (Swap[] memory) { bool swapped_; Swap memory helper_; for (uint256 i = 1; i < swaps_.length; i++) { swapped_ = false; for (uint256 j = 0; j < swaps_.length - i; j++) { if (swaps_[j + 1].data.ratio > swaps_[j].data.ratio) { helper_ = swaps_[j]; swaps_[j] = swaps_[j + 1]; swaps_[j + 1] = helper_; swapped_ = true; } } if (!swapped_) { return swaps_; } } return swaps_; } /// @dev filters `swaps_` to exactly reach `targetInAmt_`. Takes into consideration to filter out any swaps /// where both the withAbsorb and withoutAbsorb swap would be present for the same protocol, only /// leaving the withAbsorb swap (as that includes withoutAbsorb). /// Also returns the total in `sumInAmt_` and out `sumOutAmt_` amounts, which will be less than `targetInAmt_` /// in the case that the target amount can not be reached even with all swaps. function _filterSwapsUntilTarget( Swap[] memory swaps_, uint256 targetInAmt_, uint256 targetOutAmt_ ) internal returns (Swap[] memory filteredSwaps_, uint256 sumInAmt_, uint256 sumOutAmt_) { if (swaps_.length == 0) { return (swaps_, 0, 0); } uint256 filteredCount_; // find swaps needed until target in amt while (sumInAmt_ < targetInAmt_ && sumOutAmt_ < targetOutAmt_ && filteredCount_ < swaps_.length) { sumInAmt_ += swaps_[filteredCount_].data.inAmt; sumOutAmt_ += swaps_[filteredCount_].data.outAmt; ++filteredCount_; } // must not double count without absorb when with absorb is already present // until filteredCount, for any protocol where with absorb is present, // filter out the without absorb if that swap is present too. // if any is found then the while to find swaps until targetAmt must be run again // as it will be less with the filtered out element deducted. uint256 duplicatesCount_; for (uint256 i; i < filteredCount_ - 1; ++i) { for (uint256 j = i + 1; j < filteredCount_; ++j) { if (swaps_[i].path.protocol == swaps_[j].path.protocol) { // same protocol present twice (with and without absorb). // mark without absorb to be removed by setting the inAmt to 0 if (swaps_[i].data.withAbsorb) { swaps_[j].data.inAmt = 0; } else { swaps_[i].data.inAmt = 0; } duplicatesCount_++; } } } if (duplicatesCount_ > 0) { uint256 index_; // filter swaps that are set to 0 filteredSwaps_ = new Swap[](swaps_.length - duplicatesCount_); for (uint256 i; i < swaps_.length; ++i) { if (swaps_[i].data.inAmt > 0) { filteredSwaps_[index_] = swaps_[i]; ++index_; } } // recursive call again to reach target amount as planned. return _filterSwapsUntilTarget(filteredSwaps_, targetInAmt_, targetOutAmt_); } // when clean of duplicates -> finished, return filtered swaps and total sumInAmt filteredSwaps_ = new Swap[](filteredCount_); for (uint256 i; i < filteredCount_; ++i) { filteredSwaps_[i] = swaps_[i]; } return (filteredSwaps_, sumInAmt_, sumOutAmt_); } /// @dev gets the better swap based on ratio of with vs without absorb swap data. function _getBetterRatioSwapData( SwapData memory withoutAbsorb_, SwapData memory withAbsorb_ ) internal pure returns (SwapData memory swap_) { if (withAbsorb_.inAmt == 0) { // if ratio == 0, meaning inAmt is 0, then the with absorb swap is returned. return withAbsorb_; } if (withAbsorb_.ratio > withoutAbsorb_.ratio) { // If (ratio of withAbsorb > ratio of withoutAbsorb) then always absorb should be true. return withAbsorb_; } if (withAbsorb_.ratio == withoutAbsorb_.ratio) { if (withAbsorb_.inAmt == withoutAbsorb_.inAmt) { // with absorb has the same liquidity as without absorb. // running liquidate() with absorb in that case only costs extra gas. return only without absorb swap return withoutAbsorb_; } // with absorb has more liquidity, but same ratio -> return with absorb return withAbsorb_; } // ratio of without absorb is better. // Note: case where with absorb has worse ratio. but it could have significant more liquidity -> will not be // returned here as long as there is without absorb liquidity... return withoutAbsorb_; } /// @dev filters `allSwaps_` to the non zero amount `swaps_`, knowing the `nonZeroSwapsCount_` function _getNonZeroSwaps( Swap[] memory allSwaps_, uint256 nonZeroSwapsCount_ ) internal pure returns (Swap[] memory swaps_) { unchecked { swaps_ = new Swap[](nonZeroSwapsCount_); uint256 index_; for (uint256 i; i < allSwaps_.length; ++i) { if (allSwaps_[i].data.inAmt > 0) { swaps_[index_] = allSwaps_[i]; ++index_; } } } } /// @dev gets the `vault_` token in (borrow token) and token out (supply token) function _getVaultTokens(address vault_) internal view returns (address tokenIn_, address tokenOut_) { IFluidVaultT1.ConstantViews memory constants_ = IFluidVaultT1(vault_).constantsView(); return (constants_.borrowToken, constants_.supplyToken); } /// @dev returns ratio for how much outAmt_ am I getting for inAmt_. scaled by 1e27 function _calcRatio(uint256 inAmt_, uint256 outAmt_) internal pure returns (uint256) { if (outAmt_ == 0) { return 0; } return (outAmt_ * 1e27) / inAmt_; } /// @dev returns all VaultT1 type protocols at the Fluid VaultFactory function _getVaultT1s() internal view returns (address[] memory) { return FluidProtocolTypes.filterBy(VAULT_RESOLVER.getAllVaultsAddresses(), FluidProtocolTypes.VAULT_T1_TYPE); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; interface IFluidProtocol { function TYPE() external view returns (uint256); } /// @notice implements helper methods to filter Fluid protocols by a certain type library FluidProtocolTypes { uint256 internal constant VAULT_T1_TYPE = 10000; // VaultT1 borrow protocol type vaults uint256 internal constant VAULT_T2_SMART_COL_TYPE = 20000; // DEX protocol type vault uint256 internal constant VAULT_T3_SMART_DEBT_TYPE = 30000; // DEX protocol type vault uint256 internal constant VAULT_T4_SMART_COL_SMART_DEBT_TYPE = 40000; // DEX protocol type vault /// @dev filters input `addresses_` by protocol `type_`. Input addresses must be actual Fluid protocols, otherwise /// they would be wrongly assumed to be VaultT1 even if they are not Fluid VaultT1 smart contracts. /// `type_` must be a listed constant type of this library. /// Example usage is to filter all vault addresses at the Vault factory by a certain type, e.g. to not include /// DEX protocol type vaults. function filterBy(address[] memory addresses_, uint256 type_) internal view returns (address[] memory filtered_) { uint256 curType_; uint256 filteredProtocols_ = addresses_.length; for (uint256 i; i < addresses_.length; ) { try IFluidProtocol(addresses_[i]).TYPE() returns (uint256 protocolType_) { curType_ = protocolType_; } catch { curType_ = VAULT_T1_TYPE; } if (curType_ != type_) { addresses_[i] = address(0); --filteredProtocols_; } unchecked { ++i; } } filtered_ = new address[](filteredProtocols_); uint256 index_; unchecked { for (uint256 i; i < addresses_.length; ) { if (addresses_[i] != address(0)) { filtered_[index_] = addresses_[i]; ++index_; } ++i; } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; abstract contract Structs { struct AddressBool { address addr; bool value; } struct AddressUint256 { address addr; uint256 value; } /// @notice struct to set borrow rate data for version 1 struct RateDataV1Params { /// /// @param token for rate data address token; /// /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100 /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast uint256 kink; /// /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100 /// i.e. constant minimum borrow rate /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then) uint256 rateAtUtilizationZero; /// /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700 uint256 rateAtUtilizationKink; /// /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500 uint256 rateAtUtilizationMax; } /// @notice struct to set borrow rate data for version 2 struct RateDataV2Params { /// /// @param token for rate data address token; /// /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100 /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster uint256 kink1; /// /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100 /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast uint256 kink2; /// /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100 /// i.e. constant minimum borrow rate /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then) uint256 rateAtUtilizationZero; /// /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700 uint256 rateAtUtilizationKink1; /// /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200 uint256 rateAtUtilizationKink2; /// /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500 uint256 rateAtUtilizationMax; } /// @notice struct to set token config struct TokenConfig { /// /// @param token address address token; /// /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100 uint256 fee; /// /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100 uint256 threshold; /// /// @param maxUtilization maximum allowed utilization. in 1e2: 100% = 10_000; 1% = 100 /// set to 100% to disable and have default limit of 100% (avoiding SLOAD). uint256 maxUtilization; } /// @notice struct to set user supply & withdrawal config struct UserSupplyConfig { /// /// @param user address address user; /// /// @param token address address token; /// /// @param mode: 0 = without interest. 1 = with interest uint8 mode; /// /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100 /// Also used to calculate rate at which withdrawal limit should decrease (instant). uint256 expandPercent; /// /// @param expandDuration withdrawal limit expand duration in seconds. /// used to calculate rate together with expandPercent uint256 expandDuration; /// /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount. /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: /// with interest -> raw, without interest -> normal uint256 baseWithdrawalLimit; } /// @notice struct to set user borrow & payback config struct UserBorrowConfig { /// /// @param user address address user; /// /// @param token address address token; /// /// @param mode: 0 = without interest. 1 = with interest uint8 mode; /// /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100 /// Also used to calculate rate at which debt limit should decrease (instant). uint256 expandPercent; /// /// @param expandDuration debt limit expand duration in seconds. /// used to calculate rate together with expandPercent uint256 expandDuration; /// /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place. /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: /// with interest -> raw, without interest -> normal uint256 baseDebtCeiling; /// /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow. /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: /// with interest -> raw, without interest -> normal uint256 maxDebtCeiling; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { Structs as AdminModuleStructs } from "../../../liquidity/adminModule/structs.sol"; abstract contract Structs { struct RateData { uint256 version; AdminModuleStructs.RateDataV1Params rateDataV1; AdminModuleStructs.RateDataV2Params rateDataV2; } struct OverallTokenData { uint256 borrowRate; uint256 supplyRate; uint256 fee; // revenue fee uint256 lastStoredUtilization; uint256 storageUpdateThreshold; uint256 lastUpdateTimestamp; uint256 supplyExchangePrice; uint256 borrowExchangePrice; uint256 supplyRawInterest; uint256 supplyInterestFree; uint256 borrowRawInterest; uint256 borrowInterestFree; uint256 totalSupply; uint256 totalBorrow; uint256 revenue; uint256 maxUtilization; // maximum allowed utilization RateData rateData; } // amounts are always in normal (for withInterest already multiplied with exchange price) struct UserSupplyData { bool modeWithInterest; // true if mode = with interest, false = without interest uint256 supply; // user supply amount // the withdrawal limit (e.g. if 10% is the limit, and 100M is supplied, it would be 90M) uint256 withdrawalLimit; uint256 lastUpdateTimestamp; uint256 expandPercent; // withdrawal limit expand percent in 1e2 uint256 expandDuration; // withdrawal limit expand duration in seconds uint256 baseWithdrawalLimit; // the current actual max withdrawable amount (e.g. if 10% is the limit, and 100M is supplied, it would be 10M) uint256 withdrawableUntilLimit; uint256 withdrawable; // actual currently withdrawable amount (supply - withdrawal Limit) & considering balance } // amounts are always in normal (for withInterest already multiplied with exchange price) struct UserBorrowData { bool modeWithInterest; // true if mode = with interest, false = without interest uint256 borrow; // user borrow amount uint256 borrowLimit; uint256 lastUpdateTimestamp; uint256 expandPercent; uint256 expandDuration; uint256 baseBorrowLimit; uint256 maxBorrowLimit; uint256 borrowableUntilLimit; // borrowable amount until any borrow limit (incl. max utilization limit) uint256 borrowable; // actual currently borrowable amount (borrow limit - already borrowed) & considering balance, max utilization uint256 borrowLimitUtilization; // borrow limit for `maxUtilization` } }
//SPDX-License-Identifier: MIT pragma solidity 0.8.21; import { Structs } from "./structs.sol"; interface IFluidVaultResolver { function vaultByNftId(uint nftId_) external view returns (address vault_); function positionByNftId( uint nftId_ ) external view returns (Structs.UserPosition memory userPosition_, Structs.VaultEntireData memory vaultData_); function getVaultVariablesRaw(address vault_) external view returns (uint); function getVaultVariables2Raw(address vault_) external view returns (uint); function getTickHasDebtRaw(address vault_, int key_) external view returns (uint); function getTickDataRaw(address vault_, int tick_) external view returns (uint); function getBranchDataRaw(address vault_, uint branch_) external view returns (uint); function getPositionDataRaw(address vault_, uint positionId_) external view returns (uint); function getAllVaultsAddresses() external view returns (address[] memory vaults_); function getVaultLiquidation( address vault_, uint tokenInAmt_ ) external returns (Structs.LiquidationStruct memory liquidationData_); function getVaultEntireData(address vault_) external view returns (Structs.VaultEntireData memory vaultData_); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { IFluidVault } from "../../../protocols/vault/interfaces/iVault.sol"; import { Structs as FluidLiquidityResolverStructs } from "../liquidity/structs.sol"; // @dev Amounts are always in token amount for normal col / normal debt or in // shares for Dex smart col / smart debt. contract Structs { struct Configs { // can be supplyRate instead if Vault Type is smart col. in that case if 1st bit == 1 then positive else negative uint16 supplyRateMagnifier; // can be borrowRate instead if Vault Type is smart debt. in that case if 1st bit == 1 then positive else negative uint16 borrowRateMagnifier; uint16 collateralFactor; uint16 liquidationThreshold; uint16 liquidationMaxLimit; uint16 withdrawalGap; uint16 liquidationPenalty; uint16 borrowFee; address oracle; // Oracle price is always debt per col, i.e. amount of debt for 1 col. // In case of Dex this price can be used to resolve shares values w.r.t. token0 or token1: // - T2: debt token per 1 col share // - T3: debt shares per 1 col token // - T4: debt shares per 1 col share uint oraclePriceOperate; uint oraclePriceLiquidate; address rebalancer; uint lastUpdateTimestamp; } struct ExchangePricesAndRates { uint lastStoredLiquiditySupplyExchangePrice; // 0 in case of smart col uint lastStoredLiquidityBorrowExchangePrice; // 0 in case of smart debt uint lastStoredVaultSupplyExchangePrice; uint lastStoredVaultBorrowExchangePrice; uint liquiditySupplyExchangePrice; // set to 1e12 in case of smart col uint liquidityBorrowExchangePrice; // set to 1e12 in case of smart debt uint vaultSupplyExchangePrice; uint vaultBorrowExchangePrice; uint supplyRateLiquidity; // set to 0 in case of smart col. Must get per token through DexEntireData uint borrowRateLiquidity; // set to 0 in case of smart debt. Must get per token through DexEntireData // supplyRateVault or borrowRateVault: // - when normal col / debt: rate at liquidity + diff rewards or fee through magnifier (rewardsOrFeeRate below) // - when smart col / debt: rewards or fee rate at the vault itself. always == rewardsOrFeeRate below. // to get the full rates for vault when smart col / debt, combine with data from DexResolver: // - rateAtLiquidity for token0 or token1 (DexResolver) // - the rewards or fee rate at the vault (VaultResolver) // - the Dex APR (currently off-chain compiled through tracking swap events at the DEX) int supplyRateVault; // can be negative in case of smart col (meaning pay to supply) int borrowRateVault; // can be negative in case of smart debt (meaning get paid to borrow) // rewardsOrFeeRateSupply: rewards or fee rate in percent 1e2 precision (1% = 100, 100% = 10000). // positive rewards, negative fee. // for smart col vaults: supplyRateVault == supplyRateLiquidity. // for normal col vaults: relative percent to supplyRateLiquidity, e.g.: // when rewards: supplyRateLiquidity = 4%, rewardsOrFeeRateSupply = 20%, supplyRateVault = 4.8%. // when fee: supplyRateLiquidity = 4%, rewardsOrFeeRateSupply = -30%, supplyRateVault = 2.8%. int rewardsOrFeeRateSupply; // rewardsOrFeeRateBorrow: rewards or fee rate in percent 1e2 precision (1% = 100, 100% = 10000). // negative rewards, positive fee. // for smart debt vaults: borrowRateVault == borrowRateLiquidity. // for normal debt vaults: relative percent to borrowRateLiquidity, e.g.: // when rewards: borrowRateLiquidity = 4%, rewardsOrFeeRateBorrow = -20%, borrowRateVault = 3.2%. // when fee: borrowRateLiquidity = 4%, rewardsOrFeeRateBorrow = 30%, borrowRateVault = 5.2%. int rewardsOrFeeRateBorrow; } struct TotalSupplyAndBorrow { uint totalSupplyVault; uint totalBorrowVault; uint totalSupplyLiquidityOrDex; uint totalBorrowLiquidityOrDex; uint absorbedSupply; uint absorbedBorrow; } struct LimitsAndAvailability { // in case of DEX: withdrawable / borrowable amount of vault at DEX, BUT there could be that DEX can not withdraw // that much at Liquidity! So for DEX this must be combined with returned data in DexResolver. uint withdrawLimit; uint withdrawableUntilLimit; uint withdrawable; uint borrowLimit; uint borrowableUntilLimit; // borrowable amount until any borrow limit (incl. max utilization limit) uint borrowable; // actual currently borrowable amount (borrow limit - already borrowed) & considering balance, max utilization uint borrowLimitUtilization; // borrow limit for `maxUtilization` config at Liquidity uint minimumBorrowing; } struct CurrentBranchState { uint status; // if 0 then not liquidated, if 1 then liquidated, if 2 then merged, if 3 then closed int minimaTick; uint debtFactor; uint partials; uint debtLiquidity; uint baseBranchId; int baseBranchMinima; } struct VaultState { uint totalPositions; int topTick; uint currentBranch; uint totalBranch; uint totalBorrow; uint totalSupply; CurrentBranchState currentBranchState; } struct VaultEntireData { address vault; bool isSmartCol; // true if col token is a Fluid Dex bool isSmartDebt; // true if debt token is a Fluid Dex IFluidVault.ConstantViews constantVariables; Configs configs; ExchangePricesAndRates exchangePricesAndRates; TotalSupplyAndBorrow totalSupplyAndBorrow; LimitsAndAvailability limitsAndAvailability; VaultState vaultState; // liquidity related data such as supply amount, limits, expansion etc. // Also set for Dex, limits are in shares and same things apply as noted for LimitsAndAvailability above! FluidLiquidityResolverStructs.UserSupplyData liquidityUserSupplyData; // liquidity related data such as borrow amount, limits, expansion etc. // Also set for Dex, limits are in shares and same things apply as noted for LimitsAndAvailability above! FluidLiquidityResolverStructs.UserBorrowData liquidityUserBorrowData; } struct UserPosition { uint nftId; address owner; bool isLiquidated; bool isSupplyPosition; // if true that means borrowing is 0 int tick; uint tickId; uint beforeSupply; uint beforeBorrow; uint beforeDustBorrow; uint supply; uint borrow; uint dustBorrow; } /// @dev liquidation related data /// @param vault address of vault /// @param token0In address of token in /// @param token0Out address of token out /// @param token1In address of token in (if smart debt) /// @param token1Out address of token out (if smart col) /// @param inAmt (without absorb liquidity) minimum of available liquidation /// @param outAmt (without absorb liquidity) expected token out, collateral to withdraw /// @param inAmtWithAbsorb (absorb liquidity included) minimum of available liquidation. In most cases it'll be same as inAmt but sometimes can be bigger. /// @param outAmtWithAbsorb (absorb liquidity included) expected token out, collateral to withdraw. In most cases it'll be same as outAmt but sometimes can be bigger. /// @param absorbAvailable true if absorb is available /// @dev Liquidity in with absirb will always be >= without asborb. Sometimes without asborb can provide better swaps, /// sometimes with absirb can provide better swaps. But available in with absirb will always be >= One struct LiquidationStruct { address vault; address token0In; address token0Out; address token1In; address token1Out; // amounts in case of smart debt are in shares, otherwise token amounts. // smart col can not be liquidated so to exchange inAmt always use DexResolver DexState.tokenPerDebtShare // and tokenPerColShare for outAmt when Vault is smart col. uint inAmt; uint outAmt; uint inAmtWithAbsorb; uint outAmtWithAbsorb; bool absorbAvailable; } struct AbsorbStruct { address vault; bool absorbAvailable; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; contract Structs { struct SwapPath { /// /// @param protocol vault address at which the token pair is available address protocol; /// /// @param tokenIn input token, borrow token at the vault address tokenIn; /// /// @param tokenOut output token, collateral token at the vault address tokenOut; } struct SwapData { /// /// @param inAmt total input token amount uint256 inAmt; /// /// @param outAmt total output token amount received uint256 outAmt; /// /// @param withAbsorb flag for using mode "withAbsorb" when calling liquidate() on the Vault. /// Is set to true if a) liquidity without absorb would not /// cover the desired `inAmt_` or if b) the rate of with absorb is better than without absorb. bool withAbsorb; /// /// @param ratio ratio of outAmt / inAmt scaled by 1e27 uint256 ratio; } struct Swap { /// /// @param path swap path struct info such as protocol where the swap is available SwapPath path; /// /// @param data swap data struct info such as amounts SwapData data; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { IFluidVaultResolver } from "../vault/iVaultResolver.sol"; contract Variables { IFluidVaultResolver public immutable VAULT_RESOLVER; constructor(IFluidVaultResolver vaultResolver_) { VAULT_RESOLVER = vaultResolver_; } }
//SPDX-License-Identifier: MIT pragma solidity 0.8.21; /// @notice common Fluid vaults interface, some methods only available for vaults > T1 (type, simulateLiquidate, rebalance is different) interface IFluidVault { /// @notice returns the vault id function VAULT_ID() external view returns (uint256); /// @notice returns the vault id function TYPE() external view returns (uint256); /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key. function readFromStorage(bytes32 slot_) external view returns (uint256 result_); struct Tokens { address token0; address token1; } struct ConstantViews { address liquidity; address factory; address operateImplementation; address adminImplementation; address secondaryImplementation; address deployer; // address which deploys oracle address supply; // either liquidity layer or DEX protocol address borrow; // either liquidity layer or DEX protocol Tokens supplyToken; // if smart collateral then address of token0 & token1 else just supply token address at token0 and token1 as empty Tokens borrowToken; // if smart debt then address of token0 & token1 else just borrow token address at token0 and token1 as empty uint256 vaultId; uint256 vaultType; bytes32 supplyExchangePriceSlot; // if smart collateral then slot is from DEX protocol else from liquidity layer bytes32 borrowExchangePriceSlot; // if smart debt then slot is from DEX protocol else from liquidity layer bytes32 userSupplySlot; // if smart collateral then slot is from DEX protocol else from liquidity layer bytes32 userBorrowSlot; // if smart debt then slot is from DEX protocol else from liquidity layer } /// @notice returns all Vault constants function constantsView() external view returns (ConstantViews memory constantsView_); /// @notice fetches the latest user position after a liquidation function fetchLatestPosition( int256 positionTick_, uint256 positionTickId_, uint256 positionRawDebt_, uint256 tickData_ ) external view returns ( int256, // tick uint256, // raw debt uint256, // raw collateral uint256, // branchID_ uint256 // branchData_ ); /// @notice calculates the updated vault exchange prices function updateExchangePrices( uint256 vaultVariables2_ ) external view returns ( uint256 liqSupplyExPrice_, uint256 liqBorrowExPrice_, uint256 vaultSupplyExPrice_, uint256 vaultBorrowExPrice_ ); /// @notice calculates the updated vault exchange prices and writes them to storage function updateExchangePricesOnStorage() external returns ( uint256 liqSupplyExPrice_, uint256 liqBorrowExPrice_, uint256 vaultSupplyExPrice_, uint256 vaultBorrowExPrice_ ); /// @notice returns the liquidity contract address function LIQUIDITY() external view returns (address); error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated); function rebalance( int colToken0MinMax_, int colToken1MinMax_, int debtToken0MinMax_, int debtToken1MinMax_ ) external payable returns (int supplyAmt_, int borrowAmt_); /// @notice reverts with FluidLiquidateResult function simulateLiquidate(uint debtAmt_, bool absorb_) external; }
//SPDX-License-Identifier: MIT pragma solidity 0.8.21; interface IFluidVaultT1 { /// @notice returns the vault id function VAULT_ID() external view returns (uint256); /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key. function readFromStorage(bytes32 slot_) external view returns (uint256 result_); struct ConstantViews { address liquidity; address factory; address adminImplementation; address secondaryImplementation; address supplyToken; address borrowToken; uint8 supplyDecimals; uint8 borrowDecimals; uint vaultId; bytes32 liquiditySupplyExchangePriceSlot; bytes32 liquidityBorrowExchangePriceSlot; bytes32 liquidityUserSupplySlot; bytes32 liquidityUserBorrowSlot; } /// @notice returns all Vault constants function constantsView() external view returns (ConstantViews memory constantsView_); /// @notice fetches the latest user position after a liquidation function fetchLatestPosition( int256 positionTick_, uint256 positionTickId_, uint256 positionRawDebt_, uint256 tickData_ ) external view returns ( int256, // tick uint256, // raw debt uint256, // raw collateral uint256, // branchID_ uint256 // branchData_ ); /// @notice calculates the updated vault exchange prices function updateExchangePrices( uint256 vaultVariables2_ ) external view returns ( uint256 liqSupplyExPrice_, uint256 liqBorrowExPrice_, uint256 vaultSupplyExPrice_, uint256 vaultBorrowExPrice_ ); /// @notice calculates the updated vault exchange prices and writes them to storage function updateExchangePricesOnStorage() external returns ( uint256 liqSupplyExPrice_, uint256 liqBorrowExPrice_, uint256 vaultSupplyExPrice_, uint256 vaultBorrowExPrice_ ); /// @notice returns the liquidity contract address function LIQUIDITY() external view returns (address); function operate( uint256 nftId_, // if 0 then new position int256 newCol_, // if negative then withdraw int256 newDebt_, // if negative then payback address to_ // address at which the borrow & withdraw amount should go to. If address(0) then it'll go to msg.sender ) external payable returns ( uint256, // nftId_ int256, // final supply amount. if - then withdraw int256 // final borrow amount. if - then payback ); function liquidate( uint256 debtAmt_, uint256 colPerUnitDebt_, // min collateral needed per unit of debt in 1e18 address to_, bool absorb_ ) external payable returns (uint actualDebtAmt_, uint actualColAmt_); function absorb() external; function rebalance() external payable returns (int supplyAmt_, int borrowAmt_); error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated); }
{ "optimizer": { "enabled": true, "runs": 10000000 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IFluidVaultResolver","name":"vaultResolver_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FluidVaultLiquidationsResolver__AddressZero","type":"error"},{"inputs":[],"name":"FluidVaultLiquidationsResolver__InvalidParams","type":"error"},{"inputs":[],"name":"VAULT_RESOLVER","outputs":[{"internalType":"contract IFluidVaultResolver","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn_","type":"address"},{"internalType":"address","name":"tokenOut_","type":"address"},{"internalType":"uint256","name":"outAmt_","type":"uint256"}],"name":"approxOutput","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"},{"internalType":"uint256","name":"inAmt_","type":"uint256"},{"internalType":"uint256","name":"approxOutAmt_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn_","type":"address"},{"internalType":"address","name":"tokenOut_","type":"address"},{"internalType":"uint256","name":"inAmt_","type":"uint256"}],"name":"exactInput","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"},{"internalType":"uint256","name":"actualInAmt_","type":"uint256"},{"internalType":"uint256","name":"outAmt_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"},{"internalType":"uint256","name":"targetApproxOutAmt_","type":"uint256"}],"name":"filterToApproxOutAmt","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"filteredSwaps_","type":"tuple[]"},{"internalType":"uint256","name":"actualInAmt_","type":"uint256"},{"internalType":"uint256","name":"approxOutAmt_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"},{"internalType":"uint256","name":"targetInAmt_","type":"uint256"}],"name":"filterToTargetInAmt","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"filteredSwaps_","type":"tuple[]"},{"internalType":"uint256","name":"actualInAmt_","type":"uint256"},{"internalType":"uint256","name":"approxOutAmt_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllSwapPaths","outputs":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath[]","name":"paths_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllVaultsSwap","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllVaultsSwapData","outputs":[{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData[]","name":"withoutAbsorb_","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData[]","name":"withAbsorb_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllVaultsSwapRaw","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokensIn_","type":"address[]"},{"internalType":"address[]","name":"tokensOut_","type":"address[]"}],"name":"getAnySwapPaths","outputs":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath[]","name":"paths_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokensIn_","type":"address[]"},{"internalType":"address[]","name":"tokensOut_","type":"address[]"}],"name":"getAnySwaps","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokensIn_","type":"address[]"},{"internalType":"address[]","name":"tokensOut_","type":"address[]"}],"name":"getAnySwapsRaw","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"protocol_","type":"address"}],"name":"getSwapForProtocol","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap","name":"swap_","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn_","type":"address"},{"internalType":"address","name":"tokenOut_","type":"address"}],"name":"getSwapPaths","outputs":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath[]","name":"paths_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap","name":"swap_","type":"tuple"},{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256","name":"slippage_","type":"uint256"}],"name":"getSwapTx","outputs":[{"internalType":"address","name":"target_","type":"address"},{"internalType":"bytes","name":"calldata_","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"},{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256","name":"slippage_","type":"uint256"}],"name":"getSwapTxs","outputs":[{"internalType":"address[]","name":"targets_","type":"address[]"},{"internalType":"bytes[]","name":"calldatas_","type":"bytes[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn_","type":"address"},{"internalType":"address","name":"tokenOut_","type":"address"}],"name":"getSwaps","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath[]","name":"paths_","type":"tuple[]"}],"name":"getSwapsForPaths","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath[]","name":"paths_","type":"tuple[]"}],"name":"getSwapsForPathsRaw","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn_","type":"address"},{"internalType":"address","name":"tokenOut_","type":"address"}],"name":"getSwapsRaw","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault_","type":"address"}],"name":"getVaultSwapData","outputs":[{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"withoutAbsorb_","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"withAbsorb_","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults_","type":"address[]"}],"name":"getVaultsSwap","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults_","type":"address[]"}],"name":"getVaultsSwapData","outputs":[{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData[]","name":"withoutAbsorb_","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData[]","name":"withAbsorb_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults_","type":"address[]"}],"name":"getVaultsSwapRaw","outputs":[{"components":[{"components":[{"internalType":"address","name":"protocol","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"internalType":"struct Structs.SwapPath","name":"path","type":"tuple"},{"components":[{"internalType":"uint256","name":"inAmt","type":"uint256"},{"internalType":"uint256","name":"outAmt","type":"uint256"},{"internalType":"bool","name":"withAbsorb","type":"bool"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Structs.SwapData","name":"data","type":"tuple"}],"internalType":"struct Structs.Swap[]","name":"swaps_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162003ba538038062003ba5833981016040819052620000349162000068565b6001600160a01b038116608081905262000061576040516303c99f9d60e61b815260040160405180910390fd5b506200009a565b6000602082840312156200007b57600080fd5b81516001600160a01b03811681146200009357600080fd5b9392505050565b608051613ad3620000d2600039600081816102b3015281816113ea01528181611c3001528181611e49015261209e0152613ad36000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c80637f3e2b48116100e35780639f5de8751161008c578063e082bca211610066578063e082bca2146103bb578063e979e874146103ce578063ed6bf8bc146103d657600080fd5b80639f5de87514610375578063aa822df614610395578063c5f8b2e5146103a857600080fd5b8063861d3ac4116100bd578063861d3ac4146103205780638651d5ec146103415780638953b9d61461035457600080fd5b80637f3e2b48146102ae5780638011ba33146102fa578063838fef5c1461030d57600080fd5b80635a980a9f116101455780636c8559621161011f5780636c855962146102755780637119484a146102885780637bfb86ff1461029b57600080fd5b80635a980a9f1461023c5780635e47ec031461024f57806365eb6bd41461026257600080fd5b8063404fcab211610176578063404fcab2146101f15780634296bdff146102135780634c6fdc1a1461022957600080fd5b806321d3b7f41461019d578063232306ea146101bb5780633c199241146101dc575b600080fd5b6101a56103e9565b6040516101b29190612d80565b60405180910390f35b6101ce6101c9366004612db8565b6103fb565b6040516101b2929190612ea8565b6101e4610541565b6040516101b29190612f74565b6102046101ff366004612ff1565b6106b9565b6040516101b293929190613032565b61021b6106e1565b6040516101b29291906130b4565b61021b61023736600461320f565b6106f7565b6101e461024a3660046132ef565b61086f565b61020461025d3660046133df565b610b96565b610204610270366004612ff1565b610bd3565b6101a56102833660046132ef565b610beb565b6101a561029636600461320f565b610c05565b6101a56102a936600461320f565b610ea7565b6102d57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b2565b6101a561030836600461350a565b6110b1565b6101a561031b36600461350a565b6110c9565b61033361032e366004613543565b6110d8565b6040516101b292919061358c565b61020461034f3660046133df565b611311565b6103676103623660046135c3565b611341565b6040516101b29291906135e7565b6103886103833660046135c3565b6114e2565b6040516101b29190613637565b6101e46103a336600461350a565b61157f565b6101a56103b63660046132ef565b611805565b6101a56103c9366004613645565b611816565b6101a5611ab9565b6101a56103e4366004613645565b611ac6565b60606103f66102a9611c29565b905090565b6060808467ffffffffffffffff811115610417576104176130d9565b604051908082528060200260200182016040528015610440578160200160208202803683370190505b5091508467ffffffffffffffff81111561045c5761045c6130d9565b60405190808252806020026020018201604052801561048f57816020015b606081526020019060019003908161047a5790505b50905060005b85811015610537576104bf8787838181106104b2576104b26136df565b905060e0020186866110d8565b8483815181106104d1576104d16136df565b602002602001018484815181106104ea576104ea6136df565b602002602001018290528273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505050806105309061373d565b9050610495565b5094509492505050565b6060600061054d611c29565b9050805167ffffffffffffffff811115610569576105696130d9565b6040519080825280602002602001820160405280156105d257816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816105875790505b50915060008060005b83518110156106b2576106068482815181106105f9576105f96136df565b6020026020010151611ce7565b8093508194505050604051806060016040528085838151811061062b5761062b6136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815250858281518110610696576106966136df565b6020026020010181905250806106ab9061373d565b90506105db565b5050505090565b60606000806106d16106cb87876110c9565b85610b96565b9250925092505b93509350939050565b6060806106ef610237611c29565b915091509091565b606080825167ffffffffffffffff811115610714576107146130d9565b60405190808252806020026020018201604052801561077257816020015b61075f60405180608001604052806000815260200160008152602001600015158152602001600081525090565b8152602001906001900390816107325790505b509150825167ffffffffffffffff81111561078f5761078f6130d9565b6040519080825280602002602001820160405280156107ed57816020015b6107da60405180608001604052806000815260200160008152602001600015158152602001600081525090565b8152602001906001900390816107ad5790505b50905060005b83518110156108695761081e848281518110610811576108116136df565b6020026020010151611341565b848381518110610830576108306136df565b60200260200101848481518110610849576108496136df565b602002602001018290528290525050806108629061373d565b90506107f3565b50915091565b6060600061087d8386613775565b67ffffffffffffffff811115610895576108956130d9565b6040519080825280602002602001820160405280156108fe57816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816108b35790505b509050600061090b611c29565b90506000806000805b8451811015610ab8576109328582815181106105f9576105f96136df565b909350915060005b8a811015610aaf5760005b89811015610aa6578c8c8381811061095f5761095f6136df565b905060200201602081019061097491906135c3565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480156109ff57508a8a828181106109bb576109bb6136df565b90506020020160208101906109d091906135c3565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b15610a9e576040518060600160405280888581518110610a2157610a216136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815250888781518110610a8c57610a8c6136df565b60200260200101819052508560010195505b600101610945565b5060010161093a565b50600101610914565b508267ffffffffffffffff811115610ad257610ad26130d9565b604051908082528060200260200182016040528015610b3b57816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610af05790505b50955060005b83811015610b8857858181518110610b5b57610b5b6136df565b6020026020010151878281518110610b7557610b756136df565b6020908102919091010152600101610b41565b505050505050949350505050565b6060600080610bc685857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611d72565b9250925092509250925092565b60606000806106d1610be587876110c9565b85611311565b6060610bfc6103c98686868661086f565b95945050505050565b6060600080835160020267ffffffffffffffff811115610c2757610c276130d9565b604051908082528060200260200182016040528015610c6057816020015b610c4d612c6c565b815260200190600190039081610c455790505b509050610c9060405180608001604052806000815260200160008152602001600015158152602001600081525090565b610cbd60405180608001604052806000815260200160008152602001600015158152602001600081525090565b60008060005b8851811015610e9057610ce1898281518110610811576108116136df565b8051919650945015610e88578451845160019098019703610d055760008452610d13565b845115610d13578660010196505b610d288982815181106105f9576105f96136df565b8093508194505050604051806040016040528060405180606001604052808c8581518110610d5857610d586136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815250815260200186815250868260020281518110610dcf57610dcf6136df565b6020026020010181905250604051806040016040528060405180606001604052808c8581518110610e0257610e026136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815250815260200185815250868260020260010181518110610e7c57610e7c6136df565b60200260200101819052505b600101610cc3565b50610e9b85876123a3565b98975050505050505050565b6060600080835167ffffffffffffffff811115610ec657610ec66130d9565b604051908082528060200260200182016040528015610eff57816020015b610eec612c6c565b815260200190600190039081610ee45790505b509050610f2f60405180608001604052806000815260200160008152602001600015158152602001600081525090565b610f5c60405180608001604052806000815260200160008152602001600015158152602001600081525090565b610f64612c6c565b60005b875181101561109b57610f85888281518110610811576108116136df565b8094508195505050604051806040016040528060405180606001604052808b8581518110610fb557610fb56136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250815260200161101f868661247f565b9052602081015151909250156110935785600101955061104a8882815181106105f9576105f96136df565b835173ffffffffffffffffffffffffffffffffffffffff9182166040820152911660209091015284518290869083908110611087576110876136df565b60200260200101819052505b600101610f67565b506110a684866123a3565b979650505050505050565b60606110c06103e4848461157f565b90505b92915050565b60606110c06103c9848461157f565b60006060816110ea60208701876135c3565b73ffffffffffffffffffffffffffffffffffffffff161480611120575073ffffffffffffffffffffffffffffffffffffffff8416155b15611157576040517ff267e74000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620f42408310158061116b57506060850135155b8061117857506080850135155b156111af576040517fb55de08000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060608601356111cc6080880135670de0b6b3a7640000613775565b6111d6919061378c565b9050620f42406111e685826137c7565b6111f09083613775565b6111fa919061378c565b905061120960208701876135c3565b507f8433ea22000000000000000000000000000000000000000000000000000000006060870135828761124260c08b0160a08c016137da565b6040516024810194909452604484019290925273ffffffffffffffffffffffffffffffffffffffff1660648301521515608482015260a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529250611306908701876135c3565b925050935093915050565b6060600080610bc6857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86611d72565b61136e60405180608001604052806000815260200160008152602001600015158152602001600081525090565b61139b60405180608001604052806000815260200160008152602001600015158152602001600081525090565b6040517f1fcd364900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152600060248301819052917f000000000000000000000000000000000000000000000000000000000000000090911690631fcd364990604401610140604051808303816000875af1158015611436573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145a9190613812565b905060405180608001604052808260a0015181526020018260c0015181526020016000151581526020016114968360a001518460c00151612500565b815250925060405180608001604052808260e00151815260200182610100015181526020016001151581526020016114d78360e00151846101000151612500565b815250915050915091565b6114ea612c6c565b73ffffffffffffffffffffffffffffffffffffffff821661150a57919050565b60008061151684611ce7565b9150915060008061152686611341565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff808b16928201928352888116606083015287166080820152908152919350915060208101611573848461247f565b90529695505050505050565b6060600061158b611c29565b9050600080825167ffffffffffffffff8111156115aa576115aa6130d9565b6040519080825280602002602001820160405280156115d3578160200160208202803683370190505b50905060008060005b85518110156116c4576115fa8682815181106105f9576105f96136df565b909350915073ffffffffffffffffffffffffffffffffffffffff808416908a1614801561165257508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156116b457858181518110611669576116696136df565b6020026020010151848681518110611683576116836136df565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526116b18561373d565b94505b6116bd8161373d565b90506115dc565b508367ffffffffffffffff8111156116de576116de6130d9565b60405190808252806020026020018201604052801561174757816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816116fc5790505b50955060005b848110156117f9576040518060600160405280858381518110611772576117726136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff168152508782815181106117dd576117dd6136df565b6020026020010181905250806117f29061373d565b905061174d565b50505050505092915050565b6060610bfc6103e48686868661086f565b60606000825160020267ffffffffffffffff811115611837576118376130d9565b60405190808252806020026020018201604052801561187057816020015b61185d612c6c565b8152602001906001900390816118555790505b50905060006118a260405180608001604052806000815260200160008152602001600015158152602001600081525090565b6118cf60405180608001604052806000815260200160008152602001600015158152602001600081525090565b60005b86518110156119db576119018782815181106118f0576118f06136df565b602002602001015160000151611341565b80519194509250156119d35782518251600190950194036119255760008252611933565b825115611933578360010193505b6040518060400160405280888381518110611950576119506136df565b6020026020010151815260200184815250858260020281518110611976576119766136df565b6020026020010181905250604051806040016040528088838151811061199e5761199e6136df565b60200260200101518152602001838152508582600202600101815181106119c7576119c76136df565b60200260200101819052505b6001016118d2565b508267ffffffffffffffff8111156119f5576119f56130d9565b604051908082528060200260200182016040528015611a2e57816020015b611a1b612c6c565b815260200190600190039081611a135790505b5094506000805b8551811015611aae576000868281518110611a5257611a526136df565b602002602001015160200151600001511115611aa657858181518110611a7a57611a7a6136df565b6020026020010151878381518110611a9457611a946136df565b60200260200101819052508160010191505b600101611a35565b505050505050919050565b60606103f6610296611c29565b60606000825167ffffffffffffffff811115611ae457611ae46130d9565b604051908082528060200260200182016040528015611b1d57816020015b611b0a612c6c565b815260200190600190039081611b025790505b5090506000611b2a612c6c565b611b5760405180608001604052806000815260200160008152602001600015158152602001600081525090565b611b8460405180608001604052806000815260200160008152602001600015158152602001600081525090565b60005b8751811015611c1e57611ba58882815181106118f0576118f06136df565b80935081945050506040518060400160405280898381518110611bca57611bca6136df565b60200260200101518152602001611be1858561247f565b905260208101515190945015611c165784600101945083868281518110611c0a57611c0a6136df565b60200260200101819052505b600101611b87565b506110a685856123a3565b60606103f67f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a8d9f4936040518163ffffffff1660e01b8152600401600060405180830381865afa158015611c99573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611cdf91908101906138bf565b612710612533565b60008060008373ffffffffffffffffffffffffffffffffffffffff1663b7791bf26040518163ffffffff1660e01b81526004016101a060405180830381865afa158015611d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5c919061395f565b90508060a0015181608001519250925050915091565b6060600080611d8086612768565b9550611d8d8686866128b9565b9194509250905084821180611da157508381115b156106d857600060018451611db691906137c7565b9050600086841115611e0b57611dcc87856137c7565b858381518110611dde57611dde6136df565b602002602001015160200151600001516001611dfa9190613a3c565b611e0491906137c7565b905061209a565b6000611e1787856137c7565b868481518110611e2957611e296136df565b60200260200101516020015160200151611e4391906137c7565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631fcd3649888681518110611e9557611e956136df565b602090810291909101015151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260006024820152604401610140604051808303816000875af1158015611f15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f399190613812565b90506000611f4f8260a001518360c00151612500565b90506000611f848360a001518460e00151611f6a91906137c7565b8460c00151856101000151611f7f91906137c7565b612500565b905081811180611f975750838360c00151105b156120665760008360c00151846101000151611fb391906137c7565b9050848110611fef5781611fd3866b033b2e3c9fd0803ce8000000613775565b611fdd919061378c565b611fe8906001613a3c565b9550612060565b81612006826b033b2e3c9fd0803ce8000000613775565b612010919061378c565b61201b906001613a3c565b95508261202882876137c7565b61203e906b033b2e3c9fd0803ce8000000613775565b612048919061378c565b612053906001613a3c565b61205d9087613a3c565b95505b50612095565b8161207d856b033b2e3c9fd0803ce8000000613775565b612087919061378c565b612092906001613a3c565b94505b505050505b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631fcd36498785815181106120ea576120ea6136df565b602090810291909101015151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101859052604401610140604051808303816000875af115801561216a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218e9190613812565b90508583815181106121a2576121a26136df565b60200260200101516020015160000151856121bd91906137c7565b94508583815181106121d1576121d16136df565b60200260200101516020015160200151846121ec91906137c7565b9350858381518110612200576122006136df565b60200260200101516020015160400151156122aa578060e0015186848151811061222c5761222c6136df565b6020026020010151602001516000018181525050806101000151868481518110612258576122586136df565b602002602001015160200151602001818152505061227f8160e00151826101000151612500565b868481518110612291576122916136df565b6020026020010151602001516060018181525050612339565b8060a001518684815181106122c1576122c16136df565b60200260200101516020015160000181815250508060c001518684815181106122ec576122ec6136df565b60200260200101516020015160200181815250506123128160a001518260c00151612500565b868481518110612324576123246136df565b60200260200101516020015160600181815250505b85838151811061234b5761234b6136df565b60200260200101516020015160000151856123669190613a3c565b945085838151811061237a5761237a6136df565b60200260200101516020015160200151846123959190613a3c565b935050505093509350939050565b60608167ffffffffffffffff8111156123be576123be6130d9565b6040519080825280602002602001820160405280156123f757816020015b6123e4612c6c565b8152602001906001900390816123dc5790505b5090506000805b845181101561247757600085828151811061241b5761241b6136df565b60200260200101516020015160000151111561246f57848181518110612443576124436136df565b602002602001015183838151811061245d5761245d6136df565b60200260200101819052508160010191505b6001016123fe565b505092915050565b6124ac60405180608001604052806000815260200160008152602001600015158152602001600081525090565b81516000036124bc5750806110c3565b8260600151826060015111156124d35750806110c3565b82606001518260600151036124f95782518251036124f25750816110c3565b50806110c3565b5090919050565b600081600003612512575060006110c3565b82612529836b033b2e3c9fd0803ce8000000613775565b6110c0919061378c565b8151606090600090815b855181101561264957858181518110612558576125586136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156125e4575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526125e191810190613a4f565b60015b6125f25761271092506125f5565b92505b848314612641576000868281518110612610576126106136df565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015261263e82613a68565b91505b60010161253d565b508067ffffffffffffffff811115612663576126636130d9565b60405190808252806020026020018201604052801561268c578160200160208202803683370190505b5092506000805b865181101561275e57600073ffffffffffffffffffffffffffffffffffffffff168782815181106126c6576126c66136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614612756578681815181106126fb576126fb6136df565b6020026020010151858381518110612715576127156136df565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508160010191505b600101612693565b5050505092915050565b60606000612774612c6c565b60015b84518110156128b0576000925060005b81865161279491906137c7565b81101561288f578581815181106127ad576127ad6136df565b60200260200101516020015160600151868260016127cb9190613a3c565b815181106127db576127db6136df565b60200260200101516020015160600151111561287d57858181518110612803576128036136df565b602002602001015192508581600161281b9190613a3c565b8151811061282b5761282b6136df565b6020026020010151868281518110612845576128456136df565b6020908102919091010152828661285d836001613a3c565b8151811061286d5761286d6136df565b6020026020010181905250600193505b806128878161373d565b915050612787565b508261289e5750929392505050565b806128a88161373d565b915050612777565b50929392505050565b606060008085516000036128d5575084915060009050806106d8565b60005b85831080156128e657508482105b80156128f25750865181105b1561296557868181518110612909576129096136df565b60200260200101516020015160000151836129249190613a3c565b9250868181518110612938576129386136df565b60200260200101516020015160200151826129539190613a3c565b915061295e8161373d565b90506128d8565b6000805b6129746001846137c7565b811015612aaa576000612988826001613a3c565b90505b83811015612a99578981815181106129a5576129a56136df565b6020026020010151600001516000015173ffffffffffffffffffffffffffffffffffffffff168a83815181106129dd576129dd6136df565b6020026020010151600001516000015173ffffffffffffffffffffffffffffffffffffffff1603612a8957898281518110612a1a57612a1a6136df565b6020026020010151602001516040015115612a575760008a8281518110612a4357612a436136df565b602090810291909101810151015152612a7b565b60008a8381518110612a6b57612a6b6136df565b6020908102919091018101510151525b82612a858161373d565b9350505b612a928161373d565b905061298b565b50612aa38161373d565b9050612969565b508015612bb8576000818951612ac091906137c7565b67ffffffffffffffff811115612ad857612ad86130d9565b604051908082528060200260200182016040528015612b1157816020015b612afe612c6c565b815260200190600190039081612af65790505b50955060005b8951811015612b9e5760008a8281518110612b3457612b346136df565b602002602001015160200151600001511115612b8e57898181518110612b5c57612b5c6136df565b6020026020010151878381518110612b7657612b766136df565b602002602001018190525081612b8b9061373d565b91505b612b978161373d565b9050612b17565b50612baa8689896128b9565b9550955095505050506106d8565b8167ffffffffffffffff811115612bd157612bd16130d9565b604051908082528060200260200182016040528015612c0a57816020015b612bf7612c6c565b815260200190600190039081612bef5790505b50945060005b82811015612c6057888181518110612c2a57612c2a6136df565b6020026020010151868281518110612c4457612c446136df565b602002602001018190525080612c599061373d565b9050612c10565b50505093509350939050565b6040805160a08101825260009181018281526060820183905260808201929092529081908152602001612cc260405180608001604052806000815260200160008152602001600015158152602001600081525090565b905290565b612d01828251805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260409182015116910152565b6020810151612d3660608401828051825260208101516020830152604081015115156040830152606081015160608301525050565b505050565b600081518084526020808501945080840160005b83811015612d7557612d62878351612cc7565b60e0969096019590820190600101612d4f565b509495945050505050565b6020815260006110c06020830184612d3b565b73ffffffffffffffffffffffffffffffffffffffff81168114612db557600080fd5b50565b60008060008060608587031215612dce57600080fd5b843567ffffffffffffffff80821115612de657600080fd5b818701915087601f830112612dfa57600080fd5b813581811115612e0957600080fd5b88602060e083028501011115612e1e57600080fd5b60209283019650945050850135612e3481612d93565b9396929550929360400135925050565b6000815180845260005b81811015612e6a57602081850181015186830182015201612e4e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b604080825283519082018190526000906020906060840190828701845b82811015612ef757815173ffffffffffffffffffffffffffffffffffffffff1684529284019290840190600101612ec5565b50505083810382850152845180825282820190600581901b8301840187850160005b83811015612f65577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552612f53838351612e44565b94870194925090860190600101612f19565b50909998505050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612fe557612fd2838551805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260409182015116910152565b9284019260609290920191600101612f90565b50909695505050505050565b60008060006060848603121561300657600080fd5b833561301181612d93565b9250602084013561302181612d93565b929592945050506040919091013590565b6060815260006130456060830186612d3b565b60208301949094525060400152919050565b600081518084526020808501945080840160005b83811015612d75576130a18783518051825260208101516020830152604081015115156040830152606081015160608301525050565b608096909601959082019060010161306b565b6040815260006130c76040830185613057565b8281036020840152610bfc8185613057565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561312b5761312b6130d9565b60405290565b6040516080810167ffffffffffffffff8111828210171561312b5761312b6130d9565b604051610140810167ffffffffffffffff8111828210171561312b5761312b6130d9565b6040516101a0810167ffffffffffffffff8111828210171561312b5761312b6130d9565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156131e3576131e36130d9565b604052919050565b600067ffffffffffffffff821115613205576132056130d9565b5060051b60200190565b6000602080838503121561322257600080fd5b823567ffffffffffffffff81111561323957600080fd5b8301601f8101851361324a57600080fd5b803561325d613258826131eb565b61319c565b81815260059190911b8201830190838101908783111561327c57600080fd5b928401925b828410156110a657833561329481612d93565b82529284019290840190613281565b60008083601f8401126132b557600080fd5b50813567ffffffffffffffff8111156132cd57600080fd5b6020830191508360208260051b85010111156132e857600080fd5b9250929050565b6000806000806040858703121561330557600080fd5b843567ffffffffffffffff8082111561331d57600080fd5b613329888389016132a3565b9096509450602087013591508082111561334257600080fd5b5061334f878288016132a3565b95989497509550505050565b60006060828403121561336d57600080fd5b6040516060810181811067ffffffffffffffff82111715613390576133906130d9565b60405290508082356133a181612d93565b815260208301356133b181612d93565b602082015260408301356133c481612d93565b6040919091015292915050565b8015158114612db557600080fd5b60008060408084860312156133f357600080fd5b833567ffffffffffffffff81111561340a57600080fd5b8401601f8101861361341b57600080fd5b8035602061342b613258836131eb565b82815260e0928302840182019282820191908a85111561344a57600080fd5b948301945b848610156134f957858b03818112156134685760008081fd5b613470613108565b61347a8d8961335b565b815260606080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0850112156134b05760008081fd5b6134b8613131565b8a8301358152908a013588820152925060a08901356134d6816133d1565b838b015260c089013590830152808601919091528352948501949183019161344f565b509997909101359750505050505050565b6000806040838503121561351d57600080fd5b823561352881612d93565b9150602083013561353881612d93565b809150509250929050565b600080600083850361012081121561355a57600080fd5b60e081121561356857600080fd5b5083925060e084013561357a81612d93565b92959294505050610100919091013590565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006135bb6040830184612e44565b949350505050565b6000602082840312156135d557600080fd5b81356135e081612d93565b9392505050565b825181526020808401518183015260408085015115158184015260608086015181850152845160808501529184015160a0840152830151151560c083015282015160e082015261010081016135e0565b60e081016110c38284612cc7565b6000602080838503121561365857600080fd5b823567ffffffffffffffff81111561366f57600080fd5b8301601f8101851361368057600080fd5b803561368e613258826131eb565b818152606091820283018401918482019190888411156136ad57600080fd5b938501935b838510156136d3576136c4898661335b565b835293840193918501916136b2565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361376e5761376e61370e565b5060010190565b80820281158282048414176110c3576110c361370e565b6000826137c2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b818103818111156110c3576110c361370e565b6000602082840312156137ec57600080fd5b81356135e0816133d1565b805161380281612d93565b919050565b8051613802816133d1565b6000610140828403121561382557600080fd5b61382d613154565b613836836137f7565b8152613844602084016137f7565b6020820152613855604084016137f7565b6040820152613866606084016137f7565b6060820152613877608084016137f7565b608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101206138b4818501613807565b908201529392505050565b600060208083850312156138d257600080fd5b825167ffffffffffffffff8111156138e957600080fd5b8301601f810185136138fa57600080fd5b8051613908613258826131eb565b81815260059190911b8201830190838101908783111561392757600080fd5b928401925b828410156110a657835161393f81612d93565b8252928401929084019061392c565b805160ff8116811461380257600080fd5b60006101a0828403121561397257600080fd5b61397a613178565b613983836137f7565b8152613991602084016137f7565b60208201526139a2604084016137f7565b60408201526139b3606084016137f7565b60608201526139c4608084016137f7565b60808201526139d560a084016137f7565b60a08201526139e660c0840161394e565b60c08201526139f760e0840161394e565b60e08201526101008381015190820152610120808401519082015261014080840151908201526101608084015190820152610180928301519281019290925250919050565b808201808211156110c3576110c361370e565b600060208284031215613a6157600080fd5b5051919050565b600081613a7757613a7761370e565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea26469706673582212204a67e6a867ff566c7338aa7dab6c38751989ef164ccdf002c8b4f95df5935e0064736f6c63430008150033000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101985760003560e01c80637f3e2b48116100e35780639f5de8751161008c578063e082bca211610066578063e082bca2146103bb578063e979e874146103ce578063ed6bf8bc146103d657600080fd5b80639f5de87514610375578063aa822df614610395578063c5f8b2e5146103a857600080fd5b8063861d3ac4116100bd578063861d3ac4146103205780638651d5ec146103415780638953b9d61461035457600080fd5b80637f3e2b48146102ae5780638011ba33146102fa578063838fef5c1461030d57600080fd5b80635a980a9f116101455780636c8559621161011f5780636c855962146102755780637119484a146102885780637bfb86ff1461029b57600080fd5b80635a980a9f1461023c5780635e47ec031461024f57806365eb6bd41461026257600080fd5b8063404fcab211610176578063404fcab2146101f15780634296bdff146102135780634c6fdc1a1461022957600080fd5b806321d3b7f41461019d578063232306ea146101bb5780633c199241146101dc575b600080fd5b6101a56103e9565b6040516101b29190612d80565b60405180910390f35b6101ce6101c9366004612db8565b6103fb565b6040516101b2929190612ea8565b6101e4610541565b6040516101b29190612f74565b6102046101ff366004612ff1565b6106b9565b6040516101b293929190613032565b61021b6106e1565b6040516101b29291906130b4565b61021b61023736600461320f565b6106f7565b6101e461024a3660046132ef565b61086f565b61020461025d3660046133df565b610b96565b610204610270366004612ff1565b610bd3565b6101a56102833660046132ef565b610beb565b6101a561029636600461320f565b610c05565b6101a56102a936600461320f565b610ea7565b6102d57f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550781565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b2565b6101a561030836600461350a565b6110b1565b6101a561031b36600461350a565b6110c9565b61033361032e366004613543565b6110d8565b6040516101b292919061358c565b61020461034f3660046133df565b611311565b6103676103623660046135c3565b611341565b6040516101b29291906135e7565b6103886103833660046135c3565b6114e2565b6040516101b29190613637565b6101e46103a336600461350a565b61157f565b6101a56103b63660046132ef565b611805565b6101a56103c9366004613645565b611816565b6101a5611ab9565b6101a56103e4366004613645565b611ac6565b60606103f66102a9611c29565b905090565b6060808467ffffffffffffffff811115610417576104176130d9565b604051908082528060200260200182016040528015610440578160200160208202803683370190505b5091508467ffffffffffffffff81111561045c5761045c6130d9565b60405190808252806020026020018201604052801561048f57816020015b606081526020019060019003908161047a5790505b50905060005b85811015610537576104bf8787838181106104b2576104b26136df565b905060e0020186866110d8565b8483815181106104d1576104d16136df565b602002602001018484815181106104ea576104ea6136df565b602002602001018290528273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505050806105309061373d565b9050610495565b5094509492505050565b6060600061054d611c29565b9050805167ffffffffffffffff811115610569576105696130d9565b6040519080825280602002602001820160405280156105d257816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816105875790505b50915060008060005b83518110156106b2576106068482815181106105f9576105f96136df565b6020026020010151611ce7565b8093508194505050604051806060016040528085838151811061062b5761062b6136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815250858281518110610696576106966136df565b6020026020010181905250806106ab9061373d565b90506105db565b5050505090565b60606000806106d16106cb87876110c9565b85610b96565b9250925092505b93509350939050565b6060806106ef610237611c29565b915091509091565b606080825167ffffffffffffffff811115610714576107146130d9565b60405190808252806020026020018201604052801561077257816020015b61075f60405180608001604052806000815260200160008152602001600015158152602001600081525090565b8152602001906001900390816107325790505b509150825167ffffffffffffffff81111561078f5761078f6130d9565b6040519080825280602002602001820160405280156107ed57816020015b6107da60405180608001604052806000815260200160008152602001600015158152602001600081525090565b8152602001906001900390816107ad5790505b50905060005b83518110156108695761081e848281518110610811576108116136df565b6020026020010151611341565b848381518110610830576108306136df565b60200260200101848481518110610849576108496136df565b602002602001018290528290525050806108629061373d565b90506107f3565b50915091565b6060600061087d8386613775565b67ffffffffffffffff811115610895576108956130d9565b6040519080825280602002602001820160405280156108fe57816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816108b35790505b509050600061090b611c29565b90506000806000805b8451811015610ab8576109328582815181106105f9576105f96136df565b909350915060005b8a811015610aaf5760005b89811015610aa6578c8c8381811061095f5761095f6136df565b905060200201602081019061097491906135c3565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480156109ff57508a8a828181106109bb576109bb6136df565b90506020020160208101906109d091906135c3565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b15610a9e576040518060600160405280888581518110610a2157610a216136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815250888781518110610a8c57610a8c6136df565b60200260200101819052508560010195505b600101610945565b5060010161093a565b50600101610914565b508267ffffffffffffffff811115610ad257610ad26130d9565b604051908082528060200260200182016040528015610b3b57816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610af05790505b50955060005b83811015610b8857858181518110610b5b57610b5b6136df565b6020026020010151878281518110610b7557610b756136df565b6020908102919091010152600101610b41565b505050505050949350505050565b6060600080610bc685857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611d72565b9250925092509250925092565b60606000806106d1610be587876110c9565b85611311565b6060610bfc6103c98686868661086f565b95945050505050565b6060600080835160020267ffffffffffffffff811115610c2757610c276130d9565b604051908082528060200260200182016040528015610c6057816020015b610c4d612c6c565b815260200190600190039081610c455790505b509050610c9060405180608001604052806000815260200160008152602001600015158152602001600081525090565b610cbd60405180608001604052806000815260200160008152602001600015158152602001600081525090565b60008060005b8851811015610e9057610ce1898281518110610811576108116136df565b8051919650945015610e88578451845160019098019703610d055760008452610d13565b845115610d13578660010196505b610d288982815181106105f9576105f96136df565b8093508194505050604051806040016040528060405180606001604052808c8581518110610d5857610d586136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815250815260200186815250868260020281518110610dcf57610dcf6136df565b6020026020010181905250604051806040016040528060405180606001604052808c8581518110610e0257610e026136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815250815260200185815250868260020260010181518110610e7c57610e7c6136df565b60200260200101819052505b600101610cc3565b50610e9b85876123a3565b98975050505050505050565b6060600080835167ffffffffffffffff811115610ec657610ec66130d9565b604051908082528060200260200182016040528015610eff57816020015b610eec612c6c565b815260200190600190039081610ee45790505b509050610f2f60405180608001604052806000815260200160008152602001600015158152602001600081525090565b610f5c60405180608001604052806000815260200160008152602001600015158152602001600081525090565b610f64612c6c565b60005b875181101561109b57610f85888281518110610811576108116136df565b8094508195505050604051806040016040528060405180606001604052808b8581518110610fb557610fb56136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250815260200161101f868661247f565b9052602081015151909250156110935785600101955061104a8882815181106105f9576105f96136df565b835173ffffffffffffffffffffffffffffffffffffffff9182166040820152911660209091015284518290869083908110611087576110876136df565b60200260200101819052505b600101610f67565b506110a684866123a3565b979650505050505050565b60606110c06103e4848461157f565b90505b92915050565b60606110c06103c9848461157f565b60006060816110ea60208701876135c3565b73ffffffffffffffffffffffffffffffffffffffff161480611120575073ffffffffffffffffffffffffffffffffffffffff8416155b15611157576040517ff267e74000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620f42408310158061116b57506060850135155b8061117857506080850135155b156111af576040517fb55de08000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060608601356111cc6080880135670de0b6b3a7640000613775565b6111d6919061378c565b9050620f42406111e685826137c7565b6111f09083613775565b6111fa919061378c565b905061120960208701876135c3565b507f8433ea22000000000000000000000000000000000000000000000000000000006060870135828761124260c08b0160a08c016137da565b6040516024810194909452604484019290925273ffffffffffffffffffffffffffffffffffffffff1660648301521515608482015260a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529250611306908701876135c3565b925050935093915050565b6060600080610bc6857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86611d72565b61136e60405180608001604052806000815260200160008152602001600015158152602001600081525090565b61139b60405180608001604052806000815260200160008152602001600015158152602001600081525090565b6040517f1fcd364900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152600060248301819052917f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550790911690631fcd364990604401610140604051808303816000875af1158015611436573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145a9190613812565b905060405180608001604052808260a0015181526020018260c0015181526020016000151581526020016114968360a001518460c00151612500565b815250925060405180608001604052808260e00151815260200182610100015181526020016001151581526020016114d78360e00151846101000151612500565b815250915050915091565b6114ea612c6c565b73ffffffffffffffffffffffffffffffffffffffff821661150a57919050565b60008061151684611ce7565b9150915060008061152686611341565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff808b16928201928352888116606083015287166080820152908152919350915060208101611573848461247f565b90529695505050505050565b6060600061158b611c29565b9050600080825167ffffffffffffffff8111156115aa576115aa6130d9565b6040519080825280602002602001820160405280156115d3578160200160208202803683370190505b50905060008060005b85518110156116c4576115fa8682815181106105f9576105f96136df565b909350915073ffffffffffffffffffffffffffffffffffffffff808416908a1614801561165257508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156116b457858181518110611669576116696136df565b6020026020010151848681518110611683576116836136df565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526116b18561373d565b94505b6116bd8161373d565b90506115dc565b508367ffffffffffffffff8111156116de576116de6130d9565b60405190808252806020026020018201604052801561174757816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816116fc5790505b50955060005b848110156117f9576040518060600160405280858381518110611772576117726136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff168152508782815181106117dd576117dd6136df565b6020026020010181905250806117f29061373d565b905061174d565b50505050505092915050565b6060610bfc6103e48686868661086f565b60606000825160020267ffffffffffffffff811115611837576118376130d9565b60405190808252806020026020018201604052801561187057816020015b61185d612c6c565b8152602001906001900390816118555790505b50905060006118a260405180608001604052806000815260200160008152602001600015158152602001600081525090565b6118cf60405180608001604052806000815260200160008152602001600015158152602001600081525090565b60005b86518110156119db576119018782815181106118f0576118f06136df565b602002602001015160000151611341565b80519194509250156119d35782518251600190950194036119255760008252611933565b825115611933578360010193505b6040518060400160405280888381518110611950576119506136df565b6020026020010151815260200184815250858260020281518110611976576119766136df565b6020026020010181905250604051806040016040528088838151811061199e5761199e6136df565b60200260200101518152602001838152508582600202600101815181106119c7576119c76136df565b60200260200101819052505b6001016118d2565b508267ffffffffffffffff8111156119f5576119f56130d9565b604051908082528060200260200182016040528015611a2e57816020015b611a1b612c6c565b815260200190600190039081611a135790505b5094506000805b8551811015611aae576000868281518110611a5257611a526136df565b602002602001015160200151600001511115611aa657858181518110611a7a57611a7a6136df565b6020026020010151878381518110611a9457611a946136df565b60200260200101819052508160010191505b600101611a35565b505050505050919050565b60606103f6610296611c29565b60606000825167ffffffffffffffff811115611ae457611ae46130d9565b604051908082528060200260200182016040528015611b1d57816020015b611b0a612c6c565b815260200190600190039081611b025790505b5090506000611b2a612c6c565b611b5760405180608001604052806000815260200160008152602001600015158152602001600081525090565b611b8460405180608001604052806000815260200160008152602001600015158152602001600081525090565b60005b8751811015611c1e57611ba58882815181106118f0576118f06136df565b80935081945050506040518060400160405280898381518110611bca57611bca6136df565b60200260200101518152602001611be1858561247f565b905260208101515190945015611c165784600101945083868281518110611c0a57611c0a6136df565b60200260200101819052505b600101611b87565b506110a685856123a3565b60606103f67f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550773ffffffffffffffffffffffffffffffffffffffff1663a8d9f4936040518163ffffffff1660e01b8152600401600060405180830381865afa158015611c99573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611cdf91908101906138bf565b612710612533565b60008060008373ffffffffffffffffffffffffffffffffffffffff1663b7791bf26040518163ffffffff1660e01b81526004016101a060405180830381865afa158015611d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5c919061395f565b90508060a0015181608001519250925050915091565b6060600080611d8086612768565b9550611d8d8686866128b9565b9194509250905084821180611da157508381115b156106d857600060018451611db691906137c7565b9050600086841115611e0b57611dcc87856137c7565b858381518110611dde57611dde6136df565b602002602001015160200151600001516001611dfa9190613a3c565b611e0491906137c7565b905061209a565b6000611e1787856137c7565b868481518110611e2957611e296136df565b60200260200101516020015160200151611e4391906137c7565b905060007f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550773ffffffffffffffffffffffffffffffffffffffff16631fcd3649888681518110611e9557611e956136df565b602090810291909101015151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260006024820152604401610140604051808303816000875af1158015611f15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f399190613812565b90506000611f4f8260a001518360c00151612500565b90506000611f848360a001518460e00151611f6a91906137c7565b8460c00151856101000151611f7f91906137c7565b612500565b905081811180611f975750838360c00151105b156120665760008360c00151846101000151611fb391906137c7565b9050848110611fef5781611fd3866b033b2e3c9fd0803ce8000000613775565b611fdd919061378c565b611fe8906001613a3c565b9550612060565b81612006826b033b2e3c9fd0803ce8000000613775565b612010919061378c565b61201b906001613a3c565b95508261202882876137c7565b61203e906b033b2e3c9fd0803ce8000000613775565b612048919061378c565b612053906001613a3c565b61205d9087613a3c565b95505b50612095565b8161207d856b033b2e3c9fd0803ce8000000613775565b612087919061378c565b612092906001613a3c565b94505b505050505b60007f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550773ffffffffffffffffffffffffffffffffffffffff16631fcd36498785815181106120ea576120ea6136df565b602090810291909101015151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101859052604401610140604051808303816000875af115801561216a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218e9190613812565b90508583815181106121a2576121a26136df565b60200260200101516020015160000151856121bd91906137c7565b94508583815181106121d1576121d16136df565b60200260200101516020015160200151846121ec91906137c7565b9350858381518110612200576122006136df565b60200260200101516020015160400151156122aa578060e0015186848151811061222c5761222c6136df565b6020026020010151602001516000018181525050806101000151868481518110612258576122586136df565b602002602001015160200151602001818152505061227f8160e00151826101000151612500565b868481518110612291576122916136df565b6020026020010151602001516060018181525050612339565b8060a001518684815181106122c1576122c16136df565b60200260200101516020015160000181815250508060c001518684815181106122ec576122ec6136df565b60200260200101516020015160200181815250506123128160a001518260c00151612500565b868481518110612324576123246136df565b60200260200101516020015160600181815250505b85838151811061234b5761234b6136df565b60200260200101516020015160000151856123669190613a3c565b945085838151811061237a5761237a6136df565b60200260200101516020015160200151846123959190613a3c565b935050505093509350939050565b60608167ffffffffffffffff8111156123be576123be6130d9565b6040519080825280602002602001820160405280156123f757816020015b6123e4612c6c565b8152602001906001900390816123dc5790505b5090506000805b845181101561247757600085828151811061241b5761241b6136df565b60200260200101516020015160000151111561246f57848181518110612443576124436136df565b602002602001015183838151811061245d5761245d6136df565b60200260200101819052508160010191505b6001016123fe565b505092915050565b6124ac60405180608001604052806000815260200160008152602001600015158152602001600081525090565b81516000036124bc5750806110c3565b8260600151826060015111156124d35750806110c3565b82606001518260600151036124f95782518251036124f25750816110c3565b50806110c3565b5090919050565b600081600003612512575060006110c3565b82612529836b033b2e3c9fd0803ce8000000613775565b6110c0919061378c565b8151606090600090815b855181101561264957858181518110612558576125586136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156125e4575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526125e191810190613a4f565b60015b6125f25761271092506125f5565b92505b848314612641576000868281518110612610576126106136df565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015261263e82613a68565b91505b60010161253d565b508067ffffffffffffffff811115612663576126636130d9565b60405190808252806020026020018201604052801561268c578160200160208202803683370190505b5092506000805b865181101561275e57600073ffffffffffffffffffffffffffffffffffffffff168782815181106126c6576126c66136df565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614612756578681815181106126fb576126fb6136df565b6020026020010151858381518110612715576127156136df565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508160010191505b600101612693565b5050505092915050565b60606000612774612c6c565b60015b84518110156128b0576000925060005b81865161279491906137c7565b81101561288f578581815181106127ad576127ad6136df565b60200260200101516020015160600151868260016127cb9190613a3c565b815181106127db576127db6136df565b60200260200101516020015160600151111561287d57858181518110612803576128036136df565b602002602001015192508581600161281b9190613a3c565b8151811061282b5761282b6136df565b6020026020010151868281518110612845576128456136df565b6020908102919091010152828661285d836001613a3c565b8151811061286d5761286d6136df565b6020026020010181905250600193505b806128878161373d565b915050612787565b508261289e5750929392505050565b806128a88161373d565b915050612777565b50929392505050565b606060008085516000036128d5575084915060009050806106d8565b60005b85831080156128e657508482105b80156128f25750865181105b1561296557868181518110612909576129096136df565b60200260200101516020015160000151836129249190613a3c565b9250868181518110612938576129386136df565b60200260200101516020015160200151826129539190613a3c565b915061295e8161373d565b90506128d8565b6000805b6129746001846137c7565b811015612aaa576000612988826001613a3c565b90505b83811015612a99578981815181106129a5576129a56136df565b6020026020010151600001516000015173ffffffffffffffffffffffffffffffffffffffff168a83815181106129dd576129dd6136df565b6020026020010151600001516000015173ffffffffffffffffffffffffffffffffffffffff1603612a8957898281518110612a1a57612a1a6136df565b6020026020010151602001516040015115612a575760008a8281518110612a4357612a436136df565b602090810291909101810151015152612a7b565b60008a8381518110612a6b57612a6b6136df565b6020908102919091018101510151525b82612a858161373d565b9350505b612a928161373d565b905061298b565b50612aa38161373d565b9050612969565b508015612bb8576000818951612ac091906137c7565b67ffffffffffffffff811115612ad857612ad86130d9565b604051908082528060200260200182016040528015612b1157816020015b612afe612c6c565b815260200190600190039081612af65790505b50955060005b8951811015612b9e5760008a8281518110612b3457612b346136df565b602002602001015160200151600001511115612b8e57898181518110612b5c57612b5c6136df565b6020026020010151878381518110612b7657612b766136df565b602002602001018190525081612b8b9061373d565b91505b612b978161373d565b9050612b17565b50612baa8689896128b9565b9550955095505050506106d8565b8167ffffffffffffffff811115612bd157612bd16130d9565b604051908082528060200260200182016040528015612c0a57816020015b612bf7612c6c565b815260200190600190039081612bef5790505b50945060005b82811015612c6057888181518110612c2a57612c2a6136df565b6020026020010151868281518110612c4457612c446136df565b602002602001018190525080612c599061373d565b9050612c10565b50505093509350939050565b6040805160a08101825260009181018281526060820183905260808201929092529081908152602001612cc260405180608001604052806000815260200160008152602001600015158152602001600081525090565b905290565b612d01828251805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260409182015116910152565b6020810151612d3660608401828051825260208101516020830152604081015115156040830152606081015160608301525050565b505050565b600081518084526020808501945080840160005b83811015612d7557612d62878351612cc7565b60e0969096019590820190600101612d4f565b509495945050505050565b6020815260006110c06020830184612d3b565b73ffffffffffffffffffffffffffffffffffffffff81168114612db557600080fd5b50565b60008060008060608587031215612dce57600080fd5b843567ffffffffffffffff80821115612de657600080fd5b818701915087601f830112612dfa57600080fd5b813581811115612e0957600080fd5b88602060e083028501011115612e1e57600080fd5b60209283019650945050850135612e3481612d93565b9396929550929360400135925050565b6000815180845260005b81811015612e6a57602081850181015186830182015201612e4e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b604080825283519082018190526000906020906060840190828701845b82811015612ef757815173ffffffffffffffffffffffffffffffffffffffff1684529284019290840190600101612ec5565b50505083810382850152845180825282820190600581901b8301840187850160005b83811015612f65577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552612f53838351612e44565b94870194925090860190600101612f19565b50909998505050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612fe557612fd2838551805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260409182015116910152565b9284019260609290920191600101612f90565b50909695505050505050565b60008060006060848603121561300657600080fd5b833561301181612d93565b9250602084013561302181612d93565b929592945050506040919091013590565b6060815260006130456060830186612d3b565b60208301949094525060400152919050565b600081518084526020808501945080840160005b83811015612d75576130a18783518051825260208101516020830152604081015115156040830152606081015160608301525050565b608096909601959082019060010161306b565b6040815260006130c76040830185613057565b8281036020840152610bfc8185613057565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561312b5761312b6130d9565b60405290565b6040516080810167ffffffffffffffff8111828210171561312b5761312b6130d9565b604051610140810167ffffffffffffffff8111828210171561312b5761312b6130d9565b6040516101a0810167ffffffffffffffff8111828210171561312b5761312b6130d9565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156131e3576131e36130d9565b604052919050565b600067ffffffffffffffff821115613205576132056130d9565b5060051b60200190565b6000602080838503121561322257600080fd5b823567ffffffffffffffff81111561323957600080fd5b8301601f8101851361324a57600080fd5b803561325d613258826131eb565b61319c565b81815260059190911b8201830190838101908783111561327c57600080fd5b928401925b828410156110a657833561329481612d93565b82529284019290840190613281565b60008083601f8401126132b557600080fd5b50813567ffffffffffffffff8111156132cd57600080fd5b6020830191508360208260051b85010111156132e857600080fd5b9250929050565b6000806000806040858703121561330557600080fd5b843567ffffffffffffffff8082111561331d57600080fd5b613329888389016132a3565b9096509450602087013591508082111561334257600080fd5b5061334f878288016132a3565b95989497509550505050565b60006060828403121561336d57600080fd5b6040516060810181811067ffffffffffffffff82111715613390576133906130d9565b60405290508082356133a181612d93565b815260208301356133b181612d93565b602082015260408301356133c481612d93565b6040919091015292915050565b8015158114612db557600080fd5b60008060408084860312156133f357600080fd5b833567ffffffffffffffff81111561340a57600080fd5b8401601f8101861361341b57600080fd5b8035602061342b613258836131eb565b82815260e0928302840182019282820191908a85111561344a57600080fd5b948301945b848610156134f957858b03818112156134685760008081fd5b613470613108565b61347a8d8961335b565b815260606080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0850112156134b05760008081fd5b6134b8613131565b8a8301358152908a013588820152925060a08901356134d6816133d1565b838b015260c089013590830152808601919091528352948501949183019161344f565b509997909101359750505050505050565b6000806040838503121561351d57600080fd5b823561352881612d93565b9150602083013561353881612d93565b809150509250929050565b600080600083850361012081121561355a57600080fd5b60e081121561356857600080fd5b5083925060e084013561357a81612d93565b92959294505050610100919091013590565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006135bb6040830184612e44565b949350505050565b6000602082840312156135d557600080fd5b81356135e081612d93565b9392505050565b825181526020808401518183015260408085015115158184015260608086015181850152845160808501529184015160a0840152830151151560c083015282015160e082015261010081016135e0565b60e081016110c38284612cc7565b6000602080838503121561365857600080fd5b823567ffffffffffffffff81111561366f57600080fd5b8301601f8101851361368057600080fd5b803561368e613258826131eb565b818152606091820283018401918482019190888411156136ad57600080fd5b938501935b838510156136d3576136c4898661335b565b835293840193918501916136b2565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361376e5761376e61370e565b5060010190565b80820281158282048414176110c3576110c361370e565b6000826137c2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b818103818111156110c3576110c361370e565b6000602082840312156137ec57600080fd5b81356135e0816133d1565b805161380281612d93565b919050565b8051613802816133d1565b6000610140828403121561382557600080fd5b61382d613154565b613836836137f7565b8152613844602084016137f7565b6020820152613855604084016137f7565b6040820152613866606084016137f7565b6060820152613877608084016137f7565b608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101206138b4818501613807565b908201529392505050565b600060208083850312156138d257600080fd5b825167ffffffffffffffff8111156138e957600080fd5b8301601f810185136138fa57600080fd5b8051613908613258826131eb565b81815260059190911b8201830190838101908783111561392757600080fd5b928401925b828410156110a657835161393f81612d93565b8252928401929084019061392c565b805160ff8116811461380257600080fd5b60006101a0828403121561397257600080fd5b61397a613178565b613983836137f7565b8152613991602084016137f7565b60208201526139a2604084016137f7565b60408201526139b3606084016137f7565b60608201526139c4608084016137f7565b60808201526139d560a084016137f7565b60a08201526139e660c0840161394e565b60c08201526139f760e0840161394e565b60e08201526101008381015190820152610120808401519082015261014080840151908201526101608084015190820152610180928301519281019290925250919050565b808201808211156110c3576110c361370e565b600060208284031215613a6157600080fd5b5051919050565b600081613a7757613a7761370e565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea26469706673582212204a67e6a867ff566c7338aa7dab6c38751989ef164ccdf002c8b4f95df5935e0064736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507
-----Decoded View---------------
Arg [0] : vaultResolver_ (address): 0xd6C90A7B61F3e0Ac04e2F4B0359aB0ac09035507
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.