MellowWithdrawalSubcompressor

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/compressors/subcompressors/withdrawal/MellowWithdrawalSubcompressor.sol": {
      "content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundaiton, 2025.
pragma solidity ^0.8.23;

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

import {IWithdrawalSubcompressor} from "../../../interfaces/IWithdrawalSubcompressor.sol";
import {
    WithdrawalOutput,
    WithdrawableAsset,
    RequestableWithdrawal,
    ClaimableWithdrawal,
    PendingWithdrawal,
    WithdrawalLib
} from "../../../types/WithdrawalInfo.sol";
import {MultiCall} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditFacadeV3.sol";

import {MellowWithdrawalPhantomToken} from
    "@gearbox-protocol/integrations-v3/contracts/helpers/mellow/MellowWithdrawalPhantomToken.sol";
import {
    IMellowMultiVault,
    IMellowWithdrawalQueue,
    IEigenLayerWithdrawalQueue,
    Subvault,
    MellowProtocol
} from "@gearbox-protocol/integrations-v3/contracts/integrations/mellow/IMellowMultiVault.sol";
import {IMellowClaimerAdapter} from
    "@gearbox-protocol/integrations-v3/contracts/interfaces/mellow/IMellowClaimerAdapter.sol";
import {IMellow4626VaultAdapter} from
    "@gearbox-protocol/integrations-v3/contracts/interfaces/mellow/IMellow4626VaultAdapter.sol";
import {IERC4626Adapter} from "@gearbox-protocol/integrations-v3/contracts/interfaces/erc4626/IERC4626Adapter.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";

struct EpochData {
    bool isClaimed;
    uint256 sharesToClaim;
    uint256 claimableAssets;
}

struct EigenLayerWithdrawal {
    address staker;
    address delegatedTo;
    address withdrawer;
    uint256 nonce;
    uint32 startBlock;
    address[] strategies;
    uint256[] scaledShares;
}

interface ISymbioticSubvault {
    function nextEpochStart() external view returns (uint256);
    function epochDuration() external view returns (uint256);
    function withdrawalsOf(uint256 epoch, address withdrawalQueue) external view returns (uint256);
}

interface IEigenLayerDelegation {
    function minWithdrawalDelayBlocks() external view returns (uint256);
}

interface IEigenLayerWithdrawalQueueExt is IEigenLayerWithdrawalQueue {
    function delegation() external view returns (address);

    function latestWithdrawableBlock() external view returns (uint256);

    function convertScaledSharesToShares(
        EigenLayerWithdrawal memory withdrawal,
        uint256 scaledShares,
        uint256 totalScaledShares
    ) external view returns (uint256);

    function getWithdrawalRequest(uint256 index, address account)
        external
        view
        returns (
            EigenLayerWithdrawal memory data,
            bool isClaimed,
            uint256 assets,
            uint256 shares,
            uint256 accountShares
        );

    function isolatedVault() external view returns (address);
    function strategy() external view returns (address);
}

interface IEigenLayerIsolatedVault {
    function sharesToUnderlyingView(address strategy, uint256 shares) external view returns (uint256);
}

interface ISymbioticWithdrawalQueue {
    function getCurrentEpoch() external view returns (uint256);
    function getAccountData(address account)
        external
        view
        returns (uint256 sharesToClaimPrev, uint256 sharesToClaim, uint256 claimableAssets, uint256 claimEpoch);
    function getEpochData(uint256 epoch) external view returns (EpochData memory);
}

interface IMellowMultiVaultExt is IMellowMultiVault {
    function withdrawalStrategy() external view returns (address);
}

struct MellowWithdrawalAmounts {
    uint256 subvaultIndex;
    uint256 claimable;
    uint256 pending;
    uint256 staked;
}

interface IMellowWithdrawalStrategy {
    function calculateWithdrawalAmounts(address multiVault, uint256 amount)
        external
        view
        returns (MellowWithdrawalAmounts[] memory amounts);
}

contract MellowWithdrawalSubcompressor is IWithdrawalSubcompressor {
    using WithdrawalLib for PendingWithdrawal[];

    uint256 public constant version = 3_10;
    bytes32 public constant contractType = "GLOBAL::MELLOW_WD_SC";

    function getWithdrawableAssets(address, address token) external view returns (WithdrawableAsset[] memory) {
        address multiVault = MellowWithdrawalPhantomToken(token).multiVault();
        address asset = IERC4626(multiVault).asset();

        WithdrawableAsset[] memory withdrawableAssets = new WithdrawableAsset[](1);
        withdrawableAssets[0] = WithdrawableAsset(multiVault, token, asset, _getWithdrawalLength(multiVault));

        return withdrawableAssets;
    }

    function getCurrentWithdrawals(address creditAccount, address token)
        external
        view
        returns (ClaimableWithdrawal[] memory, PendingWithdrawal[] memory)
    {
        address multiVault = MellowWithdrawalPhantomToken(token).multiVault();

        ClaimableWithdrawal[] memory claimableWithdrawals = new ClaimableWithdrawal[](1);
        claimableWithdrawals[0] = _getClaimableWithdrawal(creditAccount, token, multiVault);

        if (claimableWithdrawals[0].outputs.length == 0 || claimableWithdrawals[0].outputs[0].amount == 0) {
            claimableWithdrawals = new ClaimableWithdrawal[](0);
        }

        PendingWithdrawal[] memory pendingWithdrawals = _getPendingWithdrawals(creditAccount, multiVault);

        for (uint256 i = 0; i < pendingWithdrawals.length; ++i) {
            pendingWithdrawals[i].withdrawalPhantomToken = token;
        }

        return (claimableWithdrawals, pendingWithdrawals);
    }

    function getWithdrawalRequestResult(address creditAccount, address token, address withdrawalToken, uint256 amount)
        external
        view
        returns (RequestableWithdrawal memory requestableWithdrawal)
    {
        requestableWithdrawal.token = token;
        requestableWithdrawal.amountIn = amount;

        uint256 assets = IERC4626(token).convertToAssets(amount);

        address withdrawalStrategy = IMellowMultiVaultExt(token).withdrawalStrategy();

        MellowWithdrawalAmounts[] memory amounts =
            IMellowWithdrawalStrategy(withdrawalStrategy).calculateWithdrawalAmounts(token, assets);

        uint256 liquid = assets;

        for (uint256 i = 0; i < amounts.length; ++i) {
            Subvault memory subvault = IMellowMultiVault(token).subvaultAt(amounts[i].subvaultIndex);

            if (subvault.protocol == MellowProtocol.SYMBIOTIC) {
                liquid -= amounts[i].staked + amounts[i].pending;
            } else if (subvault.protocol == MellowProtocol.EIGEN_LAYER) {
                liquid -= amounts[i].staked + amounts[i].pending;
            }
        }

        if (liquid < assets) {
            requestableWithdrawal.outputs = new WithdrawalOutput[](2);
            requestableWithdrawal.outputs[0] = WithdrawalOutput(IERC4626(token).asset(), false, liquid);
            requestableWithdrawal.outputs[1] = WithdrawalOutput(withdrawalToken, true, assets - liquid);
        } else {
            requestableWithdrawal.outputs = new WithdrawalOutput[](1);
            requestableWithdrawal.outputs[0] = WithdrawalOutput(IERC4626(token).asset(), false, assets);
        }

        requestableWithdrawal.requestCalls = new MultiCall[](2);

        address creditManager = ICreditAccountV3(creditAccount).creditManager();

        address vaultAdapter = ICreditManagerV3(creditManager).contractToAdapter(token);

        requestableWithdrawal.requestCalls[0] = MultiCall({
            target: vaultAdapter,
            callData: abi.encodeCall(IERC4626Adapter.redeem, (amount, address(0), address(0)))
        });

        address claimer = MellowWithdrawalPhantomToken(withdrawalToken).claimer();

        address claimerAdapter = ICreditManagerV3(creditManager).contractToAdapter(claimer);

        (uint256[] memory subvaultIndices, uint256[][] memory withdrawalIndices) =
            IMellowClaimerAdapter(claimerAdapter).getMultiVaultSubvaultIndices(token);

        requestableWithdrawal.requestCalls[1] = MultiCall({
            target: claimerAdapter,
            callData: abi.encodeCall(IMellowClaimerAdapter.multiAccept, (token, subvaultIndices, withdrawalIndices))
        });

        requestableWithdrawal.claimableAt = block.timestamp + _getWithdrawalLength(token);

        return requestableWithdrawal;
    }

    function _getPendingWithdrawals(address creditAccount, address multiVault)
        internal
        view
        returns (PendingWithdrawal[] memory pendingWithdrawals)
    {
        address asset = IERC4626(multiVault).asset();

        uint256 nSubvaults = IMellowMultiVault(multiVault).subvaultsCount();

        for (uint256 i = 0; i < nSubvaults; ++i) {
            Subvault memory subvault = IMellowMultiVault(multiVault).subvaultAt(i);

            if (subvault.withdrawalQueue == address(0)) continue;

            uint256 pendingAssets = IMellowWithdrawalQueue(subvault.withdrawalQueue).pendingAssetsOf(creditAccount);

            if (pendingAssets > 0) {
                pendingWithdrawals = pendingWithdrawals.concat(
                    _getSubvaultPendingWithdrawals(
                        creditAccount, multiVault, subvault.protocol, subvault.vault, subvault.withdrawalQueue, asset
                    )
                );
            }
        }

        return pendingWithdrawals;
    }

    function _getSubvaultPendingWithdrawals(
        address creditAccount,
        address multiVault,
        MellowProtocol protocol,
        address subvault,
        address withdrawalQueue,
        address asset
    ) internal view returns (PendingWithdrawal[] memory pendingWithdrawals) {
        if (protocol == MellowProtocol.SYMBIOTIC) {
            (uint256 sharesToClaimPrev, uint256 sharesToClaim,, uint256 claimEpoch) =
                ISymbioticWithdrawalQueue(withdrawalQueue).getAccountData(creditAccount);

            uint256 currentEpoch = ISymbioticWithdrawalQueue(withdrawalQueue).getCurrentEpoch();

            if (claimEpoch < currentEpoch) {
                return pendingWithdrawals;
            } else if (claimEpoch == currentEpoch) {
                pendingWithdrawals = new PendingWithdrawal[](1);
                pendingWithdrawals[0].token = multiVault;
                pendingWithdrawals[0].expectedOutputs = new WithdrawalOutput[](1);

                uint256 expectedAmount =
                    _getSymbioticExpectedWithdrawal(subvault, withdrawalQueue, sharesToClaim, currentEpoch);

                pendingWithdrawals[0].expectedOutputs[0] = WithdrawalOutput(asset, false, expectedAmount);
                pendingWithdrawals[0].claimableAt = ISymbioticSubvault(subvault).nextEpochStart();
            } else if (claimEpoch == currentEpoch + 1) {
                pendingWithdrawals = new PendingWithdrawal[](2);

                pendingWithdrawals[0].token = multiVault;
                pendingWithdrawals[0].expectedOutputs = new WithdrawalOutput[](1);

                uint256 expectedAmount =
                    _getSymbioticExpectedWithdrawal(subvault, withdrawalQueue, sharesToClaim, currentEpoch + 1);

                pendingWithdrawals[0].expectedOutputs[0] = WithdrawalOutput(asset, false, expectedAmount);
                pendingWithdrawals[0].claimableAt =
                    ISymbioticSubvault(subvault).nextEpochStart() + ISymbioticSubvault(subvault).epochDuration();

                if (sharesToClaimPrev > 0) {
                    pendingWithdrawals[1].token = multiVault;
                    pendingWithdrawals[1].expectedOutputs = new WithdrawalOutput[](1);

                    expectedAmount =
                        _getSymbioticExpectedWithdrawal(subvault, withdrawalQueue, sharesToClaimPrev, currentEpoch);

                    pendingWithdrawals[1].expectedOutputs[0] = WithdrawalOutput(asset, false, expectedAmount);
                    pendingWithdrawals[1].claimableAt = ISymbioticSubvault(subvault).nextEpochStart();
                }
            }
        }

        if (protocol == MellowProtocol.EIGEN_LAYER) {
            (, uint256[] memory withdrawals,) =
                IEigenLayerWithdrawalQueueExt(withdrawalQueue).getAccountData(creditAccount, type(uint256).max, 0, 0, 0);

            uint256 latestWithdrawableBlock = IEigenLayerWithdrawalQueueExt(withdrawalQueue).latestWithdrawableBlock();

            pendingWithdrawals = new PendingWithdrawal[](withdrawals.length);

            for (uint256 i = 0; i < withdrawals.length; ++i) {
                (EigenLayerWithdrawal memory withdrawal,,, uint256 shares, uint256 accountShares) =
                    IEigenLayerWithdrawalQueueExt(withdrawalQueue).getWithdrawalRequest(withdrawals[i], creditAccount);

                if (withdrawal.startBlock > latestWithdrawableBlock && accountShares > 0) {
                    pendingWithdrawals[i].token = multiVault;
                    pendingWithdrawals[i].expectedOutputs = new WithdrawalOutput[](1);

                    uint256 unscaledShares = IEigenLayerWithdrawalQueueExt(withdrawalQueue).convertScaledSharesToShares(
                        withdrawal, accountShares, shares
                    );

                    uint256 expectedAmount = IEigenLayerIsolatedVault(
                        IEigenLayerWithdrawalQueueExt(withdrawalQueue).isolatedVault()
                    ).sharesToUnderlyingView(IEigenLayerWithdrawalQueueExt(withdrawalQueue).strategy(), unscaledShares);

                    pendingWithdrawals[i].expectedOutputs[0] = WithdrawalOutput(asset, false, expectedAmount);
                    pendingWithdrawals[i].claimableAt =
                        block.timestamp + 12 * (withdrawal.startBlock - latestWithdrawableBlock);
                }
            }
        }
    }

    function _getClaimableWithdrawal(address creditAccount, address withdrawalToken, address multiVault)
        internal
        view
        returns (ClaimableWithdrawal memory withdrawal)
    {
        address asset = IERC4626(multiVault).asset();

        withdrawal.token = multiVault;
        withdrawal.withdrawalPhantomToken = withdrawalToken;
        withdrawal.outputs = new WithdrawalOutput[](1);
        withdrawal.outputs[0] = WithdrawalOutput(asset, false, 0);

        uint256 nSubvaults = IMellowMultiVault(multiVault).subvaultsCount();

        for (uint256 i = 0; i < nSubvaults; ++i) {
            Subvault memory subvault = IMellowMultiVault(multiVault).subvaultAt(i);

            if (subvault.withdrawalQueue == address(0)) continue;

            uint256 claimableAssets = IMellowWithdrawalQueue(subvault.withdrawalQueue).claimableAssetsOf(creditAccount);

            withdrawal.outputs[0].amount += claimableAssets;
        }

        if (withdrawal.outputs[0].amount == 0) {
            return withdrawal;
        }

        withdrawal.withdrawalTokenSpent = withdrawal.outputs[0].amount;

        withdrawal.claimCalls = new MultiCall[](1);

        address claimerAdapter;

        {
            address claimer = MellowWithdrawalPhantomToken(withdrawalToken).claimer();
            address creditManager = ICreditAccountV3(creditAccount).creditManager();

            claimerAdapter = ICreditManagerV3(creditManager).contractToAdapter(claimer);
        }

        (uint256[] memory subvaultIndices, uint256[][] memory withdrawalIndices) =
            IMellowClaimerAdapter(claimerAdapter).getUserSubvaultIndices(multiVault, creditAccount);

        withdrawal.claimCalls[0] = MultiCall(
            address(claimerAdapter),
            abi.encodeWithSelector(
                IMellowClaimerAdapter.multiAcceptAndClaim.selector,
                multiVault,
                subvaultIndices,
                withdrawalIndices,
                creditAccount,
                withdrawal.outputs[0].amount
            )
        );

        return withdrawal;
    }

    function _getWithdrawalLength(address multiVault) internal view returns (uint256) {
        uint256 withdrawalLength = 0;

        uint256 nSubvaults = IMellowMultiVault(multiVault).subvaultsCount();

        for (uint256 i = 0; i < nSubvaults; ++i) {
            Subvault memory subvault = IMellowMultiVault(multiVault).subvaultAt(i);

            if (subvault.protocol == MellowProtocol.SYMBIOTIC) {
                uint256 symbioticWithdrawalLength = ISymbioticSubvault(subvault.vault).nextEpochStart()
                    + ISymbioticSubvault(subvault.vault).epochDuration() - block.timestamp;
                if (symbioticWithdrawalLength > withdrawalLength) {
                    withdrawalLength = symbioticWithdrawalLength;
                }
            }

            if (subvault.protocol == MellowProtocol.EIGEN_LAYER) {
                uint256 eigenLayerWithdrawalLength = IEigenLayerDelegation(
                    IEigenLayerWithdrawalQueueExt(subvault.withdrawalQueue).delegation()
                ).minWithdrawalDelayBlocks() * 12;
                if (eigenLayerWithdrawalLength > withdrawalLength) {
                    withdrawalLength = eigenLayerWithdrawalLength;
                }
            }
        }

        return withdrawalLength;
    }

    function _getSymbioticExpectedWithdrawal(
        address subvault,
        address withdrawalQueue,
        uint256 sharesToClaim,
        uint256 epoch
    ) internal view returns (uint256) {
        EpochData memory epochData = ISymbioticWithdrawalQueue(withdrawalQueue).getEpochData(epoch);

        uint256 totalWithdrawals = ISymbioticSubvault(subvault).withdrawalsOf(epoch, withdrawalQueue);

        return sharesToClaim * totalWithdrawals / epochData.sharesToClaim;
    }
}
"
    },
    "lib/@gearbox-protocol/core-v3/contracts/interfaces/ICreditAccountV3.sol": {
      "content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

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

/// @title Credit account V3 interface
interface ICreditAccountV3 is IVersion {
    function factory() external view returns (address);

    function creditManager() external view returns (address);

    function safeTransfer(address token, address to, uint256 amount) external;

    function execute(address target, bytes calldata data) external returns (bytes memory result);

    function rescue(address target, bytes calldata data) external;
}
"
    },
    "lib/@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol": {
      "content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

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

/// @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 variables (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;
}

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 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, uint256);

    function addCollateral(address payer, address creditAccount, address token, uint256 amount)
        external
        returns (uint256);

    function withdrawCollateral(address creditAccount, address token, uint256 amount, address to)
        external
        returns (uint256);

    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;

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

    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 setContractAllowance(address adapter, address targetContract) external;

    function setCreditFacade(address creditFacade) external;

    function setPriceOracle(address priceOracle) external;

    function setCreditConfigurator(address creditConfigurator) external;
}
"
    },
    "contracts/interfaces/IWithdrawalSubcompressor.sol": {
      "content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;

import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
import {
    WithdrawableAsset,
    RequestableWithdrawal,
    ClaimableWithdrawal,
    PendingWithdrawal
} from "../types/WithdrawalInfo.sol";

interface IWithdrawalSubcompressor is IVersion {
    function getWithdrawableAssets(address creditManager, address token)
        external
        view
        returns (WithdrawableAsset[] memory);

    function getCurrentWithdrawals(address creditAccount, address token)
        external
        view
        returns (ClaimableWithdrawal[] memory, PendingWithdrawal[] memory);

    function getWithdrawalRequestResult(address creditAccount, address token, address withdrawalToken, uint256 amount)
        external
        view
        returns (RequestableWithdrawal memory);
}
"
    },
    "contracts/types/WithdrawalInfo.sol": {
      "content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;

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

struct WithdrawalOutput {
    address token;
    bool isDelayed;
    uint256 amount;
}

struct WithdrawableAsset {
    address token;
    address withdrawalPhantomToken;
    address underlying;
    uint256 withdrawalLength;
}

struct RequestableWithdrawal {
    address token;
    uint256 amountIn;
    WithdrawalOutput[] outputs;
    MultiCall[] requestCalls;
    uint256 claimableAt;
}

struct ClaimableWithdrawal {
    address token;
    address withdrawalPhantomToken;
    uint256 withdrawalTokenSpent;
    WithdrawalOutput[] outputs;
    MultiCall[] claimCalls;
}

struct PendingWithdrawal {
    address token;
    address withdrawalPhantomToken;
    WithdrawalOutput[] expectedOutputs;
    uint256 claimableAt;
}

library WithdrawalLib {
    function push(WithdrawableAsset[] memory w, WithdrawableAsset memory asset)
        internal
        pure
        returns (WithdrawableAsset[] memory)
    {
        WithdrawableAsset[] memory newWithdrawableAssets = new WithdrawableAsset[](w.length + 1);
        for (uint256 i = 0; i < w.length; i++) {
            newWithdrawableAssets[i] = w[i];
        }
        newWithdrawableAssets[w.length] = asset;
        return newWithdrawableAssets;
    }

    function concat(WithdrawableAsset[] memory w0, WithdrawableAsset[] memory w1)
        internal
        pure
        returns (WithdrawableAsset[] memory)
    {
        WithdrawableAsset[] memory newWithdrawableAssets = new WithdrawableAsset[](w0.length + w1.length);
        for (uint256 i = 0; i < w0.length; i++) {
            newWithdrawableAssets[i] = w0[i];
        }
        for (uint256 i = 0; i < w1.length; i++) {
            newWithdrawableAssets[w0.length + i] = w1[i];
        }
        return newWithdrawableAssets;
    }

    function concat(RequestableWithdrawal[] memory w0, RequestableWithdrawal[] memory w1)
        internal
        pure
        returns (RequestableWithdrawal[] memory)
    {
        RequestableWithdrawal[] memory withdrawals = new RequestableWithdrawal[](w0.length + w1.length);
        for (uint256 i = 0; i < w0.length; i++) {
            withdrawals[i] = w0[i];
        }
        for (uint256 i = 0; i < w1.length; i++) {
            withdrawals[w0.length + i] = w1[i];
        }
        return withdrawals;
    }

    function push(ClaimableWithdrawal[] memory w, ClaimableWithdrawal memory withdrawal)
        internal
        pure
        returns (ClaimableWithdrawal[] memory)
    {
        ClaimableWithdrawal[] memory newClaimableWithdrawals = new ClaimableWithdrawal[](w.length + 1);
        for (uint256 i = 0; i < w.length; i++) {
            newClaimableWithdrawals[i] = w[i];
        }
        newClaimableWithdrawals[w.length] = withdrawal;
        return newClaimableWithdrawals;
    }

    function concat(ClaimableWithdrawal[] memory w0, ClaimableWithdrawal[] memory w1)
        internal
        pure
        returns (ClaimableWithdrawal[] memory)
    {
        ClaimableWithdrawal[] memory withdrawals = new ClaimableWithdrawal[](w0.length + w1.length);
        for (uint256 i = 0; i < w0.length; i++) {
            withdrawals[i] = w0[i];
        }
        for (uint256 i = 0; i < w1.length; i++) {
            withdrawals[w0.length + i] = w1[i];
        }
        return withdrawals;
    }

    function push(PendingWithdrawal[] memory w, PendingWithdrawal memory withdrawal)
        internal
        pure
        returns (PendingWithdrawal[] memory)
    {
        PendingWithdrawal[] memory newPendingWithdrawals = new PendingWithdrawal[](w.length + 1);
        for (uint256 i = 0; i < w.length; i++) {
            newPendingWithdrawals[i] = w[i];
        }
        newPendingWithdrawals[w.length] = withdrawal;
        return newPendingWithdrawals;
    }

    function concat(PendingWithdrawal[] memory w0, PendingWithdrawal[] memory w1)
        internal
        pure
        returns (PendingWithdrawal[] memory)
    {
        PendingWithdrawal[] memory withdrawals = new PendingWithdrawal[](w0.length + w1.length);
        for (uint256 i = 0; i < w0.length; i++) {
            withdrawals[i] = w0[i];
        }
        for (uint256 i = 0; i < w1.length; i++) {
            withdrawals[w0.length + i] = w1[i];
        }
        return withdrawals;
    }

    function filterEmpty(PendingWithdrawal[] memory pendingWithdrawals)
        internal
        pure
        returns (PendingWithdrawal[] memory)
    {
        PendingWithdrawal[] memory filteredPendingWithdrawals = new PendingWithdrawal[](0);
        for (uint256 i = 0; i < pendingWithdrawals.length; i++) {
            if (pendingWithdrawals[i].expectedOutputs.length > 0) {
                for (uint256 j = 0; j < pendingWithdrawals[i].expectedOutputs.length; j++) {
                    if (pendingWithdrawals[i].expectedOutputs[j].amount > 0) {
                        filteredPendingWithdrawals = push(filteredPendingWithdrawals, pendingWithdrawals[i]);
                        break;
                    }
                }
            }
        }

        return filteredPendingWithdrawals;
    }

    function filterEmpty(ClaimableWithdrawal[] memory claimableWithdrawals)
        internal
        pure
        returns (ClaimableWithdrawal[] memory)
    {
        ClaimableWithdrawal[] memory filteredClaimableWithdrawals = new ClaimableWithdrawal[](0);
        for (uint256 i = 0; i < claimableWithdrawals.length; i++) {
            if (claimableWithdrawals[i].outputs.length > 0) {
                for (uint256 j = 0; j < claimableWithdrawals[i].outputs.length; j++) {
                    if (claimableWithdrawals[i].outputs[j].amount > 0) {
                        filteredClaimableWithdrawals = push(filteredClaimableWithdrawals, claimableWithdrawals[i]);
                        break;
                    }
                }
            }
        }

        return filteredClaimableWithdrawals;
    }
}
"
    },
    "lib/@gearbox-protocol/core-v3/contracts/interfaces/ICreditFacadeV3.sol": {
      "content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

import {AllowanceAction} from "./ICreditConfiguratorV3.sol";
import "./ICreditFacadeV3Multicall.sol";
import {IACLTrait} from "./base/IACLTrait.sol";
import {PriceUpdate} from "./base/IPriceFeedStore.sol";
import {IVersion} from "./base/IVersion.sol";

/// @notice Multicall element
/// @param target Call target, which is either credit facade or adapter
/// @param callData Call data
struct MultiCall {
    address target;
    bytes callData;
}

/// @notice Debt limits packed into a single slot
/// @param minDebt Minimum debt amount per credit account
/// @param maxDebt Maximum debt amount per credit account
struct DebtLimits {
    uint128 minDebt;
    uint128 maxDebt;
}

/// @notice Collateral check params
/// @param collateralHints Optional array of token masks to check first to reduce the amount of computation
///        when known subset of account's collateral tokens covers all the debt
/// @param minHealthFactor Min account's health factor in bps in order not to revert
struct FullCheckParams {
    uint256[] collateralHints;
    uint16 minHealthFactor;
}

interface ICreditFacadeV3Events {
    /// @notice Emitted when a new credit account is opened
    event OpenCreditAccount(
        address indexed creditAccount, address indexed onBehalfOf, address indexed caller, uint256 referralCode
    );

    /// @notice Emitted when account is closed
    event CloseCreditAccount(address indexed creditAccount, address indexed borrower);

    /// @notice Emitted when account is liquidated
    event LiquidateCreditAccount(
        address indexed creditAccount, address indexed liquidator, address to, uint256 remainingFunds
    );

    /// @notice Emitted when account is partially liquidated
    event PartiallyLiquidateCreditAccount(
        address indexed creditAccount,
        address indexed token,
        address indexed liquidator,
        uint256 repaidDebt,
        uint256 seizedCollateral,
        uint256 fee
    );

    /// @notice Emitted when collateral is added to account
    event AddCollateral(address indexed creditAccount, address indexed token, uint256 amount);

    /// @notice Emitted when collateral is withdrawn from account
    event WithdrawCollateral(address indexed creditAccount, address indexed token, uint256 amount, address to);

    /// @notice Emitted when a multicall is started
    event StartMultiCall(address indexed creditAccount, address indexed caller);

    /// @notice Emitted when phantom token is withdrawn by account
    event WithdrawPhantomToken(address indexed creditAccount, address indexed token, uint256 amount);

    /// @notice Emitted when a call from account to an external contract is made during a multicall
    event Execute(address indexed creditAccount, address indexed targetContract);

    /// @notice Emitted when a multicall is finished
    event FinishMultiCall();
}

/// @title Credit facade V3 interface
interface ICreditFacadeV3 is IVersion, IACLTrait, ICreditFacadeV3Events {
    function creditManager() external view returns (address);

    function underlying() external view returns (address);

    function treasury() external view returns (address);

    function priceFeedStore() external view returns (address);

    function degenNFT() external view returns (address);

    function weth() external view returns (address);

    function botList() external view returns (address);

    function maxDebtPerBlockMultiplier() external view returns (uint8);

    function maxQuotaMultiplier() external view returns (uint256);

    function expirable() external view returns (bool);

    function expirationDate() external view returns (uint40);

    function debtLimits() external view returns (uint128 minDebt, uint128 maxDebt);

    function lossPolicy() external view returns (address);

    function forbiddenTokenMask() external view returns (uint256);

    // ------------------ //
    // ACCOUNT MANAGEMENT //
    // ------------------ //

    function openCreditAccount(address onBehalfOf, MultiCall[] calldata calls, uint256 referralCode)
        external
        payable
        returns (address creditAccount);

    function closeCreditAccount(address creditAccount, MultiCall[] calldata calls) external payable;

    function liquidateCreditAccount(
        address creditAccount,
        address to,
        MultiCall[] calldata calls,
        bytes memory lossPolicyData
    ) external;

    function liquidateCreditAccount(address creditAccount, address to, MultiCall[] calldata calls) external;

    function partiallyLiquidateCreditAccount(
        address creditAccount,
        address token,
        uint256 repaidAmount,
        uint256 minSeizedAmount,
        address to,
        PriceUpdate[] calldata priceUpdates
    ) external returns (uint256 seizedAmount);

    function multicall(address creditAccount, MultiCall[] calldata calls) external payable;

    function botMulticall(address creditAccount, MultiCall[] calldata calls) external;

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

    function setExpirationDate(uint40 newExpirationDate) external;

    function setDebtLimits(uint128 newMinDebt, uint128 newMaxDebt, uint8 newMaxDebtPerBlockMultiplier) external;

    function setLossPolicy(address newLossPolicy) external;

    function setTokenAllowance(address token, AllowanceAction allowance) external;

    function pause() external;

    function unpause() external;
}
"
    },
    "lib/@gearbox-protocol/integrations-v3/contracts/helpers/mellow/MellowWithdrawalPhantomToken.sol": {
      "content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.23;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {IMellowMultiVault, IMellowWithdrawalQueue, Subvault} from "../../integrations/mellow/IMellowMultiVault.sol";
import {PhantomERC20} from "../PhantomERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {MultiCall} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditFacadeV3.sol";
import {IPhantomToken} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IPhantomToken.sol";

/// @title MellowLRT withdrawal phantom token
/// @notice Phantom ERC-20 token that represents the balance of the pending and claimable withdrawals in Mellow vaults
contract MellowWithdrawalPhantomToken is PhantomERC20, Ownable, IPhantomToken {
    event SetClaimer(address indexed claimer);

    error SubvaultClaimerMismatchException();

    bytes32 public constant override contractType = "PHANTOM_TOKEN::MELLOW_WITHDRAWAL";

    uint256 public constant override version = 3_11;

    address public immutable multiVault;

    address public claimer;

    /// @notice Constructor
    /// @param _ioProxy The address of the Instance Owner proxy
    /// @param _multiVault The MultiVault where the pending assets are tracked
    /// @param _claimer The address of the initial Claimer contract
    constructor(address _ioProxy, address _multiVault, address _claimer)
        PhantomERC20(
            IERC4626(_multiVault).asset(),
            string.concat("Mellow withdrawn ", IERC20Metadata(IERC4626(_multiVault).asset()).name()),
            string.concat("wd", IERC20Metadata(IERC4626(_multiVault).asset()).symbol()),
            IERC20Metadata(IERC4626(_multiVault).asset()).decimals()
        )
    {
        _transferOwnership(_ioProxy);

        multiVault = _multiVault;
        claimer = _claimer;
    }

    /// @notice Returns the amount of assets pending/claimable for withdrawal
    /// @param account The account for which the calculation is performed
    function balanceOf(address account) public view returns (uint256 balance) {
        uint256 nSubvaults = IMellowMultiVault(multiVault).subvaultsCount();

        for (uint256 i = 0; i < nSubvaults; ++i) {
            Subvault memory subvault = IMellowMultiVault(multiVault).subvaultAt(i);

            if (subvault.withdrawalQueue == address(0)) continue;

            balance += IMellowWithdrawalQueue(subvault.withdrawalQueue).pendingAssetsOf(account)
                + IMellowWithdrawalQueue(subvault.withdrawalQueue).claimableAssetsOf(account);
        }
    }

    /// @notice Returns phantom token's target contract and underlying
    function getPhantomTokenInfo() external view override returns (address, address) {
        return (claimer, underlying);
    }

    function serialize() external view override returns (bytes memory) {
        return abi.encode(claimer, underlying);
    }

    /// @notice Sets the address of the Claimer contract
    function setClaimer(address _claimer) external onlyOwner {
        if (_claimer != claimer) {
            uint256 nSubvaults = IMellowMultiVault(multiVault).subvaultsCount();

            for (uint256 i = 0; i < nSubvaults; ++i) {
                Subvault memory subvault = IMellowMultiVault(multiVault).subvaultAt(i);

                if (subvault.withdrawalQueue == address(0)) continue;

                address queueClaimer = IMellowWithdrawalQueue(subvault.withdrawalQueue).claimer();

                if (queueClaimer != _claimer) revert SubvaultClaimerMismatchException();
            }

            claimer = _claimer;
            emit SetClaimer(_claimer);
        }
    }
}
"
    },
    "lib/@gearbox-protocol/integrations-v3/contracts/integrations/mellow/IMellowMultiVault.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.23;

enum MellowProtocol {
    SYMBIOTIC,
    EIGEN_LAYER,
    ERC4626
}

struct Subvault {
    MellowProtocol protocol;
    address vault;
    address withdrawalQueue;
}

interface IMellowMultiVault {
    function asset() external view returns (address);
    function withdrawalQueue() external view returns (address);
    function subvaultsCount() external view returns (uint256);
    function subvaultAt(uint256 index) external view returns (Subvault memory);
    function depositWhitelist() external view returns (bool);
}

interface IMellowWithdrawalQueue {
    function pendingAssetsOf(address account) external view returns (uint256);
    function claimableAssetsOf(address account) external view returns (uint256);
    function claimer() external view returns (address);
}

interface IEigenLayerWithdrawalQueue {
    function getAccountData(
        address account,
        uint256 withdrawalsLimit,
        uint256 withdrawalsOffset,
        uint256 transferredWithdrawalsLimit,
        uint256 transferredWithdrawalsOffset
    )
        external
        view
        returns (uint256 claimableAssets, uint256[] memory withdrawals, uint256[] memory transferredWithdrawals);
}
"
    },
    "lib/@gearbox-protocol/integrations-v3/contracts/interfaces/mellow/IMellowClaimerAdapter.sol": {
      "content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.23;

import {IPhantomTokenAdapter} from "../IPhantomTokenAdapter.sol";

struct MellowMultiVaultStatus {
    address multiVault;
    address stakedPhantomToken;
    bool allowed;
}

interface IMellowClaimerAdapterEvents {
    event SetMultiVaultStatus(address indexed multiVault, bool allowed);
}

interface IMellowClaimerAdapterExceptions {
    /// @notice Error thrown when the actually claimed amount is less than the requested amount
    error InsufficientClaimedException();

    /// @notice Thrown when the staked phantom token field does not match the multivault
    error InvalidMultiVaultException();

    /// @notice Thrown when the staked phantom token added with the vault has incorrect parameters
    error InvalidStakedPhantomTokenException();

    /// @notice Thrown when the multivault is not allowed
    error MultiVaultNotAllowedException();
}

/// @title Mellow ERC4626 Vault adapter interface
/// @notice Interface for the adapter to interact with Mellow's ERC4626 vaults
interface IMellowClaimerAdapter is
    IPhantomTokenAdapter,
    IMellowClaimerAdapterExceptions,
    IMellowClaimerAdapterEvents
{
    function multiAccept(address multiVault, uint256[] calldata subvaultIndices, uint256[][] calldata indices)
        external
        returns (bool);

    function multiAcceptAndClaim(
        address multiVault,
        uint256[] calldata subvaultIndices,
        uint256[][] calldata indices,
        address,
        uint256 maxAssets
    ) external returns (bool);

    function getMultiVaultSubvaultIndices(address multiVault)
        external
        view
        returns (uint256[] memory subvaultIndices, uint256[][] memory withdrawalIndices);

    function getUserSubvaultIndices(address multiVault, address user)
        external
        view
        returns (uint256[] memory subvaultIndices, uint256[][] memory withdrawalIndices);

    function allowedMultiVaults() external view returns (address[] memory);

    function setMultiVaultStatusBatch(MellowMultiVaultStatus[] calldata multivaults) external;
}
"
    },
    "lib/@gearbox-protocol/integrations-v3/contracts/interfaces/mellow/IMellow4626VaultAdapter.sol": {
      "content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.23;

import {IERC4626Adapter} from "../erc4626/IERC4626Adapter.sol";

/// @title Mellow ERC4626 Vault adapter interface
/// @notice Interface for the adapter to interact with Mellow's ERC4626 vaults
interface IMellow4626VaultAdapter is IERC4626Adapter {
    /// @notice Thrown when the multivault in the staked phantom token does not match the one in the adapter
    error InvalidMultiVaultException();
}
"
    },
    "lib/@gearbox-protocol/integrations-v3/contracts/interfaces/erc4626/IERC4626Adapter.sol": {
      "content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.23;

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

interface IERC4626Adapter is IAdapter {
    function asset() external view returns (address);

    function vault() external view returns (address);

    function deposit(uint256 assets, address) external returns (bool useSafePrices);

    function depositDiff(uint256 leftoverAmount) external returns (bool useSafePrices);

    function mint(uint256 shares, address) external returns (bool useSafePrices);

    function withdraw(uint256 assets, address, address) external returns (bool useSafePrices);

    function redeem(uint256 shares, address, address) external returns (bool useSafePrices);

    function redeemDiff(uint256 leftoverAmount) external returns (bool useSafePrices);
}
"
    },
    "lib/@openzeppelin/contracts/interfaces/IERC4626.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol)

pragma solidity ^0.8.0;

import "../token/ERC20/IERC20.sol";
import "../token/ERC20/extensions/IERC20Metadata.sol";

/**
 * @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
 * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
 *
 * _Available since v4.7._
 */
interface IERC4626 is IERC20, IERC20Metadata {
    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);

    event Withdraw(
        address indexed sender,
        address indexed receiver,
        address indexed owner,
        uint256 assets,
        uint256 shares
    );

    /**
     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
     *
     * - MUST be an ERC-20 token contract.
     * - MUST NOT revert.
     */
    function asset() external view returns (address assetTokenAddress);

    /**
     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
     *
     * - SHOULD include any compounding that occurs from yield.
     * - MUST be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT revert.
     */
    function totalAssets() external view returns (uint256 totalManagedAssets);

    /**
     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToShares(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToAssets(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
     * through a deposit call.
     *
     * - MUST return a limited value if receiver is subject to some deposit limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
     * - MUST NOT revert.
     */
    function maxDeposit(address receiver) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
     *   in the same transaction.
     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewDeposit(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   deposit execution, and are accounted for during deposit.
     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
     * - MUST return a limited value if receiver is subject to some mint limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
     * - MUST NOT revert.
     */
    function maxMint(address receiver) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
     *   same transaction.
     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
     *   would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by minting.
     */
    function previewMint(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
     *   execution, and are accounted for during mint.
     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
     * Vault, through a withdraw call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxWithdraw(address owner) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
     *   called
     *   in the same transaction.
     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewWithdraw(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   withdraw execution, and are accounted for during withdraw.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
     * through a redeem call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxRedeem(address owner) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
     *   same transaction.
     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
     *   redemption would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
     */
    function previewRedeem(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   redeem execution, and are accounted for during redeem.
     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}
"
    },
    "lib/@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol": {
      "content": "// 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);
}
"
    },
    "lib/@gearbox-protocol/core-v3/contracts/interfaces/ICreditConfiguratorV3.sol": {
      "content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

import {IACLTrait} from "./base/IACLTrait.sol";
import {IVersion} from "./base/IVersion.sol";

enum AllowanceAction {
    FORBID,
    ALLOW
}

interface ICreditConfiguratorV3Events {
    // ------ //
    // TOKENS //
    // ------ //

    /// @notice Emitted when a token is made recognizable as collateral in the credit manager
    event AddCollateralToken(address indexed token);

    /// @notice Emitted when a new collateral token liquidation threshold is set
    event SetTokenLiquidationThreshold(address indexed token, uint16 liquidationThreshold);

    /// @notice Emitted when a collateral token liquidation th

Tags:
ERC20, Multisig, Mintable, Pausable, Swap, Staking, Yield, Voting, Timelock, Upgradeable, Multi-Signature, Factory, Oracle|addr:0x519b944e5f0e5f94fdc451e20b081e2fbb8580d1|verified:true|block:23524229|tx:0x76d0dca37d90aec8feb0f258999882633c9345ed2cd09b8db4038dd03af3e1a2|first_check:1759829469

Submitted on: 2025-10-07 11:31:09

Comments

Log in to comment.

No comments yet.