Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x6103c060 | 18798275 | 819 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CurveV1AdapterStETH
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 {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {RAY} from "@gearbox-protocol/core-v2/contracts/libraries/Constants.sol";
import {AdapterType} from "@gearbox-protocol/sdk-gov/contracts/AdapterType.sol";
import {N_COINS} from "../../integrations/curve/ICurvePool_2.sol";
import {ICurveV1Adapter} from "../../interfaces/curve/ICurveV1Adapter.sol";
import {CurveV1AdapterBase} from "./CurveV1_Base.sol";
import {CurveV1Adapter2Assets} from "./CurveV1_2.sol";
/// @title Curve V1 stETH adapter
/// @notice Same as `CurveV1Adapter2Assets` but uses stETH gateway and needs to approve LP token
contract CurveV1AdapterStETH is CurveV1Adapter2Assets {
AdapterType public constant override _gearboxAdapterType = AdapterType.CURVE_V1_STECRV_POOL;
/// @notice Sets allowance for the pool LP token to max before the operation and to 1 after
modifier withLPTokenApproval() {
_approveToken(lp_token, type(uint256).max);
_;
_approveToken(lp_token, 1);
}
/// @notice Constructor
/// @param _creditManager Credit manager address
/// @param _curveStETHPoolGateway steCRV pool gateway address
/// @param _lp_token steCRV LP token address
constructor(address _creditManager, address _curveStETHPoolGateway, address _lp_token)
CurveV1Adapter2Assets(_creditManager, _curveStETHPoolGateway, _lp_token, address(0))
{}
/// @inheritdoc CurveV1Adapter2Assets
/// @dev Unlike other adapters, approves the LP token to the target
function remove_liquidity(uint256, uint256[N_COINS] calldata)
external
override
creditFacadeOnly
withLPTokenApproval
returns (uint256 tokensToEnable, uint256 tokensToDisable)
{
(tokensToEnable, tokensToDisable) = _remove_liquidity();
}
/// @inheritdoc CurveV1Adapter2Assets
/// @dev Unlike other adapters, approves the LP token to the target
function remove_liquidity_imbalance(uint256[N_COINS] calldata amounts, uint256)
external
override
creditFacadeOnly
withLPTokenApproval
returns (uint256 tokensToEnable, uint256 tokensToDisable)
{
(tokensToEnable, tokensToDisable) = _remove_liquidity_imbalance(amounts[0] > 1, amounts[1] > 1, false, false);
}
/// @inheritdoc CurveV1AdapterBase
/// @dev Unlike other adapters, approves the LP token to the target
function remove_liquidity_one_coin(uint256 amount, uint256 i, uint256 minAmount)
public
override(CurveV1AdapterBase, ICurveV1Adapter)
creditFacadeOnly
withLPTokenApproval
returns (uint256 tokensToEnable, uint256 tokensToDisable)
{
(tokensToEnable, tokensToDisable) = _remove_liquidity_one_coin(amount, i, minAmount);
}
/// @inheritdoc CurveV1AdapterBase
/// @dev Unlike other adapters, approves the LP token to the target
function remove_liquidity_one_coin(uint256 amount, int128 i, uint256 minAmount)
public
override(CurveV1AdapterBase, ICurveV1Adapter)
creditFacadeOnly
withLPTokenApproval
returns (uint256 tokensToEnable, uint256 tokensToDisable)
{
(tokensToEnable, tokensToDisable) = _remove_liquidity_one_coin(amount, _toU256(i), minAmount);
}
/// @inheritdoc CurveV1AdapterBase
/// @dev Unlike other adapters, approves the LP token to the target
function remove_diff_liquidity_one_coin(uint256 leftoverAmount, uint256 i, uint256 rateMinRAY)
public
override(CurveV1AdapterBase, ICurveV1Adapter)
creditFacadeOnly
withLPTokenApproval
returns (uint256 tokensToEnable, uint256 tokensToDisable)
{
(tokensToEnable, tokensToDisable) = _remove_diff_liquidity_one_coin(i, leftoverAmount, rateMinRAY);
}
}// 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: 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
}// 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 {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: 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: 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
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.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: 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(); /// @notice Thrown when trying to manually set total debt parameters in a credit facade that doesn't track them error TotalDebtNotTrackedException(); // ------------- // // 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 {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: 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/",
"@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
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_creditManager","type":"address"},{"internalType":"address","name":"_curveStETHPoolGateway","type":"address"},{"internalType":"address","name":"_lp_token","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":"view","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
6103c06040523480156200001257600080fd5b5060405162002fd638038062002fd68339810160408190526200003591620008a7565b82828260008383838360028484816001600160a01b0316632954018c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000081573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a79190620008fb565b80620000b3816200058c565b604051632bdad0e360e11b8152621050d360ea1b6004820152600060248201526001600160a01b038316906357b5a1c690604401602060405180830381865afa15801562000105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200012b9190620008fb565b6001600160a01b03166080525081905062000146816200058c565b6001600160a01b03831660a081905260408051630a55006360e21b81529051632954018c916004808201926020929091908290030181865afa15801562000191573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b79190620008fb565b6001600160a01b0390811660c0529190911660e05250839050620001db816200058c565b620001e684620005b7565b610140526001600160a01b0380851661010081905261012052831661016052610180829052620002156200062f565b15156101a0526200022562000873565b6200022f62000873565b60005b61018051811015620002fd576200024a8882620006a3565b8382600481106200025f576200025f6200091b565b6001600160a01b03909216602092909202015260008382600481106200028957620002896200091b565b60200201516001600160a01b031603620002b6576040516347fbaa9760e01b815260040160405180910390fd5b620002da838260048110620002cf57620002cf6200091b565b6020020151620005b7565b828260048110620002ef57620002ef6200091b565b602002015260010162000232565b5081516001600160a01b039081166101c05260208084015182166101e052604080850151831661020052606080860151909316610220528351610240529083015161026052820151610280528101516102a0526200035a62000873565b6200036462000873565b60005b600481101562000525576001600160a01b03881615620003d15780156200039e5762000398886000198301620006a3565b620003a3565b6101c0515b838260048110620003b857620003b86200091b565b6001600160a01b039092166020929092020152620004bd565b6000806200045583604051602401620003ec91815260200190565b60408051601f198184030181529181526020820180516001600160e01b0316630b9947eb60e41b179052516024810186905260440160408051601f198184030181529190526020810180516001600160e01b03908116635b9cca9f60e11b179091526200078c16565b9150915081801562000468575060008151115b15620004b25780806020019051810190620004849190620008fb565b8584600481106200049957620004996200091b565b6001600160a01b039092166020929092020152620004ba565b505062000525565b50505b6000838260048110620004d457620004d46200091b565b60200201516001600160a01b0316146200051c5762000501838260048110620002cf57620002cf6200091b565b8282600481106200051657620005166200091b565b60200201525b60010162000367565b5081516001600160a01b039081166102c05260208084015182166102e05260408085015183166103005260609485015190921661032052825161034052820151610360528101516103805201516103a052506200097c9d5050505050505050505050505050565b6001600160a01b038116620005b457604051635919af9760e11b815260040160405180910390fd5b50565b60a051604051636ae17a4360e11b81526001600160a01b038381166004830152600092169063d5c2f48690602401602060405180830381865afa15801562000603573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000629919062000931565b92915050565b600060e0516001600160a01b03166392526c0c6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801562000690575060408051601f3d908101601f191682019092526200068d9181019062000931565b60015b6200069b5750600090565b600191505090565b60405163c661065760e01b8152600481018290526000906001600160a01b0384169063c661065790602401602060405180830381865afa9250505080156200070a575060408051601f3d908101601f191682019092526200070791810190620008fb565b60015b620007855760405163046e8dd760e31b8152600f83900b60048201526001600160a01b038416906323746eb890602401602060405180830381865afa92505050801562000776575060408051601f3d908101601f191682019092526200077391810190620008fb565b60015b156200077f5790505b62000629565b9392505050565b6000606060e0516001600160a01b031684604051620007ac91906200094b565b600060405180830381855afa9150503d8060008114620007e9576040519150601f19603f3d011682016040523d82523d6000602084013e620007ee565b606091505b5090925090508115806200080157508051155b156200086c5760e0516001600160a01b0316836040516200082391906200094b565b600060405180830381855afa9150503d806000811462000860576040519150601f19603f3d011682016040523d82523d6000602084013e62000865565b606091505b5090925090505b9250929050565b60405180608001604052806004906020820280368337509192915050565b6001600160a01b0381168114620005b457600080fd5b600080600060608486031215620008bd57600080fd5b8351620008ca8162000891565b6020850151909350620008dd8162000891565b6040850151909250620008f08162000891565b809150509250925092565b6000602082840312156200090e57600080fd5b8151620007858162000891565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156200094457600080fd5b5051919050565b6000825160005b818110156200096e576020818601810151858301520162000952565b506000920191825250919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e05161030051610320516103405161036051610380516103a0516123de62000bf86000396000818161063f0152611f810152600081816104dc0152611f520152600081816104550152611f230152600081816105f10152611ef401526000818161048f015261190e01526000818161032d01526118df01526000818161057401526118b0015260008181610618015261188101526000818161074f0152818161153f01528181611b450152611d850152600081816106660152818161151d01528181611b190152611d56015260008181610839015281816114fb01528181611aed0152611d270152600081816102f3015281816114da01528181611ac10152611cf80152600081816107ff0152818161115a0152611c100152600081816103e10152818161112b0152611be001526000818161078b015281816110fc0152611bb0015260008181610394015281816110cd0152611b800152600081816105030152818161132b015281816119360152611dad015260006107010152600061053a0152600081816107280152818161100c0152818161123b0152611ebf0152600081816105ca015281816109bd01528181610a0201528181610b9b01528181610bd401528181610c3f01528181610e5901528181610ea801526115b2015260006108600152600081816106b30152818161176301526117f2015260006104080152600081816106da01528181610edc0152818161103b015281816112ae0152611c6f015260006107c501526123de6000f3fe608060405234801561001057600080fd5b50600436106102e95760003560e01c80637dce4a8c11610191578063c7c4fe1e116100e3578063de28735911610097578063f1dc3cc911610071578063f1dc3cc914610821578063f8f1563914610834578063fc0c546a1461085b57600080fd5b8063de287359146107c0578063e3103273146107e7578063ef14101e146107fa57600080fd5b8063ce30bbdb116100c8578063ce30bbdb14610771578063d21220a714610786578063d9f3206d146107ad57600080fd5b8063c7c4fe1e14610723578063caed37871461074a57600080fd5b80639e9c1e8811610145578063bd90df701161011f578063bd90df70146106ae578063c12c21c0146106d5578063c21ee162146106fc57600080fd5b80639e9c1e8814610661578063a6417ed614610688578063ae206e241461069b57600080fd5b806387427f461161017657806387427f46146105ec5780638ba51dfc1461061357806393a581531461063a57600080fd5b80637dce4a8c146105b257806382c63066146105c557600080fd5b8063403d4e4a1161024a5780635e8d3f55116101fe57806365b2489b116101d857806365b2489b1461055c5780636e1d82711461056f57806378aa73a41461059657600080fd5b80635e8d3f55146104d7578063623d8585146104fe57806364a89bca1461053557600080fd5b806357d788751161022f57806357d788751461048a5780635b36389c146104b15780635b41b908146104c457600080fd5b8063403d4e4a146104505780634be97fb01461047757600080fd5b80631a4d01d2116102a15780632954018c116102865780632954018c1461040357806332fe0e161461042a5780633df021241461043d57600080fd5b80631a4d01d2146103c957806325be124e146103dc57600080fd5b80630b4c7e4d116102d25780630b4c7e4d146103675780630dfe16811461038f578063148f3c43146103b657600080fd5b806301b44c84146102ee5780630687116314610328575b600080fd5b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161031f565b61037a610375366004611fd4565b610882565b6040805192835260208301919091520161031f565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6103c4366004611fff565b6108b0565b61037a6103d736600461203d565b6109ad565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a610438366004612072565b610a28565b61037a61044b3660046120a4565b610b28565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61037a610485366004611fff565b610b5e565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6104bf3660046120e6565b610b8b565b61037a6104d2366004612072565b610c01565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6105257f000000000000000000000000000000000000000000000000000000000000000081565b604051901515815260200161031f565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a61056a366004612072565b610c18565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61059f61012c81565b60405161ffff909116815260200161031f565b61037a6105c0366004611fff565b610c2f565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61037a6106963660046120a4565b610c71565b6103156106a9366004612113565b610c9a565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b610779600881565b60405161031f9190612135565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6107bb366004612072565b610d5c565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6107f5366004611fd4565b610e49565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a61082f366004611fff565b610e98565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b60008061088d610eda565b6108a560018535811090602087013511600080610fa8565b909590945092505050565b6000806108bb610eda565b60006108c5611037565b905060006108d2866110c0565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa15801561091e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109429190612173565b905087811161095a57600080945094505050506109a5565b87900360006b033b2e3c9fd0803ce8000000610976888461218c565b61098091906121b1565b905061099b886109918a8585611183565b60018c1115611205565b9096509450505050505b935093915050565b6000806109b8610eda565b6109e47f000000000000000000000000000000000000000000000000000000000000000060001961126f565b6109f8856109f286600f0b90565b8561130e565b90925090506109a57f0000000000000000000000000000000000000000000000000000000000000000600161126f565b600080610a33610eda565b6000610a3d611037565b90506000610a4a886110c0565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610a96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190612173565b9050868111610ad25760008094509450505050610b1f565b86900360006b033b2e3c9fd0803ce8000000610aee888461218c565b610af891906121b1565b9050610b158a8a610b0b8d8d8787611327565b60018c1115611427565b9096509450505050505b94509492505050565b600080610b33610eda565b610b51610b4087600f0b90565b610b4a87600f0b90565b8686611477565b9150915094509492505050565b600080610b69610eda565b610b7f84610b78868887611183565b6000611205565b90969095509350505050565b600080610b96610eda565b610bc27f000000000000000000000000000000000000000000000000000000000000000060001961126f565b610bca611492565b9092509050610bfa7f0000000000000000000000000000000000000000000000000000000000000000600161126f565b9250929050565b600080610c0c610eda565b610b5186868686611477565b600080610c23610eda565b610b5186868686611565565b600080610c3a610eda565b610c667f000000000000000000000000000000000000000000000000000000000000000060001961126f565b6109f8848685611580565b600080610c7c610eda565b610b51610c8987600f0b90565b610c9387600f0b90565b8686611565565b6000806000610ca98486611684565b91509150600080610cba848461175d565b91509150818015610ccc575060008151115b15610cf05780806020019051810190610ce59190612173565b945050505050610d56565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f63616c635f746f6b656e5f616d6f756e74207265766572746564000000000000604482015260640160405180910390fd5b92915050565b600080610d67610eda565b6000610d71611037565b90506000610d7e88611874565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610dca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dee9190612173565b9050868111610e065760008094509450505050610b1f565b86900360006b033b2e3c9fd0803ce8000000610e22888461218c565b610e2c91906121b1565b9050610b158a8a610e3f8d8d8787611932565b60018c1115611a32565b600080610e54610eda565b610e807f000000000000000000000000000000000000000000000000000000000000000060001961126f565b610bca60018535811090602087013511600080611a75565b600080610ea3610eda565b610ecf7f000000000000000000000000000000000000000000000000000000000000000060001961126f565b6109f885858561130e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5c91906121d3565b6001600160a01b0316336001600160a01b031614610fa6576040517f0c1d6a3f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600080610fba86868686600019611b75565b610ffa6000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c3c92505050565b50611009868686866001611b75565b507f000000000000000000000000000000000000000000000000000000000000000095600095509350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166334878f546040518163ffffffff1660e01b8152600401602060405180830381865afa158015611097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bb91906121d3565b905090565b6000816000036110f157507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160010361112057507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160020361114f57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361117e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b919050565b606061118d611fa5565b838186600281106111a0576111a061215d565b60200201526040516111b8908290859060240161222c565b60408051601f198184030181529190526020810180516001600160e01b03167f0b4c7e4d000000000000000000000000000000000000000000000000000000001790529150509392505050565b60008061121c611214866110c0565b60001961126f565b61122584611c3c565b50611239611232866110c0565b600161126f565b7f000000000000000000000000000000000000000000000000000000000000000083611266576000610b7f565b610b7f86611ceb565b6040517ffa30b30f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063fa30b30f90604401600060405180830381600087803b1580156112f257600080fd5b505af1158015611306573d6000803e3d6000fd5b505050505050565b600080610b7f84611320868887611da9565b6000611e9a565b60607f00000000000000000000000000000000000000000000000000000000000000006113b8576040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f3df021240000000000000000000000000000000000000000000000000000000017905261141e565b6040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f5b41b908000000000000000000000000000000000000000000000000000000001790525b95945050505050565b600080611436611214876110c0565b61143f84611c3c565b5061144c611232876110c0565b61145585611ceb565b8361146157600061146a565b61146a87611ceb565b9097909650945050505050565b60008061146a868661148b89898989611327565b6000611427565b6000806114d56000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c3c92505050565b5050507f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000177f0000000000000000000000000000000000000000000000000000000000000000177f00000000000000000000000000000000000000000000000000000000000000001790600090565b60008061146a868661157989898989611932565b6000611a32565b600080600061158d611037565b6040516370a0823160e01b81526001600160a01b0380831660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156115f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161d9190612173565b9050858111611634576000809350935050506109a5565b85900360006b033b2e3c9fd0803ce8000000611650878461218c565b61165a91906121b1565b90506116758861166b8a8585611da9565b60018a1115611e9a565b90999098509650505050505050565b60608061168f611fa5565b838186600281106116a2576116a261215d565b60200201526040516116bb908290600190602401612247565b60408051601f198184030181529181526020820180516001600160e01b03167fed8e84f3000000000000000000000000000000000000000000000000000000001790525161170d908390602401612264565b60408051601f198184030181529190526020810180516001600160e01b03167f8d8ea727000000000000000000000000000000000000000000000000000000001790529093509150509250929050565b600060607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846040516117999190612296565b600060405180830381855afa9150503d80600081146117d4576040519150601f19603f3d011682016040523d82523d6000602084013e6117d9565b606091505b5090925090508115806117eb57508051155b15610bfa577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836040516118289190612296565b600060405180830381855afa9150503d8060008114611863576040519150601f19603f3d011682016040523d82523d6000602084013e611868565b606091505b50909590945092505050565b6000816000036118a557507f0000000000000000000000000000000000000000000000000000000000000000919050565b816001036118d457507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160020361190357507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361117e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b60607f00000000000000000000000000000000000000000000000000000000000000006119c3576040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167fa6417ed60000000000000000000000000000000000000000000000000000000017905261141e565b6040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f65b2489b000000000000000000000000000000000000000000000000000000001790529050949350505050565b600080611a4161121487611874565b611a4a84611c3c565b50611a5761123287611874565b611a6085611ee7565b83611a6c57600061146a565b61146a87611ee7565b600080611ab86000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c3c92505050565b508515611ae5577f0000000000000000000000000000000000000000000000000000000000000000821791505b8415611b11577f0000000000000000000000000000000000000000000000000000000000000000821791505b8315611b3d577f0000000000000000000000000000000000000000000000000000000000000000821791505b8215611b69577f0000000000000000000000000000000000000000000000000000000000000000821791505b50946000945092505050565b8415611ba557611ba57f00000000000000000000000000000000000000000000000000000000000000008261126f565b8315611bd557611bd57f00000000000000000000000000000000000000000000000000000000000000008261126f565b8215611c0557611c057f00000000000000000000000000000000000000000000000000000000000000008261126f565b8115611c3557611c357f00000000000000000000000000000000000000000000000000000000000000008261126f565b5050505050565b6040517f09c5eabe0000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906309c5eabe90611ca49085906004016122b2565b6000604051808303816000875af1158015611cc3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d5691908101906122fb565b600081600003611d1c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600103611d4b57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600203611d7a57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361117e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b60607f0000000000000000000000000000000000000000000000000000000000000000611e335760405160248101849052604481018590526064810183905260840160408051601f198184030181529190526020810180516001600160e01b03167f1a4d01d200000000000000000000000000000000000000000000000000000000179052611e92565b60405160248101849052604481018590526064810183905260840160408051601f198184030181529190526020810180516001600160e01b03167ff1dc3cc9000000000000000000000000000000000000000000000000000000001790525b949350505050565b600080611ea684611c3c565b50611eb085611ceb565b83611ebc576000610b7f565b957f000000000000000000000000000000000000000000000000000000000000000095509350505050565b600081600003611f1857507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600103611f4757507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600203611f7657507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361117e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b60405180604001604052806002906020820280368337509192915050565b8060408101831015610d5657600080fd5b60008060608385031215611fe757600080fd5b611ff18484611fc3565b946040939093013593505050565b60008060006060848603121561201457600080fd5b505081359360208301359350604090920135919050565b8035600f81900b811461117e57600080fd5b60008060006060848603121561205257600080fd5b833592506120626020850161202b565b9150604084013590509250925092565b6000806000806080858703121561208857600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080608085870312156120ba57600080fd5b6120c38561202b565b93506120d16020860161202b565b93969395505050506040820135916060013590565b600080606083850312156120f957600080fd5b8235915061210a8460208501611fc3565b90509250929050565b6000806040838503121561212657600080fd5b50508035926020909101359150565b602081016016831061215757634e487b7160e01b600052602160045260246000fd5b91905290565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561218557600080fd5b5051919050565b8082028115828204841417610d5657634e487b7160e01b600052601160045260246000fd5b6000826121ce57634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156121e557600080fd5b81516001600160a01b03811681146121fc57600080fd5b9392505050565b8060005b6002811015612226578151845260209384019390910190600101612207565b50505050565b6060810161223a8285612203565b8260408301529392505050565b606081016122558285612203565b82151560408301529392505050565b60408101610d568284612203565b60005b8381101561228d578181015183820152602001612275565b50506000910152565b600082516122a8818460208701612272565b9190910192915050565b60208152600082518060208401526122d1816040850160208701612272565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561230d57600080fd5b815167ffffffffffffffff8082111561232557600080fd5b818401915084601f83011261233957600080fd5b81518181111561234b5761234b6122e5565b604051601f8201601f19908116603f01168101908382118183101715612373576123736122e5565b8160405282815287602084870101111561238c57600080fd5b61239d836020830160208801612272565b97965050505050505056fea2646970667358221220e435a5aa2222f02e8b54ce20ad74ff44175c869fcacde6a7772f087a66034c1a64736f6c634300081100330000000000000000000000003eb95430fdb99439a86d3c6d7d01c3c561393556000000000000000000000000ef0d72c594b28252bf7ea2bfbf098792430815b100000000000000000000000006325440d014e39736583c165c2963ba99faf14e
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102e95760003560e01c80637dce4a8c11610191578063c7c4fe1e116100e3578063de28735911610097578063f1dc3cc911610071578063f1dc3cc914610821578063f8f1563914610834578063fc0c546a1461085b57600080fd5b8063de287359146107c0578063e3103273146107e7578063ef14101e146107fa57600080fd5b8063ce30bbdb116100c8578063ce30bbdb14610771578063d21220a714610786578063d9f3206d146107ad57600080fd5b8063c7c4fe1e14610723578063caed37871461074a57600080fd5b80639e9c1e8811610145578063bd90df701161011f578063bd90df70146106ae578063c12c21c0146106d5578063c21ee162146106fc57600080fd5b80639e9c1e8814610661578063a6417ed614610688578063ae206e241461069b57600080fd5b806387427f461161017657806387427f46146105ec5780638ba51dfc1461061357806393a581531461063a57600080fd5b80637dce4a8c146105b257806382c63066146105c557600080fd5b8063403d4e4a1161024a5780635e8d3f55116101fe57806365b2489b116101d857806365b2489b1461055c5780636e1d82711461056f57806378aa73a41461059657600080fd5b80635e8d3f55146104d7578063623d8585146104fe57806364a89bca1461053557600080fd5b806357d788751161022f57806357d788751461048a5780635b36389c146104b15780635b41b908146104c457600080fd5b8063403d4e4a146104505780634be97fb01461047757600080fd5b80631a4d01d2116102a15780632954018c116102865780632954018c1461040357806332fe0e161461042a5780633df021241461043d57600080fd5b80631a4d01d2146103c957806325be124e146103dc57600080fd5b80630b4c7e4d116102d25780630b4c7e4d146103675780630dfe16811461038f578063148f3c43146103b657600080fd5b806301b44c84146102ee5780630687116314610328575b600080fd5b6103157f000000000000000000000000000000000000000000000000000000000000000281565b6040519081526020015b60405180910390f35b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161031f565b61037a610375366004611fd4565b610882565b6040805192835260208301919091520161031f565b61034f7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b61037a6103c4366004611fff565b6108b0565b61037a6103d736600461203d565b6109ad565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f0000000000000000000000009ea7b04da02a5373317d745c1571c84aad03321d81565b61037a610438366004612072565b610a28565b61037a61044b3660046120a4565b610b28565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61037a610485366004611fff565b610b5e565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a6104bf3660046120e6565b610b8b565b61037a6104d2366004612072565b610c01565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6105257f000000000000000000000000000000000000000000000000000000000000000081565b604051901515815260200161031f565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a61056a366004612072565b610c18565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61059f61012c81565b60405161ffff909116815260200161031f565b61037a6105c0366004611fff565b610c2f565b61034f7f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e81565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b61037a6106963660046120a4565b610c71565b6103156106a9366004612113565b610c9a565b61034f7f000000000000000000000000ef0d72c594b28252bf7ea2bfbf098792430815b181565b61034f7f0000000000000000000000003eb95430fdb99439a86d3c6d7d01c3c56139355681565b6103157f000000000000000000000000000000000000000000000000000000000000000281565b6103157f000000000000000000000000000000000000000000000000000000000000040081565b6103157f000000000000000000000000000000000000000000000000000000000000000081565b610779600881565b60405161031f9190612135565b61034f7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8481565b61037a6107bb366004612072565b610d5c565b61034f7f000000000000000000000000523da3a8961e4dd4f6206dbf7e6c749f51796bb381565b61037a6107f5366004611fd4565b610e49565b61034f7f000000000000000000000000000000000000000000000000000000000000000081565b61037a61082f366004611fff565b610e98565b6103157f000000000000000000000000000000000000000000000000000000000000000881565b61034f7f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e81565b60008061088d610eda565b6108a560018535811090602087013511600080610fa8565b909590945092505050565b6000806108bb610eda565b60006108c5611037565b905060006108d2866110c0565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa15801561091e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109429190612173565b905087811161095a57600080945094505050506109a5565b87900360006b033b2e3c9fd0803ce8000000610976888461218c565b61098091906121b1565b905061099b886109918a8585611183565b60018c1115611205565b9096509450505050505b935093915050565b6000806109b8610eda565b6109e47f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e60001961126f565b6109f8856109f286600f0b90565b8561130e565b90925090506109a57f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e600161126f565b600080610a33610eda565b6000610a3d611037565b90506000610a4a886110c0565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610a96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190612173565b9050868111610ad25760008094509450505050610b1f565b86900360006b033b2e3c9fd0803ce8000000610aee888461218c565b610af891906121b1565b9050610b158a8a610b0b8d8d8787611327565b60018c1115611427565b9096509450505050505b94509492505050565b600080610b33610eda565b610b51610b4087600f0b90565b610b4a87600f0b90565b8686611477565b9150915094509492505050565b600080610b69610eda565b610b7f84610b78868887611183565b6000611205565b90969095509350505050565b600080610b96610eda565b610bc27f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e60001961126f565b610bca611492565b9092509050610bfa7f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e600161126f565b9250929050565b600080610c0c610eda565b610b5186868686611477565b600080610c23610eda565b610b5186868686611565565b600080610c3a610eda565b610c667f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e60001961126f565b6109f8848685611580565b600080610c7c610eda565b610b51610c8987600f0b90565b610c9387600f0b90565b8686611565565b6000806000610ca98486611684565b91509150600080610cba848461175d565b91509150818015610ccc575060008151115b15610cf05780806020019051810190610ce59190612173565b945050505050610d56565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f63616c635f746f6b656e5f616d6f756e74207265766572746564000000000000604482015260640160405180910390fd5b92915050565b600080610d67610eda565b6000610d71611037565b90506000610d7e88611874565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610dca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dee9190612173565b9050868111610e065760008094509450505050610b1f565b86900360006b033b2e3c9fd0803ce8000000610e22888461218c565b610e2c91906121b1565b9050610b158a8a610e3f8d8d8787611932565b60018c1115611a32565b600080610e54610eda565b610e807f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e60001961126f565b610bca60018535811090602087013511600080611a75565b600080610ea3610eda565b610ecf7f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e60001961126f565b6109f885858561130e565b7f0000000000000000000000003eb95430fdb99439a86d3c6d7d01c3c5613935566001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5c91906121d3565b6001600160a01b0316336001600160a01b031614610fa6576040517f0c1d6a3f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600080610fba86868686600019611b75565b610ffa6000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c3c92505050565b50611009868686866001611b75565b507f000000000000000000000000000000000000000000000000000000000000040095600095509350505050565b60007f0000000000000000000000003eb95430fdb99439a86d3c6d7d01c3c5613935566001600160a01b03166334878f546040518163ffffffff1660e01b8152600401602060405180830381865afa158015611097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bb91906121d3565b905090565b6000816000036110f157507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2919050565b8160010361112057507f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84919050565b8160020361114f57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361117e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b919050565b606061118d611fa5565b838186600281106111a0576111a061215d565b60200201526040516111b8908290859060240161222c565b60408051601f198184030181529190526020810180516001600160e01b03167f0b4c7e4d000000000000000000000000000000000000000000000000000000001790529150509392505050565b60008061121c611214866110c0565b60001961126f565b61122584611c3c565b50611239611232866110c0565b600161126f565b7f000000000000000000000000000000000000000000000000000000000000040083611266576000610b7f565b610b7f86611ceb565b6040517ffa30b30f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390527f0000000000000000000000003eb95430fdb99439a86d3c6d7d01c3c561393556169063fa30b30f90604401600060405180830381600087803b1580156112f257600080fd5b505af1158015611306573d6000803e3d6000fd5b505050505050565b600080610b7f84611320868887611da9565b6000611e9a565b60607f00000000000000000000000000000000000000000000000000000000000000006113b8576040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f3df021240000000000000000000000000000000000000000000000000000000017905261141e565b6040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f5b41b908000000000000000000000000000000000000000000000000000000001790525b95945050505050565b600080611436611214876110c0565b61143f84611c3c565b5061144c611232876110c0565b61145585611ceb565b8361146157600061146a565b61146a87611ceb565b9097909650945050505050565b60008061146a868661148b89898989611327565b6000611427565b6000806114d56000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c3c92505050565b5050507f00000000000000000000000000000000000000000000000000000000000000027f0000000000000000000000000000000000000000000000000000000000000008177f0000000000000000000000000000000000000000000000000000000000000000177f00000000000000000000000000000000000000000000000000000000000000001790600090565b60008061146a868661157989898989611932565b6000611a32565b600080600061158d611037565b6040516370a0823160e01b81526001600160a01b0380831660048301529192506000917f00000000000000000000000006325440d014e39736583c165c2963ba99faf14e16906370a0823190602401602060405180830381865afa1580156115f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161d9190612173565b9050858111611634576000809350935050506109a5565b85900360006b033b2e3c9fd0803ce8000000611650878461218c565b61165a91906121b1565b90506116758861166b8a8585611da9565b60018a1115611e9a565b90999098509650505050505050565b60608061168f611fa5565b838186600281106116a2576116a261215d565b60200201526040516116bb908290600190602401612247565b60408051601f198184030181529181526020820180516001600160e01b03167fed8e84f3000000000000000000000000000000000000000000000000000000001790525161170d908390602401612264565b60408051601f198184030181529190526020810180516001600160e01b03167f8d8ea727000000000000000000000000000000000000000000000000000000001790529093509150509250929050565b600060607f000000000000000000000000ef0d72c594b28252bf7ea2bfbf098792430815b16001600160a01b0316846040516117999190612296565b600060405180830381855afa9150503d80600081146117d4576040519150601f19603f3d011682016040523d82523d6000602084013e6117d9565b606091505b5090925090508115806117eb57508051155b15610bfa577f000000000000000000000000ef0d72c594b28252bf7ea2bfbf098792430815b16001600160a01b0316836040516118289190612296565b600060405180830381855afa9150503d8060008114611863576040519150601f19603f3d011682016040523d82523d6000602084013e611868565b606091505b50909590945092505050565b6000816000036118a557507f0000000000000000000000000000000000000000000000000000000000000000919050565b816001036118d457507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160020361190357507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361117e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b60607f00000000000000000000000000000000000000000000000000000000000000006119c3576040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167fa6417ed60000000000000000000000000000000000000000000000000000000017905261141e565b6040516024810186905260448101859052606481018490526084810183905260a40160408051601f198184030181529190526020810180516001600160e01b03167f65b2489b000000000000000000000000000000000000000000000000000000001790529050949350505050565b600080611a4161121487611874565b611a4a84611c3c565b50611a5761123287611874565b611a6085611ee7565b83611a6c57600061146a565b61146a87611ee7565b600080611ab86000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c3c92505050565b508515611ae5577f0000000000000000000000000000000000000000000000000000000000000002821791505b8415611b11577f0000000000000000000000000000000000000000000000000000000000000008821791505b8315611b3d577f0000000000000000000000000000000000000000000000000000000000000000821791505b8215611b69577f0000000000000000000000000000000000000000000000000000000000000000821791505b50946000945092505050565b8415611ba557611ba57f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28261126f565b8315611bd557611bd57f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe848261126f565b8215611c0557611c057f00000000000000000000000000000000000000000000000000000000000000008261126f565b8115611c3557611c357f00000000000000000000000000000000000000000000000000000000000000008261126f565b5050505050565b6040517f09c5eabe0000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f0000000000000000000000003eb95430fdb99439a86d3c6d7d01c3c56139355616906309c5eabe90611ca49085906004016122b2565b6000604051808303816000875af1158015611cc3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d5691908101906122fb565b600081600003611d1c57507f0000000000000000000000000000000000000000000000000000000000000002919050565b81600103611d4b57507f0000000000000000000000000000000000000000000000000000000000000008919050565b81600203611d7a57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361117e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b60607f0000000000000000000000000000000000000000000000000000000000000000611e335760405160248101849052604481018590526064810183905260840160408051601f198184030181529190526020810180516001600160e01b03167f1a4d01d200000000000000000000000000000000000000000000000000000000179052611e92565b60405160248101849052604481018590526064810183905260840160408051601f198184030181529190526020810180516001600160e01b03167ff1dc3cc9000000000000000000000000000000000000000000000000000000001790525b949350505050565b600080611ea684611c3c565b50611eb085611ceb565b83611ebc576000610b7f565b957f000000000000000000000000000000000000000000000000000000000000040095509350505050565b600081600003611f1857507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600103611f4757507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600203611f7657507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361117e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b60405180604001604052806002906020820280368337509192915050565b8060408101831015610d5657600080fd5b60008060608385031215611fe757600080fd5b611ff18484611fc3565b946040939093013593505050565b60008060006060848603121561201457600080fd5b505081359360208301359350604090920135919050565b8035600f81900b811461117e57600080fd5b60008060006060848603121561205257600080fd5b833592506120626020850161202b565b9150604084013590509250925092565b6000806000806080858703121561208857600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080608085870312156120ba57600080fd5b6120c38561202b565b93506120d16020860161202b565b93969395505050506040820135916060013590565b600080606083850312156120f957600080fd5b8235915061210a8460208501611fc3565b90509250929050565b6000806040838503121561212657600080fd5b50508035926020909101359150565b602081016016831061215757634e487b7160e01b600052602160045260246000fd5b91905290565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561218557600080fd5b5051919050565b8082028115828204841417610d5657634e487b7160e01b600052601160045260246000fd5b6000826121ce57634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156121e557600080fd5b81516001600160a01b03811681146121fc57600080fd5b9392505050565b8060005b6002811015612226578151845260209384019390910190600101612207565b50505050565b6060810161223a8285612203565b8260408301529392505050565b606081016122558285612203565b82151560408301529392505050565b60408101610d568284612203565b60005b8381101561228d578181015183820152602001612275565b50506000910152565b600082516122a8818460208701612272565b9190910192915050565b60208152600082518060208401526122d1816040850160208701612272565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561230d57600080fd5b815167ffffffffffffffff8082111561232557600080fd5b818401915084601f83011261233957600080fd5b81518181111561234b5761234b6122e5565b604051601f8201601f19908116603f01168101908382118183101715612373576123736122e5565b8160405282815287602084870101111561238c57600080fd5b61239d836020830160208801612272565b97965050505050505056fea2646970667358221220e435a5aa2222f02e8b54ce20ad74ff44175c869fcacde6a7772f087a66034c1a64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003eb95430fdb99439a86d3c6d7d01c3c561393556000000000000000000000000ef0d72c594b28252bf7ea2bfbf098792430815b100000000000000000000000006325440d014e39736583c165c2963ba99faf14e
-----Decoded View---------------
Arg [0] : _creditManager (address): 0x3EB95430FdB99439A86d3c6D7D01C3c561393556
Arg [1] : _curveStETHPoolGateway (address): 0xEf0D72C594b28252BF7Ea2bfbF098792430815b1
Arg [2] : _lp_token (address): 0x06325440D014e39736583c165C2963BA99fAf14E
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000003eb95430fdb99439a86d3c6d7d01c3c561393556
Arg [1] : 000000000000000000000000ef0d72c594b28252bf7ea2bfbf098792430815b1
Arg [2] : 00000000000000000000000006325440d014e39736583c165c2963ba99faf14e
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.