Overview
The Credit Facade V3 provides the main user interface for opening, closing, and liquidating leveraged positions in the Credit Manager. It implements the multicall functionality that allows users to batch operations and interact with external protocols through adapters.
Contract Location: contracts/credit/CreditFacadeV3.sol
Interface: ICreditFacadeV3.sol
Key Features
- Account opening with optional multicall
- Account closure and liquidation
- Multicall for batched operations
- Bot management for automated account operations
- Debt and quota size validation
- Degen NFT whitelist mode support
- Forbidden token safeguards
- Partial liquidation support
State Variables
Immutable Variables
Contract version (always returns 3_10)
Contract type identifier (always returns "CREDIT_FACADE")
Credit manager connected to this credit facade
Credit manager’s underlying token
Pool’s treasury address to pay fees to
Price feed store for on-demand price updates
WETH token address for ETH wrapping
Degen NFT address (or address(0) if not enabled)
Bot list contract address
Whether credit facade is expirable
Maximum quota size as a multiple of maxDebt (always returns 2)
Mutable Variables
Expiration timestamp (0 if not set)
maxDebtPerBlockMultiplier
Maximum amount that can be borrowed in a single block as a multiple of maxDebt
Credit account debt limits (minDebt and maxDebt)
Bitmask encoding a set of forbidden tokens
Contract that enforces policy on liquidations with loss
Core Functions
Account Management
openCreditAccount
function openCreditAccount(
address onBehalfOf,
MultiCall[] calldata calls,
uint256 referralCode
) external payable returns (address creditAccount)
Opens a new credit account and optionally performs a multicall.
Address on whose behalf to open the account
List of calls to perform after opening the account
Referral code for potential rewards (0 if none)
Returns the address of the newly opened account
- Wraps any ETH sent in the function call and sends it back to caller
- If Degen NFT is enabled, burns one from the caller
- Performs a multicall with restrictions (no debt decrease allowed)
- Runs collateral check after the multicall
Reverts if contract is paused or expired. When Degen NFT is enabled, onBehalfOf must equal msg.sender.
closeCreditAccount
function closeCreditAccount(
address creditAccount,
MultiCall[] calldata calls
) external payable
Closes a credit account after performing an optional multicall.
List of calls to perform before closing
- Only the account owner can close their account
- All calls are allowed except debt increase
- Account must have zero debt after the multicall
- Bot permissions are erased upon closure
liquidateCreditAccount
function liquidateCreditAccount(
address creditAccount,
address to,
MultiCall[] calldata calls,
bytes memory lossPolicyData
) external
Liquidates an unhealthy or expired credit account.
Address to transfer underlying surplus to
List of calls to perform before liquidation
Additional data to pass to the loss policy contract
- Only
addCollateral, withdrawCollateral, and adapter calls are allowed
- Remaining token balances cannot increase during the multicall
- If account has bad debt, liquidation must comply with loss policy
- Premium and fees differ for expired vs unhealthy liquidations
Liquidator can fully seize non-enabled tokens. Unclaimed rewards from integrated protocols are at risk.
partiallyLiquidateCreditAccount
function partiallyLiquidateCreditAccount(
address creditAccount,
address token,
uint256 repaidAmount,
uint256 minSeizedAmount,
address to,
PriceUpdate[] calldata priceUpdates
) external returns (uint256 seizedAmount)
Partially liquidates a credit account’s debt in exchange for discounted collateral.
Credit account to liquidate
Collateral token to seize (cannot be underlying)
Amount of underlying to repay
Minimum amount of token to seize (slippage protection)
Account to withdraw seized token to
On-demand price feed updates to apply before calculations
Returns the amount of token seized
- Requires approval for underlying from caller to credit manager
- Uses same liquidation discount and fees as full liquidations
- Runs collateral check after the operation
- If token is a phantom token, it’s withdrawn first and
depositedToken is sent to liquidator
Multicall Functions
multicall
function multicall(
address creditAccount,
MultiCall[] calldata calls
) external payable
Executes a batch of calls allowing users to manage their credit account.
Account to perform calls on
- Wraps any ETH sent and sends it back to caller
- All operations are allowed
- Runs collateral check after the multicall
- Only the account owner can call this function
botMulticall
function botMulticall(
address creditAccount,
MultiCall[] calldata calls
) external
Executes a batch of calls allowing an approved bot to manage a credit account.
Account to perform calls on
- Allowed calls are determined by permissions given by the account owner
- Bot must not be forbidden and must have non-zero permissions
- Runs collateral check after the multicall
Reverts if the calling bot is forbidden or has no permissions for the account.
Multicall Operations
The following operations can be included in multicall arrays:
onDemandPriceUpdates
function onDemandPriceUpdates(PriceUpdate[] memory updates) external
Updates price feeds on-demand. Must be the first call in the multicall if present.
Array of price updates to apply
addCollateral
function addCollateral(address token, uint256 amount) external
Adds collateral to the credit account.
Token to add as collateral
addCollateralWithPermit
function addCollateralWithPermit(
address token,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external
Adds collateral using ERC20 permit for gasless approval.
withdrawCollateral
function withdrawCollateral(
address token,
uint256 amount,
address to
) external
Withdraws collateral from the credit account.
Amount to withdraw (use type(uint256).max for max available minus 1)
Address to transfer token to
increaseDebt
function increaseDebt(uint256 amount) external
Borrows additional funds from the pool.
Amount of underlying to borrow
Enables the “revert on forbidden tokens” flag, requiring safe collateral check.
decreaseDebt
function decreaseDebt(uint256 amount) external
Repays debt to the pool.
Amount of underlying to repay
updateQuota
function updateQuota(
address token,
int96 quotaChange,
uint96 minQuota
) external
Increases or decreases quota for a token.
Token to update quota for (cannot be underlying)
Requested quota change (positive to increase, negative to decrease)
Minimum resulting quota (slippage protection)
Increasing quota for forbidden tokens is not allowed.
setBotPermissions
function setBotPermissions(
address bot,
uint192 permissions
) external
Sets permissions for a bot to manage the credit account.
Permission flags (cannot include SET_BOT_PERMISSIONS_PERMISSION)
storeExpectedBalances
function storeExpectedBalances(BalanceDelta[] memory balanceDeltas) external
Stores expected balances for comparison after adapter calls.
Array of token addresses and expected balance changes
compareBalances
function compareBalances() external
Compares current balances with previously stored expected balances.
Reverts with BalanceLessThanExpectedException if any balance is below expected.
setFullCheckParams
function setFullCheckParams(
uint256[] memory collateralHints,
uint16 minHealthFactor
) external
Sets custom parameters for the collateral check.
Array of token masks to check first (for gas optimization)
Custom health factor threshold in bps (must be >= 10000)
Configuration Functions
setExpirationDate
function setExpirationDate(uint40 newExpirationDate) external
Sets the credit facade expiration timestamp.
Only callable by credit configurator. Reverts if facade is not expirable.
setDebtLimits
function setDebtLimits(
uint128 newMinDebt,
uint128 newMaxDebt,
uint8 newMaxDebtPerBlockMultiplier
) external
Sets debt limits per credit account.
newMaxDebtPerBlockMultiplier
New max debt per block multiplier (type(uint8).max to disable check)
Prevents further borrowing in the current block unless the check is disabled.
setLossPolicy
function setLossPolicy(address newLossPolicy) external
Sets a new loss policy contract.
setTokenAllowance
function setTokenAllowance(
address token,
AllowanceAction allowance
) external
Changes a token’s forbidden status.
Token to change status for
Pause/Unpause
function pause() external
function unpause() external
Pauses or unpauses the contract.
pause() can only be called by pausable admins
unpause() can only be called by unpausable admins
- When paused, liquidations remain open only to emergency liquidators
Data Structures
MultiCall
struct MultiCall {
address target; // Call target (facade or adapter)
bytes callData; // Call data
}
DebtLimits
struct DebtLimits {
uint128 minDebt; // Minimum debt per account
uint128 maxDebt; // Maximum debt per account
}
FullCheckParams
struct FullCheckParams {
uint256[] collateralHints; // Optional token masks
uint16 minHealthFactor; // Health factor threshold in bps
}
Events
OpenCreditAccount
event OpenCreditAccount(
address indexed creditAccount,
address indexed onBehalfOf,
address indexed caller,
uint256 referralCode
)
CloseCreditAccount
event CloseCreditAccount(
address indexed creditAccount,
address indexed borrower
)
LiquidateCreditAccount
event LiquidateCreditAccount(
address indexed creditAccount,
address indexed liquidator,
address to,
uint256 remainingFunds
)
PartiallyLiquidateCreditAccount
event PartiallyLiquidateCreditAccount(
address indexed creditAccount,
address indexed token,
address indexed liquidator,
uint256 repaidDebt,
uint256 seizedCollateral,
uint256 fee
)
StartMultiCall / FinishMultiCall
event StartMultiCall(address indexed creditAccount, address indexed caller)
event FinishMultiCall()
Execute
event Execute(
address indexed creditAccount,
address indexed targetContract
)
Emitted when an external contract call is made during multicall.
Example Usage
Opening an Account and Borrowing
MultiCall[] memory calls = new MultiCall[](2);
// Add collateral
calls[0] = MultiCall({
target: address(creditFacade),
callData: abi.encodeCall(
ICreditFacadeV3Multicall.addCollateral,
(USDC, 10000e6)
)
});
// Increase debt
calls[1] = MultiCall({
target: address(creditFacade),
callData: abi.encodeCall(
ICreditFacadeV3Multicall.increaseDebt,
(5000e6)
)
});
address account = creditFacade.openCreditAccount{
value: 0
}(msg.sender, calls, 0);
Multicall with Adapter
MultiCall[] memory calls = new MultiCall[](1);
// Call Uniswap adapter to swap
calls[0] = MultiCall({
target: uniswapAdapter,
callData: abi.encodeCall(
IUniswapV3Adapter.exactInputSingle,
(params)
)
});
creditFacade.multicall(creditAccount, calls);
Closing an Account
MultiCall[] memory calls = new MultiCall[](1);
// Decrease debt to zero
calls[0] = MultiCall({
target: address(creditFacade),
callData: abi.encodeCall(
ICreditFacadeV3Multicall.decreaseDebt,
(type(uint256).max)
)
});
creditFacade.closeCreditAccount(creditAccount, calls);