Deleverage / Fold
Overview
Curvance PositionManagers are router-style contracts that wrap multi-step leverage and deleverage actions inside a single isolated market. For deleveraging, the PositionManager withdraws collateral-side assets, runs the manager-specific exit or swap path, repays debt, and returns defined leftover balances while the cTokens and MarketManager enforce market listing, PositionManager authorization, repayment rules, redemption rules, account liquidity, and cooldown checks.
Key Components
The deleveraging flow involves:
BasePositionManager: shareddeleverageanddeleverageForentrypoints, callback handling, delegation checks, reentrancy protection, protocol fee handling, and pre/post account-value slippage checks.Concrete PositionManagers: asset-specific conversion logic for simple ERC20 routes, vault routes, Pendle routes, Velodrome routes, and Aerodrome routes.
MarketManager: isolated-market listing, PositionManager authorization, account-status checks, repayment review, redemption review, pause state, caps, and cooldown enforcement.cTokens and
BorrowableCToken: the collateral-side cToken executeswithdrawByPositionManager, and the debt-side borrowable cToken receives repayment throughrepayFor. Live cTokens are not separate "collateral cToken" and "borrowable cToken" contract types; borrowability is a per-market configuration controlled bydebtCaps(cToken).
Deleverage Process Flow
The position unwinding flow follows these key steps:

Data Flow
Initiation: The position unwinding flow starts when the user calls
deleverage(action, slippage)for their own account, or an approved delegate callsdeleverageFor(action, account, slippage). Theactionargument is aDeleverageActioncontaining:cToken: the cToken to withdraw from.collateralAssets: the amount of that cToken's underlying asset to redeem, not cToken shares.borrowableCToken: the debt-side cToken to repay.repayAssets: the minimum debt-asset balance the PositionManager must hold after the route.swapActions: manager-specific swap instructions.auxData: manager-specific auxiliary data.
Position Token Withdrawal:
The PositionManager validates the action and calls
action.cToken.withdrawByPositionManager(action.collateralAssets, account, action). The cToken accrues, computes the shares needed withpreviewWithdrawlogic, withdraws the underlying asset to the PositionManager, and then callsonRedeem(...)so the PositionManager can run the deleverage callback.Collateral Conversion:
Collateral conversion is implemented by the concrete PositionManager's
_swapCollateralAssetToDebtAsset(action)hook. The exact route is manager-specific.SimplePositionManagerrequires exactly one collateral-asset-to-debt-asset swap. Vault managers may redeem vault shares first and can skip the external swap when the vault output already matches the debt asset. Pendle and Velodrome or Aerodrome managers exit their protocol position first, then optionally run one or more swaps whose endpoints must match the manager's expected output and final debt asset.Debt Repayment:
Debt repayment happens in the base deleverage callback after the manager-specific route finishes. The PositionManager checks that it holds at least
action.repayAssetsof the debt asset. It then reads the owner's fresh debt withdebtBalanceUpdated(owner)and repaysmin(assetsHeld, currentDebt)throughborrowableCToken.repayFor(repayAssets, owner).repayAssetsis a minimum debt-asset output floor for the deleverage route. It is not always the exact final repayment amount, and setting it to zero reverts in the PositionManager.Asset Return:
After repayment, the base callback returns the balances it explicitly sweeps:
remaining debt asset;
remaining withdrawn collateral asset;
remaining balances of each
swapActions[i].outputToken.
Do not describe this as a blanket refund of every possible intermediate token. PositionManagers are router-style contracts and should not be treated as user-specific custody for arbitrary stranded balances.
State Transitions
During deleverage, validation happens across the PositionManager, the collateral cToken, the debt cToken, and the MarketManager:

deleverageForchecks delegation on the PositionManager contract._deleveragerejectsrepayAssets == 0and requiresaction.cTokento be listed in the connected MarketManager.withdrawByPositionManagerrequires the caller to be an enabled PositionManager, accrues the cToken, computes the shares needed forcollateralAssets, withdraws the underlying to the PositionManager, and runs theonRedeemcallback.onRedeemrequires the debt-sideborrowableCTokento be listed and verifies that the callback token and amount match the action.repayForaccrues debt, checks the repayment throughMarketManager.canRepayWithReview(...), and can revert during the hold period or if a partial repay would leave debt belowMIN_LOAN_SIZE.The final redemption review runs through
MarketManager.canRedeemWithCollateralRemoval(...), which enforces redeem pause state, transfer eligibility, and account liquidity for any posted collateral that is removed.
Protocol-Specific Implementations
Curvance supports deleverage through concrete PositionManager implementations:
SimplePositionManager: generic non-native ERC20 paths using a single swap.SingleSidedVaultPositionManager: ERC4626-style vault positions that use the simple deleverage path.DualSidedVaultPositionManager: vault positions that redeem vault shares before optionally swapping into the debt asset.NativeVaultPositionManager: native-token vault positions that inherit the simple deleverage path.PendlePTPositionManager: Pendle principal-token positions.
Each implementation provides specialized logic for handling the unique characteristics of its respective protocol when exiting positions.
Access Control and Delegation
PositionManager deleverage operations can be initiated by:
the position owner through
deleverage(action, slippage);a delegate through
deleverageFor(action, account, slippage), if the account approved that delegate on the specific PositionManager contract withsetDelegateApproval(delegate, true).
Slippage Protection
Deleverage has several slippage-related controls:
the top-level
slippageparameter ondeleverageanddeleverageFor, checked byBasePositionManager.checkSlippageagainst the account's collateral-minus-debt value before and after the action;each
SwapperLib.Swap.slippage, checked by_swapSafeusing oracle-priced input and output value;external swap calldata minimum-output checks, enforced through the approved calldata checker for the swap target;
manager-specific floors, such as
repayAssets, Pendle minimum-output fields, or Velodrome PT exit and route constraints.
The top-level checkSlippage modifier is a sanity check, not a complete replacement for route quoting and swap-level limits.
Example Flow
A typical simple ERC20 deleverage flow:
The user has a WETH collateral position and USDC debt in the same isolated market.
The user calls
deleverage(action, slippage), whereaction.cTokenis the WETH cToken andaction.borrowableCTokenis the USDC cToken.The PositionManager calls
withdrawByPositionManager(action.collateralAssets, owner, action)on the WETH cToken.The WETH cToken withdraws WETH underlying to the PositionManager and calls
onRedeem.The concrete PositionManager route swaps WETH to USDC according to
swapActions.The base callback checks that the PositionManager holds at least
action.repayAssetsUSDC, reads fresh debt, and callsrepayFor(...)on the USDC cToken.Remaining swept balances are returned to the owner.
Swap-target and debt-cToken allowances opened by the flow are removed when the relevant helper reaches its cleanup path.
The flow reduces collateral and debt in one transaction while still relying on cToken and MarketManager checks for repayment, redemption, liquidity, pause state, cooldowns, and route slippage.
User Interaction Functions
deleverage()
Description: Deleverages an active Curvance position for msg.sender by redeeming collateral-side assets, converting them through the concrete PositionManager route, repaying debt, and checking pre/post account value through checkSlippage.
Contract: BasePositionManager, inherited by the concrete PositionManager used for the market.
Function signature:
DeleverageAction
action
Struct containing the collateral cToken, collateral underlying amount, debt cToken, minimum debt-asset output floor, swap route, and manager-specific auxiliary data.
uint256
slippage
Top-level PositionManager slippage tolerance in WAD, checked against account value before and after the action.
Events:
deleverageFor()
Description: Deleverages an active Curvance position for account through PositionManager delegation. The account must approve the caller on the specific PositionManager contract with setDelegateApproval(delegate, true).
Contract: BasePositionManager, inherited by the concrete PositionManager used for the market.
Function signature:
DeleverageAction
action
Structure containing deleverage operation details including position token, collateral amount, borrow token, swap data, repay amount, and auxiliary data.
address
account
The account to deleverage an active Curvance position for.
uint256
slippage
Slippage accepted by the user for the deleverage action, in WAD (1e18).
Events:
Last updated
Was this helpful?