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/InfinifiWithdrawalSubcompressor.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 {InfinifiUnwindingGateway} from
"@gearbox-protocol/integrations-v3/contracts/helpers/infinifi/InfinifiUnwindingGateway.sol";
import {InfinifiUnwindingPhantomToken} from
"@gearbox-protocol/integrations-v3/contracts/helpers/infinifi/InfinifiUnwindingPhantomToken.sol";
import {
IInfinifiLockingController,
IInfinifiUnwindingModule,
UnwindingPosition
} from "@gearbox-protocol/integrations-v3/contracts/integrations/infinifi/IInfinifiGateway.sol";
import {
IInfinifiUnwindingGateway,
UserUnwindingData
} from "@gearbox-protocol/integrations-v3/contracts/interfaces/infinifi/IInfinifiUnwindingGateway.sol";
import {IInfinifiGatewayAdapter} from
"@gearbox-protocol/integrations-v3/contracts/interfaces/infinifi/IInfinifiGatewayAdapter.sol";
import {IInfinifiUnwindingGatewayAdapter} from
"@gearbox-protocol/integrations-v3/contracts/interfaces/infinifi/IInfinifiUnwindingGatewayAdapter.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {WAD} from "@gearbox-protocol/core-v3/contracts/libraries/Constants.sol";
contract InfinifiWithdrawalSubcompressor is IWithdrawalSubcompressor {
using WithdrawalLib for PendingWithdrawal[];
uint256 public constant version = 3_10;
bytes32 public constant contractType = "GLOBAL::INFINIFI_WD_SC";
uint256 internal constant EPOCH = 1 weeks;
uint256 internal constant EPOCH_OFFSET = 3 days;
function getWithdrawableAssets(address creditManager, address token)
external
view
returns (WithdrawableAsset[] memory)
{
address infinifiUnwindingGateway = InfinifiUnwindingPhantomToken(token).infinifiUnwindingGateway();
address asset = IInfinifiUnwindingGateway(infinifiUnwindingGateway).iUSD();
address unwindingGatewayAdapter = ICreditManagerV3(creditManager).contractToAdapter(infinifiUnwindingGateway);
address[] memory lockedTokens =
IInfinifiUnwindingGatewayAdapter(unwindingGatewayAdapter).getAllowedLockedTokens();
WithdrawableAsset[] memory withdrawableAssets = new WithdrawableAsset[](lockedTokens.length);
for (uint256 i = 0; i < lockedTokens.length; i++) {
uint32 unwindingEpochs =
IInfinifiGatewayAdapter(unwindingGatewayAdapter).lockedTokenToUnwindingEpoch(lockedTokens[i]);
withdrawableAssets[i] = WithdrawableAsset(
lockedTokens[i], token, asset, _getClaimableAtFromCurrent(unwindingEpochs) - block.timestamp
);
}
return withdrawableAssets;
}
function getCurrentWithdrawals(address creditAccount, address token)
external
view
returns (ClaimableWithdrawal[] memory, PendingWithdrawal[] memory)
{
address infinifiUnwindingGateway = InfinifiUnwindingPhantomToken(token).infinifiUnwindingGateway();
ClaimableWithdrawal[] memory claimableWithdrawals = new ClaimableWithdrawal[](1);
claimableWithdrawals[0] = _getClaimableWithdrawal(creditAccount, token, infinifiUnwindingGateway);
if (claimableWithdrawals[0].outputs.length == 0 || claimableWithdrawals[0].outputs[0].amount == 0) {
claimableWithdrawals = new ClaimableWithdrawal[](0);
}
PendingWithdrawal[] memory pendingWithdrawals = _getPendingWithdrawals(creditAccount, infinifiUnwindingGateway);
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)
{
address infinifiUnwindingGateway = InfinifiUnwindingPhantomToken(withdrawalToken).infinifiUnwindingGateway();
address unwindingGatewayAdapter = ICreditManagerV3(ICreditAccountV3(creditAccount).creditManager())
.contractToAdapter(infinifiUnwindingGateway);
uint32 unwindingEpochs = IInfinifiGatewayAdapter(unwindingGatewayAdapter).lockedTokenToUnwindingEpoch(token);
if (unwindingEpochs == 0) {
return requestableWithdrawal;
}
requestableWithdrawal.token = token;
requestableWithdrawal.amountIn = amount;
requestableWithdrawal.outputs = new WithdrawalOutput[](1);
requestableWithdrawal.requestCalls = new MultiCall[](1);
requestableWithdrawal.claimableAt = _getClaimableAtFromCurrent(unwindingEpochs);
requestableWithdrawal.requestCalls[0] = MultiCall(
address(unwindingGatewayAdapter),
abi.encodeCall(IInfinifiUnwindingGatewayAdapter.startUnwinding, (amount, unwindingEpochs))
);
requestableWithdrawal.outputs[0] = WithdrawalOutput(withdrawalToken, true, 0);
address lockingController = IInfinifiUnwindingGateway(infinifiUnwindingGateway).lockingController();
uint256 exchangeRate = IInfinifiLockingController(lockingController).exchangeRate(unwindingEpochs);
requestableWithdrawal.outputs[0].amount = amount * exchangeRate / WAD;
return requestableWithdrawal;
}
function _getPendingWithdrawals(address creditAccount, address unwindingGateway)
internal
view
returns (PendingWithdrawal[] memory pendingWithdrawals)
{
address asset = IInfinifiUnwindingGateway(unwindingGateway).iUSD();
UserUnwindingData memory userUnwindingData =
IInfinifiUnwindingGateway(unwindingGateway).getUserUnwindingData(creditAccount);
if (userUnwindingData.unwindingTimestamp == 0) {
return pendingWithdrawals;
}
if (
block.timestamp
< _getClaimableAtFromUnwindingPosition(unwindingGateway, userUnwindingData.unwindingTimestamp)
) {
pendingWithdrawals = new PendingWithdrawal[](1);
pendingWithdrawals[0].token = IInfinifiLockingController(
IInfinifiUnwindingGateway(unwindingGateway).lockingController()
).shareToken(userUnwindingData.unwindingEpochs);
pendingWithdrawals[0].expectedOutputs = new WithdrawalOutput[](1);
pendingWithdrawals[0].expectedOutputs[0] = WithdrawalOutput(
asset, false, InfinifiUnwindingGateway(unwindingGateway).getPendingAssets(creditAccount)
);
pendingWithdrawals[0].claimableAt =
_getClaimableAtFromUnwindingPosition(unwindingGateway, userUnwindingData.unwindingTimestamp);
}
return pendingWithdrawals;
}
function _getClaimableWithdrawal(address creditAccount, address withdrawalToken, address unwindingGateway)
internal
view
returns (ClaimableWithdrawal memory withdrawal)
{
address asset = IInfinifiUnwindingGateway(unwindingGateway).iUSD();
UserUnwindingData memory userUnwindingData =
IInfinifiUnwindingGateway(unwindingGateway).getUserUnwindingData(creditAccount);
if (userUnwindingData.unwindingTimestamp == 0) {
return withdrawal;
}
withdrawal.token = IInfinifiLockingController(IInfinifiUnwindingGateway(unwindingGateway).lockingController())
.shareToken(userUnwindingData.unwindingEpochs);
withdrawal.outputs = new WithdrawalOutput[](1);
withdrawal.outputs[0] = WithdrawalOutput(asset, false, 0);
if (userUnwindingData.isWithdrawn) {
withdrawal.outputs[0].amount = userUnwindingData.unclaimedAssets;
} else {
uint256 pendingAssets = InfinifiUnwindingGateway(unwindingGateway).getPendingAssets(creditAccount);
if (
block.timestamp
< _getClaimableAtFromUnwindingPosition(unwindingGateway, userUnwindingData.unwindingTimestamp)
|| pendingAssets == 0
) {
return withdrawal;
}
withdrawal.outputs[0].amount = pendingAssets;
}
withdrawal.withdrawalPhantomToken = withdrawalToken;
withdrawal.withdrawalTokenSpent = withdrawal.outputs[0].amount;
withdrawal.claimCalls = new MultiCall[](1);
address unwindingGatewayAdapter =
ICreditManagerV3(ICreditAccountV3(creditAccount).creditManager()).contractToAdapter(unwindingGateway);
withdrawal.claimCalls = new MultiCall[](1);
withdrawal.claimCalls[0] = MultiCall(
address(unwindingGatewayAdapter),
abi.encodeCall(IInfinifiUnwindingGatewayAdapter.withdraw, (withdrawal.outputs[0].amount))
);
return withdrawal;
}
function _getClaimableAtFromUnwindingPosition(address unwindingGateway, uint256 unwindingTimestamp)
internal
view
returns (uint256)
{
address unwindingModule = IInfinifiUnwindingGateway(unwindingGateway).unwindingModule();
UnwindingPosition memory position =
IInfinifiUnwindingModule(unwindingModule).positions(_unwindingId(unwindingGateway, unwindingTimestamp));
uint32 claimableEpoch = position.toEpoch;
return _timestampFromEpoch(claimableEpoch);
}
function _getClaimableAtFromCurrent(uint32 unwindingEpochs) internal view returns (uint256) {
uint32 currentEpoch = _epochFromTimestamp(block.timestamp);
return _timestampFromEpoch(unwindingEpochs + currentEpoch + 1);
}
function _epochFromTimestamp(uint256 timestamp) internal pure returns (uint32) {
return uint32((timestamp - EPOCH_OFFSET) / EPOCH);
}
function _timestampFromEpoch(uint32 epoch) internal pure returns (uint256) {
return uint256(epoch) * EPOCH + EPOCH_OFFSET;
}
function _unwindingId(address unwindingGateway, uint256 unwindingTimestamp) internal pure returns (bytes32) {
return keccak256(abi.encode(unwindingGateway, unwindingTimestamp));
}
}
"
},
"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/infinifi/InfinifiUnwindingGateway.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 {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
import {SanityCheckTrait} from "@gearbox-protocol/core-v3/contracts/traits/SanityCheckTrait.sol";
import {
IInfinifiGateway,
IInfinifiLockingController,
IInfinifiUnwindingModule,
UnwindingPosition
} from "../../integrations/infinifi/IInfinifiGateway.sol";
import {IInfinifiUnwindingGateway, UserUnwindingData} from "../../interfaces/infinifi/IInfinifiUnwindingGateway.sol";
/// @title Infinifi Withdrawal Gateway
contract InfinifiUnwindingGateway is IInfinifiUnwindingGateway {
bytes32 public constant override contractType = "GATEWAY::INFINIFI_UNWINDING";
uint256 public constant override version = 3_10;
uint256 internal constant EPOCH = 1 weeks;
uint256 internal constant EPOCH_OFFSET = 3 days;
address public immutable iUSD;
address public immutable infinifiGateway;
address public immutable lockingController;
address public immutable unwindingModule;
uint256 public lastUnwindingTimestamp;
mapping(address => UserUnwindingData) internal userToUnwindingData;
constructor(address _infinifiGateway) {
infinifiGateway = _infinifiGateway;
iUSD = IInfinifiGateway(infinifiGateway).getAddress("receiptToken");
lockingController = IInfinifiGateway(infinifiGateway).getAddress("lockingController");
unwindingModule = IInfinifiLockingController(lockingController).unwindingModule();
}
function startUnwinding(uint256 shares, uint32 unwindingEpochs) external {
if (block.timestamp == lastUnwindingTimestamp) revert MoreThanOneUnwindingPerBlockException();
UserUnwindingData storage userUnwindingData = userToUnwindingData[msg.sender];
if (userUnwindingData.unwindingTimestamp != 0) revert UserAlreadyUnwindingException();
address lockedToken = IInfinifiLockingController(lockingController).shareToken(unwindingEpochs);
IERC20(lockedToken).transferFrom(msg.sender, address(this), shares);
IERC20(lockedToken).approve(infinifiGateway, shares);
userUnwindingData.shares = shares;
userUnwindingData.unwindingTimestamp = block.timestamp;
userUnwindingData.isWithdrawn = false;
userUnwindingData.unwindingEpochs = unwindingEpochs;
lastUnwindingTimestamp = block.timestamp;
IInfinifiGateway(infinifiGateway).startUnwinding(shares, unwindingEpochs);
}
function withdraw(uint256 amount) external {
UserUnwindingData memory userUnwindingData = userToUnwindingData[msg.sender];
if (userUnwindingData.unwindingTimestamp == 0) revert UserNotUnwindingException();
uint256 claimableTimestamp = _getClaimableTimestamp(userUnwindingData);
if (block.timestamp < claimableTimestamp) revert UnwindingNotClaimableException();
if (!userUnwindingData.isWithdrawn) {
uint256 balanceBefore = IERC20(iUSD).balanceOf(address(this));
IInfinifiGateway(infinifiGateway).withdraw(userUnwindingData.unwindingTimestamp);
userUnwindingData.isWithdrawn = true;
userUnwindingData.unclaimedAssets = IERC20(iUSD).balanceOf(address(this)) - balanceBefore;
}
uint256 pendingAssets = _getPendingAssets(userUnwindingData);
if (pendingAssets < amount) revert InsufficientPendingAssetsException();
userUnwindingData.unclaimedAssets -= amount;
IERC20(iUSD).transfer(msg.sender, amount);
if (userUnwindingData.unclaimedAssets <= 1) {
userUnwindingData.unwindingTimestamp = 0;
userUnwindingData.shares = 0;
userUnwindingData.unclaimedAssets = 0;
userUnwindingData.unwindingEpochs = 0;
userUnwindingData.isWithdrawn = false;
}
userToUnwindingData[msg.sender] = userUnwindingData;
}
function getPendingAssets(address user) public view returns (uint256) {
return _getPendingAssets(userToUnwindingData[user]);
}
function getUserUnwindingData(address user) external view returns (UserUnwindingData memory) {
return userToUnwindingData[user];
}
function _getPendingAssets(UserUnwindingData memory userUnwindingData) internal view returns (uint256) {
if (userUnwindingData.unwindingTimestamp == 0) return 0;
return userUnwindingData.isWithdrawn
? userUnwindingData.unclaimedAssets
: IInfinifiUnwindingModule(unwindingModule).balanceOf(address(this), userUnwindingData.unwindingTimestamp);
}
function _getClaimableTimestamp(UserUnwindingData memory userUnwindingData) internal view returns (uint256) {
UnwindingPosition memory position =
IInfinifiUnwindingModule(unwindingModule).positions(_unwindingId(userUnwindingData.unwindingTimestamp));
uint256 claimableEpoch = position.toEpoch;
return claimableEpoch * EPOCH + EPOCH_OFFSET;
}
function _unwindingId(uint256 unwindingTimestamp) internal view returns (bytes32) {
return keccak256(abi.encode(address(this), unwindingTimestamp));
}
}
"
},
"lib/@gearbox-protocol/integrations-v3/contracts/helpers/infinifi/InfinifiUnwindingPhantomToken.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 {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {PhantomERC20} from "../PhantomERC20.sol";
import {IPhantomToken} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IPhantomToken.sol";
import {IInfinifiUnwindingGateway} from "../../interfaces/infinifi/IInfinifiUnwindingGateway.sol";
/// @title Infinifi Unwinding phantom token
/// @notice Phantom ERC-20 token that represents the balance of the pending and claimable withdrawals in Infinifi Unwinding Gateway
contract InfinifiUnwindingPhantomToken is PhantomERC20, Ownable, IPhantomToken {
event SetClaimer(address indexed claimer);
error SubvaultClaimerMismatchException();
bytes32 public constant override contractType = "PHANTOM_TOKEN::INFINIFI_UNWIND";
uint256 public constant override version = 3_10;
address public immutable infinifiUnwindingGateway;
/// @notice Constructor
/// @param _infinifiUnwindingGateway The Infinifi Unwinding Gateway where the pending assets are tracked
constructor(address _infinifiUnwindingGateway)
PhantomERC20(
IInfinifiUnwindingGateway(_infinifiUnwindingGateway).iUSD(),
"Infinifi Unwinding iUSD",
"wdiUSD",
IERC20Metadata(IInfinifiUnwindingGateway(_infinifiUnwindingGateway).iUSD()).decimals()
)
{
infinifiUnwindingGateway = _infinifiUnwindingGateway;
}
/// @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) {
return IInfinifiUnwindingGateway(infinifiUnwindingGateway).getPendingAssets(account);
}
/// @notice Returns phantom token's target contract and underlying
function getPhantomTokenInfo() external view override returns (address, address) {
return (infinifiUnwindingGateway, underlying);
}
function serialize() external view override returns (bytes memory) {
return abi.encode(infinifiUnwindingGateway, underlying);
}
}
"
},
"lib/@gearbox-protocol/integrations-v3/contracts/integrations/infinifi/IInfinifiGateway.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.23;
struct UnwindingPosition {
uint256 shares;
uint32 fromEpoch;
uint32 toEpoch;
uint256 fromRewardWeight;
uint256 rewardWeightDecrease;
}
interface IInfinifiGateway {
function mint(address to, uint256 amount) external;
function stake(address to, uint256 amount) external;
function unstake(address to, uint256 amount) external;
function createPosition(uint256 amount, uint32 unwindingEpochs, address recipient) external;
function startUnwinding(uint256 shares, uint32 unwindingEpochs) external;
function withdraw(uint256 unwindingTimestamp) external;
function redeem(address to, uint256 amount, uint256 minAssetsOut) external;
function claimRedemption() external;
function getAddress(string memory name) external view returns (address);
}
interface IInfinifiMintController {
function receiptToken() external view returns (address);
function assetToReceipt(uint256 _assetAmount) external view returns (uint256);
}
interface IInfinifiLockingController {
function getEnabledBuckets() external view returns (uint32[] memory);
function shareToken(uint32 unwindingEpochs) external view returns (address);
function unwindingModule() external view returns (address);
function exchangeRate(uint32 unwindingEpochs) external view returns (uint256);
}
interface IInfinifiUnwindingModule {
function balanceOf(address user, uint256 unwindingTimestamp) external view returns (uint256);
function positions(bytes32 id) external view returns (UnwindingPosition memory);
}
interface IInfinifiRedeemController {
function receiptToAsset(uint256 amount) external view returns (uint256);
function accounting() external view returns (address);
}
interface IInfinifiAccounting {
function totalAssetsOf(address asset, uint256 farmType) external view returns (uint256);
}
"
},
"lib/@gearbox-protocol/integrations-v3/contracts/interfaces/infinifi/IInfinifiUnwindingGateway.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";
struct UserUnwindingData {
uint256 shares;
uint32 unwindingEpochs;
uint256 unwindingTimestamp;
uint256 unclaimedAssets;
bool isWithdrawn;
}
interface IInfinifiUnwindingGatewayExceptions {
/// @notice Thrown when a user attempts a second unwinding in the same block
error MoreThanOneUnwindingPerBlockException();
/// @notice Thrown when a user attempts to start unwinding while already unwinding
error UserAlreadyUnwindingException();
/// @notice Thrown when a user attempts to withdraw while not unwinding
error UserNotUnwindingException();
/// @notice Thrown when a user attempts to withdraw an unwinding that is not claimable
error UnwindingNotClaimableException();
/// @notice Thrown when a user attempts to withdraw an unwinding for more assets than are pending
error InsufficientPendingAssetsException();
}
interface IInfinifiUnwindingGateway is IVersion, IInfinifiUnwindingGatewayExceptions {
function iUSD() external view returns (address);
function lockingController() external view returns (address);
function unwindingModule() external view returns (address);
function getUserUnwindingData(address user) external view returns (UserUnwindingData memory);
function startUnwinding(uint256 shares, uint32 unwindingEpochs) external;
function withdraw(uint256 unwindingTimestamp) external;
function getPendingAssets(address user) external view returns (uint256);
}
"
},
"lib/@gearbox-protocol/integrations-v3/contracts/interfaces/infinifi/IInfinifiGatewayAdapter.sol": {
"content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {IAdapter} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IAdapter.sol";
struct LockedTokenStatus {
address lockedToken;
uint32 unwindingEpochs;
bool allowed;
}
interface IInfinifiGatewayEvents {
event SetLockedTokenStatus(address lockedToken, uint32 unwindingEpochs, bool allowed);
}
interface IInfinifiGatewayExceptions {
/// @notice Thrown when the passed unwinding epochs for the locked token do not match actual unwinding epochs in Infinifi
error LockedTokenUnwindingEpochsMismatchException();
/// @notice Thrown when the locked token is not allowed
error LockedTokenNotAllowedException();
}
/// @title Infinifi Gateway adapter interface
interface IInfinifiGatewayAdapter is IAdapter, IInfinifiGatewayExceptions, IInfinifiGatewayEvents {
function usdc() external view returns (address);
function iusd() external view returns (address);
function siusd() external view returns (address);
function lockedTokenToUnwindingEpoch(address lockedToken) external view returns (uint32);
function mint(address to, uint256 amount) external returns (bool useSafePrices);
function mintDiff(uint256 leftoverAmount) external returns (bool useSafePrices);
function stake(address to, uint256 amount) external returns (bool useSafePrices);
function stakeDiff(uint256 leftoverAmount) external returns (bool useSafePrices);
function unstake(address to, uint256 amount) external returns (bool useSafePrices);
function unstakeDiff(uint256 leftoverAmount) external returns (bool useSafePrices);
function createPosition(uint256 amount, uint32 unwindingEpochs) external returns (bool useSafePrices);
function createPositionDiff(uint256 leftoverAmount, uint32 unwindingEpochs) external returns (bool useSafePrices);
function redeem(address to, uint256 amount, uint256 minAssetsOut) external returns (bool useSafePrices);
function redeemDiff(uint256 leftoverAmount, uint256 minRateRAY) external returns (bool useSafePrices);
function claimRedemption() external returns (bool useSafePrices);
function getAllowedLockedTokens() external view returns (address[] memory);
function setLockedTokenBatchStatus(LockedTokenStatus[] calldata lockedTokens) external;
}
"
},
"lib/@gearbox-protocol/integrations-v3/contracts/interfaces/infinifi/IInfinifiUnwindingGatewayAdapter.sol": {
"content": "// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {IPhantomTokenAdapter} from "../IPhantomTokenAdapter.sol";
struct LockedTokenStatus {
address lockedToken;
uint32 unwindingEpochs;
bool allowed;
}
interface IInfinifiGatewayEvents {
event SetLockedTokenStatus(address lockedToken, uint32 unwindingEpochs, bool allowed);
}
interface IInfinifiGatewayExceptions {
/// @notice Thrown when the passed unwinding epochs for the locked token do not match actual unwinding epochs in Infinifi
error LockedTokenUnwindingEpochsMismatchException();
/// @notice Thrown when the locked token is not allowed
error LockedTokenNotAllowedException();
}
interface IInfinifiUnwindingGatewayAdapter is
IPhantomTokenAdapter,
IInfinifiGatewayExceptions,
IInfinifiGatewayEvents
{
function lockedTokenToUnwindingEpoch(address lockedToken) external view returns (uint32);
function startUnwinding(uint256 shares, uint32 unwindingEpochs) external returns (bool);
function withdraw(uint256 amount) external returns (bool);
function getAllowedLockedTokens() external view returns (address[] memory);
function setLockedTokenBatchStatus(LockedTokenStatus[] calldata lockedTokens) external;
}
"
},
"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/libraries/Constants.sol": {
"content": "// 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);
"
},
"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": "//
Submitted on: 2025-10-07 11:31:08
Comments
Log in to comment.
No comments yet.