Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
BalancerPoolDataQueries
Compiler Version
v0.7.1+commit.f4a555be
Optimization Enabled:
Yes with 9999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol"; import "@balancer-labs/v2-interfaces/contracts/pool-utils/IRateProvider.sol"; import "@balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol"; import "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ITemporarilyPausable.sol"; import "@balancer-labs/v2-interfaces/contracts/pool-utils/IRecoveryMode.sol"; enum TotalSupplyType { TOTAL_SUPPLY, VIRTUAL_SUPPLY, ACTUAL_SUPPLY } enum SwapFeeType { SWAP_FEE_PERCENTAGE, PERCENT_FEE } // The base ILinearPool does not include getWrappedTokenRate, so we redefine it here. interface ILinearPool { function getWrappedTokenRate() external view returns (uint256); function getTargets() external view returns (uint256 lowerTarget, uint256 upperTarget); } interface IWeightedPool { function getNormalizedWeights() external view returns (uint256[] memory); } interface IPoolWithScalingFactors { function getScalingFactors() external view returns (uint256[] memory); } interface IPoolWithActualSupply { function getActualSupply() external view returns (uint256); } interface IPoolWithVirtualSupply { function getVirtualSupply() external view returns (uint256); } interface IPoolWithSwapFeePercentage { function getSwapFeePercentage() external view returns (uint256); } interface IPoolWithPercentFee { function percentFee() external view returns (uint256); } interface IPoolWithAmp { function getAmplificationParameter() external view returns ( uint256 value, bool isUpdating, uint256 precision ); } struct PoolDataQueryConfig { bool loadTokenBalanceUpdatesAfterBlock; bool loadTotalSupply; bool loadSwapFees; bool loadLinearWrappedTokenRates; bool loadLinearTargets; bool loadNormalizedWeights; bool loadScalingFactors; bool loadAmps; bool loadRates; uint256 blockNumber; TotalSupplyType[] totalSupplyTypes; SwapFeeType[] swapFeeTypes; uint256[] linearPoolIdxs; uint256[] weightedPoolIdxs; uint256[] scalingFactorPoolIdxs; uint256[] ampPoolIdxs; uint256[] ratePoolIdxs; } struct PoolStatusQueryConfig { bool loadInRecoveryMode; bool loadIsPaused; } /** * @dev This contract builds on top of the Balancer V2 architecture to provide useful helpers for fetching on chain data * for Balancer pools. It is especially helpful for SOR (Smart order router) initialization. It allows for bulking * actions for many pools at once, with the overall goal to reduce network-in and network-out required for loading * useful onchain data. */ contract BalancerPoolDataQueries { IVault public immutable vault; constructor(IVault _vault) { vault = _vault; } /** * @dev Under most circumstances, you will use getPoolData as the main entry point for this contract. * It allows you to fetch various types of pool data for many pools in a single query. The response * is optimized for data out. We return the minimum amount of data from this query to facilitate * faster network requests. getPoolData replaces the generic multicall approach that over fetches data * in most situations and will revert if any query in the multicall reverts, making it difficult to identify * pools that need to be filtered from routing. This function returns an array ignoreIdxs that contains the * enumerated idxs in the poolIds array that should be filtered out. */ function getPoolData(bytes32[] memory poolIds, PoolDataQueryConfig memory config) external view returns ( uint256[][] memory balances, uint256[] memory totalSupplies, uint256[] memory swapFees, uint256[] memory linearWrappedTokenRates, uint256[][] memory linearTargets, uint256[][] memory weights, uint256[][] memory scalingFactors, uint256[] memory amps, uint256[] memory rates, uint256[] memory ignoreIdxs ) { uint256 i; address[] memory pools = new address[](poolIds.length); for (i = 0; i < poolIds.length; i++) { (pools[i], ) = vault.getPool(poolIds[i]); } if (config.loadTokenBalanceUpdatesAfterBlock) { balances = getPoolTokenBalancesWithUpdatesAfterBlock(poolIds, config.blockNumber); } if (config.loadTotalSupply) { totalSupplies = getTotalSupplyForPools(pools, config.totalSupplyTypes); } if (config.loadSwapFees) { swapFees = getSwapFeePercentageForPools(pools, config.swapFeeTypes); } if (config.loadLinearWrappedTokenRates) { address[] memory linearPools = new address[](config.linearPoolIdxs.length); for (i = 0; i < config.linearPoolIdxs.length; i++) { linearPools[i] = pools[config.linearPoolIdxs[i]]; } linearWrappedTokenRates = getWrappedTokenRateForLinearPools(linearPools); } if (config.loadNormalizedWeights) { address[] memory weightedPools = new address[](config.weightedPoolIdxs.length); for (i = 0; i < config.weightedPoolIdxs.length; i++) { weightedPools[i] = pools[config.weightedPoolIdxs[i]]; } weights = getNormalizedWeightsForPools(weightedPools); } if (config.loadScalingFactors) { address[] memory scalingFactorPools = new address[](config.scalingFactorPoolIdxs.length); for (i = 0; i < config.scalingFactorPoolIdxs.length; i++) { scalingFactorPools[i] = pools[config.scalingFactorPoolIdxs[i]]; } scalingFactors = getScalingFactorsForPools(scalingFactorPools); } if (config.loadAmps) { address[] memory ampPools = new address[](config.ampPoolIdxs.length); for (i = 0; i < config.ampPoolIdxs.length; i++) { ampPools[i] = pools[config.ampPoolIdxs[i]]; } amps = getAmpForPools(ampPools); } if (config.loadRates) { address[] memory ratePools = new address[](config.ratePoolIdxs.length); for (i = 0; i < config.ratePoolIdxs.length; i++) { ratePools[i] = pools[config.ratePoolIdxs[i]]; } rates = getRateForPools(ratePools); } if (config.loadLinearTargets) { address[] memory linearTargetPools = new address[](config.linearPoolIdxs.length); for (i = 0; i < config.linearPoolIdxs.length; i++) { linearTargetPools[i] = pools[config.linearPoolIdxs[i]]; } linearTargets = getLinearTargetsForPools(linearTargetPools); } ignoreIdxs = _getErrorIdxsFromResults( poolIds, config, totalSupplies, swapFees, linearWrappedTokenRates, amps, rates, scalingFactors, weights ); } function getPoolStatus(bytes32[] memory poolIds, PoolStatusQueryConfig memory config) external view returns (bool[] memory isPaused, bool[] memory inRecoveryMode) { uint256 i; address[] memory pools = new address[](poolIds.length); for (i = 0; i < poolIds.length; i++) { (pools[i], ) = vault.getPool(poolIds[i]); } if (config.loadIsPaused) { isPaused = getIsPausedForPools(pools); } if (config.loadInRecoveryMode) { inRecoveryMode = getInRecoveryModeForPools(pools); } } function getPoolTokenBalancesWithUpdatesAfterBlock(bytes32[] memory poolIds, uint256 blockNumber) public view returns (uint256[][] memory) { uint256[] memory balances; uint256 lastChangeBlock; uint256[][] memory allBalances = new uint256[][](poolIds.length); for (uint256 i = 0; i < poolIds.length; i++) { (, balances, lastChangeBlock) = vault.getPoolTokens(poolIds[i]); if (lastChangeBlock > blockNumber) { allBalances[i] = balances; } } return allBalances; } function getWrappedTokenRateForLinearPools(address[] memory poolAddresses) public view returns (uint256[] memory) { uint256[] memory rates = new uint256[](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { rates[i] = _getLinearWrappedTokenRate(poolAddresses[i]); } return rates; } function getAmpForPools(address[] memory poolAddresses) public view returns (uint256[] memory) { uint256[] memory amps = new uint256[](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { amps[i] = _getPoolAmp(poolAddresses[i]); } return amps; } function getRateForPools(address[] memory poolAddresses) public view returns (uint256[] memory) { uint256[] memory rates = new uint256[](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { rates[i] = _getPoolRate(poolAddresses[i]); } return rates; } function getSwapFeePercentageForPools(address[] memory poolAddresses, SwapFeeType[] memory swapFeeTypes) public view returns (uint256[] memory) { uint256[] memory swapFees = new uint256[](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { if (swapFeeTypes[i] == SwapFeeType.PERCENT_FEE) { try IPoolWithPercentFee(poolAddresses[i]).percentFee() returns (uint256 swapFee) { swapFees[i] = swapFee; } catch { swapFees[i] = 0; } } else { // In instances where we get an unknown pool type that does not support the default getSwapFeePercentage // we return a 0 swap fee. try IPoolWithSwapFeePercentage(poolAddresses[i]).getSwapFeePercentage() returns (uint256 swapFee) { swapFees[i] = swapFee; } catch { swapFees[i] = 0; } } } return swapFees; } function getTotalSupplyForPools(address[] memory poolAddresses, TotalSupplyType[] memory totalSupplyTypes) public view returns (uint256[] memory) { uint256[] memory totalSupplies = new uint256[](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { if (totalSupplyTypes[i] == TotalSupplyType.VIRTUAL_SUPPLY) { totalSupplies[i] = _getPoolVirtualSupply(poolAddresses[i]); } else if (totalSupplyTypes[i] == TotalSupplyType.ACTUAL_SUPPLY) { totalSupplies[i] = _getPoolActualSupply(poolAddresses[i]); } else { totalSupplies[i] = _getPoolTotalSupply(poolAddresses[i]); } } return totalSupplies; } function getNormalizedWeightsForPools(address[] memory poolAddresses) public view returns (uint256[][] memory) { uint256[][] memory allWeights = new uint256[][](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { allWeights[i] = _getPoolNormalizedWeights(poolAddresses[i]); } return allWeights; } function getScalingFactorsForPools(address[] memory poolAddresses) public view returns (uint256[][] memory) { uint256[][] memory allScalingFactors = new uint256[][](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { allScalingFactors[i] = _getPoolScalingFactors(poolAddresses[i]); } return allScalingFactors; } function getLinearTargetsForPools(address[] memory poolAddresses) public view returns (uint256[][] memory) { uint256[][] memory linearTargets = new uint256[][](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { linearTargets[i] = _getPoolLinearTargets(poolAddresses[i]); } return linearTargets; } function getInRecoveryModeForPools(address[] memory poolAddresses) public view returns (bool[] memory) { bool[] memory inRecoveryModes = new bool[](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { inRecoveryModes[i] = _getPoolInRecoveryMode(poolAddresses[i]); } return inRecoveryModes; } function getIsPausedForPools(address[] memory poolAddresses) public view returns (bool[] memory) { bool[] memory isPaused = new bool[](poolAddresses.length); for (uint256 i = 0; i < poolAddresses.length; i++) { isPaused[i] = _getPoolIsPaused(poolAddresses[i]); } return isPaused; } /** * @dev Our goal is to prevent queries from reverting even if one or more pools are in an invalid/corrupt state. * We wrap each query below in a try/catch block, and return a value of 0 in instances where the query reverts. * We use a 0 value as our sentinel value, but recognize it is possible for pools to return a 0 value in non error * situations (ie: pool is uninitialized). In such situations, it is still appropriate for us to flag the pool to * be ignored. */ function _getLinearWrappedTokenRate(address poolAddress) internal view returns (uint256) { try ILinearPool(poolAddress).getWrappedTokenRate() returns (uint256 rate) { return rate; } catch { return 0; } } function _getPoolLinearTargets(address poolAddress) internal view returns (uint256[] memory) { uint256[] memory targets = new uint256[](2); (targets[0], targets[1]) = ILinearPool(poolAddress).getTargets(); return targets; } function _getPoolVirtualSupply(address poolAddress) internal view returns (uint256) { try IPoolWithVirtualSupply(poolAddress).getVirtualSupply() returns (uint256 virtualSupply) { return virtualSupply; } catch { return 0; } } function _getPoolActualSupply(address poolAddress) internal view returns (uint256) { try IPoolWithActualSupply(poolAddress).getActualSupply() returns (uint256 actualSupply) { return actualSupply; } catch { return 0; } } function _getPoolTotalSupply(address poolAddress) internal view returns (uint256) { try IERC20(poolAddress).totalSupply() returns (uint256 totalSupply) { return totalSupply; } catch { return 0; } } function _getPoolRate(address poolAddress) internal view returns (uint256) { try IRateProvider(poolAddress).getRate() returns (uint256 rate) { return rate; } catch { return 0; } } function _getPoolScalingFactors(address poolAddress) internal view returns (uint256[] memory) { try IPoolWithScalingFactors(poolAddress).getScalingFactors() returns (uint256[] memory scalingFactors) { return scalingFactors; } catch { uint256[] memory empty = new uint256[](0); return empty; } } function _getPoolNormalizedWeights(address poolAddress) internal view returns (uint256[] memory) { try IWeightedPool(poolAddress).getNormalizedWeights() returns (uint256[] memory normalizedWeights) { return normalizedWeights; } catch { uint256[] memory empty = new uint256[](0); return empty; } } function _getPoolAmp(address poolAddress) internal view returns (uint256) { try IPoolWithAmp(poolAddress).getAmplificationParameter() returns (uint256 value, bool, uint256) { return value; } catch { return 0; } } function _getPoolInRecoveryMode(address poolAddress) internal view returns (bool) { try IRecoveryMode(poolAddress).inRecoveryMode() returns (bool inRecoveryMode) { return inRecoveryMode; } catch { return false; } } function _getPoolIsPaused(address poolAddress) internal view returns (bool) { try ITemporarilyPausable(poolAddress).getPausedState() returns (bool paused, uint256, uint256) { return paused; } catch { return false; } } function _getErrorIdxsFromResults( bytes32[] memory poolIds, PoolDataQueryConfig memory config, uint256[] memory totalSupplies, uint256[] memory swapFees, uint256[] memory linearWrappedTokenRates, uint256[] memory amps, uint256[] memory rates, uint256[][] memory scalingFactors, uint256[][] memory weights ) internal pure returns (uint256[] memory) { bool[] memory errors = new bool[](poolIds.length); uint256 numErrors = 0; uint256 i; for (i = 0; i < poolIds.length; i++) { if ((config.loadTotalSupply && totalSupplies[i] == 0) || (config.loadSwapFees && swapFees[i] == 0)) { errors[i] = true; } } if (config.loadLinearWrappedTokenRates) { for (i = 0; i < config.linearPoolIdxs.length; i++) { if (linearWrappedTokenRates[i] == 0) { errors[config.linearPoolIdxs[i]] = true; } } } if (config.loadAmps) { for (i = 0; i < config.ampPoolIdxs.length; i++) { if (amps[i] == 0) { errors[config.ampPoolIdxs[i]] = true; } } } if (config.loadRates) { for (i = 0; i < config.ratePoolIdxs.length; i++) { if (rates[i] == 0) { errors[config.ratePoolIdxs[i]] = true; } } } if (config.loadScalingFactors) { for (i = 0; i < config.scalingFactorPoolIdxs.length; i++) { // any failed fetches to scaling factors returns an empty array if (scalingFactors[i].length == 0) { errors[config.scalingFactorPoolIdxs[i]] = true; } } } if (config.loadNormalizedWeights) { for (i = 0; i < config.weightedPoolIdxs.length; i++) { // any failed fetches to normalized weights returns an empty array if (weights[i].length == 0) { errors[config.weightedPoolIdxs[i]] = true; } } } for (i = 0; i < errors.length; i++) { if (errors[i] == true) { numErrors++; } } uint256[] memory errorIdxs = new uint256[](numErrors); uint256 idx = 0; for (i = 0; i < errors.length; i++) { if (errors[i] == true) { errorIdxs[idx] = i; idx++; } } return errorIdxs; } }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; interface IRateProvider { /** * @dev Returns an 18 decimal fixed point number that is the exchange rate of the token to some other underlying * token. The meaning of this rate depends on the context. */ function getRate() external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; /** * @dev Interface for the RecoveryMode module. */ interface IRecoveryMode { /** * @dev Emitted when the Recovery Mode status changes. */ event RecoveryModeStateChanged(bool enabled); /** * @notice Enables Recovery Mode in the Pool, disabling protocol fee collection and allowing for safe proportional * exits with low computational complexity and no dependencies. */ function enableRecoveryMode() external; /** * @notice Disables Recovery Mode in the Pool, restoring protocol fee collection and disallowing proportional exits. */ function disableRecoveryMode() external; /** * @notice Returns true if the Pool is in Recovery Mode. */ function inRecoveryMode() external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; interface IAuthentication { /** * @dev Returns the action identifier associated with the external function described by `selector`. */ function getActionId(bytes4 selector) external view returns (bytes32); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; /** * @dev Interface for the SignatureValidator helper, used to support meta-transactions. */ interface ISignaturesValidator { /** * @dev Returns the EIP712 domain separator. */ function getDomainSeparator() external view returns (bytes32); /** * @dev Returns the next nonce used by an address to sign messages. */ function getNextNonce(address user) external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; /** * @dev Interface for the TemporarilyPausable helper. */ interface ITemporarilyPausable { /** * @dev Emitted every time the pause state changes by `_setPaused`. */ event PausedStateChanged(bool paused); /** * @dev Returns the current paused state. */ function getPausedState() external view returns ( bool paused, uint256 pauseWindowEndTime, uint256 bufferPeriodEndTime ); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; import "../openzeppelin/IERC20.sol"; /** * @dev Interface for WETH9. * See https://github.com/gnosis/canonical-weth/blob/0dd1ea3e295eef916d0c6223ec63141137d22d67/contracts/WETH9.sol */ interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; /** * @dev This is an empty interface used to represent either ERC20-conforming token contracts or ETH (using the zero * address sentinel value). We're just relying on the fact that `interface` can be used to declare new address-like * types. * * This concept is unrelated to a Pool's Asset Managers. */ interface IAsset { // solhint-disable-previous-line no-empty-blocks }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; interface IAuthorizer { /** * @dev Returns true if `account` can perform the action described by `actionId` in the contract `where`. */ function canPerform( bytes32 actionId, address account, address where ) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; // Inspired by Aave Protocol's IFlashLoanReceiver. import "../solidity-utils/openzeppelin/IERC20.sol"; interface IFlashLoanRecipient { /** * @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient. * * At the time of the call, the Vault will have transferred `amounts` for `tokens` to the recipient. Before this * call returns, the recipient must have transferred `amounts` plus `feeAmounts` for each token back to the * Vault, or else the entire flash loan will revert. * * `userData` is the same value passed in the `IVault.flashLoan` call. */ function receiveFlashLoan( IERC20[] memory tokens, uint256[] memory amounts, uint256[] memory feeAmounts, bytes memory userData ) external; }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; import "../solidity-utils/openzeppelin/IERC20.sol"; import "./IVault.sol"; import "./IAuthorizer.sol"; interface IProtocolFeesCollector { event SwapFeePercentageChanged(uint256 newSwapFeePercentage); event FlashLoanFeePercentageChanged(uint256 newFlashLoanFeePercentage); function withdrawCollectedFees( IERC20[] calldata tokens, uint256[] calldata amounts, address recipient ) external; function setSwapFeePercentage(uint256 newSwapFeePercentage) external; function setFlashLoanFeePercentage(uint256 newFlashLoanFeePercentage) external; function getSwapFeePercentage() external view returns (uint256); function getFlashLoanFeePercentage() external view returns (uint256); function getCollectedFeeAmounts(IERC20[] memory tokens) external view returns (uint256[] memory feeAmounts); function getAuthorizer() external view returns (IAuthorizer); function vault() external view returns (IVault); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma experimental ABIEncoderV2; import "../solidity-utils/openzeppelin/IERC20.sol"; import "../solidity-utils/helpers/IAuthentication.sol"; import "../solidity-utils/helpers/ISignaturesValidator.sol"; import "../solidity-utils/helpers/ITemporarilyPausable.sol"; import "../solidity-utils/misc/IWETH.sol"; import "./IAsset.sol"; import "./IAuthorizer.sol"; import "./IFlashLoanRecipient.sol"; import "./IProtocolFeesCollector.sol"; pragma solidity >=0.7.0 <0.9.0; /** * @dev Full external interface for the Vault core contract - no external or public methods exist in the contract that * don't override one of these declarations. */ interface IVault is ISignaturesValidator, ITemporarilyPausable, IAuthentication { // Generalities about the Vault: // // - Whenever documentation refers to 'tokens', it strictly refers to ERC20-compliant token contracts. Tokens are // transferred out of the Vault by calling the `IERC20.transfer` function, and transferred in by calling // `IERC20.transferFrom`. In these cases, the sender must have previously allowed the Vault to use their tokens by // calling `IERC20.approve`. The only deviation from the ERC20 standard that is supported is functions not returning // a boolean value: in these scenarios, a non-reverting call is assumed to be successful. // // - All non-view functions in the Vault are non-reentrant: calling them while another one is mid-execution (e.g. // while execution control is transferred to a token contract during a swap) will result in a revert. View // functions can be called in a re-reentrant way, but doing so might cause them to return inconsistent results. // Contracts calling view functions in the Vault must make sure the Vault has not already been entered. // // - View functions revert if referring to either unregistered Pools, or unregistered tokens for registered Pools. // Authorizer // // Some system actions are permissioned, like setting and collecting protocol fees. This permissioning system exists // outside of the Vault in the Authorizer contract: the Vault simply calls the Authorizer to check if the caller // can perform a given action. /** * @dev Returns the Vault's Authorizer. */ function getAuthorizer() external view returns (IAuthorizer); /** * @dev Sets a new Authorizer for the Vault. The caller must be allowed by the current Authorizer to do this. * * Emits an `AuthorizerChanged` event. */ function setAuthorizer(IAuthorizer newAuthorizer) external; /** * @dev Emitted when a new authorizer is set by `setAuthorizer`. */ event AuthorizerChanged(IAuthorizer indexed newAuthorizer); // Relayers // // Additionally, it is possible for an account to perform certain actions on behalf of another one, using their // Vault ERC20 allowance and Internal Balance. These accounts are said to be 'relayers' for these Vault functions, // and are expected to be smart contracts with sound authentication mechanisms. For an account to be able to wield // this power, two things must occur: // - The Authorizer must grant the account the permission to be a relayer for the relevant Vault function. This // means that Balancer governance must approve each individual contract to act as a relayer for the intended // functions. // - Each user must approve the relayer to act on their behalf. // This double protection means users cannot be tricked into approving malicious relayers (because they will not // have been allowed by the Authorizer via governance), nor can malicious relayers approved by a compromised // Authorizer or governance drain user funds, since they would also need to be approved by each individual user. /** * @dev Returns true if `user` has approved `relayer` to act as a relayer for them. */ function hasApprovedRelayer(address user, address relayer) external view returns (bool); /** * @dev Allows `relayer` to act as a relayer for `sender` if `approved` is true, and disallows it otherwise. * * Emits a `RelayerApprovalChanged` event. */ function setRelayerApproval( address sender, address relayer, bool approved ) external; /** * @dev Emitted every time a relayer is approved or disapproved by `setRelayerApproval`. */ event RelayerApprovalChanged(address indexed relayer, address indexed sender, bool approved); // Internal Balance // // Users can deposit tokens into the Vault, where they are allocated to their Internal Balance, and later // transferred or withdrawn. It can also be used as a source of tokens when joining Pools, as a destination // when exiting them, and as either when performing swaps. This usage of Internal Balance results in greatly reduced // gas costs when compared to relying on plain ERC20 transfers, leading to large savings for frequent users. // // Internal Balance management features batching, which means a single contract call can be used to perform multiple // operations of different kinds, with different senders and recipients, at once. /** * @dev Returns `user`'s Internal Balance for a set of tokens. */ function getInternalBalance(address user, IERC20[] memory tokens) external view returns (uint256[] memory); /** * @dev Performs a set of user balance operations, which involve Internal Balance (deposit, withdraw or transfer) * and plain ERC20 transfers using the Vault's allowance. This last feature is particularly useful for relayers, as * it lets integrators reuse a user's Vault allowance. * * For each operation, if the caller is not `sender`, it must be an authorized relayer for them. */ function manageUserBalance(UserBalanceOp[] memory ops) external payable; /** * @dev Data for `manageUserBalance` operations, which include the possibility for ETH to be sent and received without manual WETH wrapping or unwrapping. */ struct UserBalanceOp { UserBalanceOpKind kind; IAsset asset; uint256 amount; address sender; address payable recipient; } // There are four possible operations in `manageUserBalance`: // // - DEPOSIT_INTERNAL // Increases the Internal Balance of the `recipient` account by transferring tokens from the corresponding // `sender`. The sender must have allowed the Vault to use their tokens via `IERC20.approve()`. // // ETH can be used by passing the ETH sentinel value as the asset and forwarding ETH in the call: it will be wrapped // and deposited as WETH. Any ETH amount remaining will be sent back to the caller (not the sender, which is // relevant for relayers). // // Emits an `InternalBalanceChanged` event. // // // - WITHDRAW_INTERNAL // Decreases the Internal Balance of the `sender` account by transferring tokens to the `recipient`. // // ETH can be used by passing the ETH sentinel value as the asset. This will deduct WETH instead, unwrap it and send // it to the recipient as ETH. // // Emits an `InternalBalanceChanged` event. // // // - TRANSFER_INTERNAL // Transfers tokens from the Internal Balance of the `sender` account to the Internal Balance of `recipient`. // // Reverts if the ETH sentinel value is passed. // // Emits an `InternalBalanceChanged` event. // // // - TRANSFER_EXTERNAL // Transfers tokens from `sender` to `recipient`, using the Vault's ERC20 allowance. This is typically used by // relayers, as it lets them reuse a user's Vault allowance. // // Reverts if the ETH sentinel value is passed. // // Emits an `ExternalBalanceTransfer` event. enum UserBalanceOpKind { DEPOSIT_INTERNAL, WITHDRAW_INTERNAL, TRANSFER_INTERNAL, TRANSFER_EXTERNAL } /** * @dev Emitted when a user's Internal Balance changes, either from calls to `manageUserBalance`, or through * interacting with Pools using Internal Balance. * * Because Internal Balance works exclusively with ERC20 tokens, ETH deposits and withdrawals will use the WETH * address. */ event InternalBalanceChanged(address indexed user, IERC20 indexed token, int256 delta); /** * @dev Emitted when a user's Vault ERC20 allowance is used by the Vault to transfer tokens to an external account. */ event ExternalBalanceTransfer(IERC20 indexed token, address indexed sender, address recipient, uint256 amount); // Pools // // There are three specialization settings for Pools, which allow for cheaper swaps at the cost of reduced // functionality: // // - General: no specialization, suited for all Pools. IGeneralPool is used for swap request callbacks, passing the // balance of all tokens in the Pool. These Pools have the largest swap costs (because of the extra storage reads), // which increase with the number of registered tokens. // // - Minimal Swap Info: IMinimalSwapInfoPool is used instead of IGeneralPool, which saves gas by only passing the // balance of the two tokens involved in the swap. This is suitable for some pricing algorithms, like the weighted // constant product one popularized by Balancer V1. Swap costs are smaller compared to general Pools, and are // independent of the number of registered tokens. // // - Two Token: only allows two tokens to be registered. This achieves the lowest possible swap gas cost. Like // minimal swap info Pools, these are called via IMinimalSwapInfoPool. enum PoolSpecialization { GENERAL, MINIMAL_SWAP_INFO, TWO_TOKEN } /** * @dev Registers the caller account as a Pool with a given specialization setting. Returns the Pool's ID, which * is used in all Pool-related functions. Pools cannot be deregistered, nor can the Pool's specialization be * changed. * * The caller is expected to be a smart contract that implements either `IGeneralPool` or `IMinimalSwapInfoPool`, * depending on the chosen specialization setting. This contract is known as the Pool's contract. * * Note that the same contract may register itself as multiple Pools with unique Pool IDs, or in other words, * multiple Pools may share the same contract. * * Emits a `PoolRegistered` event. */ function registerPool(PoolSpecialization specialization) external returns (bytes32); /** * @dev Emitted when a Pool is registered by calling `registerPool`. */ event PoolRegistered(bytes32 indexed poolId, address indexed poolAddress, PoolSpecialization specialization); /** * @dev Returns a Pool's contract address and specialization setting. */ function getPool(bytes32 poolId) external view returns (address, PoolSpecialization); /** * @dev Registers `tokens` for the `poolId` Pool. Must be called by the Pool's contract. * * Pools can only interact with tokens they have registered. Users join a Pool by transferring registered tokens, * exit by receiving registered tokens, and can only swap registered tokens. * * Each token can only be registered once. For Pools with the Two Token specialization, `tokens` must have a length * of two, that is, both tokens must be registered in the same `registerTokens` call, and they must be sorted in * ascending order. * * The `tokens` and `assetManagers` arrays must have the same length, and each entry in these indicates the Asset * Manager for the corresponding token. Asset Managers can manage a Pool's tokens via `managePoolBalance`, * depositing and withdrawing them directly, and can even set their balance to arbitrary amounts. They are therefore * expected to be highly secured smart contracts with sound design principles, and the decision to register an * Asset Manager should not be made lightly. * * Pools can choose not to assign an Asset Manager to a given token by passing in the zero address. Once an Asset * Manager is set, it cannot be changed except by deregistering the associated token and registering again with a * different Asset Manager. * * Emits a `TokensRegistered` event. */ function registerTokens( bytes32 poolId, IERC20[] memory tokens, address[] memory assetManagers ) external; /** * @dev Emitted when a Pool registers tokens by calling `registerTokens`. */ event TokensRegistered(bytes32 indexed poolId, IERC20[] tokens, address[] assetManagers); /** * @dev Deregisters `tokens` for the `poolId` Pool. Must be called by the Pool's contract. * * Only registered tokens (via `registerTokens`) can be deregistered. Additionally, they must have zero total * balance. For Pools with the Two Token specialization, `tokens` must have a length of two, that is, both tokens * must be deregistered in the same `deregisterTokens` call. * * A deregistered token can be re-registered later on, possibly with a different Asset Manager. * * Emits a `TokensDeregistered` event. */ function deregisterTokens(bytes32 poolId, IERC20[] memory tokens) external; /** * @dev Emitted when a Pool deregisters tokens by calling `deregisterTokens`. */ event TokensDeregistered(bytes32 indexed poolId, IERC20[] tokens); /** * @dev Returns detailed information for a Pool's registered token. * * `cash` is the number of tokens the Vault currently holds for the Pool. `managed` is the number of tokens * withdrawn and held outside the Vault by the Pool's token Asset Manager. The Pool's total balance for `token` * equals the sum of `cash` and `managed`. * * Internally, `cash` and `managed` are stored using 112 bits. No action can ever cause a Pool's token `cash`, * `managed` or `total` balance to be greater than 2^112 - 1. * * `lastChangeBlock` is the number of the block in which `token`'s total balance was last modified (via either a * join, exit, swap, or Asset Manager update). This value is useful to avoid so-called 'sandwich attacks', for * example when developing price oracles. A change of zero (e.g. caused by a swap with amount zero) is considered a * change for this purpose, and will update `lastChangeBlock`. * * `assetManager` is the Pool's token Asset Manager. */ function getPoolTokenInfo(bytes32 poolId, IERC20 token) external view returns ( uint256 cash, uint256 managed, uint256 lastChangeBlock, address assetManager ); /** * @dev Returns a Pool's registered tokens, the total balance for each, and the latest block when *any* of * the tokens' `balances` changed. * * The order of the `tokens` array is the same order that will be used in `joinPool`, `exitPool`, as well as in all * Pool hooks (where applicable). Calls to `registerTokens` and `deregisterTokens` may change this order. * * If a Pool only registers tokens once, and these are sorted in ascending order, they will be stored in the same * order as passed to `registerTokens`. * * Total balances include both tokens held by the Vault and those withdrawn by the Pool's Asset Managers. These are * the amounts used by joins, exits and swaps. For a detailed breakdown of token balances, use `getPoolTokenInfo` * instead. */ function getPoolTokens(bytes32 poolId) external view returns ( IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock ); /** * @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will * trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized * Pool shares. * * If the caller is not `sender`, it must be an authorized relayer for them. * * The `assets` and `maxAmountsIn` arrays must have the same length, and each entry indicates the maximum amount * to send for each asset. The amounts to send are decided by the Pool and not the Vault: it just enforces * these maximums. * * If joining a Pool that holds WETH, it is possible to send ETH directly: the Vault will do the wrapping. To enable * this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead of the * WETH address. Note that it is not possible to combine ETH and WETH in the same join. Any excess ETH will be sent * back to the caller (not the sender, which is important for relayers). * * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when * interacting with Pools that register and deregister tokens frequently. If sending ETH however, the array must be * sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the final * `assets` array might not be sorted. Pools with no registered tokens cannot be joined. * * If `fromInternalBalance` is true, the caller's Internal Balance will be preferred: ERC20 transfers will only * be made for the difference between the requested amount and Internal Balance (if any). Note that ETH cannot be * withdrawn from Internal Balance: attempting to do so will trigger a revert. * * This causes the Vault to call the `IBasePool.onJoinPool` hook on the Pool's contract, where Pools implement * their own custom logic. This typically requires additional information from the user (such as the expected number * of Pool shares). This can be encoded in the `userData` argument, which is ignored by the Vault and passed * directly to the Pool's contract, as is `recipient`. * * Emits a `PoolBalanceChanged` event. */ function joinPool( bytes32 poolId, address sender, address recipient, JoinPoolRequest memory request ) external payable; struct JoinPoolRequest { IAsset[] assets; uint256[] maxAmountsIn; bytes userData; bool fromInternalBalance; } /** * @dev Called by users to exit a Pool, which transfers tokens from the Pool's balance to `recipient`. This will * trigger custom Pool behavior, which will typically ask for something in return from `sender` - often tokenized * Pool shares. The amount of tokens that can be withdrawn is limited by the Pool's `cash` balance (see * `getPoolTokenInfo`). * * If the caller is not `sender`, it must be an authorized relayer for them. * * The `tokens` and `minAmountsOut` arrays must have the same length, and each entry in these indicates the minimum * token amount to receive for each token contract. The amounts to send are decided by the Pool and not the Vault: * it just enforces these minimums. * * If exiting a Pool that holds WETH, it is possible to receive ETH directly: the Vault will do the unwrapping. To * enable this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead * of the WETH address. Note that it is not possible to combine ETH and WETH in the same exit. * * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when * interacting with Pools that register and deregister tokens frequently. If receiving ETH however, the array must * be sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the * final `assets` array might not be sorted. Pools with no registered tokens cannot be exited. * * If `toInternalBalance` is true, the tokens will be deposited to `recipient`'s Internal Balance. Otherwise, * an ERC20 transfer will be performed. Note that ETH cannot be deposited to Internal Balance: attempting to * do so will trigger a revert. * * `minAmountsOut` is the minimum amount of tokens the user expects to get out of the Pool, for each token in the * `tokens` array. This array must match the Pool's registered tokens. * * This causes the Vault to call the `IBasePool.onExitPool` hook on the Pool's contract, where Pools implement * their own custom logic. This typically requires additional information from the user (such as the expected number * of Pool shares to return). This can be encoded in the `userData` argument, which is ignored by the Vault and * passed directly to the Pool's contract. * * Emits a `PoolBalanceChanged` event. */ function exitPool( bytes32 poolId, address sender, address payable recipient, ExitPoolRequest memory request ) external; struct ExitPoolRequest { IAsset[] assets; uint256[] minAmountsOut; bytes userData; bool toInternalBalance; } /** * @dev Emitted when a user joins or exits a Pool by calling `joinPool` or `exitPool`, respectively. */ event PoolBalanceChanged( bytes32 indexed poolId, address indexed liquidityProvider, IERC20[] tokens, int256[] deltas, uint256[] protocolFeeAmounts ); enum PoolBalanceChangeKind { JOIN, EXIT } // Swaps // // Users can swap tokens with Pools by calling the `swap` and `batchSwap` functions. To do this, // they need not trust Pool contracts in any way: all security checks are made by the Vault. They must however be // aware of the Pools' pricing algorithms in order to estimate the prices Pools will quote. // // The `swap` function executes a single swap, while `batchSwap` can perform multiple swaps in sequence. // In each individual swap, tokens of one kind are sent from the sender to the Pool (this is the 'token in'), // and tokens of another kind are sent from the Pool to the recipient in exchange (this is the 'token out'). // More complex swaps, such as one token in to multiple tokens out can be achieved by batching together // individual swaps. // // There are two swap kinds: // - 'given in' swaps, where the amount of tokens in (sent to the Pool) is known, and the Pool determines (via the // `onSwap` hook) the amount of tokens out (to send to the recipient). // - 'given out' swaps, where the amount of tokens out (received from the Pool) is known, and the Pool determines // (via the `onSwap` hook) the amount of tokens in (to receive from the sender). // // Additionally, it is possible to chain swaps using a placeholder input amount, which the Vault replaces with // the calculated output of the previous swap. If the previous swap was 'given in', this will be the calculated // tokenOut amount. If the previous swap was 'given out', it will use the calculated tokenIn amount. These extended // swaps are known as 'multihop' swaps, since they 'hop' through a number of intermediate tokens before arriving at // the final intended token. // // In all cases, tokens are only transferred in and out of the Vault (or withdrawn from and deposited into Internal // Balance) after all individual swaps have been completed, and the net token balance change computed. This makes // certain swap patterns, such as multihops, or swaps that interact with the same token pair in multiple Pools, cost // much less gas than they would otherwise. // // It also means that under certain conditions it is possible to perform arbitrage by swapping with multiple // Pools in a way that results in net token movement out of the Vault (profit), with no tokens being sent in (only // updating the Pool's internal accounting). // // To protect users from front-running or the market changing rapidly, they supply a list of 'limits' for each token // involved in the swap, where either the maximum number of tokens to send (by passing a positive value) or the // minimum amount of tokens to receive (by passing a negative value) is specified. // // Additionally, a 'deadline' timestamp can also be provided, forcing the swap to fail if it occurs after // this point in time (e.g. if the transaction failed to be included in a block promptly). // // If interacting with Pools that hold WETH, it is possible to both send and receive ETH directly: the Vault will do // the wrapping and unwrapping. To enable this mechanism, the IAsset sentinel value (the zero address) must be // passed in the `assets` array instead of the WETH address. Note that it is possible to combine ETH and WETH in the // same swap. Any excess ETH will be sent back to the caller (not the sender, which is relevant for relayers). // // Finally, Internal Balance can be used when either sending or receiving tokens. enum SwapKind { GIVEN_IN, GIVEN_OUT } /** * @dev Performs a swap with a single Pool. * * If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens * taken from the Pool, which must be greater than or equal to `limit`. * * If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens * sent to the Pool, which must be less than or equal to `limit`. * * Internal Balance usage and the recipient are determined by the `funds` struct. * * Emits a `Swap` event. */ function swap( SingleSwap memory singleSwap, FundManagement memory funds, uint256 limit, uint256 deadline ) external payable returns (uint256); /** * @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on * the `kind` value. * * `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address). * Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault. * * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be * used to extend swap behavior. */ struct SingleSwap { bytes32 poolId; SwapKind kind; IAsset assetIn; IAsset assetOut; uint256 amount; bytes userData; } /** * @dev Performs a series of swaps with one or multiple Pools. In each individual swap, the caller determines either * the amount of tokens sent to or received from the Pool, depending on the `kind` value. * * Returns an array with the net Vault asset balance deltas. Positive amounts represent tokens (or ETH) sent to the * Vault, and negative amounts represent tokens (or ETH) sent by the Vault. Each delta corresponds to the asset at * the same index in the `assets` array. * * Swaps are executed sequentially, in the order specified by the `swaps` array. Each array element describes a * Pool, the token to be sent to this Pool, the token to receive from it, and an amount that is either `amountIn` or * `amountOut` depending on the swap kind. * * Multihop swaps can be executed by passing an `amount` value of zero for a swap. This will cause the amount in/out * of the previous swap to be used as the amount in for the current one. In a 'given in' swap, 'tokenIn' must equal * the previous swap's `tokenOut`. For a 'given out' swap, `tokenOut` must equal the previous swap's `tokenIn`. * * The `assets` array contains the addresses of all assets involved in the swaps. These are either token addresses, * or the IAsset sentinel value for ETH (the zero address). Each entry in the `swaps` array specifies tokens in and * out by referencing an index in `assets`. Note that Pools never interact with ETH directly: it will be wrapped to * or unwrapped from WETH by the Vault. * * Internal Balance usage, sender, and recipient are determined by the `funds` struct. The `limits` array specifies * the minimum or maximum amount of each token the vault is allowed to transfer. * * `batchSwap` can be used to make a single swap, like `swap` does, but doing so requires more gas than the * equivalent `swap` call. * * Emits `Swap` events. */ function batchSwap( SwapKind kind, BatchSwapStep[] memory swaps, IAsset[] memory assets, FundManagement memory funds, int256[] memory limits, uint256 deadline ) external payable returns (int256[] memory); /** * @dev Data for each individual swap executed by `batchSwap`. The asset in and out fields are indexes into the * `assets` array passed to that function, and ETH assets are converted to WETH. * * If `amount` is zero, the multihop mechanism is used to determine the actual amount based on the amount in/out * from the previous swap, depending on the swap kind. * * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be * used to extend swap behavior. */ struct BatchSwapStep { bytes32 poolId; uint256 assetInIndex; uint256 assetOutIndex; uint256 amount; bytes userData; } /** * @dev Emitted for each individual swap performed by `swap` or `batchSwap`. */ event Swap( bytes32 indexed poolId, IERC20 indexed tokenIn, IERC20 indexed tokenOut, uint256 amountIn, uint256 amountOut ); /** * @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the * `recipient` account. * * If the caller is not `sender`, it must be an authorized relayer for them. * * If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20 * transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender` * must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of * `joinPool`. * * If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of * transferred. This matches the behavior of `exitPool`. * * Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a * revert. */ struct FundManagement { address sender; bool fromInternalBalance; address payable recipient; bool toInternalBalance; } /** * @dev Simulates a call to `batchSwap`, returning an array of Vault asset deltas. Calls to `swap` cannot be * simulated directly, but an equivalent `batchSwap` call can and will yield the exact same result. * * Each element in the array corresponds to the asset at the same index, and indicates the number of tokens (or ETH) * the Vault would take from the sender (if positive) or send to the recipient (if negative). The arguments it * receives are the same that an equivalent `batchSwap` call would receive. * * Unlike `batchSwap`, this function performs no checks on the sender or recipient field in the `funds` struct. * This makes it suitable to be called by off-chain applications via eth_call without needing to hold tokens, * approve them for the Vault, or even know a user's address. * * Note that this function is not 'view' (due to implementation details): the client code must explicitly execute * eth_call instead of eth_sendTransaction. */ function queryBatchSwap( SwapKind kind, BatchSwapStep[] memory swaps, IAsset[] memory assets, FundManagement memory funds ) external returns (int256[] memory assetDeltas); // Flash Loans /** * @dev Performs a 'flash loan', sending tokens to `recipient`, executing the `receiveFlashLoan` hook on it, * and then reverting unless the tokens plus a proportional protocol fee have been returned. * * The `tokens` and `amounts` arrays must have the same length, and each entry in these indicates the loan amount * for each token contract. `tokens` must be sorted in ascending order. * * The 'userData' field is ignored by the Vault, and forwarded as-is to `recipient` as part of the * `receiveFlashLoan` call. * * Emits `FlashLoan` events. */ function flashLoan( IFlashLoanRecipient recipient, IERC20[] memory tokens, uint256[] memory amounts, bytes memory userData ) external; /** * @dev Emitted for each individual flash loan performed by `flashLoan`. */ event FlashLoan(IFlashLoanRecipient indexed recipient, IERC20 indexed token, uint256 amount, uint256 feeAmount); // Asset Management // // Each token registered for a Pool can be assigned an Asset Manager, which is able to freely withdraw the Pool's // tokens from the Vault, deposit them, or assign arbitrary values to its `managed` balance (see // `getPoolTokenInfo`). This makes them extremely powerful and dangerous. Even if an Asset Manager only directly // controls one of the tokens in a Pool, a malicious manager could set that token's balance to manipulate the // prices of the other tokens, and then drain the Pool with swaps. The risk of using Asset Managers is therefore // not constrained to the tokens they are managing, but extends to the entire Pool's holdings. // // However, a properly designed Asset Manager smart contract can be safely used for the Pool's benefit, // for example by lending unused tokens out for interest, or using them to participate in voting protocols. // // This concept is unrelated to the IAsset interface. /** * @dev Performs a set of Pool balance operations, which may be either withdrawals, deposits or updates. * * Pool Balance management features batching, which means a single contract call can be used to perform multiple * operations of different kinds, with different Pools and tokens, at once. * * For each operation, the caller must be registered as the Asset Manager for `token` in `poolId`. */ function managePoolBalance(PoolBalanceOp[] memory ops) external; struct PoolBalanceOp { PoolBalanceOpKind kind; bytes32 poolId; IERC20 token; uint256 amount; } /** * Withdrawals decrease the Pool's cash, but increase its managed balance, leaving the total balance unchanged. * * Deposits increase the Pool's cash, but decrease its managed balance, leaving the total balance unchanged. * * Updates don't affect the Pool's cash balance, but because the managed balance changes, it does alter the total. * The external amount can be either increased or decreased by this call (i.e., reporting a gain or a loss). */ enum PoolBalanceOpKind { WITHDRAW, DEPOSIT, UPDATE } /** * @dev Emitted when a Pool's token Asset Manager alters its balance via `managePoolBalance`. */ event PoolBalanceManaged( bytes32 indexed poolId, address indexed assetManager, IERC20 indexed token, int256 cashDelta, int256 managedDelta ); // Protocol Fees // // Some operations cause the Vault to collect tokens in the form of protocol fees, which can then be withdrawn by // permissioned accounts. // // There are two kinds of protocol fees: // // - flash loan fees: charged on all flash loans, as a percentage of the amounts lent. // // - swap fees: a percentage of the fees charged by Pools when performing swaps. For a number of reasons, including // swap gas costs and interface simplicity, protocol swap fees are not charged on each individual swap. Rather, // Pools are expected to keep track of how much they have charged in swap fees, and pay any outstanding debts to the // Vault when they are joined or exited. This prevents users from joining a Pool with unpaid debt, as well as // exiting a Pool in debt without first paying their share. /** * @dev Returns the current protocol fee module. */ function getProtocolFeesCollector() external view returns (IProtocolFeesCollector); /** * @dev Safety mechanism to pause most Vault operations in the event of an emergency - typically detection of an * error in some part of the system. * * The Vault can only be paused during an initial time period, after which pausing is forever disabled. * * While the contract is paused, the following features are disabled: * - depositing and transferring internal balance * - transferring external balance (using the Vault's allowance) * - swaps * - joining Pools * - Asset Manager interactions * * Internal Balance can still be withdrawn, and Pools exited. */ function setPaused(bool paused) external; /** * @dev Returns the Vault's WETH instance. */ function WETH() external view returns (IWETH); // solhint-disable-previous-line func-name-mixedcase }
{ "optimizer": { "enabled": true, "runs": 9999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IVault","name":"_vault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"}],"name":"getAmpForPools","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"}],"name":"getInRecoveryModeForPools","outputs":[{"internalType":"bool[]","name":"","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"}],"name":"getIsPausedForPools","outputs":[{"internalType":"bool[]","name":"","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"}],"name":"getLinearTargetsForPools","outputs":[{"internalType":"uint256[][]","name":"","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"}],"name":"getNormalizedWeightsForPools","outputs":[{"internalType":"uint256[][]","name":"","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"poolIds","type":"bytes32[]"},{"components":[{"internalType":"bool","name":"loadTokenBalanceUpdatesAfterBlock","type":"bool"},{"internalType":"bool","name":"loadTotalSupply","type":"bool"},{"internalType":"bool","name":"loadSwapFees","type":"bool"},{"internalType":"bool","name":"loadLinearWrappedTokenRates","type":"bool"},{"internalType":"bool","name":"loadLinearTargets","type":"bool"},{"internalType":"bool","name":"loadNormalizedWeights","type":"bool"},{"internalType":"bool","name":"loadScalingFactors","type":"bool"},{"internalType":"bool","name":"loadAmps","type":"bool"},{"internalType":"bool","name":"loadRates","type":"bool"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"enum TotalSupplyType[]","name":"totalSupplyTypes","type":"uint8[]"},{"internalType":"enum SwapFeeType[]","name":"swapFeeTypes","type":"uint8[]"},{"internalType":"uint256[]","name":"linearPoolIdxs","type":"uint256[]"},{"internalType":"uint256[]","name":"weightedPoolIdxs","type":"uint256[]"},{"internalType":"uint256[]","name":"scalingFactorPoolIdxs","type":"uint256[]"},{"internalType":"uint256[]","name":"ampPoolIdxs","type":"uint256[]"},{"internalType":"uint256[]","name":"ratePoolIdxs","type":"uint256[]"}],"internalType":"struct PoolDataQueryConfig","name":"config","type":"tuple"}],"name":"getPoolData","outputs":[{"internalType":"uint256[][]","name":"balances","type":"uint256[][]"},{"internalType":"uint256[]","name":"totalSupplies","type":"uint256[]"},{"internalType":"uint256[]","name":"swapFees","type":"uint256[]"},{"internalType":"uint256[]","name":"linearWrappedTokenRates","type":"uint256[]"},{"internalType":"uint256[][]","name":"linearTargets","type":"uint256[][]"},{"internalType":"uint256[][]","name":"weights","type":"uint256[][]"},{"internalType":"uint256[][]","name":"scalingFactors","type":"uint256[][]"},{"internalType":"uint256[]","name":"amps","type":"uint256[]"},{"internalType":"uint256[]","name":"rates","type":"uint256[]"},{"internalType":"uint256[]","name":"ignoreIdxs","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"poolIds","type":"bytes32[]"},{"components":[{"internalType":"bool","name":"loadInRecoveryMode","type":"bool"},{"internalType":"bool","name":"loadIsPaused","type":"bool"}],"internalType":"struct PoolStatusQueryConfig","name":"config","type":"tuple"}],"name":"getPoolStatus","outputs":[{"internalType":"bool[]","name":"isPaused","type":"bool[]"},{"internalType":"bool[]","name":"inRecoveryMode","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"poolIds","type":"bytes32[]"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPoolTokenBalancesWithUpdatesAfterBlock","outputs":[{"internalType":"uint256[][]","name":"","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"}],"name":"getRateForPools","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"}],"name":"getScalingFactorsForPools","outputs":[{"internalType":"uint256[][]","name":"","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"},{"internalType":"enum SwapFeeType[]","name":"swapFeeTypes","type":"uint8[]"}],"name":"getSwapFeePercentageForPools","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"},{"internalType":"enum TotalSupplyType[]","name":"totalSupplyTypes","type":"uint8[]"}],"name":"getTotalSupplyForPools","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"poolAddresses","type":"address[]"}],"name":"getWrappedTokenRateForLinearPools","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b50604051620028ef380380620028ef83398101604081905262000034916200004a565b60601b6001600160601b0319166080526200007a565b6000602082840312156200005c578081fd5b81516001600160a01b038116811462000073578182fd5b9392505050565b60805160601c612848620000a76000398061056352806107045280610d1452806113cb52506128486000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063b3a460011161008c578063ecfb5a7c11610066578063ecfb5a7c146101eb578063ed5017f6146101fe578063fbfa77cf14610227578063fd4363781461023c576100ea565b8063b3a46001146101b2578063b4a9f0c8146101c5578063c4fb0f82146101d8576100ea565b8063716bb27a116100c8578063716bb27a1461014c5780637b2de5331461016c578063828f7c7d1461017f57806396ebd93414610192576100ea565b806304013a7d146100ef57806317615f32146101185780634b3dcc1e1461012b575b600080fd5b6101026100fd366004611ff9565b61024f565b60405161010f919061274e565b60405180910390f35b610102610126366004611fbe565b61046f565b61013e6101393660046122d4565b610507565b60405161010f929190612720565b61015f61015a366004612356565b6106a0565b60405161010f919061261f565b61010261017a366004611fbe565b6107fb565b61015f61018d366004611fbe565b61088a565b6101a56101a0366004611fbe565b610923565b60405161010f919061270d565b61015f6101c0366004611fbe565b6109b7565b6101026101d336600461205a565b610a50565b6101026101e6366004611fbe565b610b84565b61015f6101f9366004611fbe565b610c13565b61021161020c3660046120b1565b610cac565b60405161010f9a99989796959493929190612632565b61022f6113c9565b60405161010f919061276a565b6101a561024a366004611fbe565b6113ed565b606080835167ffffffffffffffff8111801561026a57600080fd5b50604051908082528060200260200182016040528015610294578160200160208202803683370190505b50905060005b84518110156104655760018482815181106102b157fe5b602002602001015160018111156102c457fe5b1415610396578481815181106102d657fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16634c1a41156040518163ffffffff1660e01b815260040160206040518083038186803b15801561032357600080fd5b505afa925050508015610353575060408051601f3d908101601f19168201909252610350918101906124f1565b60015b61037657600082828151811061036557fe5b602002602001018181525050610391565b8083838151811061038357fe5b602002602001018181525050505b61045d565b8481815181106103a257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff166355c676286040518163ffffffff1660e01b815260040160206040518083038186803b1580156103ef57600080fd5b505afa92505050801561041f575060408051601f3d908101601f1916820190925261041c918101906124f1565b60015b61044257600082828151811061043157fe5b60200260200101818152505061045d565b8083838151811061044f57fe5b602002602001018181525050505b60010161029a565b5090505b92915050565b606080825167ffffffffffffffff8111801561048a57600080fd5b506040519080825280602002602001820160405280156104b4578160200160208202803683370190505b50905060005b83518110156104fe576104df8482815181106104d257fe5b6020026020010151611481565b8282815181106104eb57fe5b60209081029190910101526001016104ba565b5090505b919050565b60608060006060855167ffffffffffffffff8111801561052657600080fd5b50604051908082528060200260200182016040528015610550578160200160208202803683370190505b509050600091505b855182101561066e577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f6c009278784815181106105a957fe5b60200260200101516040518263ffffffff1660e01b81526004016105cd9190612761565b604080518083038186803b1580156105e457600080fd5b505afa1580156105f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061c9190611f85565b5081838151811061062957fe5b602002602001018173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508180600101925050610558565b84602001511561068457610681816113ed565b93505b8451156106975761069481610923565b92505b50509250929050565b60608060006060855167ffffffffffffffff811180156106bf57600080fd5b506040519080825280602002602001820160405280156106f357816020015b60608152602001906001900390816106de5790505b50905060005b86518110156107f1577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f94d466888838151811061074a57fe5b60200260200101516040518263ffffffff1660e01b815260040161076e9190612761565b60006040518083038186803b15801561078657600080fd5b505afa15801561079a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107c29190810190612399565b909550935050858311156107e957838282815181106107dd57fe5b60200260200101819052505b6001016106f9565b5095945050505050565b606080825167ffffffffffffffff8111801561081657600080fd5b50604051908082528060200260200182016040528015610840578160200160208202803683370190505b50905060005b83518110156104fe5761086b84828151811061085e57fe5b602002602001015161150c565b82828151811061087757fe5b6020908102919091010152600101610846565b606080825167ffffffffffffffff811180156108a557600080fd5b506040519080825280602002602001820160405280156108d957816020015b60608152602001906001900390816108c45790505b50905060005b83518110156104fe576109048482815181106108f757fe5b602002602001015161159b565b82828151811061091057fe5b60209081029190910101526001016108df565b606080825167ffffffffffffffff8111801561093e57600080fd5b50604051908082528060200260200182016040528015610968578160200160208202803683370190505b50905060005b83518110156104fe5761099384828151811061098657fe5b6020026020010151611631565b82828151811061099f57fe5b9115156020928302919091019091015260010161096e565b606080825167ffffffffffffffff811180156109d257600080fd5b50604051908082528060200260200182016040528015610a0657816020015b60608152602001906001900390816109f15790505b50905060005b83518110156104fe57610a31848281518110610a2457fe5b60200260200101516116a6565b828281518110610a3d57fe5b6020908102919091010152600101610a0c565b606080835167ffffffffffffffff81118015610a6b57600080fd5b50604051908082528060200260200182016040528015610a95578160200160208202803683370190505b50905060005b8451811015610465576001848281518110610ab257fe5b60200260200101516002811115610ac557fe5b1415610b0457610ae7858281518110610ada57fe5b60200260200101516116ee565b828281518110610af357fe5b602002602001018181525050610b7c565b6002848281518110610b1257fe5b60200260200101516002811115610b2557fe5b1415610b4757610ae7858281518110610b3a57fe5b6020026020010151611736565b610b63858281518110610b5657fe5b602002602001015161177e565b828281518110610b6f57fe5b6020026020010181815250505b600101610a9b565b606080825167ffffffffffffffff81118015610b9f57600080fd5b50604051908082528060200260200182016040528015610bc9578160200160208202803683370190505b50905060005b83518110156104fe57610bf4848281518110610be757fe5b60200260200101516117c6565b828281518110610c0057fe5b6020908102919091010152600101610bcf565b606080825167ffffffffffffffff81118015610c2e57600080fd5b50604051908082528060200260200182016040528015610c6257816020015b6060815260200190600190039081610c4d5790505b50905060005b83518110156104fe57610c8d848281518110610c8057fe5b602002602001015161180e565b828281518110610c9957fe5b6020908102919091010152600101610c68565b606080606080606080606080606080600060608d5167ffffffffffffffff81118015610cd757600080fd5b50604051908082528060200260200182016040528015610d01578160200160208202803683370190505b509050600091505b8d51821015610e1f577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f6c009278f8481518110610d5a57fe5b60200260200101516040518263ffffffff1660e01b8152600401610d7e9190612761565b604080518083038186803b158015610d9557600080fd5b505afa158015610da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcd9190611f85565b50818381518110610dda57fe5b602002602001018173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508180600101925050610d09565b8c5115610e3857610e358e8e61012001516106a0565b9b505b8c6020015115610e5457610e51818e6101400151610a50565b9a505b8c6040015115610e7057610e6d818e610160015161024f565b99505b8c6060015115610f4e5760608d61018001515167ffffffffffffffff81118015610e9957600080fd5b50604051908082528060200260200182016040528015610ec3578160200160208202803683370190505b509050600092505b8d610180015151831015610f4157818e61018001518481518110610eeb57fe5b602002602001015181518110610efd57fe5b6020026020010151818481518110610f1157fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191610ecb565b610f4a8161046f565b9950505b8c60a001511561102c5760608d6101a001515167ffffffffffffffff81118015610f7757600080fd5b50604051908082528060200260200182016040528015610fa1578160200160208202803683370190505b509050600092505b8d6101a001515183101561101f57818e6101a001518481518110610fc957fe5b602002602001015181518110610fdb57fe5b6020026020010151818481518110610fef57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191610fa9565b611028816109b7565b9750505b8c60c001511561110a5760608d6101c001515167ffffffffffffffff8111801561105557600080fd5b5060405190808252806020026020018201604052801561107f578160200160208202803683370190505b509050600092505b8d6101c00151518310156110fd57818e6101c0015184815181106110a757fe5b6020026020010151815181106110b957fe5b60200260200101518184815181106110cd57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191611087565b6111068161088a565b9650505b8c60e00151156111e85760608d6101e001515167ffffffffffffffff8111801561113357600080fd5b5060405190808252806020026020018201604052801561115d578160200160208202803683370190505b509050600092505b8d6101e00151518310156111db57818e6101e00151848151811061118557fe5b60200260200101518151811061119757fe5b60200260200101518184815181106111ab57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191611165565b6111e4816107fb565b9550505b8c6101000151156112c75760608d61020001515167ffffffffffffffff8111801561121257600080fd5b5060405190808252806020026020018201604052801561123c578160200160208202803683370190505b509050600092505b8d6102000151518310156112ba57818e6102000151848151811061126457fe5b60200260200101518151811061127657fe5b602002602001015181848151811061128a57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191611244565b6112c381610b84565b9450505b8c60800151156113a55760608d61018001515167ffffffffffffffff811180156112f057600080fd5b5060405190808252806020026020018201604052801561131a578160200160208202803683370190505b509050600092505b8d61018001515183101561139857818e6101800151848151811061134257fe5b60200260200101518151811061135457fe5b602002602001015181848151811061136857fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191611322565b6113a181610c13565b9850505b6113b68e8e8d8d8d8a8a8d8f6118e5565b925050509295989b9194979a5092959850565b7f000000000000000000000000000000000000000000000000000000000000000081565b606080825167ffffffffffffffff8111801561140857600080fd5b50604051908082528060200260200182016040528015611432578160200160208202803683370190505b50905060005b83518110156104fe5761145d84828151811061145057fe5b6020026020010151611cf4565b82828151811061146957fe5b91151560209283029190910190910152600101611438565b60008173ffffffffffffffffffffffffffffffffffffffff1663f5431aa86040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b505afa9250505080156114f9575060408051601f3d908101601f191682019092526114f6918101906124f1565b60015b61150557506000610502565b9050610502565b60008173ffffffffffffffffffffffffffffffffffffffff16636daccffa6040518163ffffffff1660e01b815260040160606040518083038186803b15801561155457600080fd5b505afa925050508015611584575060408051601f3d908101601f1916820190925261158191810190612509565b60015b61159057506000610502565b829350505050610502565b60608173ffffffffffffffffffffffffffffffffffffffff16631dd746ea6040518163ffffffff1660e01b815260040160006040518083038186803b1580156115e357600080fd5b505afa92505050801561161857506040513d6000823e601f3d908101601f191682016040526116159190810190612465565b60015b6115055750604080516000815260208101909152610502565b60008173ffffffffffffffffffffffffffffffffffffffff1663b35056b86040518163ffffffff1660e01b815260040160206040518083038186803b15801561167957600080fd5b505afa9250505080156114f9575060408051601f3d908101601f191682019092526114f691810190612498565b60608173ffffffffffffffffffffffffffffffffffffffff1663f89f27ed6040518163ffffffff1660e01b815260040160006040518083038186803b1580156115e357600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff1663de82cd346040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff1663876f303b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff1663679aefce6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b6040805160028082526060808301845292839291906020830190803683370190505090508273ffffffffffffffffffffffffffffffffffffffff166363fe3b566040518163ffffffff1660e01b8152600401604080518083038186803b15801561187757600080fd5b505afa15801561188b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118af9190612541565b826000815181106118bc57fe5b60200260200101836001815181106118d057fe5b60209081029190910101919091525292915050565b6060808a5167ffffffffffffffff8111801561190057600080fd5b5060405190808252806020026020018201604052801561192a578160200160208202803683370190505b5090506000805b8c518110156119b4578b60200151801561195e57508a818151811061195257fe5b60200260200101516000145b8061198857508b604001518015611988575089818151811061197c57fe5b60200260200101516000145b156119ac57600183828151811061199b57fe5b911515602092830291909101909101525b600101611931565b8b6060015115611a2b575060005b8b610180015151811015611a2b578881815181106119dc57fe5b602002602001015160001415611a23576001838d61018001518381518110611a0057fe5b602002602001015181518110611a1257fe5b911515602092830291909101909101525b6001016119c2565b8b60e0015115611aa2575060005b8b6101e0015151811015611aa257878181518110611a5357fe5b602002602001015160001415611a9a576001838d6101e001518381518110611a7757fe5b602002602001015181518110611a8957fe5b911515602092830291909101909101525b600101611a39565b8b610100015115611b1a575060005b8b610200015151811015611b1a57868181518110611acb57fe5b602002602001015160001415611b12576001838d61020001518381518110611aef57fe5b602002602001015181518110611b0157fe5b911515602092830291909101909101525b600101611ab1565b8b60c0015115611b92575060005b8b6101c0015151811015611b9257858181518110611b4257fe5b60200260200101515160001415611b8a576001838d6101c001518381518110611b6757fe5b602002602001015181518110611b7957fe5b911515602092830291909101909101525b600101611b28565b8b60a0015115611c0a575060005b8b6101a0015151811015611c0a57848181518110611bba57fe5b60200260200101515160001415611c02576001838d6101a001518381518110611bdf57fe5b602002602001015181518110611bf157fe5b911515602092830291909101909101525b600101611ba0565b5060005b8251811015611c4657828181518110611c2357fe5b60200260200101511515600115151415611c3e576001909101905b600101611c0e565b60608267ffffffffffffffff81118015611c5f57600080fd5b50604051908082528060200260200182016040528015611c89578160200160208202803683370190505b50905060008092505b8451831015611ce257848381518110611ca757fe5b60200260200101511515600115151415611cd75782828281518110611cc857fe5b60209081029190910101526001015b600190920191611c92565b509d9c50505050505050505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff16631c0de0516040518163ffffffff1660e01b815260040160606040518083038186803b158015611d3c57600080fd5b505afa925050508015611584575060408051601f3d908101601f19168201909252611581918101906124bb565b600082601f830112611d79578081fd5b8135611d8c611d87826127b2565b61278b565b818152915060208083019084810181840286018201871015611dad57600080fd5b60005b84811015611dd5578135611dc3816127d2565b84529282019290820190600101611db0565b505050505092915050565b600082601f830112611df0578081fd5b8135611dfe611d87826127b2565b818152915060208083019084810181840286018201871015611e1f57600080fd5b60005b84811015611dd557813584529282019290820190600101611e22565b600082601f830112611e4e578081fd5b8135611e5c611d87826127b2565b818152915060208083019084810181840286018201871015611e7d57600080fd5b6000805b85811015611ea957823560028110611e97578283fd5b85529383019391830191600101611e81565b50505050505092915050565b600082601f830112611ec5578081fd5b8135611ed3611d87826127b2565b818152915060208083019084810181840286018201871015611ef457600080fd5b60005b84811015611dd5578135611f0a81612805565b84529282019290820190600101611ef7565b600082601f830112611f2c578081fd5b8151611f3a611d87826127b2565b818152915060208083019084810181840286018201871015611f5b57600080fd5b60005b84811015611dd557815184529282019290820190600101611f5e565b8035610469816127f7565b60008060408385031215611f97578182fd5b8251611fa2816127d2565b6020840151909250611fb381612805565b809150509250929050565b600060208284031215611fcf578081fd5b813567ffffffffffffffff811115611fe5578182fd5b611ff184828501611d69565b949350505050565b6000806040838503121561200b578182fd5b823567ffffffffffffffff80821115612022578384fd5b61202e86838701611d69565b93506020850135915080821115612043578283fd5b5061205085828601611e3e565b9150509250929050565b6000806040838503121561206c578182fd5b823567ffffffffffffffff80821115612083578384fd5b61208f86838701611d69565b935060208501359150808211156120a4578283fd5b5061205085828601611eb5565b600080604083850312156120c3578182fd5b823567ffffffffffffffff808211156120da578384fd5b6120e686838701611de0565b935060208501359150808211156120fb578283fd5b8185019150610220808388031215612111578384fd5b61211a8161278b565b90506121268784611f7a565b81526121358760208501611f7a565b60208201526121478760408501611f7a565b60408201526121598760608501611f7a565b606082015261216b8760808501611f7a565b608082015261217d8760a08501611f7a565b60a082015261218f8760c08501611f7a565b60c08201526121a18760e08501611f7a565b60e08201526101006121b588828601611f7a565b90820152610120838101359082015261014080840135838111156121d7578586fd5b6121e389828701611eb5565b82840152505061016080840135838111156121fc578586fd5b61220889828701611e3e565b8284015250506101808084013583811115612221578586fd5b61222d89828701611de0565b8284015250506101a08084013583811115612246578586fd5b61225289828701611de0565b8284015250506101c0808401358381111561226b578586fd5b61227789828701611de0565b8284015250506101e08084013583811115612290578586fd5b61229c89828701611de0565b82840152505061020080840135838111156122b5578586fd5b6122c189828701611de0565b8284015250508093505050509250929050565b60008082840360608112156122e7578283fd5b833567ffffffffffffffff8111156122fd578384fd5b61230986828701611de0565b9350506040601f198201121561231d578182fd5b50612328604061278b565b6020840135612336816127f7565b81526040840135612346816127f7565b6020820152919491935090915050565b60008060408385031215612368578182fd5b823567ffffffffffffffff81111561237e578283fd5b61238a85828601611de0565b95602094909401359450505050565b6000806000606084860312156123ad578081fd5b835167ffffffffffffffff808211156123c4578283fd5b818601915086601f8301126123d7578283fd5b81516123e5611d87826127b2565b80828252602080830192508086018b828387028901011115612405578788fd5b8796505b8487101561243057805161241c816127d2565b845260019690960195928101928101612409565b508901519097509350505080821115612447578283fd5b5061245486828701611f1c565b925050604084015190509250925092565b600060208284031215612476578081fd5b815167ffffffffffffffff81111561248c578182fd5b611ff184828501611f1c565b6000602082840312156124a9578081fd5b81516124b4816127f7565b9392505050565b6000806000606084860312156124cf578081fd5b83516124da816127f7565b602085015160409095015190969495509392505050565b600060208284031215612502578081fd5b5051919050565b60008060006060848603121561251d578081fd5b83519250602084015161252f816127f7565b80925050604084015190509250925092565b60008060408385031215612553578182fd5b505080516020909101519092909150565b6000815180845260208085019450848183028601828601855b858110156125a75783830389526125958383516125f0565b9885019892509084019060010161257d565b5090979650505050505050565b6000815180845260208085019450808401835b838110156125e55781511515875295820195908201906001016125c7565b509495945050505050565b6000815180845260208085019450808401835b838110156125e557815187529582019590820190600101612603565b6000602082526124b46020830184612564565b60006101408083526126468184018e612564565b9050828103602084015261265a818d6125f0565b9050828103604084015261266e818c6125f0565b90508281036060840152612682818b6125f0565b90508281036080840152612696818a612564565b905082810360a08401526126aa8189612564565b905082810360c08401526126be8188612564565b905082810360e08401526126d281876125f0565b90508281036101008401526126e781866125f0565b90508281036101208401526126fc81856125f0565b9d9c50505050505050505050505050565b6000602082526124b460208301846125b4565b60006040825261273360408301856125b4565b828103602084015261274581856125b4565b95945050505050565b6000602082526124b460208301846125f0565b90815260200190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405181810167ffffffffffffffff811182821017156127aa57600080fd5b604052919050565b600067ffffffffffffffff8211156127c8578081fd5b5060209081020190565b73ffffffffffffffffffffffffffffffffffffffff811681146127f457600080fd5b50565b80151581146127f457600080fd5b600381106127f457600080fdfea2646970667358221220ca3984f20141bfd5cfeb0527ebaa61758fcf55e38cecb2ccbda647cf7bf9f2c764736f6c63430007010033000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063b3a460011161008c578063ecfb5a7c11610066578063ecfb5a7c146101eb578063ed5017f6146101fe578063fbfa77cf14610227578063fd4363781461023c576100ea565b8063b3a46001146101b2578063b4a9f0c8146101c5578063c4fb0f82146101d8576100ea565b8063716bb27a116100c8578063716bb27a1461014c5780637b2de5331461016c578063828f7c7d1461017f57806396ebd93414610192576100ea565b806304013a7d146100ef57806317615f32146101185780634b3dcc1e1461012b575b600080fd5b6101026100fd366004611ff9565b61024f565b60405161010f919061274e565b60405180910390f35b610102610126366004611fbe565b61046f565b61013e6101393660046122d4565b610507565b60405161010f929190612720565b61015f61015a366004612356565b6106a0565b60405161010f919061261f565b61010261017a366004611fbe565b6107fb565b61015f61018d366004611fbe565b61088a565b6101a56101a0366004611fbe565b610923565b60405161010f919061270d565b61015f6101c0366004611fbe565b6109b7565b6101026101d336600461205a565b610a50565b6101026101e6366004611fbe565b610b84565b61015f6101f9366004611fbe565b610c13565b61021161020c3660046120b1565b610cac565b60405161010f9a99989796959493929190612632565b61022f6113c9565b60405161010f919061276a565b6101a561024a366004611fbe565b6113ed565b606080835167ffffffffffffffff8111801561026a57600080fd5b50604051908082528060200260200182016040528015610294578160200160208202803683370190505b50905060005b84518110156104655760018482815181106102b157fe5b602002602001015160018111156102c457fe5b1415610396578481815181106102d657fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16634c1a41156040518163ffffffff1660e01b815260040160206040518083038186803b15801561032357600080fd5b505afa925050508015610353575060408051601f3d908101601f19168201909252610350918101906124f1565b60015b61037657600082828151811061036557fe5b602002602001018181525050610391565b8083838151811061038357fe5b602002602001018181525050505b61045d565b8481815181106103a257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff166355c676286040518163ffffffff1660e01b815260040160206040518083038186803b1580156103ef57600080fd5b505afa92505050801561041f575060408051601f3d908101601f1916820190925261041c918101906124f1565b60015b61044257600082828151811061043157fe5b60200260200101818152505061045d565b8083838151811061044f57fe5b602002602001018181525050505b60010161029a565b5090505b92915050565b606080825167ffffffffffffffff8111801561048a57600080fd5b506040519080825280602002602001820160405280156104b4578160200160208202803683370190505b50905060005b83518110156104fe576104df8482815181106104d257fe5b6020026020010151611481565b8282815181106104eb57fe5b60209081029190910101526001016104ba565b5090505b919050565b60608060006060855167ffffffffffffffff8111801561052657600080fd5b50604051908082528060200260200182016040528015610550578160200160208202803683370190505b509050600091505b855182101561066e577f000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c873ffffffffffffffffffffffffffffffffffffffff1663f6c009278784815181106105a957fe5b60200260200101516040518263ffffffff1660e01b81526004016105cd9190612761565b604080518083038186803b1580156105e457600080fd5b505afa1580156105f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061c9190611f85565b5081838151811061062957fe5b602002602001018173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508180600101925050610558565b84602001511561068457610681816113ed565b93505b8451156106975761069481610923565b92505b50509250929050565b60608060006060855167ffffffffffffffff811180156106bf57600080fd5b506040519080825280602002602001820160405280156106f357816020015b60608152602001906001900390816106de5790505b50905060005b86518110156107f1577f000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c873ffffffffffffffffffffffffffffffffffffffff1663f94d466888838151811061074a57fe5b60200260200101516040518263ffffffff1660e01b815260040161076e9190612761565b60006040518083038186803b15801561078657600080fd5b505afa15801561079a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107c29190810190612399565b909550935050858311156107e957838282815181106107dd57fe5b60200260200101819052505b6001016106f9565b5095945050505050565b606080825167ffffffffffffffff8111801561081657600080fd5b50604051908082528060200260200182016040528015610840578160200160208202803683370190505b50905060005b83518110156104fe5761086b84828151811061085e57fe5b602002602001015161150c565b82828151811061087757fe5b6020908102919091010152600101610846565b606080825167ffffffffffffffff811180156108a557600080fd5b506040519080825280602002602001820160405280156108d957816020015b60608152602001906001900390816108c45790505b50905060005b83518110156104fe576109048482815181106108f757fe5b602002602001015161159b565b82828151811061091057fe5b60209081029190910101526001016108df565b606080825167ffffffffffffffff8111801561093e57600080fd5b50604051908082528060200260200182016040528015610968578160200160208202803683370190505b50905060005b83518110156104fe5761099384828151811061098657fe5b6020026020010151611631565b82828151811061099f57fe5b9115156020928302919091019091015260010161096e565b606080825167ffffffffffffffff811180156109d257600080fd5b50604051908082528060200260200182016040528015610a0657816020015b60608152602001906001900390816109f15790505b50905060005b83518110156104fe57610a31848281518110610a2457fe5b60200260200101516116a6565b828281518110610a3d57fe5b6020908102919091010152600101610a0c565b606080835167ffffffffffffffff81118015610a6b57600080fd5b50604051908082528060200260200182016040528015610a95578160200160208202803683370190505b50905060005b8451811015610465576001848281518110610ab257fe5b60200260200101516002811115610ac557fe5b1415610b0457610ae7858281518110610ada57fe5b60200260200101516116ee565b828281518110610af357fe5b602002602001018181525050610b7c565b6002848281518110610b1257fe5b60200260200101516002811115610b2557fe5b1415610b4757610ae7858281518110610b3a57fe5b6020026020010151611736565b610b63858281518110610b5657fe5b602002602001015161177e565b828281518110610b6f57fe5b6020026020010181815250505b600101610a9b565b606080825167ffffffffffffffff81118015610b9f57600080fd5b50604051908082528060200260200182016040528015610bc9578160200160208202803683370190505b50905060005b83518110156104fe57610bf4848281518110610be757fe5b60200260200101516117c6565b828281518110610c0057fe5b6020908102919091010152600101610bcf565b606080825167ffffffffffffffff81118015610c2e57600080fd5b50604051908082528060200260200182016040528015610c6257816020015b6060815260200190600190039081610c4d5790505b50905060005b83518110156104fe57610c8d848281518110610c8057fe5b602002602001015161180e565b828281518110610c9957fe5b6020908102919091010152600101610c68565b606080606080606080606080606080600060608d5167ffffffffffffffff81118015610cd757600080fd5b50604051908082528060200260200182016040528015610d01578160200160208202803683370190505b509050600091505b8d51821015610e1f577f000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c873ffffffffffffffffffffffffffffffffffffffff1663f6c009278f8481518110610d5a57fe5b60200260200101516040518263ffffffff1660e01b8152600401610d7e9190612761565b604080518083038186803b158015610d9557600080fd5b505afa158015610da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcd9190611f85565b50818381518110610dda57fe5b602002602001018173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508180600101925050610d09565b8c5115610e3857610e358e8e61012001516106a0565b9b505b8c6020015115610e5457610e51818e6101400151610a50565b9a505b8c6040015115610e7057610e6d818e610160015161024f565b99505b8c6060015115610f4e5760608d61018001515167ffffffffffffffff81118015610e9957600080fd5b50604051908082528060200260200182016040528015610ec3578160200160208202803683370190505b509050600092505b8d610180015151831015610f4157818e61018001518481518110610eeb57fe5b602002602001015181518110610efd57fe5b6020026020010151818481518110610f1157fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191610ecb565b610f4a8161046f565b9950505b8c60a001511561102c5760608d6101a001515167ffffffffffffffff81118015610f7757600080fd5b50604051908082528060200260200182016040528015610fa1578160200160208202803683370190505b509050600092505b8d6101a001515183101561101f57818e6101a001518481518110610fc957fe5b602002602001015181518110610fdb57fe5b6020026020010151818481518110610fef57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191610fa9565b611028816109b7565b9750505b8c60c001511561110a5760608d6101c001515167ffffffffffffffff8111801561105557600080fd5b5060405190808252806020026020018201604052801561107f578160200160208202803683370190505b509050600092505b8d6101c00151518310156110fd57818e6101c0015184815181106110a757fe5b6020026020010151815181106110b957fe5b60200260200101518184815181106110cd57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191611087565b6111068161088a565b9650505b8c60e00151156111e85760608d6101e001515167ffffffffffffffff8111801561113357600080fd5b5060405190808252806020026020018201604052801561115d578160200160208202803683370190505b509050600092505b8d6101e00151518310156111db57818e6101e00151848151811061118557fe5b60200260200101518151811061119757fe5b60200260200101518184815181106111ab57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191611165565b6111e4816107fb565b9550505b8c6101000151156112c75760608d61020001515167ffffffffffffffff8111801561121257600080fd5b5060405190808252806020026020018201604052801561123c578160200160208202803683370190505b509050600092505b8d6102000151518310156112ba57818e6102000151848151811061126457fe5b60200260200101518151811061127657fe5b602002602001015181848151811061128a57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191611244565b6112c381610b84565b9450505b8c60800151156113a55760608d61018001515167ffffffffffffffff811180156112f057600080fd5b5060405190808252806020026020018201604052801561131a578160200160208202803683370190505b509050600092505b8d61018001515183101561139857818e6101800151848151811061134257fe5b60200260200101518151811061135457fe5b602002602001015181848151811061136857fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600190920191611322565b6113a181610c13565b9850505b6113b68e8e8d8d8d8a8a8d8f6118e5565b925050509295989b9194979a5092959850565b7f000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c881565b606080825167ffffffffffffffff8111801561140857600080fd5b50604051908082528060200260200182016040528015611432578160200160208202803683370190505b50905060005b83518110156104fe5761145d84828151811061145057fe5b6020026020010151611cf4565b82828151811061146957fe5b91151560209283029190910190910152600101611438565b60008173ffffffffffffffffffffffffffffffffffffffff1663f5431aa86040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b505afa9250505080156114f9575060408051601f3d908101601f191682019092526114f6918101906124f1565b60015b61150557506000610502565b9050610502565b60008173ffffffffffffffffffffffffffffffffffffffff16636daccffa6040518163ffffffff1660e01b815260040160606040518083038186803b15801561155457600080fd5b505afa925050508015611584575060408051601f3d908101601f1916820190925261158191810190612509565b60015b61159057506000610502565b829350505050610502565b60608173ffffffffffffffffffffffffffffffffffffffff16631dd746ea6040518163ffffffff1660e01b815260040160006040518083038186803b1580156115e357600080fd5b505afa92505050801561161857506040513d6000823e601f3d908101601f191682016040526116159190810190612465565b60015b6115055750604080516000815260208101909152610502565b60008173ffffffffffffffffffffffffffffffffffffffff1663b35056b86040518163ffffffff1660e01b815260040160206040518083038186803b15801561167957600080fd5b505afa9250505080156114f9575060408051601f3d908101601f191682019092526114f691810190612498565b60608173ffffffffffffffffffffffffffffffffffffffff1663f89f27ed6040518163ffffffff1660e01b815260040160006040518083038186803b1580156115e357600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff1663de82cd346040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff1663876f303b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff1663679aefce6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c957600080fd5b6040805160028082526060808301845292839291906020830190803683370190505090508273ffffffffffffffffffffffffffffffffffffffff166363fe3b566040518163ffffffff1660e01b8152600401604080518083038186803b15801561187757600080fd5b505afa15801561188b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118af9190612541565b826000815181106118bc57fe5b60200260200101836001815181106118d057fe5b60209081029190910101919091525292915050565b6060808a5167ffffffffffffffff8111801561190057600080fd5b5060405190808252806020026020018201604052801561192a578160200160208202803683370190505b5090506000805b8c518110156119b4578b60200151801561195e57508a818151811061195257fe5b60200260200101516000145b8061198857508b604001518015611988575089818151811061197c57fe5b60200260200101516000145b156119ac57600183828151811061199b57fe5b911515602092830291909101909101525b600101611931565b8b6060015115611a2b575060005b8b610180015151811015611a2b578881815181106119dc57fe5b602002602001015160001415611a23576001838d61018001518381518110611a0057fe5b602002602001015181518110611a1257fe5b911515602092830291909101909101525b6001016119c2565b8b60e0015115611aa2575060005b8b6101e0015151811015611aa257878181518110611a5357fe5b602002602001015160001415611a9a576001838d6101e001518381518110611a7757fe5b602002602001015181518110611a8957fe5b911515602092830291909101909101525b600101611a39565b8b610100015115611b1a575060005b8b610200015151811015611b1a57868181518110611acb57fe5b602002602001015160001415611b12576001838d61020001518381518110611aef57fe5b602002602001015181518110611b0157fe5b911515602092830291909101909101525b600101611ab1565b8b60c0015115611b92575060005b8b6101c0015151811015611b9257858181518110611b4257fe5b60200260200101515160001415611b8a576001838d6101c001518381518110611b6757fe5b602002602001015181518110611b7957fe5b911515602092830291909101909101525b600101611b28565b8b60a0015115611c0a575060005b8b6101a0015151811015611c0a57848181518110611bba57fe5b60200260200101515160001415611c02576001838d6101a001518381518110611bdf57fe5b602002602001015181518110611bf157fe5b911515602092830291909101909101525b600101611ba0565b5060005b8251811015611c4657828181518110611c2357fe5b60200260200101511515600115151415611c3e576001909101905b600101611c0e565b60608267ffffffffffffffff81118015611c5f57600080fd5b50604051908082528060200260200182016040528015611c89578160200160208202803683370190505b50905060008092505b8451831015611ce257848381518110611ca757fe5b60200260200101511515600115151415611cd75782828281518110611cc857fe5b60209081029190910101526001015b600190920191611c92565b509d9c50505050505050505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff16631c0de0516040518163ffffffff1660e01b815260040160606040518083038186803b158015611d3c57600080fd5b505afa925050508015611584575060408051601f3d908101601f19168201909252611581918101906124bb565b600082601f830112611d79578081fd5b8135611d8c611d87826127b2565b61278b565b818152915060208083019084810181840286018201871015611dad57600080fd5b60005b84811015611dd5578135611dc3816127d2565b84529282019290820190600101611db0565b505050505092915050565b600082601f830112611df0578081fd5b8135611dfe611d87826127b2565b818152915060208083019084810181840286018201871015611e1f57600080fd5b60005b84811015611dd557813584529282019290820190600101611e22565b600082601f830112611e4e578081fd5b8135611e5c611d87826127b2565b818152915060208083019084810181840286018201871015611e7d57600080fd5b6000805b85811015611ea957823560028110611e97578283fd5b85529383019391830191600101611e81565b50505050505092915050565b600082601f830112611ec5578081fd5b8135611ed3611d87826127b2565b818152915060208083019084810181840286018201871015611ef457600080fd5b60005b84811015611dd5578135611f0a81612805565b84529282019290820190600101611ef7565b600082601f830112611f2c578081fd5b8151611f3a611d87826127b2565b818152915060208083019084810181840286018201871015611f5b57600080fd5b60005b84811015611dd557815184529282019290820190600101611f5e565b8035610469816127f7565b60008060408385031215611f97578182fd5b8251611fa2816127d2565b6020840151909250611fb381612805565b809150509250929050565b600060208284031215611fcf578081fd5b813567ffffffffffffffff811115611fe5578182fd5b611ff184828501611d69565b949350505050565b6000806040838503121561200b578182fd5b823567ffffffffffffffff80821115612022578384fd5b61202e86838701611d69565b93506020850135915080821115612043578283fd5b5061205085828601611e3e565b9150509250929050565b6000806040838503121561206c578182fd5b823567ffffffffffffffff80821115612083578384fd5b61208f86838701611d69565b935060208501359150808211156120a4578283fd5b5061205085828601611eb5565b600080604083850312156120c3578182fd5b823567ffffffffffffffff808211156120da578384fd5b6120e686838701611de0565b935060208501359150808211156120fb578283fd5b8185019150610220808388031215612111578384fd5b61211a8161278b565b90506121268784611f7a565b81526121358760208501611f7a565b60208201526121478760408501611f7a565b60408201526121598760608501611f7a565b606082015261216b8760808501611f7a565b608082015261217d8760a08501611f7a565b60a082015261218f8760c08501611f7a565b60c08201526121a18760e08501611f7a565b60e08201526101006121b588828601611f7a565b90820152610120838101359082015261014080840135838111156121d7578586fd5b6121e389828701611eb5565b82840152505061016080840135838111156121fc578586fd5b61220889828701611e3e565b8284015250506101808084013583811115612221578586fd5b61222d89828701611de0565b8284015250506101a08084013583811115612246578586fd5b61225289828701611de0565b8284015250506101c0808401358381111561226b578586fd5b61227789828701611de0565b8284015250506101e08084013583811115612290578586fd5b61229c89828701611de0565b82840152505061020080840135838111156122b5578586fd5b6122c189828701611de0565b8284015250508093505050509250929050565b60008082840360608112156122e7578283fd5b833567ffffffffffffffff8111156122fd578384fd5b61230986828701611de0565b9350506040601f198201121561231d578182fd5b50612328604061278b565b6020840135612336816127f7565b81526040840135612346816127f7565b6020820152919491935090915050565b60008060408385031215612368578182fd5b823567ffffffffffffffff81111561237e578283fd5b61238a85828601611de0565b95602094909401359450505050565b6000806000606084860312156123ad578081fd5b835167ffffffffffffffff808211156123c4578283fd5b818601915086601f8301126123d7578283fd5b81516123e5611d87826127b2565b80828252602080830192508086018b828387028901011115612405578788fd5b8796505b8487101561243057805161241c816127d2565b845260019690960195928101928101612409565b508901519097509350505080821115612447578283fd5b5061245486828701611f1c565b925050604084015190509250925092565b600060208284031215612476578081fd5b815167ffffffffffffffff81111561248c578182fd5b611ff184828501611f1c565b6000602082840312156124a9578081fd5b81516124b4816127f7565b9392505050565b6000806000606084860312156124cf578081fd5b83516124da816127f7565b602085015160409095015190969495509392505050565b600060208284031215612502578081fd5b5051919050565b60008060006060848603121561251d578081fd5b83519250602084015161252f816127f7565b80925050604084015190509250925092565b60008060408385031215612553578182fd5b505080516020909101519092909150565b6000815180845260208085019450848183028601828601855b858110156125a75783830389526125958383516125f0565b9885019892509084019060010161257d565b5090979650505050505050565b6000815180845260208085019450808401835b838110156125e55781511515875295820195908201906001016125c7565b509495945050505050565b6000815180845260208085019450808401835b838110156125e557815187529582019590820190600101612603565b6000602082526124b46020830184612564565b60006101408083526126468184018e612564565b9050828103602084015261265a818d6125f0565b9050828103604084015261266e818c6125f0565b90508281036060840152612682818b6125f0565b90508281036080840152612696818a612564565b905082810360a08401526126aa8189612564565b905082810360c08401526126be8188612564565b905082810360e08401526126d281876125f0565b90508281036101008401526126e781866125f0565b90508281036101208401526126fc81856125f0565b9d9c50505050505050505050505050565b6000602082526124b460208301846125b4565b60006040825261273360408301856125b4565b828103602084015261274581856125b4565b95945050505050565b6000602082526124b460208301846125f0565b90815260200190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405181810167ffffffffffffffff811182821017156127aa57600080fd5b604052919050565b600067ffffffffffffffff8211156127c8578081fd5b5060209081020190565b73ffffffffffffffffffffffffffffffffffffffff811681146127f457600080fd5b50565b80151581146127f457600080fd5b600381106127f457600080fdfea2646970667358221220ca3984f20141bfd5cfeb0527ebaa61758fcf55e38cecb2ccbda647cf7bf9f2c764736f6c63430007010033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8
-----Decoded View---------------
Arg [0] : _vault (address): 0xBA12222222228d8Ba445958a75a0704d566BF2C8
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.