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 leveraged positions across various asset types:

  • Simple Tokens: Standard ERC20 tokens.

  • Pendle LP Tokens: Liquidity provider tokens from Pendle.

  • Pendle PT Tokens: Principal tokens from Pendle.

  • Velodrome/Aerodrome LP Tokens: Liquidity provider tokens from Velodrome and Aerodrome.

  • Liquid Staking Tokens: stETH, shMON

  • ERC4626 Yield Vaults: sFRAX, sUSDe, sUSDS

Key Components

The leverage system involves several interconnected components:

  • Position Management: Base contract that handles the core leverage logic.

  • Market Manager: Manages risk parameters and validates leverage actions.

  • Swapper: Executes token swaps to convert borrowed tokens to collateral.

  • cTokens: Manage borrowing and collateral positions.

Leverage Flow

1. Initial Deposit

Users first deposit assets into a cToken contract, which represents their initial collateral position.

2. Leverage Request

A leverage request is initiated through one of the following methods:

  • leverage(): Direct leverage of an existing position.

  • depositAndLeverage(): Deposit new collateral and leverage in a single transaction..

  • leverageFor(): Leverage on behalf of another user (requires delegation)

3. Validation & Maximum Borrowing

The system checks how much the user can borrow based on:

  • Current collateral value.

  • Collateralization ratio of the collateralized cToken.

  • Existing debt.

  • Available liquidity in the BorrowableCToken market.

maxBorrowAmount = _maxRemainingLeverageOf(account, borrowToken)

4. Token Borrowing

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

borrowToken.borrowForPositionManagement(account, borrowAmount, leverageData)

5. Asset Conversion

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

  • Simple Tokens: Direct swaps through external DEXs.

  • Pendle LP Tokens: Tokens are swapped and then added to Pendle liquidity pools.

  • Velodrome/Aerodrome LP: Tokens are swapped and then added to the appropriate DEX pools.

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

Asset-Specific Flows

Simple Token Leverage

For standard ERC20 tokens, the process is straightforward:

  • Borrow the underlying token from an BorrowableCToken.

  • Swap the borrowed asset for the collateral cToken's underlying.

  • Deposit the resulting tokens as additional collateral.

Pendle LP Token Leverage

For Pendle LP tokens, the process involves:

  • Borrow the underlying token from a BorrowableCToken.

  • If necessary, swap the borrowed token to a valid Pendle input token.

  • Use the Pendle Router to add liquidity and mint LP tokens.

  • Deposit the resulting LP tokens as additional collateral.

Velodrome/Aerodrome LP Token Leverage

For Velodrome or Aerodrome LP tokens:

  • Borrow the underlying token from an eToken.

  • If the borrowed token isn't part of the LP pair, swap it.

  • Balance the amounts for optimal LP provision.

  • Use the appropriate router to add liquidity.

  • Deposit the resulting LP tokens as additional collateral.

Protocol Fees

When leveraging positions, users pay a protocol fee, which is calculated as:

fee = FixedPointMathLib.mulDivUp(amount, getProtocolLeverageFee(), WAD)

The fee is taken from the borrowed amount before swapping.

Slippage Protection

To protect users from unexpected price movements during the leverage process:

  • Users specify a maximum acceptable slippage parameter.

  • The system monitors the pre/post value of the user's position.

  • If the value loss exceeds the specified slippage, the transaction reverts.

This protection is implemented through the checkSlippage modifier.

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

Delegation of leverage actions requires careful permission management:

  • Only approved delegates can perform leverageFor operations.

  • Users can revoke permissions through the Central Registry.

  • The system verifies delegation status before each operation.

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 assets into a Curvance position and then leverages the position to increase both collateral and debt. Includes slippage protection through the checkSlippage modifier. The caller must have approved this contract to have delegated actions on the position token.

Contract: PositionManagement

Function signature:

function depositAndLeverage(
    uint256 assets,
    LeverageAction calldata action,
    uint256 slippage
) external;
Type
Name
Description

uint256

assets

The amount of the underlying assets to deposit.

LeverageStruct

leverageData

Structure containing leverage operation details including borrow token, amount, position token, swap data, and auxiliary data.

uint256

slippage

Slippage accepted by the user for the leverage action, in WAD (1e18).

Events:

// In cToken
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev `keccak256(bytes("Deposit(address,address,uint256,uint256)"))`.
uint256 internal constant _DEPOSIT_EVENT_SIGNATURE = 0xdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7;
// In CToken
event Transfer(address indexed from, address indexed to, uint256 value);
event Borrow(address account, uint256 amount);
// In BaseCToken
event CollateralUpdated(uint256 shares, bool increased, address account);
// Only emitted if this is the user's first position in the specific token
event PositionUpdated(address cToken, address account, bool open);

leverage()

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

Contract: PositionManagement

Function signature:

function leverage(
    LeverageStruct calldata leverageData,
    uint256 slippage
) external checkSlippage(msg.sender, slippage) nonReentrant
Type
Name
Description

LeverageStruct

leverageData

Structure containing leverage operation details including borrow token, amount, position token, swap data, and auxiliary data.

uint256

slippage

Slippage accepted by the user for the leverage action, in WAD (1e18).

Events:

// In CToken.sol
event Transfer(address indexed from, address indexed to, uint256 value);
event Borrow(address account, uint256 amount);
// 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:

function leverageFor(
    LeverageStruct calldata leverageData,
    address account,
    uint256 slippage
) external checkSlippage(account, slippage) nonReentrant
Type
Name
Description

LeverageStruct

leverageData

Structure containing leverage operation details including borrow token, amount, position token, swap data, and auxiliary data.

address

account

The account to leverage an active Curvance position for.

uint256

slippage

Slippage accepted by the user for the leverage action, in WAD (1e18).

Events:

// In CToken.sol
event Transfer(address indexed from, address indexed to, uint256 value);
event Borrow(address account, uint256 amount);
// In BaseCToken.sol
event CollateralUpdated(uint256 shares, bool increased, address account);

Last updated