> For the complete documentation index, see [llms.txt](https://docs.curvance.com/app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.curvance.com/app/developer-docs/position-management/leverage.md).

# Leverage

### Overview

Leveraged positions in Curvance allow users to increase their exposure to certain assets by borrowing additional capital against their collateral. This documentation explains the core mechanics, data flows, and components involved in creating leveraged positions.

### Core Concepts

#### Position Types

Curvance supports leverage through concrete PositionManager implementations:

* **`SimplePositionManager`:** generic non-native ERC20 positions, such as major or stablecoin assets.
* **`PendlePTPositionManager`:** Pendle principal-token positions.
* **`SingleSidedVaultPositionManager`, `DualSidedVaultPositionManager`, `NativeVaultPositionManager:`**&#x76;ault and native-vault position paths.

#### Key Components

The leverage system involves several interconnected components:

* **`BasePositionManager`:** shared entrypoints, callback handling, delegation checks, reentrancy protection, pre/post account-value slippage checks, and protocol fee handling.
* **Concrete PositionManagers:** asset-specific hooks that convert the borrowed asset into the collateral-side asset or protocol receipt token.
* **`MarketManager`:** market listing, PositionManager authorization, collateral caps, debt caps, account liquidity, borrow pauses, and terminal borrow validation.
* **cTokens and `BorrowableCToken`:** live cTokens share the same underlying implementation family. A cToken can receive deposits and collateral, and it is borrowable in a market only when `marketManager.debtCaps(cToken) > 0`.
* **`SwapperLib` and `CentralRegistry`:** approved external swap calldata, swap-level value checks, and protocol configuration such as `protocolLeverageFee()`.

### Leverage Flow

<figure><img src="/files/aJLi2VenwPWoeNZvlpbu" alt="" width="188"><figcaption></figcaption></figure>

#### 1. Initial Deposit and Request Flow

For a new position, `depositAndLeverage(assets, action, slippage)` pulls the initial underlying asset from the caller, calls `action.cToken.depositAsCollateral(assets, msg.sender)`, and then executes the leverage leg.

For an existing position, `leverage(action, slippage)` adds debt and collateral without a fresh initial deposit. The account still needs enough posted collateral in the same isolated market for the terminal borrow check to pass.

For delegated execution, `leverageFor(action, account, slippage)` requires the `account` to approve the caller on the PositionManager contract being used.

#### 3. Validation & Maximum Borrowing

There is no public `_maxRemainingLeverageOf(account, borrowToken)` function in the protocol contracts. For pre-trade sizing, integrators can use `ProtocolReader.hypotheticalLeverageOf(account, cToken, borrowableCToken, assets, bufferTime)`, which returns the current leverage, theoretical max leverage, adjusted max leverage, maximum debt amount, loan-size error flag, and oracle-error flag.

Execution is still enforced by the contracts. `BasePositionManager` calls `borrowForPositionManager`, the borrowed cToken checks that the caller is an enabled PositionManager, accrues interest, notifies the hold-period cooldown, borrows to the PositionManager, runs the callback, and then calls `marketManager.canBorrow(...)` for the terminal position. Debt caps, borrow pauses, account liquidity, and available cToken liquidity can still make the transaction revert.

```solidity
maxBorrowAmount = _maxRemainingLeverageOf(account, borrowToken)
```

#### 4. Token Borrowing

The system borrows tokens from the specified BorrowableCToken through a callback pattern:

```solidity
action.borrowableCToken.borrowForPositionManager(
    action.borrowAssets,
    account,
    action
);
```

#### 5. Asset Conversion

Depending on the token type, different specialized swapping mechanisms are used:

* **Simple Tokens:** Direct swaps through external DEXs.
* **Vault Tokens:** If a collateral cToken is a vault, and the borrowed cToken is a simple ERC20, the manager converts the borrowed asset into the vault deposit asset, deposits into the vault, and then deposits the minted vault receipt tokens into `action.cToken` as collateral. If the borrowed asset already matches the vault underlying, the swap is skipped. Native vaults unwrap `wrappedNative`, or swap into the native token, before depositing.
* **Pendle PT Tokens:** validates the supplied Pendle market, optionally pre-swaps the borrowed asset into `pendleAction.input.tokenIn`, and uses the Pendle Router to mint PT tokens. The resulting PT balance is deposited into `action.cToken` as collateral.

Each implementation handles the specific logic required for that token type.

### Asset-Specific Flows

#### Simple Token Leverage

Simple ERC20 leverage uses `SimplePositionManager`. The borrowed asset and target collateral asset must be different, and the manager requires one external swap whose `inputToken` is the debt asset, `outputToken` is `action.cToken.asset()`, and `inputAmount` equals the post-fee `action.borrowAssets`. The resulting collateral asset balance is deposited into `action.cToken` as collateral for the owner.

#### Vault Token Leverage

Vault token leverage is handled by vault-specific PositionManagers. The leverage path depends on whether the vault deposit asset is an ERC20 underlying or the chain's native token.

#### Pendle PT Token Leverage

Pendle PT leverage uses `PendlePTPositionManager`. `auxData` decodes as `(address lpToken, uint256 minPtAmount, PendleLib.PendleAction pendleAction)`. If a Curvance external swap is provided, its output must match `pendleAction.input.tokenIn`, and the manager enters the PT path through `PendleLib._enterPendle(..., true, ...)`.

### Protocol Fees

When leveraging, the base callback applies `centralRegistry.protocolLeverageFee()` to the borrowed amount before the manager-specific conversion path runs:

```solidity
uint256 fee = FixedPointMathLib.mulDivUp(
    actionAssets,
    centralRegistry.protocolLeverageFee(),
    BPS
);
```

The fee is BPS-denominated, not WAD-denominated, and it is transferred to `centralRegistry.daoAddress()`. For the simple ERC20 path, `swapAction.inputAmount` must match the net post-fee amount, because `SimplePositionManager` compares `swapAction.inputAmount` against the mutated `action.borrowAssets`.

### Slippage Protection

Leverage has several slippage and sanity checks:

* `checkSlippage(account, slippage)` compares the account's collateral-minus-debt value before and after the action using `marketManager.statusOf(account)`. The contract comments describe this as a sanity check, not the user's only slippage protection.
* `SwapperLib._swapSafe` validates the external swap target through the Central Registry calldata checker, enforces the calldata checker's minimum output, and compares oracle-priced input and output value against `swapAction.slippage`.
* `action.expectedShares` is enforced after the converted collateral asset is deposited into `action.cToken`.

### Security Considerations

#### Position Monitoring

Leveraged positions increase risk exposure and should be monitored closely for:

* Price movements that could trigger liquidations.
* Changes in market conditions affecting collateral value.
* Available liquidity for potential deleveraging.

#### Permission Management

Delegated leverage is checked on the PositionManager being called. `leverageFor(action, account, slippage)` calls `_checkDelegate(account, msg.sender)`, so the account must approve the caller on that PositionManager with `setDelegateApproval(delegate, true)`.

Users can revoke that PositionManager-specific approval with `setDelegateApproval(delegate, false)`. They can also mass-revoke prior delegate approvals across Curvance contracts by calling `centralRegistry.incrementApprovalIndex()`.

### Integration Points

When integrating with the leverage system, consider:

* Providing clear slippage parameters to protect users.
* Understanding the specific asset type and its leverage implementation.
* Ensuring sufficient collateral to avoid immediate liquidation risk.
* Monitoring gas costs, which vary based on the complexity of the leverage operation.

By understanding these core mechanics, developers can effectively integrate with and extend Curvance's leveraged position capabilities.

***

## User Interaction Functions

### Leverage Functions

#### depositAndLeverage()

**Description:** Deposits underlying assets into `action.cToken` as collateral and then leverages the position to increase both collateral and debt. Includes the `checkSlippage` sanity check. The caller must ERC20-approve the PositionManager to pull the initial underlying `assets`; cToken delegate approval is not required for this pre-deposit path because `depositAsCollateral` explicitly allows enabled PositionManager contracts to deposit for the receiver.

**Contract:** PositionManagement

**Function signature:**

```solidity
function depositAndLeverage(
    uint256 assets,
    LeverageAction calldata action,
    uint256 slippage
) external;
```

<table><thead><tr><th width="176">Type</th><th width="153">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of the underlying assets to deposit.</td></tr><tr><td>LeverageStruct</td><td>leverageData</td><td>Structure containing leverage operation details including borrow token, amount, position token, swap data, and auxiliary data.</td></tr><tr><td>uint256</td><td>slippage</td><td>Slippage accepted by the user for the leverage action, in WAD (1e18).</td></tr></tbody></table>

**Events:**

```solidity
// PositionManager entrypoints do not emit a dedicated leverage event.

// ERC20 share and underlying transfers can emit Transfer.
event Transfer(address indexed from, address indexed to, uint256 value);
// PositionManager entrypoints do not emit a dedicated leverage event.

// ERC20 share and underlying transfers can emit Transfer.
event Transfer(address indexed from, address indexed to, uint256 value);

// cToken deposit path, inherited from ERC4626 and emitted by BaseCToken.
event Deposit(address indexed by, address indexed owner, uint256 assets, uint256 shares);

// Collateral posting/removal on BaseCToken.
event CollateralUpdated(uint256 shares, bool increased, address account);

// Borrow path on BorrowableCToken.
event Borrow(uint256 assets, uint256 debtAssetsOwed, address account);

// MarketManager position index updates, emitted when collateral or debt is first added
// to the account's active positions in this market.
event PositionUpdated(address cToken, address account, bool open);
// cToken deposit path, inherited from ERC4626 and emitted by BaseCToken.
event Deposit(address indexed by, address indexed owner, uint256 assets, uint256 shares);
```

***

#### leverage()

**Description:** Leverages an existing Curvance position to increase both collateral and debt. Includes slippage protection through the checkSlippage modifier.

**Contract:** PositionManagement

**Function signature:**

```solidity
function leverage(
    LeverageAction calldata action,
    uint256 slippage
) external
```

<table><thead><tr><th width="169">Type</th><th width="163">Name</th><th>Description</th></tr></thead><tbody><tr><td>LeverageStruct</td><td>leverageData</td><td>Structure containing leverage operation details including borrow token, amount, position token, swap data, and auxiliary data.</td></tr><tr><td>uint256</td><td>slippage</td><td>Slippage accepted by the user for the leverage action, in WAD (1e18).</td></tr></tbody></table>

**Events:**

```solidity
// In CToken.sol
event Transfer(address indexed from, address indexed to, uint256 value);
event Borrow(address account, uint256 amount);
```

```solidity
// Only emitted if this is the user's first position in the specific token
event PositionUpdated(address cToken, address account);
```

***

#### leverageFor()

**Description:** Leverages an existing Curvance position on behalf of another account via delegation. Includes slippage protection through the checkSlippage modifier. Requires delegation approval from the account being leveraged for.

**Contract:** PositionManagement

**Function signature:**

```solidity
function leverageFor(
    LeverageAction calldata action,
    address account,
    uint256 slippage
) external
```

<table><thead><tr><th width="176">Type</th><th width="160">Name</th><th>Description</th></tr></thead><tbody><tr><td>LeverageStruct</td><td>leverageData</td><td>Structure containing leverage operation details including borrow token, amount, position token, swap data, and auxiliary data.</td></tr><tr><td>address</td><td>account</td><td>The account to leverage an active Curvance position for.</td></tr><tr><td>uint256</td><td>slippage</td><td>Slippage accepted by the user for the leverage action, in WAD (1e18).</td></tr></tbody></table>

**Events:**

```solidity
// In CToken.sol
event Transfer(address indexed from, address indexed to, uint256 value);
event Borrow(address account, uint256 amount);
```

```solidity
// In BaseCToken.sol
event CollateralUpdated(uint256 shares, bool increased, address account);
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.curvance.com/app/developer-docs/position-management/leverage.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
