Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
19555233 | 320 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
CurveV1Adapter2Assets
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {AdapterType} from "@gearbox-protocol/sdk-gov/contracts/AdapterType.sol"; import {IAdapter} from "@gearbox-protocol/core-v2/contracts/interfaces/IAdapter.sol"; import {ICurvePool2Assets, N_COINS} from "../../integrations/curve/ICurvePool_2.sol"; import {ICurveV1_2AssetsAdapter} from "../../interfaces/curve/ICurveV1_2AssetsAdapter.sol"; import {CurveV1AdapterBase} from "./CurveV1_Base.sol"; /// @title Curve V1 2 assets adapter /// @notice Implements logic allowing to interact with Curve pools with 2 assets contract CurveV1Adapter2Assets is CurveV1AdapterBase, ICurveV1_2AssetsAdapter { function _gearboxAdapterType() external pure virtual override returns (AdapterType) { return AdapterType.CURVE_V1_2ASSETS; } /// @notice Constructor /// @param _creditManager Credit manager address /// @param _curvePool Target Curve pool address /// @param _lp_token Pool LP token address /// @param _metapoolBase Base pool address (for metapools only) or zero address constructor(address _creditManager, address _curvePool, address _lp_token, address _metapoolBase) CurveV1AdapterBase(_creditManager, _curvePool, _lp_token, _metapoolBase, N_COINS) {} /// @notice Add liquidity to the pool /// @param amounts Amounts of tokens to add /// @dev `min_mint_amount` parameter is ignored because calldata is passed directly to the target contract function add_liquidity(uint256[N_COINS] calldata amounts, uint256) external override creditFacadeOnly // U:[CRV2-1] returns (uint256 tokensToEnable, uint256 tokensToDisable) { (tokensToEnable, tokensToDisable) = _add_liquidity(amounts[0] > 1, amounts[1] > 1, false, false); // U:[CRV2-2] } /// @dev Returns calldata for adding liquidity in coin `i` function _getAddLiquidityOneCoinCallData(uint256 i, uint256 amount, uint256 minAmount) internal pure override returns (bytes memory) { uint256[2] memory amounts; amounts[i] = amount; return abi.encodeCall(ICurvePool2Assets.add_liquidity, (amounts, minAmount)); } /// @dev Returns calldata for calculating the result of adding liquidity in coin `i` function _getCalcAddOneCoinCallData(uint256 i, uint256 amount) internal pure override returns (bytes memory, bytes memory) { uint256[2] memory amounts; amounts[i] = amount; return ( abi.encodeCall(ICurvePool2Assets.calc_token_amount, (amounts, true)), abi.encodeWithSignature("calc_token_amount(uint256[2])", amounts) ); } /// @notice Remove liquidity from the pool /// @dev '_amount' and 'min_amounts' parameters are ignored because calldata is directly passed to the target contract function remove_liquidity(uint256, uint256[N_COINS] calldata) external virtual creditFacadeOnly // U:[CRV2-1] returns (uint256 tokensToEnable, uint256 tokensToDisable) { (tokensToEnable, tokensToDisable) = _remove_liquidity(); // U:[CRV2-3] } /// @notice Withdraw exact amounts of tokens from the pool /// @param amounts Amounts of tokens to withdraw /// @dev `max_burn_amount` parameter is ignored because calldata is directly passed to the target contract function remove_liquidity_imbalance(uint256[N_COINS] calldata amounts, uint256) external virtual override creditFacadeOnly // U:[CRV2-1] returns (uint256 tokensToEnable, uint256 tokensToDisable) { (tokensToEnable, tokensToDisable) = _remove_liquidity_imbalance(amounts[0] > 1, amounts[1] > 1, false, false); // U:[CRV2-4] } }
// SPDX-License-Identifier: UNLICENSED // Gearbox. Generalized leverage protocol that allows to take leverage and then use it across other DeFi protocols and platforms in a composable way. // (c) Gearbox Foundation, 2023 pragma solidity ^0.8.17; enum AdapterType { ABSTRACT, UNISWAP_V2_ROUTER, UNISWAP_V3_ROUTER, CURVE_V1_EXCHANGE_ONLY, YEARN_V2, CURVE_V1_2ASSETS, CURVE_V1_3ASSETS, CURVE_V1_4ASSETS, CURVE_V1_STECRV_POOL, CURVE_V1_WRAPPER, CONVEX_V1_BASE_REWARD_POOL, CONVEX_V1_BOOSTER, CONVEX_V1_CLAIM_ZAP, LIDO_V1, UNIVERSAL, LIDO_WSTETH_V1, BALANCER_VAULT, AAVE_V2_LENDING_POOL, AAVE_V2_WRAPPED_ATOKEN, COMPOUND_V2_CERC20, COMPOUND_V2_CETHER, ERC4626_VAULT, VELODROME_V2_ROUTER, CURVE_STABLE_NG, CAMELOT_V3_ROUTER, CONVEX_L2_BOOSTER, CONVEX_L2_REWARD_POOL, AAVE_V3_LENDING_POOL }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.0; import { AdapterType } from "@gearbox-protocol/sdk-gov/contracts/AdapterType.sol"; /// @title Adapter interface interface IAdapter { function _gearboxAdapterType() external view returns (AdapterType); function _gearboxAdapterVersion() external view returns (uint16); function creditManager() external view returns (address); function addressProvider() external view returns (address); function targetContract() external view returns (address); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.10; import {ICurvePool} from "./ICurvePool.sol"; uint256 constant N_COINS = 2; /// @title ICurvePool2Assets /// @dev Extends original pool contract with liquidity functions interface ICurvePool2Assets is ICurvePool { function add_liquidity(uint256[N_COINS] memory amounts, uint256 min_mint_amount) external; function remove_liquidity(uint256 _amount, uint256[N_COINS] memory min_amounts) external; function remove_liquidity_imbalance(uint256[N_COINS] calldata amounts, uint256 max_burn_amount) external; function calc_token_amount(uint256[N_COINS] calldata _amounts, bool _is_deposit) external view returns (uint256); function get_twap_balances( uint256[N_COINS] calldata _first_balances, uint256[N_COINS] calldata _last_balances, uint256 _time_elapsed ) external view returns (uint256[N_COINS] memory); function get_balances() external view returns (uint256[N_COINS] memory); function get_previous_balances() external view returns (uint256[N_COINS] memory); function get_price_cumulative_last() external view returns (uint256[N_COINS] memory); }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {N_COINS} from "../../integrations/curve/ICurvePool_2.sol"; import {ICurveV1Adapter} from "./ICurveV1Adapter.sol"; /// @title Curve V1 2 assets adapter interface interface ICurveV1_2AssetsAdapter is ICurveV1Adapter { function add_liquidity(uint256[N_COINS] calldata amounts, uint256) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function remove_liquidity(uint256, uint256[N_COINS] calldata) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function remove_liquidity_imbalance(uint256[N_COINS] calldata amounts, uint256) external returns (uint256 tokensToEnable, uint256 tokensToDisable); }
// SPDX-License-Identifier: GPL-2.0-or-later // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {RAY} from "@gearbox-protocol/core-v2/contracts/libraries/Constants.sol"; import {BitMask} from "@gearbox-protocol/core-v3/contracts/libraries/BitMask.sol"; import {IncorrectParameterException} from "@gearbox-protocol/core-v3/contracts/interfaces/IExceptions.sol"; import {ICurvePool} from "../../integrations/curve/ICurvePool.sol"; import {ICurveV1Adapter} from "../../interfaces/curve/ICurveV1Adapter.sol"; import {AbstractAdapter} from "../AbstractAdapter.sol"; /// @title Curve adapter base /// @notice Implements logic allowing credit accounts to interact with Curve pools with arbitrary number of coins, /// supporting stable/crypto plain/meta/lending pools of different versions abstract contract CurveV1AdapterBase is AbstractAdapter, ICurveV1Adapter { using BitMask for uint256; uint16 public constant override _gearboxAdapterVersion = 3_00; /// @notice Pool LP token address (added for backward compatibility) address public immutable override token; /// @notice Pool LP token address address public immutable override lp_token; /// @notice Collateral token mask of pool LP token in the credit manager uint256 public immutable override lpTokenMask; /// @notice Base pool address (for metapools only) address public immutable override metapoolBase; /// @notice Number of coins in the pool uint256 public immutable override nCoins; /// @notice Whether pool is cryptoswap or stableswap bool public immutable override use256; address public immutable override token0; address public immutable override token1; address public immutable override token2; address public immutable override token3; uint256 public immutable override token0Mask; uint256 public immutable override token1Mask; uint256 public immutable override token2Mask; uint256 public immutable override token3Mask; address public immutable override underlying0; address public immutable override underlying1; address public immutable override underlying2; address public immutable override underlying3; uint256 public immutable override underlying0Mask; uint256 public immutable override underlying1Mask; uint256 public immutable override underlying2Mask; uint256 public immutable override underlying3Mask; /// @notice Constructor /// @param _creditManager Credit manager address /// @param _curvePool Target Curve pool address /// @param _lp_token Pool LP token address /// @param _metapoolBase Metapool's base pool address (must have 2 or 3 coins) or zero address /// @param _nCoins Number of coins in the pool constructor(address _creditManager, address _curvePool, address _lp_token, address _metapoolBase, uint256 _nCoins) AbstractAdapter(_creditManager, _curvePool) // U:[CRVB-1] nonZeroAddress(_lp_token) // U:[CRVB-1] { lpTokenMask = _getMaskOrRevert(_lp_token); // U:[CRVB-1] token = _lp_token; // U:[CRVB-1] lp_token = _lp_token; // U:[CRVB-1] metapoolBase = _metapoolBase; // U:[CRVB-1] nCoins = _nCoins; // U:[CRVB-1] use256 = _use256(); address[4] memory tokens; uint256[4] memory tokenMasks; unchecked { for (uint256 i; i < nCoins; ++i) { tokens[i] = _getCoin(_curvePool, i); // U:[CRVB-1] if (tokens[i] == address(0)) revert IncorrectParameterException(); // U:[CRVB-1] tokenMasks[i] = _getMaskOrRevert(tokens[i]); // U:[CRVB-1] } } token0 = tokens[0]; token1 = tokens[1]; token2 = tokens[2]; token3 = tokens[3]; token0Mask = tokenMasks[0]; token1Mask = tokenMasks[1]; token2Mask = tokenMasks[2]; token3Mask = tokenMasks[3]; // underlying tokens (only relevant for meta and lending pools) address[4] memory underlyings; uint256[4] memory underlyingMasks; unchecked { for (uint256 i; i < 4; ++i) { if (_metapoolBase != address(0)) { underlyings[i] = i == 0 ? token0 : _getCoin(_metapoolBase, i - 1); // U:[CRVB-1] } else { // some pools are proxy contracts and return empty data when there is no function with given signature, // which later results in revert when trying to decode the result, so low-level call is used instead (bool success, bytes memory returnData) = _callWithAlternative( abi.encodeWithSignature("underlying_coins(uint256)", i), abi.encodeWithSignature("underlying_coins(int128)", i) ); // U:[CRVB-1] if (success && returnData.length > 0) underlyings[i] = abi.decode(returnData, (address)); else break; } if (underlyings[i] != address(0)) underlyingMasks[i] = _getMaskOrRevert(underlyings[i]); // U:[CRVB-1] } } underlying0 = underlyings[0]; underlying1 = underlyings[1]; underlying2 = underlyings[2]; underlying3 = underlyings[3]; underlying0Mask = underlyingMasks[0]; underlying1Mask = underlyingMasks[1]; underlying2Mask = underlyingMasks[2]; underlying3Mask = underlyingMasks[3]; } // -------- // // EXCHANGE // // -------- // /// @notice Exchanges one pool asset to another /// @param i Index of the asset to spend /// @param j Index of the asset to receive /// @param dx Amount of asset i to spend /// @param min_dy Minimum amount of asset j to receive function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { return _exchange(i, j, dx, min_dy); // U:[CRVB-3] } /// @dev Same as the previous one but accepts coin indexes as `int128` function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { return _exchange(_toU256(i), _toU256(j), dx, min_dy); // U:[CRVB-3] } /// @dev Implementation of both versions of `exchange` function _exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { (tokensToEnable, tokensToDisable) = _exchange_impl(i, j, _getExchangeCallData(i, j, dx, min_dy), false); // U:[CRVB-3] } /// @notice Exchanges the entire balance of one pool asset to another, except the specified amount /// @param i Index of the asset to spend /// @param j Index of the asset to receive /// @param leftoverAmount Amount of input asset to keep on the account /// @param rateMinRAY Minimum exchange rate between assets i and j, scaled by 1e27 function exchange_diff(uint256 i, uint256 j, uint256 leftoverAmount, uint256 rateMinRAY) external override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { address creditAccount = _creditAccount(); // U:[CRVB-4] address tokenIn = _get_token(i); // U:[CRVB-4] uint256 dx = IERC20(tokenIn).balanceOf(creditAccount); // U:[CRVB-4] if (dx <= leftoverAmount) return (0, 0); unchecked { dx -= leftoverAmount; // U:[CRVB-4] } uint256 min_dy = (dx * rateMinRAY) / RAY; // U:[CRVB-4] (tokensToEnable, tokensToDisable) = _exchange_impl(i, j, _getExchangeCallData(i, j, dx, min_dy), leftoverAmount <= 1); // U:[CRVB-4] } /// @dev Internal implementation of `exchange` and `exchange_diff` /// - passes calldata to the target contract /// - sets max approval for the input token before the call and resets it to 1 after /// - enables output asset after the call /// - disables input asset only when exchanging the entire balance function _exchange_impl(uint256 i, uint256 j, bytes memory callData, bool disableTokenIn) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { _approveToken(_get_token(i), type(uint256).max); // U:[CRVB-3,4] _execute(callData); // U:[CRVB-3,4] _approveToken(_get_token(i), 1); // U:[CRVB-3,4] (tokensToEnable, tokensToDisable) = (_get_token_mask(j), disableTokenIn ? _get_token_mask(i) : 0); // U:[CRVB-3,4] } /// @dev Returns calldata for `exchange` and `exchange_diff` calls function _getExchangeCallData(uint256 i, uint256 j, uint256 dx, uint256 min_dy) internal view returns (bytes memory) { return use256 ? abi.encodeWithSignature("exchange(uint256,uint256,uint256,uint256)", i, j, dx, min_dy) : abi.encodeWithSignature("exchange(int128,int128,uint256,uint256)", i, j, dx, min_dy); // U:[CRVB-3,4] } /// @notice Exchanges one pool's underlying asset to another /// @param i Index of the underlying asset to spend /// @param j Index of the underlying asset to receive /// @param dx Amount of underlying asset i to spend /// @param min_dy Minimum amount of underlying asset j to receive function exchange_underlying(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { return _exchange_underlying(i, j, dx, min_dy); // U:[CRVB-5] } /// @dev Same as the previous one but accepts coin indexes as `int128` function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy) external override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { return _exchange_underlying(_toU256(i), _toU256(j), dx, min_dy); // U:[CRVB-5] } /// @dev Implementation of both versions of `exchange_underlying` function _exchange_underlying(uint256 i, uint256 j, uint256 dx, uint256 min_dy) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { (tokensToEnable, tokensToDisable) = _exchange_underlying_impl(i, j, _getExchangeUnderlyingCallData(i, j, dx, min_dy), false); // U:[CRVB-5] } /// @notice Exchanges the entire balance of one pool's underlying asset to another, except the specified amount /// @param i Index of the underlying asset to spend /// @param j Index of the underlying asset to receive /// @param rateMinRAY Minimum exchange rate between underlying assets i and j, scaled by 1e27 function exchange_diff_underlying(uint256 i, uint256 j, uint256 leftoverAmount, uint256 rateMinRAY) external override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { address creditAccount = _creditAccount(); // U:[CRVB-6] address tokenIn = _get_underlying(i); // U:[CRVB-6] uint256 dx = IERC20(tokenIn).balanceOf(creditAccount); // U:[CRVB-6] if (dx <= leftoverAmount) return (0, 0); unchecked { dx -= leftoverAmount; // U:[CRVB-6] } uint256 min_dy = (dx * rateMinRAY) / RAY; // U:[CRVB-6] (tokensToEnable, tokensToDisable) = _exchange_underlying_impl(i, j, _getExchangeUnderlyingCallData(i, j, dx, min_dy), leftoverAmount <= 1); // U:[CRVB-6] } /// @dev Internal implementation of `exchange_underlying` and `exchange_diff_underlying` /// - passes calldata to the target contract /// - sets max approval for the input token before the call and resets it to 1 after /// - enables output asset after the call /// - disables input asset only when exchanging the entire balance function _exchange_underlying_impl(uint256 i, uint256 j, bytes memory callData, bool disableTokenIn) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { _approveToken(_get_underlying(i), type(uint256).max); // U:[CRVB-5,6] _execute(callData); // U:[CRVB-5,6] _approveToken(_get_underlying(i), 1); // U:[CRVB-5,6] (tokensToEnable, tokensToDisable) = (_get_underlying_mask(j), disableTokenIn ? _get_underlying_mask(i) : 0); // U:[CRVB-5,6] } /// @dev Returns calldata for `exchange_underlying` and `exchange_diff_underlying` calls function _getExchangeUnderlyingCallData(uint256 i, uint256 j, uint256 dx, uint256 min_dy) internal view returns (bytes memory) { return use256 ? abi.encodeWithSignature("exchange_underlying(uint256,uint256,uint256,uint256)", i, j, dx, min_dy) : abi.encodeWithSignature("exchange_underlying(int128,int128,uint256,uint256)", i, j, dx, min_dy); // U:[CRVB-5,6] } // ------------- // // ADD LIQUIDITY // // ------------- // /// @dev Internal implementation of `add_liquidity` /// - passes calldata to the target contract /// - sets max approvals for the specified tokens before the call and resets them to 1 after /// - enables LP token function _add_liquidity(bool t0Approve, bool t1Approve, bool t2Approve, bool t3Approve) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { _approveTokens(t0Approve, t1Approve, t2Approve, t3Approve, type(uint256).max); // U:[CRV2-2, CRV3-2, CRV4-2] _execute(msg.data); // U:[CRV2-2, CRV3-2, CRV4-2] _approveTokens(t0Approve, t1Approve, t2Approve, t3Approve, 1); // U:[CRV2-2, CRV3-2, CRV4-2] (tokensToEnable, tokensToDisable) = (lpTokenMask, 0); // U:[CRV2-2, CRV3-2, CRV4-2] } /// @notice Adds given amount of asset as liquidity to the pool /// @param amount Amount to deposit /// @param i Index of the asset to deposit /// @param minAmount Minimum amount of LP tokens to receive function add_liquidity_one_coin(uint256 amount, uint256 i, uint256 minAmount) external override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { (tokensToEnable, tokensToDisable) = _add_liquidity_one_coin_impl(i, _getAddLiquidityOneCoinCallData(i, amount, minAmount), false); // U:[CRVB-7] } /// @notice Adds the entire balance of asset as liquidity to the pool, except the specified amount /// @param leftoverAmount Amount of underlying to keep on the account /// @param i Index of the asset to deposit /// @param rateMinRAY Minimum exchange rate between deposited asset and LP token, scaled by 1e27 function add_diff_liquidity_one_coin(uint256 leftoverAmount, uint256 i, uint256 rateMinRAY) external override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { address creditAccount = _creditAccount(); // U:[CRVB-8] address tokenIn = _get_token(i); // U:[CRVB-8] uint256 amount = IERC20(tokenIn).balanceOf(creditAccount); // U:[CRVB-8] if (amount <= leftoverAmount) return (0, 0); unchecked { amount -= leftoverAmount; // U:[CRVB-8] } uint256 minAmount = (amount * rateMinRAY) / RAY; // U:[CRVB-8] (tokensToEnable, tokensToDisable) = _add_liquidity_one_coin_impl(i, _getAddLiquidityOneCoinCallData(i, amount, minAmount), leftoverAmount <= 1); // U:[CRVB-8] } /// @dev Internal implementation of `add_liquidity_one_coin' and `add_diff_liquidity_one_coin` /// - passes calldata to the target contract /// - sets max approval for the input token before the call and resets it to 1 after /// - enables LP token /// - disables input token only when adding the entire balance function _add_liquidity_one_coin_impl(uint256 i, bytes memory callData, bool disableTokenIn) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { _approveToken(_get_token(i), type(uint256).max); // U:[CRVB-7,8] _execute(callData); // U:[CRVB-7,8] _approveToken(_get_token(i), 1); // U:[CRVB-7,8] (tokensToEnable, tokensToDisable) = (lpTokenMask, disableTokenIn ? _get_token_mask(i) : 0); // U:[CRVB-7,8] } /// @notice Returns the amount of LP token received for adding a single asset to the pool /// @param amount Amount to deposit /// @param i Index of the asset to deposit function calc_add_one_coin(uint256 amount, uint256 i) external view override returns (uint256) { // some pools omit the second argument of `calc_token_amount` function, so // a call with alternative signature is made in case the first one fails (bytes memory callData, bytes memory callDataAlt) = _getCalcAddOneCoinCallData(i, amount); (bool success, bytes memory returnData) = _callWithAlternative(callData, callDataAlt); if (success && returnData.length > 0) { return abi.decode(returnData, (uint256)); } else { revert("calc_token_amount reverted"); } } /// @dev Returns calldata for adding liquidity in coin `i`, must be overriden in derived adapters function _getAddLiquidityOneCoinCallData(uint256 i, uint256 amount, uint256 minAmount) internal view virtual returns (bytes memory callData); /// @dev Returns calldata for calculating the result of adding liquidity in coin `i`, /// must be overriden in derived adapters function _getCalcAddOneCoinCallData(uint256 i, uint256 amount) internal view virtual returns (bytes memory callData, bytes memory callDataAlt); // ---------------- // // REMOVE LIQUIDITY // // ---------------- // /// @dev Internal implementation of `remove_liquidity` /// - passes calldata to the target contract /// - enables all pool tokens function _remove_liquidity() internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { _execute(msg.data); // U:[CRV2-3, CRV3-3, CRV4-3] (tokensToEnable, tokensToDisable) = (token0Mask | token1Mask | token2Mask | token3Mask, 0); // U:[CRV2-3, CRV3-3, CRV4-3] } /// @dev Internal implementation of `remove_liquidity_imbalance` /// - passes calldata to the target contract /// - enables specified pool tokens function _remove_liquidity_imbalance(bool t0Enable, bool t1Enable, bool t2Enable, bool t3Enable) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { _execute(msg.data); // U:[CRV2-4, CRV3-4, CRV4-4] if (t0Enable) tokensToEnable = tokensToEnable.enable(token0Mask); // U:[CRV2-4, CRV3-4, CRV4-4] if (t1Enable) tokensToEnable = tokensToEnable.enable(token1Mask); // U:[CRV2-4, CRV3-4, CRV4-4] if (t2Enable) tokensToEnable = tokensToEnable.enable(token2Mask); // U:[CRV3-4, CRV4-4] if (t3Enable) tokensToEnable = tokensToEnable.enable(token3Mask); // U:[CRV4-4] tokensToDisable = 0; // U:[CRV2-4, CRV3-4, CRV4-4] } /// @notice Removes liquidity from the pool in a specified asset /// @param amount Amount of liquidity to remove /// @param i Index of the asset to withdraw /// @param minAmount Minimum amount of asset to receive function remove_liquidity_one_coin(uint256 amount, uint256 i, uint256 minAmount) external virtual override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { (tokensToEnable, tokensToDisable) = _remove_liquidity_one_coin(amount, i, minAmount); // U:[CRVB-9] } /// @dev Same as the previous one but accepts coin indexes as `int128` function remove_liquidity_one_coin(uint256 amount, int128 i, uint256 minAmount) external virtual override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { (tokensToEnable, tokensToDisable) = _remove_liquidity_one_coin(amount, _toU256(i), minAmount); // U:[CRVB-9] } /// @dev Implementation of both versions of `remove_liquidity_one_coin` function _remove_liquidity_one_coin(uint256 amount, uint256 i, uint256 minAmount) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { (tokensToEnable, tokensToDisable) = _remove_liquidity_one_coin_impl(i, _getRemoveLiquidityOneCoinCallData(i, amount, minAmount), false); // U:[CRVB-9] } /// @notice Removes all liquidity from the pool, except the specified amount, in a specified asset /// @param leftoverAmount Amount of Curve LP to keep on the account /// @param i Index of the asset to withdraw /// @param rateMinRAY Minimum exchange rate between LP token and received token, scaled by 1e27 function remove_diff_liquidity_one_coin(uint256 leftoverAmount, uint256 i, uint256 rateMinRAY) external virtual override creditFacadeOnly // U:[CRVB-2] returns (uint256 tokensToEnable, uint256 tokensToDisable) { return _remove_diff_liquidity_one_coin(i, leftoverAmount, rateMinRAY); // U:[CRVB-10] } /// @dev Implementation of `remove_diff_liquidity_one_coin` function _remove_diff_liquidity_one_coin(uint256 i, uint256 leftoverAmount, uint256 rateMinRAY) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { address creditAccount = _creditAccount(); // U:[CRVB-10] uint256 amount = IERC20(lp_token).balanceOf(creditAccount); // U:[CRVB-10] if (amount <= leftoverAmount) return (0, 0); unchecked { amount -= leftoverAmount; // U:[CRVB-10] } uint256 minAmount = (amount * rateMinRAY) / RAY; // U:[CRVB-10] (tokensToEnable, tokensToDisable) = _remove_liquidity_one_coin_impl( i, _getRemoveLiquidityOneCoinCallData(i, amount, minAmount), leftoverAmount <= 1 ); // U:[CRVB-10] } /// @dev Internal implementation of `remove_liquidity_one_coin` and `remove_diff_liquidity_one_coin` /// - passes calldata to the targe contract /// - enables received asset /// - disables LP token only when removing all liquidity function _remove_liquidity_one_coin_impl(uint256 i, bytes memory callData, bool disableLP) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) { _execute(callData); (tokensToEnable, tokensToDisable) = (_get_token_mask(i), disableLP ? lpTokenMask : 0); // U:[CRVB-9,10] } /// @dev Returns calldata for `remove_liquidity_one_coin` and `remove_diff_liquidity_one_coin` calls function _getRemoveLiquidityOneCoinCallData(uint256 i, uint256 amount, uint256 minAmount) internal view returns (bytes memory) { return use256 ? abi.encodeWithSignature("remove_liquidity_one_coin(uint256,uint256,uint256)", amount, i, minAmount) : abi.encodeWithSignature("remove_liquidity_one_coin(uint256,int128,uint256)", amount, i, minAmount); // U:[CRVB-9,10] } // ------- // // HELPERS // // ------- // /// @dev Returns true if pool is a cryptoswap pool, which is determined by whether it implements `mid_fee` function _use256() internal view returns (bool result) { try ICurvePool(targetContract).mid_fee() returns (uint256) { result = true; } catch { result = false; } } /// @dev Returns `i`-th coin of the `pool`, tries both signatures function _getCoin(address pool, uint256 i) internal view returns (address coin) { try ICurvePool(pool).coins(i) returns (address addr) { coin = addr; } catch { try ICurvePool(pool).coins(int128(int256(i))) returns (address addr) { coin = addr; } catch {} } } /// @dev Performs a low-level call to the target contract with provided calldata, and, should it fail, /// makes a second call with alternative calldata function _callWithAlternative(bytes memory callData, bytes memory callDataAlt) internal view returns (bool success, bytes memory returnData) { (success, returnData) = targetContract.staticcall(callData); if (!success || returnData.length == 0) { (success, returnData) = targetContract.staticcall(callDataAlt); } } /// @dev Returns token `i`'s address function _get_token(uint256 i) internal view returns (address addr) { if (i == 0) return token0; if (i == 1) return token1; if (i == 2) return token2; if (i == 3) return token3; } /// @dev Returns underlying `i`'s address function _get_underlying(uint256 i) internal view returns (address addr) { if (i == 0) return underlying0; if (i == 1) return underlying1; if (i == 2) return underlying2; if (i == 3) return underlying3; } /// @dev Returns token `i`'s mask function _get_token_mask(uint256 i) internal view returns (uint256 mask) { if (i == 0) return token0Mask; if (i == 1) return token1Mask; if (i == 2) return token2Mask; if (i == 3) return token3Mask; } /// @dev Returns underlying `i`'s mask function _get_underlying_mask(uint256 i) internal view returns (uint256 mask) { if (i == 0) return underlying0Mask; if (i == 1) return underlying1Mask; if (i == 2) return underlying2Mask; if (i == 3) return underlying3Mask; } /// @dev Sets target contract's approval for specified tokens to `amount` function _approveTokens(bool t0Approve, bool t1Approve, bool t2Approve, bool t3Approve, uint256 amount) internal { if (t0Approve) _approveToken(token0, amount); if (t1Approve) _approveToken(token1, amount); if (t2Approve) _approveToken(token2, amount); if (t3Approve) _approveToken(token3, amount); } /// @dev Returns `int128`-typed number as `uint256` function _toU256(int128 i) internal pure returns (uint256) { return uint256(int256(i)); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.10; interface ICurvePool { function coins(uint256 i) external view returns (address); function underlying_coins(uint256 i) external view returns (address); function balances(uint256 i) external view returns (uint256); function coins(int128) external view returns (address); function underlying_coins(int128) external view returns (address); function balances(int128) external view returns (uint256); function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external; function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external; function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy) external; function exchange_underlying(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external; function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns (uint256); function get_dy_underlying(uint256 i, uint256 j, uint256 dx) external view returns (uint256); function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256); function get_dy(uint256 i, uint256 j, uint256 dx) external view returns (uint256); function get_virtual_price() external view returns (uint256); function virtual_price() external view returns (uint256); function token() external view returns (address); function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_amount) external; function remove_liquidity_one_coin(uint256 _token_amount, uint256 i, uint256 min_amount) external; function A() external view returns (uint256); function A_precise() external view returns (uint256); function calc_withdraw_one_coin(uint256 _burn_amount, int128 i) external view returns (uint256); function calc_withdraw_one_coin(uint256 _burn_amount, uint256 i) external view returns (uint256); function admin_balances(uint256 i) external view returns (uint256); function admin() external view returns (address); function fee() external view returns (uint256); function admin_fee() external view returns (uint256); function block_timestamp_last() external view returns (uint256); function initial_A() external view returns (uint256); function future_A() external view returns (uint256); function initial_A_time() external view returns (uint256); function future_A_time() external view returns (uint256); function mid_fee() external view returns (uint256); // Some pools implement ERC20 function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint256); function balanceOf(address) external view returns (uint256); function allowance(address, address) external view returns (uint256); function totalSupply() external view returns (uint256); }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IAdapter} from "@gearbox-protocol/core-v2/contracts/interfaces/IAdapter.sol"; /// @title Curve V1 base adapter interface interface ICurveV1Adapter is IAdapter { function token() external view returns (address); function lp_token() external view returns (address); function lpTokenMask() external view returns (uint256); function metapoolBase() external view returns (address); function nCoins() external view returns (uint256); function use256() external view returns (bool); function token0() external view returns (address); function token1() external view returns (address); function token2() external view returns (address); function token3() external view returns (address); function token0Mask() external view returns (uint256); function token1Mask() external view returns (uint256); function token2Mask() external view returns (uint256); function token3Mask() external view returns (uint256); function underlying0() external view returns (address); function underlying1() external view returns (address); function underlying2() external view returns (address); function underlying3() external view returns (address); function underlying0Mask() external view returns (uint256); function underlying1Mask() external view returns (uint256); function underlying2Mask() external view returns (uint256); function underlying3Mask() external view returns (uint256); // -------- // // EXCHANGE // // -------- // function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function exchange_diff(uint256 i, uint256 j, uint256 leftoverAmount, uint256 rateMinRAY) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function exchange_underlying(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function exchange_diff_underlying(uint256 i, uint256 j, uint256 leftoverAmount, uint256 rateMinRAY) external returns (uint256 tokensToEnable, uint256 tokensToDisable); // ------------- // // ADD LIQUIDITY // // ------------- // function add_liquidity_one_coin(uint256 amount, uint256 i, uint256 minAmount) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function add_diff_liquidity_one_coin(uint256 leftoverAmount, uint256 i, uint256 rateMinRAY) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function calc_add_one_coin(uint256 amount, uint256 i) external view returns (uint256); // ---------------- // // REMOVE LIQUIDITY // // ---------------- // function remove_liquidity_one_coin(uint256 amount, uint256 i, uint256 minAmount) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function remove_liquidity_one_coin(uint256 amount, int128 i, uint256 minAmount) external returns (uint256 tokensToEnable, uint256 tokensToDisable); function remove_diff_liquidity_one_coin(uint256 leftoverAmount, uint256 i, uint256 rateMinRAY) external returns (uint256 tokensToEnable, uint256 tokensToDisable); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; // Denominations uint256 constant WAD = 1e18; uint256 constant RAY = 1e27; uint16 constant PERCENTAGE_FACTOR = 1e4; //percentage plus two decimals // 25% of type(uint256).max uint256 constant ALLOWANCE_THRESHOLD = type(uint96).max >> 3; // FEE = 50% uint16 constant DEFAULT_FEE_INTEREST = 50_00; // 50% // LIQUIDATION_FEE 1.5% uint16 constant DEFAULT_FEE_LIQUIDATION = 1_50; // 1.5% // LIQUIDATION PREMIUM 4% uint16 constant DEFAULT_LIQUIDATION_PREMIUM = 4_00; // 4% // LIQUIDATION_FEE_EXPIRED 2% uint16 constant DEFAULT_FEE_LIQUIDATION_EXPIRED = 1_00; // 2% // LIQUIDATION PREMIUM EXPIRED 2% uint16 constant DEFAULT_LIQUIDATION_PREMIUM_EXPIRED = 2_00; // 2% // DEFAULT PROPORTION OF MAX BORROWED PER BLOCK TO MAX BORROWED PER ACCOUNT uint16 constant DEFAULT_LIMIT_PER_BLOCK_MULTIPLIER = 2; // Seconds in a year uint256 constant SECONDS_PER_YEAR = 365 days; uint256 constant SECONDS_PER_ONE_AND_HALF_YEAR = (SECONDS_PER_YEAR * 3) / 2; // OPERATIONS // Leverage decimals - 100 is equal to 2x leverage (100% * collateral amount + 100% * borrowed amount) uint8 constant LEVERAGE_DECIMALS = 100; // Maximum withdraw fee for pool in PERCENTAGE_FACTOR format uint8 constant MAX_WITHDRAW_FEE = 100; uint256 constant EXACT_INPUT = 1; uint256 constant EXACT_OUTPUT = 2; address constant UNIVERSAL_CONTRACT = 0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC;
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IncorrectParameterException} from "../interfaces/IExceptions.sol"; uint256 constant UNDERLYING_TOKEN_MASK = 1; /// @title Bit mask library /// @notice Implements functions that manipulate bit masks /// Bit masks are utilized extensively by Gearbox to efficiently store token sets (enabled tokens on accounts /// or forbidden tokens) and check for set inclusion. A mask is a uint256 number that has its i-th bit set to /// 1 if i-th item is included into the set. For example, each token has a mask equal to 2**i, so set inclusion /// can be checked by checking tokenMask & setMask != 0. library BitMask { /// @dev Calculates an index of an item based on its mask (using a binary search) /// @dev The input should always have only 1 bit set, otherwise the result may be unpredictable function calcIndex(uint256 mask) internal pure returns (uint8 index) { if (mask == 0) revert IncorrectParameterException(); // U:[BM-1] uint16 lb = 0; // U:[BM-2] uint16 ub = 256; // U:[BM-2] uint16 mid = 128; // U:[BM-2] unchecked { while (true) { uint256 newMask = 1 << mid; if (newMask & mask != 0) return uint8(mid); // U:[BM-2] if (newMask > mask) ub = mid; // U:[BM-2] else lb = mid; // U:[BM-2] mid = (lb + ub) >> 1; // U:[BM-2] } } } /// @dev Calculates the number of `1` bits /// @param enabledTokensMask Bit mask to compute the number of `1` bits in function calcEnabledTokens(uint256 enabledTokensMask) internal pure returns (uint256 totalTokensEnabled) { unchecked { while (enabledTokensMask > 0) { enabledTokensMask &= enabledTokensMask - 1; // U:[BM-3] ++totalTokensEnabled; // U:[BM-3] } } } /// @dev Enables bits from the second mask in the first mask /// @param enabledTokenMask The initial mask /// @param bitsToEnable Mask of bits to enable function enable(uint256 enabledTokenMask, uint256 bitsToEnable) internal pure returns (uint256) { return enabledTokenMask | bitsToEnable; // U:[BM-4] } /// @dev Disables bits from the second mask in the first mask /// @param enabledTokenMask The initial mask /// @param bitsToDisable Mask of bits to disable function disable(uint256 enabledTokenMask, uint256 bitsToDisable) internal pure returns (uint256) { return enabledTokenMask & ~bitsToDisable; // U:[BM-4] } /// @dev Computes a new mask with sets of new enabled and disabled bits /// @dev bitsToEnable and bitsToDisable are applied sequentially to original mask /// @param enabledTokensMask The initial mask /// @param bitsToEnable Mask with bits to enable /// @param bitsToDisable Mask with bits to disable function enableDisable(uint256 enabledTokensMask, uint256 bitsToEnable, uint256 bitsToDisable) internal pure returns (uint256) { return (enabledTokensMask | bitsToEnable) & (~bitsToDisable); // U:[BM-5] } /// @dev Enables bits from the second mask in the first mask, skipping specified bits /// @param enabledTokenMask The initial mask /// @param bitsToEnable Mask with bits to enable /// @param invertedSkipMask An inversion of mask of immutable bits function enable(uint256 enabledTokenMask, uint256 bitsToEnable, uint256 invertedSkipMask) internal pure returns (uint256) { return enabledTokenMask | (bitsToEnable & invertedSkipMask); // U:[BM-6] } /// @dev Disables bits from the second mask in the first mask, skipping specified bits /// @param enabledTokenMask The initial mask /// @param bitsToDisable Mask with bits to disable /// @param invertedSkipMask An inversion of mask of immutable bits function disable(uint256 enabledTokenMask, uint256 bitsToDisable, uint256 invertedSkipMask) internal pure returns (uint256) { return enabledTokenMask & (~(bitsToDisable & invertedSkipMask)); // U:[BM-6] } /// @dev Computes a new mask with sets of new enabled and disabled bits, skipping some bits /// @dev bitsToEnable and bitsToDisable are applied sequentially to original mask. Skipmask is applied in both cases. /// @param enabledTokensMask The initial mask /// @param bitsToEnable Mask with bits to enable /// @param bitsToDisable Mask with bits to disable /// @param invertedSkipMask An inversion of mask of immutable bits function enableDisable( uint256 enabledTokensMask, uint256 bitsToEnable, uint256 bitsToDisable, uint256 invertedSkipMask ) internal pure returns (uint256) { return (enabledTokensMask | (bitsToEnable & invertedSkipMask)) & (~(bitsToDisable & invertedSkipMask)); // U:[BM-7] } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; // ------- // // GENERAL // // ------- // /// @notice Thrown on attempting to set an important address to zero address error ZeroAddressException(); /// @notice Thrown when attempting to pass a zero amount to a funding-related operation error AmountCantBeZeroException(); /// @notice Thrown on incorrect input parameter error IncorrectParameterException(); /// @notice Thrown when balance is insufficient to perform an operation error InsufficientBalanceException(); /// @notice Thrown if parameter is out of range error ValueOutOfRangeException(); /// @notice Thrown when trying to send ETH to a contract that is not allowed to receive ETH directly error ReceiveIsNotAllowedException(); /// @notice Thrown on attempting to set an EOA as an important contract in the system error AddressIsNotContractException(address); /// @notice Thrown on attempting to receive a token that is not a collateral token or was forbidden error TokenNotAllowedException(); /// @notice Thrown on attempting to add a token that is already in a collateral list error TokenAlreadyAddedException(); /// @notice Thrown when attempting to use quota-related logic for a token that is not quoted in quota keeper error TokenIsNotQuotedException(); /// @notice Thrown on attempting to interact with an address that is not a valid target contract error TargetContractNotAllowedException(); /// @notice Thrown if function is not implemented error NotImplementedException(); // ------------------ // // CONTRACTS REGISTER // // ------------------ // /// @notice Thrown when an address is expected to be a registered credit manager, but is not error RegisteredCreditManagerOnlyException(); /// @notice Thrown when an address is expected to be a registered pool, but is not error RegisteredPoolOnlyException(); // ---------------- // // ADDRESS PROVIDER // // ---------------- // /// @notice Reverts if address key isn't found in address provider error AddressNotFoundException(); // ----------------- // // POOL, PQK, GAUGES // // ----------------- // /// @notice Thrown by pool-adjacent contracts when a credit manager being connected has a wrong pool address error IncompatibleCreditManagerException(); /// @notice Thrown when attempting to set an incompatible successor staking contract error IncompatibleSuccessorException(); /// @notice Thrown when attempting to vote in a non-approved contract error VotingContractNotAllowedException(); /// @notice Thrown when attempting to unvote more votes than there are error InsufficientVotesException(); /// @notice Thrown when attempting to borrow more than the second point on a two-point curve error BorrowingMoreThanU2ForbiddenException(); /// @notice Thrown when a credit manager attempts to borrow more than its limit in the current block, or in general error CreditManagerCantBorrowException(); /// @notice Thrown when attempting to connect a quota keeper to an incompatible pool error IncompatiblePoolQuotaKeeperException(); /// @notice Thrown when the quota is outside of min/max bounds error QuotaIsOutOfBoundsException(); // -------------- // // CREDIT MANAGER // // -------------- // /// @notice Thrown on failing a full collateral check after multicall error NotEnoughCollateralException(); /// @notice Thrown if an attempt to approve a collateral token to adapter's target contract fails error AllowanceFailedException(); /// @notice Thrown on attempting to perform an action for a credit account that does not exist error CreditAccountDoesNotExistException(); /// @notice Thrown on configurator attempting to add more than 255 collateral tokens error TooManyTokensException(); /// @notice Thrown if more than the maximum number of tokens were enabled on a credit account error TooManyEnabledTokensException(); /// @notice Thrown when attempting to execute a protocol interaction without active credit account set error ActiveCreditAccountNotSetException(); /// @notice Thrown when trying to update credit account's debt more than once in the same block error DebtUpdatedTwiceInOneBlockException(); /// @notice Thrown when trying to repay all debt while having active quotas error DebtToZeroWithActiveQuotasException(); /// @notice Thrown when a zero-debt account attempts to update quota error UpdateQuotaOnZeroDebtAccountException(); /// @notice Thrown when attempting to close an account with non-zero debt error CloseAccountWithNonZeroDebtException(); /// @notice Thrown when value of funds remaining on the account after liquidation is insufficient error InsufficientRemainingFundsException(); /// @notice Thrown when Credit Facade tries to write over a non-zero active Credit Account error ActiveCreditAccountOverridenException(); // ------------------- // // CREDIT CONFIGURATOR // // ------------------- // /// @notice Thrown on attempting to use a non-ERC20 contract or an EOA as a token error IncorrectTokenContractException(); /// @notice Thrown if the newly set LT if zero or greater than the underlying's LT error IncorrectLiquidationThresholdException(); /// @notice Thrown if borrowing limits are incorrect: minLimit > maxLimit or maxLimit > blockLimit error IncorrectLimitsException(); /// @notice Thrown if the new expiration date is less than the current expiration date or current timestamp error IncorrectExpirationDateException(); /// @notice Thrown if a contract returns a wrong credit manager or reverts when trying to retrieve it error IncompatibleContractException(); /// @notice Thrown if attempting to forbid an adapter that is not registered in the credit manager error AdapterIsNotRegisteredException(); // ------------- // // CREDIT FACADE // // ------------- // /// @notice Thrown when attempting to perform an action that is forbidden in whitelisted mode error ForbiddenInWhitelistedModeException(); /// @notice Thrown if credit facade is not expirable, and attempted aciton requires expirability error NotAllowedWhenNotExpirableException(); /// @notice Thrown if a selector that doesn't match any allowed function is passed to the credit facade in a multicall error UnknownMethodException(); /// @notice Thrown when trying to close an account with enabled tokens error CloseAccountWithEnabledTokensException(); /// @notice Thrown if a liquidator tries to liquidate an account with a health factor above 1 error CreditAccountNotLiquidatableException(); /// @notice Thrown if too much new debt was taken within a single block error BorrowedBlockLimitException(); /// @notice Thrown if the new debt principal for a credit account falls outside of borrowing limits error BorrowAmountOutOfLimitsException(); /// @notice Thrown if a user attempts to open an account via an expired credit facade error NotAllowedAfterExpirationException(); /// @notice Thrown if expected balances are attempted to be set twice without performing a slippage check error ExpectedBalancesAlreadySetException(); /// @notice Thrown if attempting to perform a slippage check when excepted balances are not set error ExpectedBalancesNotSetException(); /// @notice Thrown if balance of at least one token is less than expected during a slippage check error BalanceLessThanExpectedException(); /// @notice Thrown when trying to perform an action that is forbidden when credit account has enabled forbidden tokens error ForbiddenTokensException(); /// @notice Thrown when new forbidden tokens are enabled during the multicall error ForbiddenTokenEnabledException(); /// @notice Thrown when enabled forbidden token balance is increased during the multicall error ForbiddenTokenBalanceIncreasedException(); /// @notice Thrown when the remaining token balance is increased during the liquidation error RemainingTokenBalanceIncreasedException(); /// @notice Thrown if `botMulticall` is called by an address that is not approved by account owner or is forbidden error NotApprovedBotException(); /// @notice Thrown when attempting to perform a multicall action with no permission for it error NoPermissionException(uint256 permission); /// @notice Thrown when attempting to give a bot unexpected permissions error UnexpectedPermissionsException(); /// @notice Thrown when a custom HF parameter lower than 10000 is passed into the full collateral check error CustomHealthFactorTooLowException(); /// @notice Thrown when submitted collateral hint is not a valid token mask error InvalidCollateralHintException(); // ------ // // ACCESS // // ------ // /// @notice Thrown on attempting to call an access restricted function not as credit account owner error CallerNotCreditAccountOwnerException(); /// @notice Thrown on attempting to call an access restricted function not as configurator error CallerNotConfiguratorException(); /// @notice Thrown on attempting to call an access-restructed function not as account factory error CallerNotAccountFactoryException(); /// @notice Thrown on attempting to call an access restricted function not as credit manager error CallerNotCreditManagerException(); /// @notice Thrown on attempting to call an access restricted function not as credit facade error CallerNotCreditFacadeException(); /// @notice Thrown on attempting to call an access restricted function not as controller or configurator error CallerNotControllerException(); /// @notice Thrown on attempting to pause a contract without pausable admin rights error CallerNotPausableAdminException(); /// @notice Thrown on attempting to unpause a contract without unpausable admin rights error CallerNotUnpausableAdminException(); /// @notice Thrown on attempting to call an access restricted function not as gauge error CallerNotGaugeException(); /// @notice Thrown on attempting to call an access restricted function not as quota keeper error CallerNotPoolQuotaKeeperException(); /// @notice Thrown on attempting to call an access restricted function not as voter error CallerNotVoterException(); /// @notice Thrown on attempting to call an access restricted function not as allowed adapter error CallerNotAdapterException(); /// @notice Thrown on attempting to call an access restricted function not as migrator error CallerNotMigratorException(); /// @notice Thrown when an address that is not the designated executor attempts to execute a transaction error CallerNotExecutorException(); /// @notice Thrown on attempting to call an access restricted function not as veto admin error CallerNotVetoAdminException(); // ------------------- // // CONTROLLER TIMELOCK // // ------------------- // /// @notice Thrown when the new parameter values do not satisfy required conditions error ParameterChecksFailedException(); /// @notice Thrown when attempting to execute a non-queued transaction error TxNotQueuedException(); /// @notice Thrown when attempting to execute a transaction that is either immature or stale error TxExecutedOutsideTimeWindowException(); /// @notice Thrown when execution of a transaction fails error TxExecutionRevertedException(); /// @notice Thrown when the value of a parameter on execution is different from the value on queue error ParameterChangedAfterQueuedTxException(); // -------- // // BOT LIST // // -------- // /// @notice Thrown when attempting to set non-zero permissions for a forbidden or special bot error InvalidBotException(); // --------------- // // ACCOUNT FACTORY // // --------------- // /// @notice Thrown when trying to deploy second master credit account for a credit manager error MasterCreditAccountAlreadyDeployedException(); /// @notice Thrown when trying to rescue funds from a credit account that is currently in use error CreditAccountIsInUseException(); // ------------ // // PRICE ORACLE // // ------------ // /// @notice Thrown on attempting to set a token price feed to an address that is not a correct price feed error IncorrectPriceFeedException(); /// @notice Thrown on attempting to interact with a price feed for a token not added to the price oracle error PriceFeedDoesNotExistException(); /// @notice Thrown when price feed returns incorrect price for a token error IncorrectPriceException(); /// @notice Thrown when token's price feed becomes stale error StalePriceException();
// SPDX-License-Identifier: GPL-2.0-or-later // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IAdapter} from "@gearbox-protocol/core-v2/contracts/interfaces/IAdapter.sol"; import {ICreditManagerV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol"; import {CallerNotCreditFacadeException} from "@gearbox-protocol/core-v3/contracts/interfaces/IExceptions.sol"; import {ACLTrait} from "@gearbox-protocol/core-v3/contracts/traits/ACLTrait.sol"; /// @title Abstract adapter /// @dev Inheriting adapters MUST use provided internal functions to perform all operations with credit accounts abstract contract AbstractAdapter is IAdapter, ACLTrait { /// @notice Credit manager the adapter is connected to address public immutable override creditManager; /// @notice Address provider contract address public immutable override addressProvider; /// @notice Address of the contract the adapter is interacting with address public immutable override targetContract; /// @notice Constructor /// @param _creditManager Credit manager to connect the adapter to /// @param _targetContract Address of the adapted contract constructor(address _creditManager, address _targetContract) ACLTrait(ICreditManagerV3(_creditManager).addressProvider()) nonZeroAddress(_targetContract) { creditManager = _creditManager; addressProvider = ICreditManagerV3(_creditManager).addressProvider(); targetContract = _targetContract; } /// @dev Ensures that caller of the function is credit facade connected to the credit manager /// @dev Inheriting adapters MUST use this modifier in all external functions that operate on credit accounts modifier creditFacadeOnly() { _revertIfCallerNotCreditFacade(); _; } /// @dev Ensures that caller is credit facade connected to the credit manager function _revertIfCallerNotCreditFacade() internal view { if (msg.sender != ICreditManagerV3(creditManager).creditFacade()) { revert CallerNotCreditFacadeException(); } } /// @dev Ensures that active credit account is set and returns its address function _creditAccount() internal view returns (address) { return ICreditManagerV3(creditManager).getActiveCreditAccountOrRevert(); } /// @dev Ensures that token is registered as collateral in the credit manager and returns its mask function _getMaskOrRevert(address token) internal view returns (uint256 tokenMask) { tokenMask = ICreditManagerV3(creditManager).getTokenMaskOrRevert(token); } /// @dev Approves target contract to spend given token from the active credit account /// Reverts if active credit account is not set or token is not registered as collateral /// @param token Token to approve /// @param amount Amount to approve function _approveToken(address token, uint256 amount) internal { ICreditManagerV3(creditManager).approveCreditAccount(token, amount); } /// @dev Executes an external call from the active credit account to the target contract /// Reverts if active credit account is not set /// @param callData Data to call the target contract with /// @return result Call result function _execute(bytes memory callData) internal returns (bytes memory result) { return ICreditManagerV3(creditManager).execute(callData); } /// @dev Executes a swap operation without input token approval /// Reverts if active credit account is not set or any of passed tokens is not registered as collateral /// @param tokenIn Input token that credit account spends in the call /// @param tokenOut Output token that credit account receives after the call /// @param callData Data to call the target contract with /// @param disableTokenIn Whether `tokenIn` should be disabled after the call /// (for operations that spend the entire account's balance of the input token) /// @return tokensToEnable Bit mask of tokens that should be enabled after the call /// @return tokensToDisable Bit mask of tokens that should be disabled after the call /// @return result Call result function _executeSwapNoApprove(address tokenIn, address tokenOut, bytes memory callData, bool disableTokenIn) internal returns (uint256 tokensToEnable, uint256 tokensToDisable, bytes memory result) { tokensToEnable = _getMaskOrRevert(tokenOut); uint256 tokenInMask = _getMaskOrRevert(tokenIn); if (disableTokenIn) tokensToDisable = tokenInMask; result = _execute(callData); } /// @dev Executes a swap operation with maximum input token approval, and revokes approval after the call /// Reverts if active credit account is not set or any of passed tokens is not registered as collateral /// @param tokenIn Input token that credit account spends in the call /// @param tokenOut Output token that credit account receives after the call /// @param callData Data to call the target contract with /// @param disableTokenIn Whether `tokenIn` should be disabled after the call /// (for operations that spend the entire account's balance of the input token) /// @return tokensToEnable Bit mask of tokens that should be enabled after the call /// @return tokensToDisable Bit mask of tokens that should be disabled after the call /// @return result Call result /// @custom:expects Credit manager reverts when trying to approve non-collateral token function _executeSwapSafeApprove(address tokenIn, address tokenOut, bytes memory callData, bool disableTokenIn) internal returns (uint256 tokensToEnable, uint256 tokensToDisable, bytes memory result) { tokensToEnable = _getMaskOrRevert(tokenOut); if (disableTokenIn) tokensToDisable = _getMaskOrRevert(tokenIn); _approveToken(tokenIn, type(uint256).max); result = _execute(callData); _approveToken(tokenIn, 1); } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; uint8 constant BOT_PERMISSIONS_SET_FLAG = 1; uint8 constant DEFAULT_MAX_ENABLED_TOKENS = 4; address constant INACTIVE_CREDIT_ACCOUNT_ADDRESS = address(1); /// @notice Debt management type /// - `INCREASE_DEBT` borrows additional funds from the pool, updates account's debt and cumulative interest index /// - `DECREASE_DEBT` repays debt components (quota interest and fees -> base interest and fees -> debt principal) /// and updates all corresponding state varibles (base interest index, quota interest and fees, debt). /// When repaying all the debt, ensures that account has no enabled quotas. enum ManageDebtAction { INCREASE_DEBT, DECREASE_DEBT } /// @notice Collateral/debt calculation mode /// - `GENERIC_PARAMS` returns generic data like account debt and cumulative indexes /// - `DEBT_ONLY` is same as `GENERIC_PARAMS` but includes more detailed debt info, like accrued base/quota /// interest and fees /// - `FULL_COLLATERAL_CHECK_LAZY` checks whether account is sufficiently collateralized in a lazy fashion, /// i.e. it stops iterating over collateral tokens once TWV reaches the desired target. /// Since it may return underestimated TWV, it's only available for internal use. /// - `DEBT_COLLATERAL` is same as `DEBT_ONLY` but also returns total value and total LT-weighted value of /// account's tokens, this mode is used during account liquidation /// - `DEBT_COLLATERAL_SAFE_PRICES` is same as `DEBT_COLLATERAL` but uses safe prices from price oracle enum CollateralCalcTask { GENERIC_PARAMS, DEBT_ONLY, FULL_COLLATERAL_CHECK_LAZY, DEBT_COLLATERAL, DEBT_COLLATERAL_SAFE_PRICES } struct CreditAccountInfo { uint256 debt; uint256 cumulativeIndexLastUpdate; uint128 cumulativeQuotaInterest; uint128 quotaFees; uint256 enabledTokensMask; uint16 flags; uint64 lastDebtUpdate; address borrower; } struct CollateralDebtData { uint256 debt; uint256 cumulativeIndexNow; uint256 cumulativeIndexLastUpdate; uint128 cumulativeQuotaInterest; uint256 accruedInterest; uint256 accruedFees; uint256 totalDebtUSD; uint256 totalValue; uint256 totalValueUSD; uint256 twvUSD; uint256 enabledTokensMask; uint256 quotedTokensMask; address[] quotedTokens; address _poolQuotaKeeper; } struct CollateralTokenData { address token; uint16 ltInitial; uint16 ltFinal; uint40 timestampRampStart; uint24 rampDuration; } struct RevocationPair { address spender; address token; } interface ICreditManagerV3Events { /// @notice Emitted when new credit configurator is set event SetCreditConfigurator(address indexed newConfigurator); } /// @title Credit manager V3 interface interface ICreditManagerV3 is IVersion, ICreditManagerV3Events { function pool() external view returns (address); function underlying() external view returns (address); function creditFacade() external view returns (address); function creditConfigurator() external view returns (address); function addressProvider() external view returns (address); function accountFactory() external view returns (address); function name() external view returns (string memory); // ------------------ // // ACCOUNT MANAGEMENT // // ------------------ // function openCreditAccount(address onBehalfOf) external returns (address); function closeCreditAccount(address creditAccount) external; function liquidateCreditAccount( address creditAccount, CollateralDebtData calldata collateralDebtData, address to, bool isExpired ) external returns (uint256 remainingFunds, uint256 loss); function manageDebt(address creditAccount, uint256 amount, uint256 enabledTokensMask, ManageDebtAction action) external returns (uint256 newDebt, uint256 tokensToEnable, uint256 tokensToDisable); function addCollateral(address payer, address creditAccount, address token, uint256 amount) external returns (uint256 tokensToEnable); function withdrawCollateral(address creditAccount, address token, uint256 amount, address to) external returns (uint256 tokensToDisable); function externalCall(address creditAccount, address target, bytes calldata callData) external returns (bytes memory result); function approveToken(address creditAccount, address token, address spender, uint256 amount) external; function revokeAdapterAllowances(address creditAccount, RevocationPair[] calldata revocations) external; // -------- // // ADAPTERS // // -------- // function adapterToContract(address adapter) external view returns (address targetContract); function contractToAdapter(address targetContract) external view returns (address adapter); function execute(bytes calldata data) external returns (bytes memory result); function approveCreditAccount(address token, uint256 amount) external; function setActiveCreditAccount(address creditAccount) external; function getActiveCreditAccountOrRevert() external view returns (address creditAccount); // ----------------- // // COLLATERAL CHECKS // // ----------------- // function priceOracle() external view returns (address); function fullCollateralCheck( address creditAccount, uint256 enabledTokensMask, uint256[] calldata collateralHints, uint16 minHealthFactor, bool useSafePrices ) external returns (uint256 enabledTokensMaskAfter); function isLiquidatable(address creditAccount, uint16 minHealthFactor) external view returns (bool); function calcDebtAndCollateral(address creditAccount, CollateralCalcTask task) external view returns (CollateralDebtData memory cdd); // ------ // // QUOTAS // // ------ // function poolQuotaKeeper() external view returns (address); function quotedTokensMask() external view returns (uint256); function updateQuota(address creditAccount, address token, int96 quotaChange, uint96 minQuota, uint96 maxQuota) external returns (uint256 tokensToEnable, uint256 tokensToDisable); // --------------------- // // CREDIT MANAGER PARAMS // // --------------------- // function maxEnabledTokens() external view returns (uint8); function fees() external view returns ( uint16 feeInterest, uint16 feeLiquidation, uint16 liquidationDiscount, uint16 feeLiquidationExpired, uint16 liquidationDiscountExpired ); function collateralTokensCount() external view returns (uint8); function getTokenMaskOrRevert(address token) external view returns (uint256 tokenMask); function getTokenByMask(uint256 tokenMask) external view returns (address token); function liquidationThresholds(address token) external view returns (uint16 lt); function ltParams(address token) external view returns (uint16 ltInitial, uint16 ltFinal, uint40 timestampRampStart, uint24 rampDuration); function collateralTokenByMask(uint256 tokenMask) external view returns (address token, uint16 liquidationThreshold); // ------------ // // ACCOUNT INFO // // ------------ // function creditAccountInfo(address creditAccount) external view returns ( uint256 debt, uint256 cumulativeIndexLastUpdate, uint128 cumulativeQuotaInterest, uint128 quotaFees, uint256 enabledTokensMask, uint16 flags, uint64 lastDebtUpdate, address borrower ); function getBorrowerOrRevert(address creditAccount) external view returns (address borrower); function flagsOf(address creditAccount) external view returns (uint16); function setFlagFor(address creditAccount, uint16 flag, bool value) external; function enabledTokensMaskOf(address creditAccount) external view returns (uint256); function creditAccounts() external view returns (address[] memory); function creditAccounts(uint256 offset, uint256 limit) external view returns (address[] memory); function creditAccountsLen() external view returns (uint256); // ------------- // // CONFIGURATION // // ------------- // function addToken(address token) external; function setCollateralTokenData( address token, uint16 ltInitial, uint16 ltFinal, uint40 timestampRampStart, uint24 rampDuration ) external; function setFees( uint16 feeInterest, uint16 feeLiquidation, uint16 liquidationDiscount, uint16 feeLiquidationExpired, uint16 liquidationDiscountExpired ) external; function setQuotedMask(uint256 quotedTokensMask) external; function setMaxEnabledTokens(uint8 maxEnabledTokens) external; function setContractAllowance(address adapter, address targetContract) external; function setCreditFacade(address creditFacade) external; function setPriceOracle(address priceOracle) external; function setCreditConfigurator(address creditConfigurator) external; }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IACL} from "@gearbox-protocol/core-v2/contracts/interfaces/IACL.sol"; import {AP_ACL, IAddressProviderV3, NO_VERSION_CONTROL} from "../interfaces/IAddressProviderV3.sol"; import {CallerNotConfiguratorException} from "../interfaces/IExceptions.sol"; import {SanityCheckTrait} from "./SanityCheckTrait.sol"; /// @title ACL trait /// @notice Utility class for ACL (access-control list) consumers abstract contract ACLTrait is SanityCheckTrait { /// @notice ACL contract address address public immutable acl; /// @notice Constructor /// @param addressProvider Address provider contract address constructor(address addressProvider) nonZeroAddress(addressProvider) { acl = IAddressProviderV3(addressProvider).getAddressOrRevert(AP_ACL, NO_VERSION_CONTROL); } /// @dev Ensures that function caller has configurator role modifier configuratorOnly() { _ensureCallerIsConfigurator(); _; } /// @dev Reverts if the caller is not the configurator /// @dev Used to cut contract size on modifiers function _ensureCallerIsConfigurator() internal view { if (!_isConfigurator({account: msg.sender})) { revert CallerNotConfiguratorException(); } } /// @dev Checks whether given account has configurator role function _isConfigurator(address account) internal view returns (bool) { return IACL(acl).isConfigurator(account); } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; /// @title Version interface /// @notice Defines contract version interface IVersion { /// @notice Contract version function version() external view returns (uint256); }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; import { IVersion } from "./IVersion.sol"; interface IACLExceptions { /// @dev Thrown when attempting to delete an address from a set that is not a pausable admin error AddressNotPausableAdminException(address addr); /// @dev Thrown when attempting to delete an address from a set that is not a unpausable admin error AddressNotUnpausableAdminException(address addr); } interface IACLEvents { /// @dev Emits when a new admin is added that can pause contracts event PausableAdminAdded(address indexed newAdmin); /// @dev Emits when a Pausable admin is removed event PausableAdminRemoved(address indexed admin); /// @dev Emits when a new admin is added that can unpause contracts event UnpausableAdminAdded(address indexed newAdmin); /// @dev Emits when an Unpausable admin is removed event UnpausableAdminRemoved(address indexed admin); } /// @title ACL interface interface IACL is IACLEvents, IACLExceptions, IVersion { /// @dev Returns true if the address is a pausable admin and false if not /// @param addr Address to check function isPausableAdmin(address addr) external view returns (bool); /// @dev Returns true if the address is unpausable admin and false if not /// @param addr Address to check function isUnpausableAdmin(address addr) external view returns (bool); /// @dev Returns true if an address has configurator rights /// @param account Address to check function isConfigurator(address account) external view returns (bool); /// @dev Returns address of configurator function owner() external view returns (address); }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; uint256 constant NO_VERSION_CONTROL = 0; bytes32 constant AP_CONTRACTS_REGISTER = "CONTRACTS_REGISTER"; bytes32 constant AP_ACL = "ACL"; bytes32 constant AP_PRICE_ORACLE = "PRICE_ORACLE"; bytes32 constant AP_ACCOUNT_FACTORY = "ACCOUNT_FACTORY"; bytes32 constant AP_DATA_COMPRESSOR = "DATA_COMPRESSOR"; bytes32 constant AP_TREASURY = "TREASURY"; bytes32 constant AP_GEAR_TOKEN = "GEAR_TOKEN"; bytes32 constant AP_WETH_TOKEN = "WETH_TOKEN"; bytes32 constant AP_WETH_GATEWAY = "WETH_GATEWAY"; bytes32 constant AP_ROUTER = "ROUTER"; bytes32 constant AP_BOT_LIST = "BOT_LIST"; bytes32 constant AP_GEAR_STAKING = "GEAR_STAKING"; bytes32 constant AP_ZAPPER_REGISTER = "ZAPPER_REGISTER"; interface IAddressProviderV3Events { /// @notice Emitted when an address is set for a contract key event SetAddress(bytes32 indexed key, address indexed value, uint256 indexed version); } /// @title Address provider V3 interface interface IAddressProviderV3 is IAddressProviderV3Events, IVersion { function addresses(bytes32 key, uint256 _version) external view returns (address); function getAddressOrRevert(bytes32 key, uint256 _version) external view returns (address result); function setAddress(bytes32 key, address value, bool saveVersion) external; }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {ZeroAddressException} from "../interfaces/IExceptions.sol"; /// @title Sanity check trait abstract contract SanityCheckTrait { /// @dev Ensures that passed address is non-zero modifier nonZeroAddress(address addr) { _revertIfZeroAddress(addr); _; } /// @dev Reverts if address is zero function _revertIfZeroAddress(address addr) private pure { if (addr == address(0)) revert ZeroAddressException(); } }
{ "remappings": [ "@1inch/=node_modules/@1inch/", "@arbitrum/=node_modules/@arbitrum/", "@chainlink/=node_modules/@chainlink/", "@eth-optimism/=node_modules/@eth-optimism/", "@gearbox-protocol/=node_modules/@gearbox-protocol/", "@openzeppelin/=node_modules/@openzeppelin/", "@redstone-finance/=node_modules/@redstone-finance/", "ds-test/=lib/forge-std/lib/ds-test/src/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 1000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_creditManager","type":"address"},{"internalType":"address","name":"_curvePool","type":"address"},{"internalType":"address","name":"_lp_token","type":"address"},{"internalType":"address","name":"_metapoolBase","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotCreditFacadeException","type":"error"},{"inputs":[],"name":"IncorrectParameterException","type":"error"},{"inputs":[],"name":"ZeroAddressException","type":"error"},{"inputs":[],"name":"_gearboxAdapterType","outputs":[{"internalType":"enum AdapterType","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"_gearboxAdapterVersion","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acl","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"leftoverAmount","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"rateMinRAY","type":"uint256"}],"name":"add_diff_liquidity_one_coin","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"amounts","type":"uint256[2]"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"add_liquidity","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"minAmount","type":"uint256"}],"name":"add_liquidity_one_coin","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addressProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"}],"name":"calc_add_one_coin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"creditManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int128","name":"i","type":"int128"},{"internalType":"int128","name":"j","type":"int128"},{"internalType":"uint256","name":"dx","type":"uint256"},{"internalType":"uint256","name":"min_dy","type":"uint256"}],"name":"exchange","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"j","type":"uint256"},{"internalType":"uint256","name":"dx","type":"uint256"},{"internalType":"uint256","name":"min_dy","type":"uint256"}],"name":"exchange","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"j","type":"uint256"},{"internalType":"uint256","name":"leftoverAmount","type":"uint256"},{"internalType":"uint256","name":"rateMinRAY","type":"uint256"}],"name":"exchange_diff","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"j","type":"uint256"},{"internalType":"uint256","name":"leftoverAmount","type":"uint256"},{"internalType":"uint256","name":"rateMinRAY","type":"uint256"}],"name":"exchange_diff_underlying","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"j","type":"uint256"},{"internalType":"uint256","name":"dx","type":"uint256"},{"internalType":"uint256","name":"min_dy","type":"uint256"}],"name":"exchange_underlying","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int128","name":"i","type":"int128"},{"internalType":"int128","name":"j","type":"int128"},{"internalType":"uint256","name":"dx","type":"uint256"},{"internalType":"uint256","name":"min_dy","type":"uint256"}],"name":"exchange_underlying","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lpTokenMask","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lp_token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metapoolBase","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nCoins","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"leftoverAmount","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"rateMinRAY","type":"uint256"}],"name":"remove_diff_liquidity_one_coin","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256[2]","name":"","type":"uint256[2]"}],"name":"remove_liquidity","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"amounts","type":"uint256[2]"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"remove_liquidity_imbalance","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"int128","name":"i","type":"int128"},{"internalType":"uint256","name":"minAmount","type":"uint256"}],"name":"remove_liquidity_one_coin","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"minAmount","type":"uint256"}],"name":"remove_liquidity_one_coin","outputs":[{"internalType":"uint256","name":"tokensToEnable","type":"uint256"},{"internalType":"uint256","name":"tokensToDisable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0Mask","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1Mask","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token2Mask","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token3","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token3Mask","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying0Mask","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying1Mask","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying2Mask","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying3","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying3Mask","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"use256","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6103c06040523480156200001257600080fd5b5060405162002e7538038062002e7583398101604081905262000035916200089f565b8383838360028484816001600160a01b0316632954018c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200007c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a2919062000907565b80620000ae8162000584565b604051632bdad0e360e11b8152621050d360ea1b6004820152600060248201526001600160a01b038316906357b5a1c690604401602060405180830381865afa15801562000100573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000126919062000907565b6001600160a01b031660805250819050620001418162000584565b6001600160a01b03831660a081905260408051630a55006360e21b81529051632954018c916004808201926020929091908290030181865afa1580156200018c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b2919062000907565b6001600160a01b0390811660c0529190911660e05250839050620001d68162000584565b620001e184620005af565b610140526001600160a01b03808516610100819052610120528316610160526101808290526200021062000627565b15156101a052620002206200086b565b6200022a6200086b565b60005b61018051811015620002f8576200024588826200069b565b8382600481106200025a576200025a62000927565b6001600160a01b039092166020929092020152600083826004811062000284576200028462000927565b60200201516001600160a01b031603620002b1576040516347fbaa9760e01b815260040160405180910390fd5b620002d5838260048110620002ca57620002ca62000927565b6020020151620005af565b828260048110620002ea57620002ea62000927565b60200201526001016200022d565b5081516001600160a01b039081166101c05260208084015182166101e052604080850151831661020052606080860151909316610220528351610240529083015161026052820151610280528101516102a052620003556200086b565b6200035f6200086b565b60005b600481101562000520576001600160a01b03881615620003cc5780156200039957620003938860001983016200069b565b6200039e565b6101c0515b838260048110620003b357620003b362000927565b6001600160a01b039092166020929092020152620004b8565b6000806200045083604051602401620003e791815260200190565b60408051601f198184030181529181526020820180516001600160e01b0316630b9947eb60e41b179052516024810186905260440160408051601f198184030181529190526020810180516001600160e01b03908116635b9cca9f60e11b179091526200078416565b9150915081801562000463575060008151115b15620004ad57808060200190518101906200047f919062000907565b85846004811062000494576200049462000927565b6001600160a01b039092166020929092020152620004b5565b505062000520565b50505b6000838260048110620004cf57620004cf62000927565b60200201516001600160a01b0316146200051757620004fc838260048110620002ca57620002ca62000927565b82826004811062000511576200051162000927565b60200201525b60010162000362565b5081516001600160a01b039081166102c05260208084015182166102e05260408085015183166103005260609485015190921661032052825161034052820151610360528101516103805201516103a05250620009889a5050505050505050505050565b6001600160a01b038116620005ac57604051635919af9760e11b815260040160405180910390fd5b50565b60a051604051636ae17a4360e11b81526001600160a01b038381166004830152600092169063d5c2f48690602401602060405180830381865afa158015620005fb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200062191906200093d565b92915050565b600060e0516001600160a01b03166392526c0c6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801562000688575060408051601f3d908101601f1916820190925262000685918101906200093d565b60015b620006935750600090565b600191505090565b60405163c661065760e01b8152600481018290526000906001600160a01b0384169063c661065790602401602060405180830381865afa92505050801562000702575060408051601f3d908101601f19168201909252620006ff9181019062000907565b60015b6200077d5760405163046e8dd760e31b8152600f83900b60048201526001600160a01b038416906323746eb890602401602060405180830381865afa9250505080156200076e575060408051601f3d908101601f191682019092526200076b9181019062000907565b60015b15620007775790505b62000621565b9392505050565b6000606060e0516001600160a01b031684604051620007a4919062000957565b600060405180830381855afa9150503d8060008114620007e1576040519150601f19603f3d011682016040523d82523d6000602084013e620007e6565b606091505b509092509050811580620007f957508051155b15620008645760e0516001600160a01b0316836040516200081b919062000957565b600060405180830381855afa9150503d806000811462000858576040519150601f19603f3d011682016040523d82523d6000602084013e6200085d565b606091505b5090925090505b9250929050565b60405180608001604052806004906020820280368337509192915050565b6001600160a01b0381168114620005ac57600080fd5b60008060008060808587031215620008b657600080fd5b8451620008c38162000889565b6020860151909450620008d68162000889565b6040860151909350620008e98162000889565b6060860151909250620008fc8162000889565b939692955090935050565b6000602082840312156200091a57600080fd5b81516200077d8162000889565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156200095057600080fd5b5051919050565b6000825160005b818110156200097a57602081860181015185830152016200095e565b506000920191825250919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e05161030051610320516103405161036051610380516103a0516122a262000bd36000396000818161063f0152611e450152600081816104dc0152611e160152600081816104550152611de70152600081816105f10152611db801526000818161048f015261173301526000818161032d015261170401526000818161057401526116d501526000818161061801526116a601526000818161074f015281816113630152818161196a0152611c49015260008181610666015281816113410152818161193e0152611c1a0152600081816108330152818161131f015281816119120152611beb0152600081816102f3015281816112fe015281816118e60152611bbc0152600081816107f90152818161101d0152611a350152600081816103e101528181610fee0152611a0501526000818161078501528181610fbf01526119d501526000818161039401528181610f9001526119a50152600081816105030152818161114f0152818161175b0152611c71015260006107010152600061053a01526000818161072801528181610ecf015281816110fe0152611d830152600081816105ca01526113d60152600061085a0152600081816106b3015281816115880152611617015260006104080152600081816106da01528181610d9f01528181610efe01528181611a940152611b4f015260006107bf01526122a26000f3fe608060405234801561001057600080fd5b50600436106102e95760003560e01c80637dce4a8c11610191578063c7c4fe1e116100e3578063de28735911610097578063f1dc3cc911610071578063f1dc3cc91461081b578063f8f156391461082e578063fc0c546a1461085557600080fd5b8063de287359146107ba578063e3103273146107e1578063ef14101e146107f457600080fd5b8063ce30bbdb116100c8578063ce30bbdb14610771578063d21220a714610780578063d9f3206d146107a757600080fd5b8063c7c4fe1e14610723578063caed37871461074a57600080fd5b80639e9c1e8811610145578063bd90df701161011f578063bd90df70146106ae578063c12c21c0146106d5578063c21ee162146106fc57600080fd5b80639e9c1e8814610661578063a6417ed614610688578063ae206e241461069b57600080fd5b806387427f461161017657806387427f46146105ec5780638ba51dfc1461061357806393a581531461063a57600080fd5b80637dce4a8c146105b257806382c63066146105c557600080fd5b8063403d4e4a1161024a5780635e8d3f55116101fe57806365b2489b116101d857806365b2489b1461055c5780636e1d82711461056f57806378aa73a41461059657600080fd5b80635e8d3f55146104d7578063623d8585146104fe57806364a89bca1461053557600080fd5b806357d788751161022f57806357d788751461048a5780635b36389c146104b15780635b41b908146104c457600080fd5b8063403d4e4a146104505780634be97fb01461047757600080fd5b80631a4d01d2116102a15780632954018c116102865780632954018c1461040357806332fe0e161461042a5780633df021241461043d57600080fd5b80631a4d01d2146103c957806325be124e146103dc57600080fd5b80630b4c7e4d116102d25780630b4c7e4d146103675780630dfe16811461038f578063148f3c43146103b657600080fd5b806301b44c84146102ee5780630687116314610328575b600080fd5b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161031f565b61037a610375366004611e98565b61087c565b6040805192835260208301919091520161031f565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6103c4366004611ec3565b6108aa565b61037a6103d7366004611f01565b6109a7565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a610438366004611f36565b6109d2565b61037a61044b366004611f68565b610ad2565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61037a610485366004611ec3565b610b08565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6104bf366004611faa565b610b29565b61037a6104d2366004611f36565b610b3c565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6105257f000000000000000000000000000000000000000000000000000000000000000081565b604051901515815260200161031f565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a61056a366004611f36565b610b53565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61059f61012c81565b60405161ffff909116815260200161031f565b61037a6105c0366004611ec3565b610b6a565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61037a610696366004611f68565b610b8c565b6103156106a9366004611fd7565b610bb5565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b600560405161031f9190611ff9565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6107b5366004611f36565b610c77565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6107ef366004611e98565b610d64565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a610829366004611ec3565b610d87565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b600080610887610d9d565b61089f60018535811090602087013511600080610e6b565b909590945092505050565b6000806108b5610d9d565b60006108bf610efa565b905060006108cc86610f83565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093c9190612037565b9050878111610954576000809450945050505061099f565b87900360006b033b2e3c9fd0803ce80000006109708884612050565b61097a9190612075565b90506109958861098b8a8585611046565b60018c11156110c8565b9096509450505050505b935093915050565b6000806109b2610d9d565b6109c6856109c086600f0b90565b85611132565b90969095509350505050565b6000806109dd610d9d565b60006109e7610efa565b905060006109f488610f83565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610a40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a649190612037565b9050868111610a7c5760008094509450505050610ac9565b86900360006b033b2e3c9fd0803ce8000000610a988884612050565b610aa29190612075565b9050610abf8a8a610ab58d8d878761114b565b60018c111561124b565b9096509450505050505b94509492505050565b600080610add610d9d565b610afb610aea87600f0b90565b610af487600f0b90565b868661129b565b9150915094509492505050565b600080610b13610d9d565b6109c684610b22868887611046565b60006110c8565b600080610b34610d9d565b61089f6112b6565b600080610b47610d9d565b610afb8686868661129b565b600080610b5e610d9d565b610afb86868686611389565b600080610b75610d9d565b610b808486856113a4565b91509150935093915050565b600080610b97610d9d565b610afb610ba487600f0b90565b610bae87600f0b90565b8686611389565b6000806000610bc484866114a8565b91509150600080610bd58484611582565b91509150818015610be7575060008151115b15610c0b5780806020019051810190610c009190612037565b945050505050610c71565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f63616c635f746f6b656e5f616d6f756e74207265766572746564000000000000604482015260640160405180910390fd5b92915050565b600080610c82610d9d565b6000610c8c610efa565b90506000610c9988611699565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610ce5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d099190612037565b9050868111610d215760008094509450505050610ac9565b86900360006b033b2e3c9fd0803ce8000000610d3d8884612050565b610d479190612075565b9050610abf8a8a610d5a8d8d8787611757565b60018c1115611857565b600080610d6f610d9d565b61089f6001853581109060208701351160008061189a565b600080610d92610d9d565b6109c6858585611132565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1f9190612097565b6001600160a01b0316336001600160a01b031614610e69576040517f0c1d6a3f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600080610e7d8686868660001961199a565b610ebd6000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6192505050565b50610ecc86868686600161199a565b507f000000000000000000000000000000000000000000000000000000000000000095600095509350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166334878f546040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7e9190612097565b905090565b600081600003610fb457507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600103610fe357507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160020361101257507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361104157507f0000000000000000000000000000000000000000000000000000000000000000919050565b919050565b6060611050611e69565b8381866002811061106357611063612021565b602002015260405161107b90829085906024016120f0565b60408051601f198184030181529190526020810180516001600160e01b03167f0b4c7e4d000000000000000000000000000000000000000000000000000000001790529150509392505050565b6000806110df6110d786610f83565b600019611b10565b6110e884611a61565b506110fc6110f586610f83565b6001611b10565b7f0000000000000000000000000000000000000000000000000000000000000000836111295760006109c6565b6109c686611baf565b6000806109c684611144868887611c6d565b6000611d5e565b60607f00000000000000000000000000000000000000000000000000000000000000006111dc576040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f3df0212400000000000000000000000000000000000000000000000000000000179052611242565b6040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f5b41b908000000000000000000000000000000000000000000000000000000001790525b95945050505050565b60008061125a6110d787610f83565b61126384611a61565b506112706110f587610f83565b61127985611baf565b8361128557600061128e565b61128e87611baf565b9097909650945050505050565b60008061128e86866112af8989898961114b565b600061124b565b6000806112f96000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6192505050565b5050507f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000177f0000000000000000000000000000000000000000000000000000000000000000177f00000000000000000000000000000000000000000000000000000000000000001790600090565b60008061128e868661139d89898989611757565b6000611857565b60008060006113b1610efa565b6040516370a0823160e01b81526001600160a01b0380831660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561141d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114419190612037565b90508581116114585760008093509350505061099f565b85900360006b033b2e3c9fd0803ce80000006114748784612050565b61147e9190612075565b90506114998861148f8a8585611c6d565b60018a1115611d5e565b90999098509650505050505050565b6060806114b3611e69565b838186600281106114c6576114c6612021565b60200201526040516114df90829060019060240161210b565b60408051601f198184030181529181526020820180516001600160e01b03167fed8e84f30000000000000000000000000000000000000000000000000000000017905251611531908390602401612128565b60408051601f198184030181529190526020810180516001600160e01b03167f8d8ea727000000000000000000000000000000000000000000000000000000001790529093509150505b9250929050565b600060607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846040516115be919061215a565b600060405180830381855afa9150503d80600081146115f9576040519150601f19603f3d011682016040523d82523d6000602084013e6115fe565b606091505b50909250905081158061161057508051155b1561157b577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168360405161164d919061215a565b600060405180830381855afa9150503d8060008114611688576040519150601f19603f3d011682016040523d82523d6000602084013e61168d565b606091505b50909590945092505050565b6000816000036116ca57507f0000000000000000000000000000000000000000000000000000000000000000919050565b816001036116f957507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160020361172857507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361104157507f0000000000000000000000000000000000000000000000000000000000000000919050565b60607f00000000000000000000000000000000000000000000000000000000000000006117e8576040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167fa6417ed600000000000000000000000000000000000000000000000000000000179052611242565b6040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f65b2489b000000000000000000000000000000000000000000000000000000001790529050949350505050565b6000806118666110d787611699565b61186f84611a61565b5061187c6110f587611699565b61188585611dab565b8361189157600061128e565b61128e87611dab565b6000806118dd6000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6192505050565b50851561190a577f0000000000000000000000000000000000000000000000000000000000000000821791505b8415611936577f0000000000000000000000000000000000000000000000000000000000000000821791505b8315611962577f0000000000000000000000000000000000000000000000000000000000000000821791505b821561198e577f0000000000000000000000000000000000000000000000000000000000000000821791505b50946000945092505050565b84156119ca576119ca7f000000000000000000000000000000000000000000000000000000000000000082611b10565b83156119fa576119fa7f000000000000000000000000000000000000000000000000000000000000000082611b10565b8215611a2a57611a2a7f000000000000000000000000000000000000000000000000000000000000000082611b10565b8115611a5a57611a5a7f000000000000000000000000000000000000000000000000000000000000000082611b10565b5050505050565b6040517f09c5eabe0000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906309c5eabe90611ac9908590600401612176565b6000604051808303816000875af1158015611ae8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c7191908101906121bf565b6040517ffa30b30f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063fa30b30f90604401600060405180830381600087803b158015611b9357600080fd5b505af1158015611ba7573d6000803e3d6000fd5b505050505050565b600081600003611be057507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600103611c0f57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600203611c3e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361104157507f0000000000000000000000000000000000000000000000000000000000000000919050565b60607f0000000000000000000000000000000000000000000000000000000000000000611cf75760405160248101849052604481018590526064810183905260840160408051601f198184030181529190526020810180516001600160e01b03167f1a4d01d200000000000000000000000000000000000000000000000000000000179052611d56565b60405160248101849052604481018590526064810183905260840160408051601f198184030181529190526020810180516001600160e01b03167ff1dc3cc9000000000000000000000000000000000000000000000000000000001790525b949350505050565b600080611d6a84611a61565b50611d7485611baf565b83611d805760006109c6565b957f000000000000000000000000000000000000000000000000000000000000000095509350505050565b600081600003611ddc57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600103611e0b57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600203611e3a57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361104157507f0000000000000000000000000000000000000000000000000000000000000000919050565b60405180604001604052806002906020820280368337509192915050565b8060408101831015610c7157600080fd5b60008060608385031215611eab57600080fd5b611eb58484611e87565b946040939093013593505050565b600080600060608486031215611ed857600080fd5b505081359360208301359350604090920135919050565b8035600f81900b811461104157600080fd5b600080600060608486031215611f1657600080fd5b83359250611f2660208501611eef565b9150604084013590509250925092565b60008060008060808587031215611f4c57600080fd5b5050823594602084013594506040840135936060013592509050565b60008060008060808587031215611f7e57600080fd5b611f8785611eef565b9350611f9560208601611eef565b93969395505050506040820135916060013590565b60008060608385031215611fbd57600080fd5b82359150611fce8460208501611e87565b90509250929050565b60008060408385031215611fea57600080fd5b50508035926020909101359150565b60208101601c831061201b57634e487b7160e01b600052602160045260246000fd5b91905290565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561204957600080fd5b5051919050565b8082028115828204841417610c7157634e487b7160e01b600052601160045260246000fd5b60008261209257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156120a957600080fd5b81516001600160a01b03811681146120c057600080fd5b9392505050565b8060005b60028110156120ea5781518452602093840193909101906001016120cb565b50505050565b606081016120fe82856120c7565b8260408301529392505050565b6060810161211982856120c7565b82151560408301529392505050565b60408101610c7182846120c7565b60005b83811015612151578181015183820152602001612139565b50506000910152565b6000825161216c818460208701612136565b9190910192915050565b6020815260008251806020840152612195816040850160208701612136565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156121d157600080fd5b815167ffffffffffffffff808211156121e957600080fd5b818401915084601f8301126121fd57600080fd5b81518181111561220f5761220f6121a9565b604051601f8201601f19908116603f01168101908382118183101715612237576122376121a9565b8160405282815287602084870101111561225057600080fd5b612261836020830160208801612136565b97965050505050505056fea26469706673582212201e8916c95317b348fbf21aec2b4fb74a423805a36fb0e9fb78003f0515a5e57864736f6c63430008110033000000000000000000000000e35eb22a349baba4f1a28a9cdba641d3b72c6203000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102e95760003560e01c80637dce4a8c11610191578063c7c4fe1e116100e3578063de28735911610097578063f1dc3cc911610071578063f1dc3cc91461081b578063f8f156391461082e578063fc0c546a1461085557600080fd5b8063de287359146107ba578063e3103273146107e1578063ef14101e146107f457600080fd5b8063ce30bbdb116100c8578063ce30bbdb14610771578063d21220a714610780578063d9f3206d146107a757600080fd5b8063c7c4fe1e14610723578063caed37871461074a57600080fd5b80639e9c1e8811610145578063bd90df701161011f578063bd90df70146106ae578063c12c21c0146106d5578063c21ee162146106fc57600080fd5b80639e9c1e8814610661578063a6417ed614610688578063ae206e241461069b57600080fd5b806387427f461161017657806387427f46146105ec5780638ba51dfc1461061357806393a581531461063a57600080fd5b80637dce4a8c146105b257806382c63066146105c557600080fd5b8063403d4e4a1161024a5780635e8d3f55116101fe57806365b2489b116101d857806365b2489b1461055c5780636e1d82711461056f57806378aa73a41461059657600080fd5b80635e8d3f55146104d7578063623d8585146104fe57806364a89bca1461053557600080fd5b806357d788751161022f57806357d788751461048a5780635b36389c146104b15780635b41b908146104c457600080fd5b8063403d4e4a146104505780634be97fb01461047757600080fd5b80631a4d01d2116102a15780632954018c116102865780632954018c1461040357806332fe0e161461042a5780633df021241461043d57600080fd5b80631a4d01d2146103c957806325be124e146103dc57600080fd5b80630b4c7e4d116102d25780630b4c7e4d146103675780630dfe16811461038f578063148f3c43146103b657600080fd5b806301b44c84146102ee5780630687116314610328575b600080fd5b6103157f000000000000000000000000000000000000000000000000000000000000000881565b6040519081526020015b60405180910390f35b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161031f565b61037a610375366004611e98565b61087c565b6040805192835260208301919091520161031f565b61034f7f0000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b381565b61037a6103c4366004611ec3565b6108aa565b61037a6103d7366004611f01565b6109a7565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f0000000000000000000000009ea7b04da02a5373317d745c1571c84aad03321d81565b61037a610438366004611f36565b6109d2565b61037a61044b366004611f68565b610ad2565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61037a610485366004611ec3565b610b08565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6104bf366004611faa565b610b29565b61037a6104d2366004611f36565b610b3c565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6105257f000000000000000000000000000000000000000000000000000000000000000081565b604051901515815260200161031f565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a61056a366004611f36565b610b53565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61059f61012c81565b60405161ffff909116815260200161031f565b61037a6105c0366004611ec3565b610b6a565b61034f7f000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d81565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61037a610696366004611f68565b610b8c565b6103156106a9366004611fd7565b610bb5565b61034f7f000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d81565b61034f7f000000000000000000000000e35eb22a349baba4f1a28a9cdba641d3b72c620381565b6103157f000000000000000000000000000000000000000000000000000000000000000281565b6103157f000000000000000000000000000000000000000000000000000000000000008081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b600560405161031f9190611ff9565b61034f7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f81565b61037a6107b5366004611f36565b610c77565b61034f7f000000000000000000000000523da3a8961e4dd4f6206dbf7e6c749f51796bb381565b61037a6107ef366004611e98565b610d64565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a610829366004611ec3565b610d87565b6103157f000000000000000000000000000000000000000000000000000000000000000481565b61034f7f000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d81565b600080610887610d9d565b61089f60018535811090602087013511600080610e6b565b909590945092505050565b6000806108b5610d9d565b60006108bf610efa565b905060006108cc86610f83565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093c9190612037565b9050878111610954576000809450945050505061099f565b87900360006b033b2e3c9fd0803ce80000006109708884612050565b61097a9190612075565b90506109958861098b8a8585611046565b60018c11156110c8565b9096509450505050505b935093915050565b6000806109b2610d9d565b6109c6856109c086600f0b90565b85611132565b90969095509350505050565b6000806109dd610d9d565b60006109e7610efa565b905060006109f488610f83565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610a40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a649190612037565b9050868111610a7c5760008094509450505050610ac9565b86900360006b033b2e3c9fd0803ce8000000610a988884612050565b610aa29190612075565b9050610abf8a8a610ab58d8d878761114b565b60018c111561124b565b9096509450505050505b94509492505050565b600080610add610d9d565b610afb610aea87600f0b90565b610af487600f0b90565b868661129b565b9150915094509492505050565b600080610b13610d9d565b6109c684610b22868887611046565b60006110c8565b600080610b34610d9d565b61089f6112b6565b600080610b47610d9d565b610afb8686868661129b565b600080610b5e610d9d565b610afb86868686611389565b600080610b75610d9d565b610b808486856113a4565b91509150935093915050565b600080610b97610d9d565b610afb610ba487600f0b90565b610bae87600f0b90565b8686611389565b6000806000610bc484866114a8565b91509150600080610bd58484611582565b91509150818015610be7575060008151115b15610c0b5780806020019051810190610c009190612037565b945050505050610c71565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f63616c635f746f6b656e5f616d6f756e74207265766572746564000000000000604482015260640160405180910390fd5b92915050565b600080610c82610d9d565b6000610c8c610efa565b90506000610c9988611699565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610ce5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d099190612037565b9050868111610d215760008094509450505050610ac9565b86900360006b033b2e3c9fd0803ce8000000610d3d8884612050565b610d479190612075565b9050610abf8a8a610d5a8d8d8787611757565b60018c1115611857565b600080610d6f610d9d565b61089f6001853581109060208701351160008061189a565b600080610d92610d9d565b6109c6858585611132565b7f000000000000000000000000e35eb22a349baba4f1a28a9cdba641d3b72c62036001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1f9190612097565b6001600160a01b0316336001600160a01b031614610e69576040517f0c1d6a3f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600080610e7d8686868660001961199a565b610ebd6000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6192505050565b50610ecc86868686600161199a565b507f000000000000000000000000000000000000000000000000000000000000008095600095509350505050565b60007f000000000000000000000000e35eb22a349baba4f1a28a9cdba641d3b72c62036001600160a01b03166334878f546040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7e9190612097565b905090565b600081600003610fb457507f0000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b3919050565b81600103610fe357507f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f919050565b8160020361101257507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361104157507f0000000000000000000000000000000000000000000000000000000000000000919050565b919050565b6060611050611e69565b8381866002811061106357611063612021565b602002015260405161107b90829085906024016120f0565b60408051601f198184030181529190526020810180516001600160e01b03167f0b4c7e4d000000000000000000000000000000000000000000000000000000001790529150509392505050565b6000806110df6110d786610f83565b600019611b10565b6110e884611a61565b506110fc6110f586610f83565b6001611b10565b7f0000000000000000000000000000000000000000000000000000000000000080836111295760006109c6565b6109c686611baf565b6000806109c684611144868887611c6d565b6000611d5e565b60607f00000000000000000000000000000000000000000000000000000000000000006111dc576040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f3df0212400000000000000000000000000000000000000000000000000000000179052611242565b6040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f5b41b908000000000000000000000000000000000000000000000000000000001790525b95945050505050565b60008061125a6110d787610f83565b61126384611a61565b506112706110f587610f83565b61127985611baf565b8361128557600061128e565b61128e87611baf565b9097909650945050505050565b60008061128e86866112af8989898961114b565b600061124b565b6000806112f96000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6192505050565b5050507f00000000000000000000000000000000000000000000000000000000000000087f0000000000000000000000000000000000000000000000000000000000000004177f0000000000000000000000000000000000000000000000000000000000000000177f00000000000000000000000000000000000000000000000000000000000000001790600090565b60008061128e868661139d89898989611757565b6000611857565b60008060006113b1610efa565b6040516370a0823160e01b81526001600160a01b0380831660048301529192506000917f000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d16906370a0823190602401602060405180830381865afa15801561141d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114419190612037565b90508581116114585760008093509350505061099f565b85900360006b033b2e3c9fd0803ce80000006114748784612050565b61147e9190612075565b90506114998861148f8a8585611c6d565b60018a1115611d5e565b90999098509650505050505050565b6060806114b3611e69565b838186600281106114c6576114c6612021565b60200201526040516114df90829060019060240161210b565b60408051601f198184030181529181526020820180516001600160e01b03167fed8e84f30000000000000000000000000000000000000000000000000000000017905251611531908390602401612128565b60408051601f198184030181529190526020810180516001600160e01b03167f8d8ea727000000000000000000000000000000000000000000000000000000001790529093509150505b9250929050565b600060607f000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d6001600160a01b0316846040516115be919061215a565b600060405180830381855afa9150503d80600081146115f9576040519150601f19603f3d011682016040523d82523d6000602084013e6115fe565b606091505b50909250905081158061161057508051155b1561157b577f000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d6001600160a01b03168360405161164d919061215a565b600060405180830381855afa9150503d8060008114611688576040519150601f19603f3d011682016040523d82523d6000602084013e61168d565b606091505b50909590945092505050565b6000816000036116ca57507f0000000000000000000000000000000000000000000000000000000000000000919050565b816001036116f957507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160020361172857507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361104157507f0000000000000000000000000000000000000000000000000000000000000000919050565b60607f00000000000000000000000000000000000000000000000000000000000000006117e8576040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167fa6417ed600000000000000000000000000000000000000000000000000000000179052611242565b6040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f65b2489b000000000000000000000000000000000000000000000000000000001790529050949350505050565b6000806118666110d787611699565b61186f84611a61565b5061187c6110f587611699565b61188585611dab565b8361189157600061128e565b61128e87611dab565b6000806118dd6000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6192505050565b50851561190a577f0000000000000000000000000000000000000000000000000000000000000008821791505b8415611936577f0000000000000000000000000000000000000000000000000000000000000004821791505b8315611962577f0000000000000000000000000000000000000000000000000000000000000000821791505b821561198e577f0000000000000000000000000000000000000000000000000000000000000000821791505b50946000945092505050565b84156119ca576119ca7f0000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b382611b10565b83156119fa576119fa7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f82611b10565b8215611a2a57611a2a7f000000000000000000000000000000000000000000000000000000000000000082611b10565b8115611a5a57611a5a7f000000000000000000000000000000000000000000000000000000000000000082611b10565b5050505050565b6040517f09c5eabe0000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f000000000000000000000000e35eb22a349baba4f1a28a9cdba641d3b72c620316906309c5eabe90611ac9908590600401612176565b6000604051808303816000875af1158015611ae8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c7191908101906121bf565b6040517ffa30b30f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390527f000000000000000000000000e35eb22a349baba4f1a28a9cdba641d3b72c6203169063fa30b30f90604401600060405180830381600087803b158015611b9357600080fd5b505af1158015611ba7573d6000803e3d6000fd5b505050505050565b600081600003611be057507f0000000000000000000000000000000000000000000000000000000000000008919050565b81600103611c0f57507f0000000000000000000000000000000000000000000000000000000000000004919050565b81600203611c3e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361104157507f0000000000000000000000000000000000000000000000000000000000000000919050565b60607f0000000000000000000000000000000000000000000000000000000000000000611cf75760405160248101849052604481018590526064810183905260840160408051601f198184030181529190526020810180516001600160e01b03167f1a4d01d200000000000000000000000000000000000000000000000000000000179052611d56565b60405160248101849052604481018590526064810183905260840160408051601f198184030181529190526020810180516001600160e01b03167ff1dc3cc9000000000000000000000000000000000000000000000000000000001790525b949350505050565b600080611d6a84611a61565b50611d7485611baf565b83611d805760006109c6565b957f000000000000000000000000000000000000000000000000000000000000008095509350505050565b600081600003611ddc57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600103611e0b57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600203611e3a57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361104157507f0000000000000000000000000000000000000000000000000000000000000000919050565b60405180604001604052806002906020820280368337509192915050565b8060408101831015610c7157600080fd5b60008060608385031215611eab57600080fd5b611eb58484611e87565b946040939093013593505050565b600080600060608486031215611ed857600080fd5b505081359360208301359350604090920135919050565b8035600f81900b811461104157600080fd5b600080600060608486031215611f1657600080fd5b83359250611f2660208501611eef565b9150604084013590509250925092565b60008060008060808587031215611f4c57600080fd5b5050823594602084013594506040840135936060013592509050565b60008060008060808587031215611f7e57600080fd5b611f8785611eef565b9350611f9560208601611eef565b93969395505050506040820135916060013590565b60008060608385031215611fbd57600080fd5b82359150611fce8460208501611e87565b90509250929050565b60008060408385031215611fea57600080fd5b50508035926020909101359150565b60208101601c831061201b57634e487b7160e01b600052602160045260246000fd5b91905290565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561204957600080fd5b5051919050565b8082028115828204841417610c7157634e487b7160e01b600052601160045260246000fd5b60008261209257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156120a957600080fd5b81516001600160a01b03811681146120c057600080fd5b9392505050565b8060005b60028110156120ea5781518452602093840193909101906001016120cb565b50505050565b606081016120fe82856120c7565b8260408301529392505050565b6060810161211982856120c7565b82151560408301529392505050565b60408101610c7182846120c7565b60005b83811015612151578181015183820152602001612139565b50506000910152565b6000825161216c818460208701612136565b9190910192915050565b6020815260008251806020840152612195816040850160208701612136565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156121d157600080fd5b815167ffffffffffffffff808211156121e957600080fd5b818401915084601f8301126121fd57600080fd5b81518181111561220f5761220f6121a9565b604051601f8201601f19908116603f01168101908382118183101715612237576122376121a9565b8160405282815287602084870101111561225057600080fd5b612261836020830160208801612136565b97965050505050505056fea26469706673582212201e8916c95317b348fbf21aec2b4fb74a423805a36fb0e9fb78003f0515a5e57864736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e35eb22a349baba4f1a28a9cdba641d3b72c6203000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d0000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _creditManager (address): 0xe35eb22a349BABA4F1A28a9cdBA641D3B72C6203
Arg [1] : _curvePool (address): 0xF36a4BA50C603204c3FC6d2dA8b78A7b69CBC67d
Arg [2] : _lp_token (address): 0xF36a4BA50C603204c3FC6d2dA8b78A7b69CBC67d
Arg [3] : _metapoolBase (address): 0x0000000000000000000000000000000000000000
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000e35eb22a349baba4f1a28a9cdba641d3b72c6203
Arg [1] : 000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d
Arg [2] : 000000000000000000000000f36a4ba50c603204c3fc6d2da8b78a7b69cbc67d
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.