MON Price: $0.018991 (+1.04%)

Contract

0xC379FfBb25939ba323E82d44b1446b147E5a41D3

Overview

MON Balance

Monad Chain LogoMonad Chain LogoMonad Chain Logo0 MON

MON Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
377281822025-11-24 17:10:1463 days ago1764004214  Contract Creation0 MON
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CurveStableLPPriceFeed

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 1000 runs

Other Settings:
shanghai EvmVersion
// SPDX-License-Identifier: GPL-2.0-or-later
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;

import {LPPriceFeed} from "../LPPriceFeed.sol";
import {PriceFeedParams} from "../PriceFeedParams.sol";
import {ICurvePool} from "../../interfaces/curve/ICurvePool.sol";
import {WAD} from "@gearbox-protocol/core-v3/contracts/libraries/Constants.sol";

/// @title Curve stable LP price feed
/// @dev For stableswap pools, aggregate is simply the minimum of underlying tokens prices
/// @dev Older pools may be decoupled from their LP token, so constructor accepts both token and pool
contract CurveStableLPPriceFeed is LPPriceFeed {
    uint256 public constant override version = 3_11;
    bytes32 public constant override contractType = "PRICE_FEED::CURVE_STABLE";

    uint16 public immutable nCoins;

    address public immutable priceFeed0;
    uint32 public immutable stalenessPeriod0;
    bool public immutable skipCheck0;

    address public immutable priceFeed1;
    uint32 public immutable stalenessPeriod1;
    bool public immutable skipCheck1;

    address public immutable priceFeed2;
    uint32 public immutable stalenessPeriod2;
    bool public immutable skipCheck2;

    address public immutable priceFeed3;
    uint32 public immutable stalenessPeriod3;
    bool public immutable skipCheck3;

    constructor(
        address _owner,
        uint256 _lowerBound,
        address _token,
        address _pool,
        PriceFeedParams[4] memory priceFeeds
    )
        LPPriceFeed(_owner, _token, _pool) // U:[CRV-S-1]
        nonZeroAddress(priceFeeds[0].priceFeed) // U:[CRV-S-2]
        nonZeroAddress(priceFeeds[1].priceFeed) // U:[CRV-S-2]
    {
        priceFeed0 = priceFeeds[0].priceFeed;
        priceFeed1 = priceFeeds[1].priceFeed;
        priceFeed2 = priceFeeds[2].priceFeed;
        priceFeed3 = priceFeeds[3].priceFeed;

        stalenessPeriod0 = priceFeeds[0].stalenessPeriod;
        stalenessPeriod1 = priceFeeds[1].stalenessPeriod;
        stalenessPeriod2 = priceFeeds[2].stalenessPeriod;
        stalenessPeriod3 = priceFeeds[3].stalenessPeriod;

        nCoins = priceFeed2 == address(0) ? 2 : (priceFeed3 == address(0) ? 3 : 4); // U:[CRV-S-2]

        skipCheck0 = _validatePriceFeedMetadata(priceFeed0, stalenessPeriod0);
        skipCheck1 = _validatePriceFeedMetadata(priceFeed1, stalenessPeriod1);
        skipCheck2 = nCoins > 2 ? _validatePriceFeedMetadata(priceFeed2, stalenessPeriod2) : false;
        skipCheck3 = nCoins > 3 ? _validatePriceFeedMetadata(priceFeed3, stalenessPeriod3) : false;

        _setLimiter(_lowerBound); // U:[CRV-S-1]
    }

    function getAggregatePriceAndTimestamp() public view override returns (int256 answer, uint256 updatedAt) {
        (answer, updatedAt) = _getValidatedPrice(priceFeed0, stalenessPeriod0, skipCheck0); // U:[CRV-S-2]

        (int256 answer2, uint256 updatedAt2) = _getValidatedPrice(priceFeed1, stalenessPeriod1, skipCheck1);
        (answer, updatedAt) = _agg(answer, updatedAt, answer2, updatedAt2); // U:[CRV-S-2]

        if (nCoins > 2) {
            (answer2, updatedAt2) = _getValidatedPrice(priceFeed2, stalenessPeriod2, skipCheck2);
            (answer, updatedAt) = _agg(answer, updatedAt, answer2, updatedAt2); // U:[CRV-S-2]

            if (nCoins > 3) {
                (answer2, updatedAt2) = _getValidatedPrice(priceFeed3, stalenessPeriod3, skipCheck3);
                (answer, updatedAt) = _agg(answer, updatedAt, answer2, updatedAt2); // U:[CRV-S-2]
            }
        }
    }

    function getLPExchangeRate() public view override returns (uint256) {
        return uint256(ICurvePool(lpContract).get_virtual_price()); // U:[CRV-S-1]
    }

    function getScale() public pure override returns (uint256) {
        return WAD; // U:[CRV-S-1]
    }

    function _agg(int256 answer1, uint256 updatedAt1, int256 answer2, uint256 updatedAt2)
        internal
        view
        returns (int256 answer, uint256 updatedAt)
    {
        return (answer1 < answer2 ? answer1 : answer2, updatedAt1 < updatedAt2 ? updatedAt1 : updatedAt2);
    }
}

// SPDX-License-Identifier: GPL-2.0-or-later
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

import {PERCENTAGE_FACTOR} from "@gearbox-protocol/core-v3/contracts/libraries/Constants.sol";
import {PriceFeedValidationTrait} from "../traits/PriceFeedValidationTrait.sol";
import {SanityCheckTrait} from "@gearbox-protocol/core-v3/contracts/traits/SanityCheckTrait.sol";

import {ILPPriceFeed} from "../interfaces/ILPPriceFeed.sol";

/// @dev Window size in bps, used to compute upper bound given lower bound
uint256 constant WINDOW_SIZE = 200;

/// @dev Buffer size in bps, used to compute new lower bound given current exchange rate
uint256 constant BUFFER_SIZE = 100;

/// @title LP price feed
/// @notice Abstract contract for LP token price feeds.
///         It is assumed that the price of an LP token is the product of its exchange rate and some aggregate function
///         of underlying tokens prices. This contract simplifies creation of such price feeds and provides standard
///         validation of the LP token exchange rate that protects against price manipulation.
abstract contract LPPriceFeed is ILPPriceFeed, Ownable, SanityCheckTrait, PriceFeedValidationTrait {
    /// @notice Answer precision (always 8 decimals for USD price feeds)
    uint8 public constant override decimals = 8; // U:[LPPF-2]

    /// @notice Indicates that price oracle can skip checks for this price feed's answers
    bool public constant override skipPriceCheck = true; // U:[LPPF-2]

    /// @notice LP token for which the prices are computed
    address public immutable override lpToken;

    /// @notice LP contract (can be different from LP token)
    address public immutable override lpContract;

    /// @notice Lower bound for the LP token exchange rate
    uint256 public override lowerBound;

    /// @notice Constructor
    /// @param _owner Owner of the price feed that can update exchange rate bounds
    /// @param _lpToken  LP token for which the prices are computed
    /// @param _lpContract LP contract (can be different from LP token)
    /// @dev Derived price feeds must call `_setLimiter` in their constructor after
    ///      initializing all state variables needed for exchange rate calculation
    constructor(address _owner, address _lpToken, address _lpContract)
        nonZeroAddress(_lpToken) // U:[LPPF-1]
        nonZeroAddress(_lpContract) // U:[LPPF-1]
    {
        transferOwnership(_owner); // U:[LPPF-1]
        lpToken = _lpToken; // U:[LPPF-1]
        lpContract = _lpContract; // U:[LPPF-1]
    }

    /// @notice Price feed description
    function description() external view override returns (string memory) {
        return string.concat(ERC20(lpToken).symbol(), " / USD LP price feed"); // U:[LPPF-2]
    }

    /// @notice Serialized price feed parameters
    function serialize() public view virtual override returns (bytes memory) {
        uint256 lb = lowerBound;
        return abi.encode(lpToken, lpContract, lb, _calcUpperBound(lb));
    }

    /// @notice Returns USD price of the LP token with 8 decimals
    function latestRoundData() external view override returns (uint80, int256, uint256, uint256, uint80) {
        uint256 exchangeRate = getLPExchangeRate();
        uint256 lb = lowerBound;
        if (exchangeRate < lb) revert ExchangeRateOutOfBoundsException(); // U:[LPPF-3]

        uint256 ub = _calcUpperBound(lb);
        if (exchangeRate > ub) exchangeRate = ub; // U:[LPPF-3]

        (int256 answer, uint256 updatedAt) = getAggregatePriceAndTimestamp(); // U:[LPPF-3]
        answer = int256((exchangeRate * uint256(answer)) / getScale()); // U:[LPPF-3]
        return (0, answer, 0, updatedAt, 0);
    }

    /// @notice Returns aggregate price of underlying tokens with 8 decimals
    /// @dev Exists for backward compatability
    function getAggregatePrice() external view override returns (int256 answer) {
        (answer,) = getAggregatePriceAndTimestamp();
    }

    /// @notice Upper bound for the LP token exchange rate
    function upperBound() external view returns (uint256) {
        return _calcUpperBound(lowerBound); // U:[LPPF-4]
    }

    /// @notice Returns aggregate price of underlying tokens with 8 decimals
    /// @dev Must be implemented by derived price feeds
    /// @dev `answer` must be positive
    /// @dev `updatedAt` must be the earliest of update timestamps of underlying feeds
    function getAggregatePriceAndTimestamp() public view virtual override returns (int256 answer, uint256 updatedAt);

    /// @notice Returns LP token exchange rate
    /// @dev Must be implemented by derived price feeds
    function getLPExchangeRate() public view virtual override returns (uint256 exchangeRate);

    /// @notice Returns LP token exchange rate scale
    /// @dev Must be implemented by derived price feeds
    function getScale() public view virtual override returns (uint256 scale);

    // ------------- //
    // CONFIGURATION //
    // ------------- //

    /// @notice Sets new lower and upper bounds for the LP token exchange rate
    /// @param newLowerBound New lower bound value
    function setLimiter(uint256 newLowerBound)
        external
        override
        onlyOwner // U:[LPPF-6]
    {
        _setLimiter(newLowerBound); // U:[LPPF-6]
    }

    // --------- //
    // INTERNALS //
    // --------- //

    /// @dev `setLimiter` implementation: sets new bounds, ensures that current value is within them, emits event
    function _setLimiter(uint256 lower) internal {
        if (lower == 0) revert LowerBoundCantBeZeroException(); // U:[LPPF-6]
        uint256 upper = _ensureValueInBounds(getLPExchangeRate(), lower); // U:[LPPF-6]
        lowerBound = lower; // U:[LPPF-6]
        emit SetBounds(lower, upper); // U:[LPPF-6]
    }

    /// @dev Computes upper bound as `_lowerBound * (1 + WINDOW_SIZE)`
    function _calcUpperBound(uint256 _lowerBound) internal pure returns (uint256) {
        return _lowerBound * (PERCENTAGE_FACTOR + WINDOW_SIZE) / PERCENTAGE_FACTOR; // U:[LPPF-4]
    }

    /// @dev Computes lower bound as `exchangeRate * (1 - BUFFER_SIZE)`
    function _calcLowerBound(uint256 exchangeRate) internal pure returns (uint256) {
        return exchangeRate * (PERCENTAGE_FACTOR - BUFFER_SIZE) / PERCENTAGE_FACTOR; // U:[LPPF-6]
    }

    /// @dev Ensures that value is in bounds, returns upper bound computed from lower bound
    function _ensureValueInBounds(uint256 value, uint256 lower) internal pure returns (uint256 upper) {
        if (value < lower) revert ExchangeRateOutOfBoundsException();
        upper = _calcUpperBound(lower);
        if (value > upper) revert ExchangeRateOutOfBoundsException();
    }
}

// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;

import {IPriceFeed} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IPriceFeed.sol";

/// @title LP price feed interface
interface ILPPriceFeed is IPriceFeed {
    // ------ //
    // EVENTS //
    // ------ //

    /// @notice Emitted when new LP token exchange rate bounds are set
    event SetBounds(uint256 lowerBound, uint256 upperBound);

    // ------ //
    // ERRORS //
    // ------ //

    /// @notice Thrown when trying to set exchange rate lower bound to zero
    error LowerBoundCantBeZeroException();

    /// @notice Thrown when exchange rate falls below lower bound during price calculation
    ///         or new boudns don't contain exchange rate during bounds update
    error ExchangeRateOutOfBoundsException();

    // ------- //
    // GETTERS //
    // ------- //

    function lpToken() external view returns (address);
    function lpContract() external view returns (address);

    function lowerBound() external view returns (uint256);
    function upperBound() external view returns (uint256);

    function getAggregatePriceAndTimestamp() external view returns (int256 answer, uint256 updatedAt);
    function getAggregatePrice() external view returns (int256 answer);
    function getLPExchangeRate() external view returns (uint256 exchangeRate);
    function getScale() external view returns (uint256 scale);

    // ------------- //
    // CONFIGURATION //
    // ------------- //

    function setLimiter(uint256 newLowerBound) external;
}

File 4 of 18 : PriceFeedParams.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;

struct PriceFeedParams {
    address priceFeed;
    uint32 stalenessPeriod;
}

// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;

interface ICurvePool {
    function get_virtual_price() external view returns (uint256);

    function price_oracle() external view returns (uint256);

    function price_oracle(uint256 index) external view returns (uint256);
}

// SPDX-License-Identifier: GPL-2.0-or-later
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;

import {
    AddressIsNotContractException,
    IncorrectParameterException,
    IncorrectPriceException,
    IncorrectPriceFeedException,
    StalePriceException
} from "@gearbox-protocol/core-v3/contracts/interfaces/IExceptions.sol";
import {IPriceFeed} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IPriceFeed.sol";
import {OptionalCall} from "@gearbox-protocol/core-v3/contracts/libraries/OptionalCall.sol";

/// @title Price feed validation trait
abstract contract PriceFeedValidationTrait {
    /// @dev Ensures that price feed's answer is positive and not stale.
    ///      If `skipCheck` is true, only checks that price is non-negative to allow zero price feed to be used.
    function _checkAnswer(int256 price, uint256 updatedAt, uint32 stalenessPeriod, bool skipCheck) internal view {
        if (price < 0 || !skipCheck && price == 0) revert IncorrectPriceException();
        if (!skipCheck && block.timestamp >= updatedAt + stalenessPeriod) revert StalePriceException();
    }

    /// @dev Validates that `priceFeed` is a contract that adheres to Chainlink interface
    /// @dev Reverts if `priceFeed` does not have exactly 8 decimals
    /// @dev Reverts if `stalenessPeriod` is inconsistent with `priceFeed`'s `skipPriceCheck()` flag
    ///      (which is considered to be false if `priceFeed` does not have this function)
    function _validatePriceFeedMetadata(address priceFeed, uint32 stalenessPeriod)
        internal
        view
        returns (bool skipCheck)
    {
        if (priceFeed.code.length == 0) revert AddressIsNotContractException(priceFeed);

        try IPriceFeed(priceFeed).decimals() returns (uint8 _decimals) {
            if (_decimals != 8) revert IncorrectPriceFeedException();
        } catch {
            revert IncorrectPriceFeedException();
        }

        // NOTE: Some external price feeds without `skipPriceCheck` may have a fallback function that changes state,
        // which can cause a `THROW` that burns all gas, or does not change state and instead returns empty data.
        // To handle these cases, we use a special call construction with a strict gas limit.
        (bool success, bytes memory returnData) = OptionalCall.staticCallOptionalSafe({
            target: priceFeed,
            data: abi.encodeWithSelector(IPriceFeed.skipPriceCheck.selector),
            gasAllowance: 10_000
        });
        if (success) skipCheck = abi.decode(returnData, (bool));
        if (skipCheck && stalenessPeriod != 0 || !skipCheck && stalenessPeriod == 0) {
            revert IncorrectParameterException();
        }
    }

    /// @dev Returns answer from a price feed with optional sanity and staleness checks
    function _getValidatedPrice(address priceFeed, uint32 stalenessPeriod, bool skipCheck)
        internal
        view
        returns (int256 answer, uint256 updatedAt)
    {
        (, answer,, updatedAt,) = IPriceFeed(priceFeed).latestRoundData();
        _checkAnswer(answer, updatedAt, stalenessPeriod, skipCheck);
    }
}

File 7 of 18 : Constants.sol
// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

bytes32 constant AP_GEAR_TOKEN = "GLOBAL::GEAR_TOKEN";
bytes32 constant AP_INSTANCE_MANAGER_PROXY = "INSTANCE_MANAGER_PROXY";
bytes32 constant AP_CROSS_CHAIN_GOVERNANCE_PROXY = "CROSS_CHAIN_GOVERNANCE_PROXY";
bytes32 constant AP_PRICE_FEED_STORE = "PRICE_FEED_STORE";
uint256 constant NO_VERSION_CONTROL = 0;

uint256 constant WAD = 1e18;
uint256 constant RAY = 1e27;
uint16 constant PERCENTAGE_FACTOR = 1e4;

uint256 constant SECONDS_PER_YEAR = 365 days;
uint256 constant EPOCH_LENGTH = 7 days;
uint256 constant FIRST_EPOCH_TIMESTAMP = 1702900800;
uint256 constant EPOCHS_TO_WITHDRAW = 4;

uint8 constant MAX_SANE_ENABLED_TOKENS = 20;
uint256 constant MAX_SANE_EPOCH_LENGTH = 28 days;
uint256 constant MAX_SANE_ACTIVE_BOTS = 5;

uint8 constant MAX_WITHDRAW_FEE = 100;

uint8 constant DEFAULT_LIMIT_PER_BLOCK_MULTIPLIER = 2;

uint8 constant BOT_PERMISSIONS_SET_FLAG = 1;

uint256 constant UNDERLYING_TOKEN_MASK = 1;

address constant INACTIVE_CREDIT_ACCOUNT_ADDRESS = address(1);

File 8 of 18 : IExceptions.sol
// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
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 attempting to connect a gauge to an incompatible pool quota keeper
error IncompatibleGaugeException();

/// @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 if new credit configurator's set of allowed adapters differs from the current one
error IncorrectAdaptersSetException();

/// @notice Thrown if attempting to schedule a token's LT ramping that is too short in duration
error RampDurationTooShortException();

/// @notice Thrown if attempting to set liquidation fees such that the sum of premium and fee changes
error InconsistentLiquidationFeesException();

/// @notice Thrown if attempting to set expired liquidation fees such that the sum of premium and fee changes
error InconsistentExpiredLiquidationFeesException();

// ------------- //
// 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(bytes4 selector);

/// @notice Thrown if a liquidator tries to liquidate an account with a health factor above 1
error CreditAccountNotLiquidatableException();

/// @notice Thrown if a liquidator tries to liquidate an account with loss but violates the loss policy
error CreditAccountNotLiquidatableWithLossException();

/// @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(address token);

/// @notice Thrown when trying to perform an action that is forbidden when credit account has enabled forbidden tokens
error ForbiddenTokensException(uint256 forbiddenTokensMask);

/// @notice Thrown when forbidden token quota is increased during the multicall
error ForbiddenTokenQuotaIncreasedException(address token);

/// @notice Thrown when enabled forbidden token balance is increased during the multicall
error ForbiddenTokenBalanceIncreasedException(address token);

/// @notice Thrown when the remaining token balance is increased during the liquidation
error RemainingTokenBalanceIncreasedException(address token);

/// @notice Thrown if `botMulticall` is called by an address that is not approved by account owner or is forbidden
error NotApprovedBotException(address bot);

/// @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(uint256 permissions);

/// @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(uint256 mask);

/// @notice Thrown when trying to seize underlying token during partial liquidation
error UnderlyingIsNotLiquidatableException();

/// @notice Thrown when amount of collateral seized during partial liquidation is less than required
error SeizedLessThanRequiredException(uint256 seizedAmount);

// ------ //
// 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 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();

// -------- //
// BOT LIST //
// -------- //

/// @notice Thrown when attempting to set non-zero permissions for a forbidden bot
error InvalidBotException();

/// @notice Thrown when attempting to set permissions for a bot that don't meet its requirements
error IncorrectBotPermissionsException();

/// @notice Thrown when attempting to set non-zero permissions for too many bots
error TooManyActiveBotsException();

// --------------- //
// 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 trying to apply an on-demand price update to a non-updatable price feed
error PriceFeedIsNotUpdatableException();

/// @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: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

/// @title Optional call library
/// @notice Implements a function that calls a contract that may not have an expected selector.
///         Handles the case where the contract has a fallback function that may or may not change state.
library OptionalCall {
    function staticCallOptionalSafe(address target, bytes memory data, uint256 gasAllowance)
        internal
        view
        returns (bool, bytes memory)
    {
        (bool success, bytes memory returnData) = target.staticcall{gas: gasAllowance}(data);
        return returnData.length > 0 ? (success, returnData) : (false, returnData);
    }
}

File 10 of 18 : SanityCheckTrait.sol
// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
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();
    }
}

// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

/// @title Version interface
/// @notice Defines contract version and type
interface IVersion {
    /// @notice Contract version
    function version() external view returns (uint256);

    /// @notice Contract type
    function contractType() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

import {IVersion} from "./IVersion.sol";
import {IStateSerializer} from "./IStateSerializer.sol";

/// @title Price feed interface
/// @notice Interface for Chainlink-like price feeds that can be plugged into Gearbox's price oracle
/// @dev Price feeds must have type `PRICE_FEED::{POSTFIX}`
interface IPriceFeed is IVersion, IStateSerializer {
    /// @notice Whether price feed implements its own staleness and sanity checks
    function skipPriceCheck() external view returns (bool);

    /// @notice Scale decimals of price feed answers
    function decimals() external view returns (uint8);

    /// @notice Price feed description
    function description() external view returns (string memory);

    /// @notice Price feed answer in standard Chainlink format, only `answer` and `updatedAt` fields are used
    function latestRoundData() external view returns (uint80, int256 answer, uint256, uint256 updatedAt, uint80);
}

/// @title Updatable price feed interface
/// @notice Extended version of `IPriceFeed` for pull oracles that allow on-demand updates
interface IUpdatablePriceFeed is IPriceFeed {
    /// @notice Emitted when price is updated
    event UpdatePrice(uint256 price);

    /// @notice Whether price feed is updatable
    function updatable() external view returns (bool);

    /// @notice Performs on-demand price update
    function updatePrice(bytes calldata data) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 14 of 18 : IStateSerializer.sol
// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

/// @title State serializer interface
/// @notice Generic interface for a contract that can serialize its state into a bytes array
interface IStateSerializer {
    /// @notice Serializes the state of the contract into a bytes array `serializedData`
    function serialize() external view returns (bytes memory serializedData);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(address from, address to, uint256 amount) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

Settings
{
  "remappings": [
    "@1inch/=lib/@gearbox-protocol/core-v3/lib/@1inch/",
    "@gearbox-protocol/=lib/@gearbox-protocol/",
    "@openzeppelin/=lib/@gearbox-protocol/core-v3/lib/@openzeppelin/",
    "@redstone-finance/=node_modules/@redstone-finance/",
    "@solady/=lib/@solady/src/",
    "ds-test/=lib/@gearbox-protocol/sdk-gov/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/@gearbox-protocol/core-v3/lib/@openzeppelin/lib/erc4626-tests/",
    "forge-std/=lib/@gearbox-protocol/core-v3/lib/forge-std/src/"
  ],
  "optimizer": {
    "runs": 1000,
    "enabled": true
  },
  "metadata": {
    "bytecodeHash": "none",
    "useLiteralContent": true
  },
  "evmVersion": "shanghai",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_lowerBound","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_pool","type":"address"},{"components":[{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint32","name":"stalenessPeriod","type":"uint32"}],"internalType":"struct PriceFeedParams[4]","name":"priceFeeds","type":"tuple[4]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"AddressIsNotContractException","type":"error"},{"inputs":[],"name":"ExchangeRateOutOfBoundsException","type":"error"},{"inputs":[],"name":"IncorrectParameterException","type":"error"},{"inputs":[],"name":"IncorrectPriceException","type":"error"},{"inputs":[],"name":"IncorrectPriceFeedException","type":"error"},{"inputs":[],"name":"LowerBoundCantBeZeroException","type":"error"},{"inputs":[],"name":"StalePriceException","type":"error"},{"inputs":[],"name":"ZeroAddressException","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lowerBound","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"upperBound","type":"uint256"}],"name":"SetBounds","type":"event"},{"inputs":[],"name":"contractType","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAggregatePrice","outputs":[{"internalType":"int256","name":"answer","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAggregatePriceAndTimestamp","outputs":[{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLPExchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"latestRoundData","outputs":[{"internalType":"uint80","name":"","type":"uint80"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint80","name":"","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lowerBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nCoins","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed3","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"serialize","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newLowerBound","type":"uint256"}],"name":"setLimiter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"skipCheck0","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skipCheck1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skipCheck2","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skipCheck3","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skipPriceCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stalenessPeriod0","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stalenessPeriod1","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stalenessPeriod2","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stalenessPeriod3","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upperBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

61026060405234801562000011575f80fd5b5060405162001b3b38038062001b3b833981016040819052620000349162000749565b8483836200004233620001f0565b816200004e816200023f565b816200005a816200023f565b62000065856200026a565b50506001600160a01b039182166080521660a0525080515162000088816200023f565b60208201515162000099816200023f565b8251516001600160a01b0390811660e05260208085018051518316610140526040860180515184166101a08190526060880180515190951661020052875184015163ffffffff908116610100529251840151831661016052905183015182166101c0529251909101511661022052156200013057610200516001600160a01b0316156200012857600462000133565b600362000133565b60025b60ff1660c05260e051610100516200014c9190620002ea565b1515610120526101405161016051620001669190620002ea565b15156101805260c051600261ffff9091161162000184575f6200019c565b6200019c6101a0516101c051620002ea60201b60201c565b15156101e05260c051600361ffff90911611620001ba575f620001d2565b620001d26102005161022051620002ea60201b60201c565b151561024052620001e3866200047d565b5050505050505062000925565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381166200026757604051635919af9760e11b815260040160405180910390fd5b50565b62000274620004f9565b6001600160a01b038116620002df5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6200026781620001f0565b5f826001600160a01b03163b5f03620003225760405163df4c572d60e01b81526001600160a01b0384166004820152602401620002d6565b826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156200037f575060408051601f3d908101601f191682019092526200037c9181019062000831565b60015b6200039d576040516367a7cd4360e01b815260040160405180910390fd5b8060ff16600814620003c2576040516367a7cd4360e01b815260040160405180910390fd5b506040805160048152602481019091526020810180516001600160e01b0390811663d62ada1160e01b179091525f91829162000405918791612710906200055616565b9150915081156200042957808060200190518101906200042691906200085a565b92505b8280156200043c575063ffffffff841615155b806200045657508215801562000456575063ffffffff8416155b1562000475576040516347fbaa9760e01b815260040160405180910390fd5b505092915050565b805f036200049e5760405163016b011560e21b815260040160405180910390fd5b5f620004b4620004ad620005dd565b8362000648565b600183905560408051848152602081018390529192507f5ab79ffcd89b6380c7fbdd89d02cfe3d9c53c99a85e150c2319075018d1aac5c910160405180910390a15050565b5f546001600160a01b03163314620005545760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620002d6565b565b5f60605f80866001600160a01b031685876040516200057691906200087b565b5f604051808303818686fa925050503d805f8114620005b1576040519150601f19603f3d011682016040523d82523d5f602084013e620005b6565b606091505b50915091505f815111620005cc575f81620005cf565b81815b935093505050935093915050565b5f60a0516001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200061d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620006439190620008a9565b905090565b5f818310156200066b57604051633708d96960e21b815260040160405180910390fd5b6200067682620006a0565b9050808311156200069a57604051633708d96960e21b815260040160405180910390fd5b92915050565b5f612710620006b160c882620008d5565b620006bd9084620008eb565b6200069a919062000905565b80516001600160a01b0381168114620006e0575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b03811182821017156200071e576200071e620006e5565b60405290565b604080519081016001600160401b03811182821017156200071e576200071e620006e5565b5f805f805f61018080878903121562000760575f80fd5b6200076b87620006c9565b9550602080880151955060406200078560408a01620006c9565b95506200079560608a01620006c9565b945089609f8a0112620007a6575f80fd5b620007b0620006f9565b92890192808b851115620007c2575f80fd5b60808b015b858110156200081e5783818e031215620007df575f80fd5b620007e962000724565b620007f482620006c9565b81528582015163ffffffff811681146200080c575f80fd5b818701528352918401918301620007c7565b5080955050505050509295509295909350565b5f6020828403121562000842575f80fd5b815160ff8116811462000853575f80fd5b9392505050565b5f602082840312156200086b575f80fd5b8151801515811462000853575f80fd5b5f82515f5b818110156200089c576020818601810151858301520162000880565b505f920191825250919050565b5f60208284031215620008ba575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156200069a576200069a620008c1565b80820281158282048414176200069a576200069a620008c1565b5f826200092057634e487b7160e01b5f52601260045260245ffd5b500490565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e0516102005161022051610240516110f662000a455f395f8181610345015261094301525f81816104b9015261092201525f81816102c7015261090101525f8181610536015261089501525f8181610507015261087401525f818161055d015261085301525f818161037c01526107e801525f818161028a01526107c701525f818161040a01526107a601525f81816103a3015261077601525f81816101f0015261075501525f818161024b015261073401525f818161047f0152818161082801526108d601525f81816103ca015281816105d401526109c101525f81816102ff0152818161067d01526109a001526110f65ff3fe608060405234801561000f575f80fd5b50600436106101e7575f3560e01c8063a384d6ff11610109578063c42889cf1161009e578063da9274451161006e578063da92744514610531578063e5693f4114610558578063f2fde38b1461057f578063feaf968c14610592575f80fd5b8063c42889cf146104b4578063cb2ef6f7146104db578063d16cc85014610502578063d62ada1114610529575f80fd5b8063bbc8613e116100d9578063bbc8613e14610442578063bc489a651461045f578063bc8018b114610472578063c21ee1621461047a575f80fd5b8063a384d6ff146103fc578063ab0ca0e114610405578063b09ad8a01461042c578063b5cddab814610434575f80fd5b80635fcbd2851161017f5780637ff361ec1161014f5780637ff361ec1461037757806387584f001461039e5780638acee3cf146103c55780638da5cb5b146103ec575f80fd5b80635fcbd285146102fa578063715018a6146103215780637284e4161461032b57806377b1c7d414610340575f80fd5b80633fdc155e116101ba5780633fdc155e146102ac578063427cb6fe146102c2578063515fbcb3146102e957806354fd4d50146102f1575f80fd5b8063178793e8146101eb578063313ce5671461022c578063385aee1b146102465780633e777fd214610285575b5f80fd5b6102127f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020015b60405180910390f35b610234600881565b60405160ff9091168152602001610223565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610223565b6102127f000000000000000000000000000000000000000000000000000000000000000081565b6102b46105d1565b604051908152602001610223565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6102b4610657565b6102b461013781565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b610329610666565b005b610333610679565b6040516102239190610eb9565b6103677f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610223565b6103677f000000000000000000000000000000000000000000000000000000000000000081565b6103677f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b031661026d565b6102b460015481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6102b4610721565b670de0b6b3a76400006102b4565b61044a61072d565b60408051928352602083019190915201610223565b61032961046d366004610ed2565b610984565b610333610998565b6104a17f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610223565b6102127f000000000000000000000000000000000000000000000000000000000000000081565b6102b47f50524943455f464545443a3a43555256455f535441424c45000000000000000081565b6102127f000000000000000000000000000000000000000000000000000000000000000081565b610367600181565b6103677f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61032961058d366004610ee9565b610a2b565b61059a610abd565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a001610223565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa15801561062e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106529190610f0f565b905090565b5f61066061072d565b50919050565b61066e610b51565b6106775f610baa565b565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa1580156106d6573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106fd9190810190610f3a565b60405160200161070d9190610fe2565b604051602081830303815290604052905090565b5f610652600154610c11565b5f8061079a7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610c3a565b90925090505f8061080c7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610c3a565b9150915061081c84848484610cbb565b9094509250600261ffff7f000000000000000000000000000000000000000000000000000000000000000016111561097e576108b97f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610c3a565b90925090506108ca84848484610cbb565b9094509250600361ffff7f000000000000000000000000000000000000000000000000000000000000000016111561097e576109677f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610c3a565b909250905061097884848484610cbb565b90945092505b50509091565b61098c610b51565b61099581610ce8565b50565b6001546060907f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000826109ea81610c11565b604080516001600160a01b03958616602082015294909316928401929092526060830152608082015260a00160405160208183030381529060405291505090565b610a33610b51565b6001600160a01b038116610ab45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61099581610baa565b5f805f805f80610acb6105d1565b60015490915080821015610af257604051633708d96960e21b815260040160405180910390fd5b5f610afc82610c11565b905080831115610b0a578092505b5f80610b1461072d565b91509150610b27670de0b6b3a764000090565b610b318387611036565b610b3b919061104d565b5f9b909a508b9950909750889650945050505050565b5f546001600160a01b031633146106775760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aab565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f612710610c2060c88261106c565b610c2a9084611036565b610c34919061104d565b92915050565b5f80846001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610c78573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c9c919061109d565b50919450909250610cb39150839050828686610d78565b935093915050565b5f80838612610cca5783610ccc565b855b838610610cd95783610cdb565b855b9150915094509492505050565b805f03610d21576040517f05ac045400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610d33610d2d6105d1565b83610e1e565b600183905560408051848152602081018390529192507f5ab79ffcd89b6380c7fbdd89d02cfe3d9c53c99a85e150c2319075018d1aac5c910160405180910390a15050565b5f841280610d8d575080158015610d8d575083155b15610dc4576040517f53b798e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80158015610de15750610ddd63ffffffff83168461106c565b4210155b15610e18576040517f16dd0ffb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b5f81831015610e4057604051633708d96960e21b815260040160405180910390fd5b610e4982610c11565b905080831115610c3457604051633708d96960e21b815260040160405180910390fd5b5f5b83811015610e86578181015183820152602001610e6e565b50505f910152565b5f8151808452610ea5816020860160208601610e6c565b601f01601f19169290920160200192915050565b602081525f610ecb6020830184610e8e565b9392505050565b5f60208284031215610ee2575f80fd5b5035919050565b5f60208284031215610ef9575f80fd5b81356001600160a01b0381168114610ecb575f80fd5b5f60208284031215610f1f575f80fd5b5051919050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610f4a575f80fd5b815167ffffffffffffffff80821115610f61575f80fd5b818401915084601f830112610f74575f80fd5b815181811115610f8657610f86610f26565b604051601f8201601f19908116603f01168101908382118183101715610fae57610fae610f26565b81604052828152876020848701011115610fc6575f80fd5b610fd7836020830160208801610e6c565b979650505050505050565b5f8251610ff3818460208701610e6c565b7f202f20555344204c502070726963652066656564000000000000000000000000920191825250601401919050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610c3457610c34611022565b5f8261106757634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610c3457610c34611022565b805169ffffffffffffffffffff81168114611098575f80fd5b919050565b5f805f805f60a086880312156110b1575f80fd5b6110ba8661107f565b94506020860151935060408601519250606086015191506110dd6080870161107f565b9050929550929590935056fea164736f6c6343000817000a00000000000000000000000074a868ac479ee145029bb80827bb77f7b7c441cb0000000000000000000000000000000000000000000000000eaf299174e9df7d000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab0000000000000000000000004ec6a3222fa6fa8c671db3060fdbdbcab94f7bc40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5980273ea70aa2f7982aabc90f607185fbad50f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed861082c8d5f9c469c08e549390457102ddca4a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561000f575f80fd5b50600436106101e7575f3560e01c8063a384d6ff11610109578063c42889cf1161009e578063da9274451161006e578063da92744514610531578063e5693f4114610558578063f2fde38b1461057f578063feaf968c14610592575f80fd5b8063c42889cf146104b4578063cb2ef6f7146104db578063d16cc85014610502578063d62ada1114610529575f80fd5b8063bbc8613e116100d9578063bbc8613e14610442578063bc489a651461045f578063bc8018b114610472578063c21ee1621461047a575f80fd5b8063a384d6ff146103fc578063ab0ca0e114610405578063b09ad8a01461042c578063b5cddab814610434575f80fd5b80635fcbd2851161017f5780637ff361ec1161014f5780637ff361ec1461037757806387584f001461039e5780638acee3cf146103c55780638da5cb5b146103ec575f80fd5b80635fcbd285146102fa578063715018a6146103215780637284e4161461032b57806377b1c7d414610340575f80fd5b80633fdc155e116101ba5780633fdc155e146102ac578063427cb6fe146102c2578063515fbcb3146102e957806354fd4d50146102f1575f80fd5b8063178793e8146101eb578063313ce5671461022c578063385aee1b146102465780633e777fd214610285575b5f80fd5b6102127f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020015b60405180910390f35b610234600881565b60405160ff9091168152602001610223565b61026d7f0000000000000000000000004ec6a3222fa6fa8c671db3060fdbdbcab94f7bc481565b6040516001600160a01b039091168152602001610223565b6102127f000000000000000000000000000000000000000000000000000000000000000081565b6102b46105d1565b604051908152602001610223565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6102b4610657565b6102b461013781565b61026d7f000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab81565b610329610666565b005b610333610679565b6040516102239190610eb9565b6103677f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610223565b6103677f000000000000000000000000000000000000000000000000000000000000000181565b6103677f000000000000000000000000000000000000000000000000000000000000000181565b61026d7f000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab81565b5f546001600160a01b031661026d565b6102b460015481565b61026d7f000000000000000000000000e5980273ea70aa2f7982aabc90f607185fbad50f81565b6102b4610721565b670de0b6b3a76400006102b4565b61044a61072d565b60408051928352602083019190915201610223565b61032961046d366004610ed2565b610984565b610333610998565b6104a17f000000000000000000000000000000000000000000000000000000000000000381565b60405161ffff9091168152602001610223565b6102127f000000000000000000000000000000000000000000000000000000000000000081565b6102b47f50524943455f464545443a3a43555256455f535441424c45000000000000000081565b6102127f000000000000000000000000000000000000000000000000000000000000000081565b610367600181565b6103677f000000000000000000000000000000000000000000000000000000000000000181565b61026d7f000000000000000000000000ed861082c8d5f9c469c08e549390457102ddca4a81565b61032961058d366004610ee9565b610a2b565b61059a610abd565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a001610223565b5f7f000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab6001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa15801561062e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106529190610f0f565b905090565b5f61066061072d565b50919050565b61066e610b51565b6106775f610baa565b565b60607f000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab6001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa1580156106d6573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106fd9190810190610f3a565b60405160200161070d9190610fe2565b604051602081830303815290604052905090565b5f610652600154610c11565b5f8061079a7f0000000000000000000000004ec6a3222fa6fa8c671db3060fdbdbcab94f7bc47f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000001610c3a565b90925090505f8061080c7f000000000000000000000000e5980273ea70aa2f7982aabc90f607185fbad50f7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000001610c3a565b9150915061081c84848484610cbb565b9094509250600261ffff7f000000000000000000000000000000000000000000000000000000000000000316111561097e576108b97f000000000000000000000000ed861082c8d5f9c469c08e549390457102ddca4a7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000001610c3a565b90925090506108ca84848484610cbb565b9094509250600361ffff7f000000000000000000000000000000000000000000000000000000000000000316111561097e576109677f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610c3a565b909250905061097884848484610cbb565b90945092505b50509091565b61098c610b51565b61099581610ce8565b50565b6001546060907f000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab7f000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab826109ea81610c11565b604080516001600160a01b03958616602082015294909316928401929092526060830152608082015260a00160405160208183030381529060405291505090565b610a33610b51565b6001600160a01b038116610ab45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61099581610baa565b5f805f805f80610acb6105d1565b60015490915080821015610af257604051633708d96960e21b815260040160405180910390fd5b5f610afc82610c11565b905080831115610b0a578092505b5f80610b1461072d565b91509150610b27670de0b6b3a764000090565b610b318387611036565b610b3b919061104d565b5f9b909a508b9950909750889650945050505050565b5f546001600160a01b031633146106775760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aab565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f612710610c2060c88261106c565b610c2a9084611036565b610c34919061104d565b92915050565b5f80846001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610c78573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c9c919061109d565b50919450909250610cb39150839050828686610d78565b935093915050565b5f80838612610cca5783610ccc565b855b838610610cd95783610cdb565b855b9150915094509492505050565b805f03610d21576040517f05ac045400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610d33610d2d6105d1565b83610e1e565b600183905560408051848152602081018390529192507f5ab79ffcd89b6380c7fbdd89d02cfe3d9c53c99a85e150c2319075018d1aac5c910160405180910390a15050565b5f841280610d8d575080158015610d8d575083155b15610dc4576040517f53b798e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80158015610de15750610ddd63ffffffff83168461106c565b4210155b15610e18576040517f16dd0ffb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b5f81831015610e4057604051633708d96960e21b815260040160405180910390fd5b610e4982610c11565b905080831115610c3457604051633708d96960e21b815260040160405180910390fd5b5f5b83811015610e86578181015183820152602001610e6e565b50505f910152565b5f8151808452610ea5816020860160208601610e6c565b601f01601f19169290920160200192915050565b602081525f610ecb6020830184610e8e565b9392505050565b5f60208284031215610ee2575f80fd5b5035919050565b5f60208284031215610ef9575f80fd5b81356001600160a01b0381168114610ecb575f80fd5b5f60208284031215610f1f575f80fd5b5051919050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610f4a575f80fd5b815167ffffffffffffffff80821115610f61575f80fd5b818401915084601f830112610f74575f80fd5b815181811115610f8657610f86610f26565b604051601f8201601f19908116603f01168101908382118183101715610fae57610fae610f26565b81604052828152876020848701011115610fc6575f80fd5b610fd7836020830160208801610e6c565b979650505050505050565b5f8251610ff3818460208701610e6c565b7f202f20555344204c502070726963652066656564000000000000000000000000920191825250601401919050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610c3457610c34611022565b5f8261106757634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610c3457610c34611022565b805169ffffffffffffffffffff81168114611098575f80fd5b919050565b5f805f805f60a086880312156110b1575f80fd5b6110ba8661107f565b94506020860151935060408601519250606086015191506110dd6080870161107f565b9050929550929590935056fea164736f6c6343000817000a

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000074a868ac479ee145029bb80827bb77f7b7c441cb0000000000000000000000000000000000000000000000000eaf299174e9df7d000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab0000000000000000000000004ec6a3222fa6fa8c671db3060fdbdbcab94f7bc40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5980273ea70aa2f7982aabc90f607185fbad50f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed861082c8d5f9c469c08e549390457102ddca4a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _owner (address): 0x74A868AC479EE145029bB80827BB77F7B7c441cB
Arg [1] : _lowerBound (uint256): 1058110142163836797
Arg [2] : _token (address): 0x942644106B073E30D72c2C5D7529D5C296ea91ab
Arg [3] : _pool (address): 0x942644106B073E30D72c2C5D7529D5C296ea91ab
Arg [4] : priceFeeds (tuple[4]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 00000000000000000000000074a868ac479ee145029bb80827bb77f7b7c441cb
Arg [1] : 0000000000000000000000000000000000000000000000000eaf299174e9df7d
Arg [2] : 000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab
Arg [3] : 000000000000000000000000942644106b073e30d72c2c5d7529d5c296ea91ab
Arg [4] : 0000000000000000000000004ec6a3222fa6fa8c671db3060fdbdbcab94f7bc4
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 000000000000000000000000e5980273ea70aa2f7982aabc90f607185fbad50f
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [8] : 000000000000000000000000ed861082c8d5f9c469c08e549390457102ddca4a
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000000


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.