Position Tokens (pToken)
Overview
Position Tokens (pTokens) are Curvance's collateral tokens that represent user deposits in various yield-generating strategies. These ERC4626-compliant tokens allow users to deposit assets into Curvance vaults and optionally use them as collateral for borrowing in the lending markets. pTokens are designed to be fully liquid, ensuring that assets can be immediately withdrawn or liquidated if needed.
Core Architecture
pTokens follow a hierarchical inheritance structure:
BasePToken: The foundational abstract contract implementing ERC4626 vault functionality.
SimplePToken: For basic assets that don't generate external rewards (e.g., WETH, stablecoins).
CompoundingPToken: Extended functionality for assets that generate yield (supports auto-compounding).
CompoundingWithExitFeePToken: Adds an exit fee mechanism to compounding vaults.
Protocol-Specific Implementations: Custom implementations for different DeFi protocols.
Key Contracts and Interactions
pTokens interact with several core Curvance contracts:
CentralRegistry: Protocol configuration and permissions management.
MarketManager: Handles collateral position registration and risk parameters.
Various External Protocol Contracts: For staking, providing liquidity, and claiming rewards.
Types of pTokens
Simple pTokens
Simple pTokens (SimplePToken
) are designed for assets that don't generate external rewards. They provide a straightforward wrapper for assets like:
Wrapped ETH
Liquid Staking Tokens (LSTs)
Principal Tokens
Stablecoins
Yield-bearing stablecoins
Compounding pTokens
Compounding pTokens (CompoundingPToken
) extend basic functionality by adding auto-compounding yield features. These vaults:
Automatically harvest rewards.
Convert rewards back into the underlying asset.
Reinvest into the yield-generating position.
Distribute yield to all vault users through an increasing share value.
Protocol-Specific Implementations
Curvance offers various protocol-specific pToken implementations, but not limited to:
AuraPToken: For Aura Finance (Balancer) LP positions.
Convex2PoolPToken/Convex3PoolPToken: For Curve/Convex 2-token and 3-token LP positions.
VelodromeStablePToken/VelodromeVolatilePToken: For Velodrome stable and volatile LP positions.
AerodromeStablePToken/AerodromeVolatilePToken: For Aerodrome stable and volatile LP positions.
StakedGMXPToken: For staked GMX positions.
PendleLPPToken: For Pendle LP positions.
Each implementation handles the specific deposit, withdrawal, and reward harvesting logic for its respective protocol.
State Management
pTokens maintain several key state variables:
Data Flow
Deposit Flow
User calls
deposit()
with underlying assets.Contract calculates shares based on current exchange rate.
If it's a compounding vault, the
_afterDeposit()
hook is called to stake tokens in the external protocol.Underlying tokens are transferred from the user to the contract.
Vault shares (pTokens) are minted to the user.
If user selects to use as collateral, the vault notifies the MarketManager.
Withdrawal Flow
User calls
withdraw()
with the amount of assets to withdraw.If it's a compounding vault, the
_beforeWithdraw()
hook is called to unstake tokens from the external protocol.Contract calculates shares to burn based on current exchange rate.
Underlying tokens are transferred from the contract to the user.
Vault shares (pTokens) are burned.
If user had posted the tokens as collateral, the vault notifies the MarketManager.
Collateral Management Flow
User calls
postCollateral()
to use pTokens as borrowing collateral.Contract verifies the asset is eligible as collateral and under the global cap.
MarketManager is notified of the new collateral position.
User's pTokens are marked as collateral and transfer-restricted.
Reward Harvesting Flow (Compounding Vaults)
harvest()
function is called (permissioned or by a keeper).External rewards are claimed from the underlying protocol.
Rewards are swapped back to the underlying asset.
New tokens are deposited back into the strategy.
Yield is gradually distributed to all vault users through a vesting mechanism.
Yield Distribution Mechanism
Compounding pTokens use a unique vesting approach to distribute yield:
Harvested rewards are not immediately reflected in the vault's total assets.
Instead, rewards vest linearly over a defined period (default is 1 day).
This creates a smoother increase in share price and reduces MEV opportunities.
The vesting mechanism is implemented through the following structure:
Security Features
pTokens incorporate multiple security measures:
Collateral Restrictions: Assets posted as collateral cannot be transferred.
Pause Mechanisms: Deposit, withdrawal, and harvesting can be paused independently.
Reentrancy Protection: All critical functions have reentrancy guards.
Slippage Protection: Swap and liquidity operations have minimum output requirements.
Chain Validation: Protocol-specific implementations validate they're on the correct chain.
Permissioned Operations: Sensitive functions restricted to DAO or elevated permissions.
Oracle Integration
pTokens integrate with Curvance's oracle system for accurate valuation:
Protocol-Specific Adaptors: Custom oracle adaptors for complex assets like Pendle LP tokens.
TWAP Support: Time-weighted average prices for more accurate valuations.
Price Feeds: Integration with primary price oracles for underlying assets.
User Interaction Functions
Deposits
deposit()
Contract: pToken
Description: Deposits assets into the vault and receives shares.
Function signature:
uint256
assets
The amount of underlying assets to deposit.
address
receiver
The account that should receive the pToken shares.
Return data:
uint256
shares
The amount of pToken shares received by receiver.
depositAsCollateral()
Contract: pToken
Description: Deposits assets and marks shares as collateral in one transaction.
Function signature:
uint256
assets
The amount of underlying assets to deposit.
uint256
receiver
The account that should receive the pToken shares.
Return Data:
uint256
shares
The amount of pToken shares received by receiver.
depositAsCollateralFor()
Contract: pToken
Description: The depositAsCollateralFor
function enables users to deposit assets and automatically post them as collateral on behalf of another address, returning the amount of pToken shares received by the receiver. Unlike depositAsCollateral
, this function requires explicit delegation permission, where the receiver must have previously approved the caller to act on their behalf. This makes it particularly useful for smart contract integrations, portfolio management tools, and protocols that assist users in capital optimization. The function operates by first checking delegation permissions, then transferring assets from the caller to the vault, minting shares to the receiver, and finally posting those shares as collateral through the marketManager
.
Users should exercise caution when delegating this permission, as delegates could potentially abuse it by repeatedly posting shares as collateral, which could temporarily prevent withdrawals and effectively lock a user's funds. If the caller lacks proper delegation permissions, the function will still deposit assets but won't post them as collateral.
Function signature:
uint256
assets
The amount of underlying assets to deposit.
uint256
receiver
The account that should receive the pToken shares.
Return Data:
uint256
shares
The amount of pToken shares received by receiver.
mint()
Contract: pToken
Description: User specifies shares to receive and deposits corresponding assets.
Function signature:
uint256
shares
The amount of shares to mint.
address
receiver
The account that should receive the pToken shares.
Return Data:
uint256
shares
The amount of pToken shares received by receiver.
Withdrawals
withdraw()
Contract: pToken
Description: Facilitates the withdrawal of assets from the market and the burning of shares. Initially, it verifies if the owner is eligible to redeem shares within the given market. Upon successful validation, it proceeds to burn the shares and subsequently returns the asset. Importantly, it does not force the withdrawals. If the caller is withdrawing another owner's pTokens, they must first have enough approval.
Function signature:
uint256
assets
The amount of underlying assets to withdraw.
address
receiver
The account that should receive the assets.
address
owner
The account that will burn their shares to withdraw assets.
Return data:
uint256
shares
The amount of shares that were burned.
redeem()
Function: Burns shares to receive assets
Function signature:
uint256
shares
The amount of shares to redeem.
address
receiver
The account that should receive the assets.
address
owner
The account that will burn their shares to receive assets.
Return data:
uint256
assets
The amount of underlying assets sent to the receiver.
redeemCollateral()
Description: Redeems collateralized shares to receive assets.
Function signature:
uint256
shares
The amount of collateralized shares to redeem.
receiver
receiver
The account that should receive the assets.
Return data:
uint256
assets
The amount of underlying assets sent to the receiver.
redeemCollateralFor()
Description: Redeems collateralized shares on behalf of an owner.
Function signature:
uint256
shares
The amount of collateralized shares to redeem.
address
receiver
The account that should receive the assets.
address
owner
The account that owns the shares being redeemed.
Return data:
uint256
assets
The amount of underlying assets sent to the receiver.
Compounding Vault Specifics
For compounding vaults like AuraPToken, Convex2PoolPToken, Convex3PoolPToken, and StakedGMXPToken:
Vesting Mechanism
Compounding vaults use a vesting mechanism to gradually distribute yield:
data
Encoded swap parameters to convert rewards to underlying assets.
When yield is harvested:
Rewards are claimed from the external protocol.
A protocol fee is taken.
Remaining rewards are swapped to the underlying asset.
The yield is distributed over the vesting period (default 1 day).
Getting Vault Status
Returns current information about the vault's yield distribution:
rewardRate
: Rate at which yield is being distributed.vestingPeriodEnd
: When the current vesting period ends.lastVestClaim
: Last time vesting rewards were claimed.
Considerations
Rehypothecation Prevention: Curvance prevents rehypothecation of collateral assets, limiting systemic risk.
Collateral Caps: Restricts the total exogenous risk from any single asset.
20-Minute Minimum Duration: Collateral must be posted for at least 20 minutes.
Safe Functions: Enhanced protection against reentrancy and other vulnerabilities.
Liquidation Safeguards: Only authorized contracts can seize collateral during liquidations.
Last updated