Trade
Available on BNB Chain Core Pool.
Overview
Venus Trade is a relative performance trading system built as a peripheral orchestration layer on top of Venus Protocol's existing lending and borrowing infrastructure. It allows users to express a view that one asset will outperform another — packaged into a single, easy-to-manage position with automated execution, proportional closing, and built-in yield generation.
Users deposit a stablecoin collateral (the Default Settlement Asset, or DSA), select a long and short vToken pair, and Trade handles all leveraged execution — flash loans, swaps, supply, and borrow — atomically in a single transaction.
This is not directional trading. Trade positions profit (or lose) based on the relative price movement between two assets, regardless of whether the overall market is going up or down. While held, positions also generate yield: supply APY on the long asset, DSA APY on collateral, minus borrow APY on the short asset.
RelativePositionManager
The main orchestration contract that manages the full lifecycle of Trade positions — from activation and opening to proportional closing and deactivation
PositionAccount
A dedicated smart contract account deployed per user per trading pair. All collateral, borrow positions, and yield accrual live here, fully isolated from other positions
Paired Positions
Long and short legs treated as a single unit with combined PnL, health, and lifecycle management
Default Settlement Asset (DSA)
A designated stablecoin (USDT or USDC) used as collateral and as the currency for all PnL settlement
Proportional Closing
Flexible partial or full position closing using on-chain flash loans and token swaps, with automatic dust handling
Capital Utilization Tracking
Real-time calculation of how much deposited collateral is locked by open positions, enabling accurate withdrawable balance reporting
No changes were made to the Venus Core Pool, Comptroller, vToken contracts, interest rate models, oracles, or any existing protocol infrastructure. Existing users are not affected.
Architecture
The Trade system consists of four contracts:
RelativePositionManager
Central orchestration contract. Manages position state, validates operations, calculates utilization, and delegates execution to PositionAccount.
PositionAccount
A minimal proxy clone deployed per user per trading pair. Holds all funds, enters Venus markets, and delegates leverage execution to LeverageStrategiesManager.
LeverageStrategiesManager
Pre-existing Venus periphery contract. Executes flash loans via the Comptroller and invokes the SwapHelper.
SwapHelper
Pre-existing Venus periphery contract. Executes authorized on-chain swaps using signed multicall data.

Position Isolation
Every unique (user, longVToken, shortVToken) triple gets its own PositionAccount — a minimal EIP-1167 clone deployed with a deterministic CREATE2 salt. Collateral, debt, and Health Factor are entirely independent across accounts. A liquidation or loss on one PositionAccount cannot affect any other.

Fund custody
Each PositionAccount is a separate on-chain address. Venus vTokens and underlying balances are held there, not in the RelativePositionManager.
Access restriction
PositionAccount.onlyRelativePositionManager reverts any call not originating from the single trusted manager address.
Comptroller membership
Each PositionAccount enters Venus markets independently. Its Health Factor is computed solely from its own supplied and borrowed balances.
Delegate approval
During initialization the PositionAccount approves both the RelativePositionManager and LeverageStrategiesManager as delegates in the Comptroller — this allows flash-loan execution while keeping all debt on the PositionAccount, not on the manager.
Deterministic deployment
Clones are deployed with ClonesUpgradeable.cloneDeterministic(impl, keccak256(user, long, short)). A given user cannot create two accounts for the same pair; the address is unique and pre-determined.
Key Concepts
Long Leg and Short Leg
A Trade position always consists of two legs:
Long Leg — the asset expected to outperform. Supplied into Venus to earn supply APY.
Short Leg — the asset expected to underperform. Borrowed from Venus, creating an interest cost.
The two legs are treated as a single position with combined PnL — users never manage them separately.
Default Settlement Asset (DSA)
When activating a position, the user selects a Default Settlement Asset (USDT or USDC). The DSA serves as:
The initial collateral deposited into the PositionAccount
The asset that backs borrow risk (its collateral factor determines how much can be borrowed)
The currency in which realized profits are accumulated
The asset used to cover losses on close
Leverage
Leverage amplifies exposure to relative price movement. The maximum leverage is derived from the collateral factors of the DSA and long asset:
Where tolerance is the proportionalCloseTolerance, used as a buffer to prevent activations that would immediately be at the boundary of the safe borrow range. Leverage is recorded at activation and is fixed for the position's lifecycle.
Capital Utilization
Capital utilization measures how much of the deposited DSA principal is "locked" by the open leveraged position. The remainder — Available Capital — can be withdrawn or used to scale the position further. See Capital Utilization for the full formula.
Yield Generation
Trade positions generate yield while held:
Supply APY
The long asset is supplied into Venus and earns lending yield
DSA APY
The stablecoin collateral is supplied into Venus and earns yield
Borrow APY
Interest paid on the borrowed short asset (deducted from yield)
Net APY
DSA APY + Supply APY − Borrow APY
All yield accrues automatically and is reflected in position balances in real time. There is no claim or harvest step.
Implementation Details
1. RelativePositionManager
The primary external interface for all Trade operations. All user-facing calls pass through this contract, which enforces lifecycle rules, validates parameters, computes capital utilization, and delegates execution to the PositionAccount.
Inheritance:
AccessControlledV8— governance-gated admin functions via AccessControlManagerReentrancyGuardUpgradeable— reentrancy protection on all state-changing callsCustom two-level pause —
isPartiallyPaused/isCompletelyPausedwithwhenNotPausedandwhenNotCompletelyPausedmodifiers
Key state:
activateAndOpenPosition
Atomically activates a new position for the caller and executes the first leveraged open in a single transaction. If a PositionAccount clone does not yet exist for this (user, long, short) triple, it is deployed in the same transaction.
The function executes three sequential phases:
Validation — verifies that
longVTokenandshortVTokenare listed in the Comptroller and are not the same market, that neither is vBNB, that the DSA index maps to an active registered DSA, thateffectiveLeverageis in[1e18, maxLeverage], and that no active position already exists for this pair.Activation — deploys the PositionAccount clone if needed (via
ClonesUpgradeable.cloneDeterministic), incrementscycleId, records the position configuration, callsComptroller.enterMarketBehalfto register the DSA market for the PositionAccount, and callsvToken.mintBehalfto depositinitialPrincipal. The returned vToken amount is stored assuppliedPrincipalVTokens.Open — validates
shortAmount ≤ maxBorrow(available capital × clamped leverage / short price), then callspositionAccount.enterLeverage(longVToken, 0, shortVToken, shortAmount, minLongAmount, swapData). The LeverageStrategiesManager flash-loansshortAmount, swaps to the long asset, and supplies it to the PositionAccount's long vToken position.
The caller must approve initialPrincipal of the DSA underlying to the RelativePositionManager before calling. The function uses mintBehalf so that the vToken balance accrues directly on the PositionAccount — the RPM itself holds no collateral.
scalePosition
Adds additional short exposure to an existing active position. Optionally accepts more DSA principal if additionalPrincipal > 0.
Scaling recalculates maxBorrow from the updated available capital (including any newly deposited principal) before validating shortAmount. The stored effectiveLeverage is not updated by scaling — it remains fixed at the value set during activation and is used for utilization calculations across the position's lifecycle.
closeWithProfit
Proportionally closes a fraction of the position when the long asset has outperformed the short asset. Takes two swap legs: one to repay debt and one to harvest the profit into DSA principal.
The caller specifies closeFractionBps (1–10000) to indicate what fraction of the position to close. The protocol validates that the total long amount specified (longAmountToRedeemForRepay + longAmountToRedeemForProfit) is within proportionalCloseTolerance of the expected proportional amount:
Execution flow:
Redeem
longAmountToRedeemForRepayfrom the PositionAccount's long vToken positionSwap long → short via
positionAccount.exitLeverage()to repay the proportional debtRedeem
longAmountToRedeemForProfitfrom the long vToken positionSwap long → DSA and mint as DSA principal on the PositionAccount
Update
suppliedPrincipalVTokens+= newly minted DSA vTokens (profit increases Available Capital)
One-leg close (skip profit conversion): The profit swap leg is optional. Pass longAmountToRedeemForProfit = 0, minAmountOutProfit = 0, and swapDataProfit = "0x" to skip it. The repay leg always executes. If there is outstanding short debt, longAmountToRedeemForRepay must be non-zero — passing zero while debt exists reverts with MinAmountOutRepayBelowDebt.
closeWithLoss
Proportionally closes a fraction of the position when the long asset value is insufficient to cover the proportional short debt. Uses a two-leg approach to repay the full debt fraction.
Leg 1 — redeems long collateral, swaps long → short, repays as much debt as possible
Leg 2 — redeems DSA collateral, swaps DSA → short (or uses directly if DSA == short via
exitSingleAssetLeverage), repays remaining debt
Leg 2 is optional — pass dsaAmountToRedeemForSecondSwap = 0 if leg 1 fully covers the debt. The suppliedPrincipalVTokens counter is decremented by the DSA vTokens burned in leg 2, reflecting the principal consumed to cover the loss.
One-leg close behavior: Both legs are individually optional, enabling single-asset close paths:
Long only
Set dsaAmountToRedeemForSecondSwap = 0
Leg 1 (long → short swap) fully covers the proportional debt; no DSA needs to be burned
DSA only
Set longAmountToRedeemForFirstSwap = 0 and shortAmountToRepayForFirstSwap = 0
Long collateral has been partially or fully seized by a liquidator; only DSA principal remains to repay debt
Restriction: If longAmountToRedeemForFirstSwap = 0 but shortAmountToRepayForFirstSwap != 0, the call reverts with InvalidLongAmountToRedeem. Skipping the long leg while claiming a non-zero repay from it would illegitimately reduce the second-leg repay obligation without any actual collateral being redeemed.
supplyPrincipal
Deposits additional DSA collateral into the PositionAccount without opening a new leveraged trade. Transfers DSA from the caller, calls vToken.mintBehalf to supply it on the PositionAccount, and increments suppliedPrincipalVTokens.
This is the primary defensive Health Factor management tool. Supplying more principal increases the DSA collateral backing the borrow, directly raising the Health Factor without any position unwind or swap. Users facing a declining Health Factor should call this before the position becomes liquidatable. Allowed during partial pause — classified as a defensive operation and never blocked during incidents.
withdrawPrincipal
Withdraws Available Capital (unused DSA collateral) from the PositionAccount to the caller's wallet.
The maximum withdrawable amount is computed by getUtilizationInfo() as availableCapitalUSD / dsaPrice. The function redeems the corresponding DSA vTokens from the PositionAccount and decrements suppliedPrincipalVTokens. Blocked during partial pause.
deactivatePosition
Fully exits a position after the short debt has been repaid to zero. Exits all Venus markets, redeems all remaining collateral (both DSA and long), and transfers everything to the caller's wallet.
After deactivation, isActive is set to false and suppliedPrincipalVTokens is cleared. The PositionAccount contract remains deployed — a subsequent call to activateAndOpenPosition increments cycleId and starts a fresh cycle without redeploying the clone.
When DSA ≠ long, collateral is redeemed from two separate markets. When DSA == long, a single redemption is performed with a treasury fee grossup to avoid over-redemption:
2. PositionAccount
A minimal proxy clone (EIP-1167) deployed per user per trading pair. It holds all collateral and debt positions in Venus and is the sole entity that enters markets and executes borrows and supplies — the RelativePositionManager never holds funds itself.
Deployment: Clones use ClonesUpgradeable.cloneDeterministic with a CREATE2 salt:
This makes the PositionAccount address deterministic and pre-computable via getPositionAccountAddress() before the account is deployed.
Access control: The onlyRelativePositionManager modifier reverts any call not originating from the single trusted RelativePositionManager address. No EOA or other contract can directly move funds out of a PositionAccount.
initialize
Called once when the clone is first deployed. Sets the position owner, long vToken, and short vToken for this clone, and approves both the RelativePositionManager and LeverageStrategiesManager as delegates in the Venus Comptroller.
The delegate approval is what allows the RelativePositionManager to call Comptroller.enterMarketBehalf and vToken.mintBehalf on behalf of the PositionAccount while the PositionAccount remains the on-chain owner of all collateral and debt. The RelativePositionManager and LeverageStrategiesManager addresses are set in the constructor as immutables shared across all clones.
enterLeverage
Initiates the flash loan sequence to open a leveraged long position. Called by the RelativePositionManager as part of activateAndOpenPosition and scalePosition.
Internally delegates to LeverageStrategiesManager.flashLoan(...), which:
Flash-loans
borrowedAmountToFlashLoanof the short asset from the Comptroller's flash loan moduleSwaps the short asset to the long asset via the SwapHelper using
swapDataSupplies the resulting long tokens to the PositionAccount's long vToken position via
vToken.mintBehalfRepays the flash loan by opening a borrow on the PositionAccount's short vToken position
exitLeverage
Initiates the flash loan sequence to close a leveraged position — redeem collateral, swap, and repay debt. Used in both closeWithProfit and closeWithLoss.
Internally delegates to LeverageStrategiesManager.flashLoan(...), which:
Flash-loans
borrowedAmountToFlashLoanof the short assetRedeems
collateralAmountToRedeemForSwapfrom the PositionAccount's collateral vToken positionSwaps the redeemed collateral to the short asset via the SwapHelper
Repays the flash loan + the original borrow debt using the swap output
exitSingleAssetLeverage
Used when the DSA and the short asset are the same token (e.g., the position uses USDC as both DSA and borrow). In this case, no swap is required to repay the debt — DSA collateral is redeemed directly to cover the borrow.
Position Data Model
cycleId provides a monotonically increasing identifier for each activation. This allows off-chain systems and events to distinguish between different activation cycles of the same pair without ambiguity.
suppliedPrincipalVTokens is updated on every principal supply, withdrawal, profit conversion, and after liquidations (synced down if the actual balance has been reduced by a liquidator).
Position Lifecycle
Stage 1: Activation and Opening
activateAndOpenPosition() is the entry point. It combines activation and first open into one atomic transaction.
Activation steps:
Validate that the long and short markets are listed in the Comptroller and are not the same market
Validate that vBNB is not used (not supported)
Validate that the DSA index refers to an active, registered DSA vToken
Validate leverage is in the range
[1e18, maxLeverage]Deploy a PositionAccount clone if one does not exist for this
(user, long, short)tripleSet
isActive = true, incrementcycleId, recorddsaIndex,dsaVToken,effectiveLeverageEnter the DSA market on behalf of the PositionAccount via
Comptroller.enterMarketBehalfTransfer DSA from the user and mint vTokens on behalf of the PositionAccount via
vToken.mintBehalfRecord
suppliedPrincipalVTokensEmit
PositionActivatedandPrincipalSupplied
Opening steps (executed after activation):
Calculate
maxBorrowfrom available capital and clamped leverageValidate
shortAmount <= maxBorrowCall
positionAccount.enterLeverage(longVToken, 0, shortVToken, shortAmount, minLongAmount, swapData)LeverageStrategiesManager flash-loans
shortAmountof the short asset, swaps to the long asset, and mints it on the PositionAccountAny dust from the swap is swept from the PositionAccount to the user's wallet
Emit
PositionOpened
Maximum leverage formula:
Where tolerance is the proportionalCloseTolerance used as a buffer. This prevents activations that would immediately be at the boundary of the safe borrow range.
Stage 2: Scaling (Adding to a Position)
scalePosition() adds additional exposure to an existing active position.
Optionally supplies additional DSA principal if
additionalPrincipal > 0Recalculates
maxBorrowusing the updated available capitalCalls
positionAccount.enterLeverage(...)for the additional amountEmits
PositionScaled
The stored effectiveLeverage is not changed by scaling. Only suppliedPrincipalVTokens increases if additional principal is supplied.
Stage 3: Closing
Closing is proportional. The caller specifies closeFractionBps (1–10000 BPS, where 10000 = 100%) and the system closes exactly that fraction of the current position.
There are two closing paths depending on whether the position is in profit or in loss.
Profit Close (closeWithProfit)
closeWithProfit)Used when the long asset value (converted to short asset) exceeds the proportional short debt.
Validation:
Execution:
Redeem
longAmountToRedeemForRepayfrom the PositionAccount's long vToken positionSwap long → short via
positionAccount.exitLeverage()Repay
amountToRepayof short debtRedeem
longAmountToRedeemForProfitfrom the long vToken positionSwap long → DSA and mint as DSA principal on the PositionAccount
Update
suppliedPrincipalVTokens+= newly minted DSA vTokensEmit
PositionClosedandProfitConverted
Loss Close (closeWithLoss)
closeWithLoss)Used when the proportional long asset value is insufficient to cover the full proportional short debt.
Two-leg repayment:
Leg 1: Redeem long collateral → swap to short → repay as much debt as possible
Leg 2: Redeem DSA collateral → swap to short (or use directly if DSA == short) → repay remaining debt
Both legs are individually optional. Set dsaAmountToRedeemForSecondSwap = 0 to use long collateral only (leg 1 fully covers debt). Set longAmountToRedeemForFirstSwap = 0 and shortAmountToRepayForFirstSwap = 0 together to use DSA only (leg 2 only) — this is the correct path when the long collateral has been partially or fully seized by a liquidator and only DSA principal remains.
Validation:
Execution:
Leg 1 (if
longAmountToRedeemForFirstSwap > 0):positionAccount.exitLeverage(longVToken → shortVToken)— redeems long collateral, swaps to short, repays debtLeg 2 (if
dsaAmountToRedeemForSecondSwap > 0):positionAccount.exitLeverage(dsaVToken → shortVToken)— orexitSingleAssetLeveragewhen DSA == shortUpdate
suppliedPrincipalVTokens-= DSA vTokens burned in leg 2Emit
PositionClosed
Stage 4: Principal Management
supplyPrincipal() — deposit additional DSA without opening a new trade. Transfers DSA from the user, mints vTokens on the PositionAccount, increments suppliedPrincipalVTokens. This is the recommended action when the Health Factor is declining: adding DSA principal directly increases the collateral backing the borrow and raises HF without any position unwind. A small partial close (closeWithProfit or closeWithLoss with a low closeFractionBps) is the alternative: it repays a proportional slice of debt, which similarly raises HF but also reduces position size.
withdrawPrincipal() — withdraw Available Capital back to the user's wallet. Validates that amount <= withdrawableAmount (from getUtilizationInfo()), redeems the corresponding DSA vTokens from the PositionAccount, and decrements suppliedPrincipalVTokens.
Stage 5: Deactivation
deactivatePosition() fully exits the position account for a trading pair.
Prerequisites: The short debt must be fully repaid (zero borrow balance).
Steps:
Set
isActive = false, clearsuppliedPrincipalVTokensExit all markets and redeem all remaining collateral:
DSA ≠ long: Redeem all long vTokens, exit DSA market, redeem all DSA vTokens separately
DSA == long: Redeem all vTokens from the shared market (accounting for the treasury redemption fee grossup)
Transfer all redeemed underlying to the user's wallet
Emit
PositionDeactivated
After deactivation, the PositionAccount contract remains deployed. A new activation (activateAndOpenPosition) will increment cycleId and start a fresh position cycle without redeploying the contract.
Capital Utilization
Capital utilization determines how much of the user's DSA principal is "in use" by the open position and how much can be withdrawn or used to open new positions.
Formula
Leverage Clamping
The stored effectiveLeverage is the leverage set at activation. However, if collateral factors change after activation (e.g., governance lowers a CF), the actual maximum leverage may drop below the stored value. In this case, clampedLeverage = min(storedLeverage, currentMaxLeverage) is used for all utilization and borrow capacity calculations.
This ensures that capital utilization reporting and borrow limits remain conservative and safe even when market parameters change post-activation.
Two Utilization Paths
The system tracks utilization from two perspectives simultaneously:
Nominal: "Given the leverage ratio I agreed to, how much capital does this position conceptually consume?"
This path uses the stored leverage and is predictable for users.
Actual: "Given the current value of my long collateral and short debt, how much DSA backing is actually needed to maintain the position safely?"
This path accounts for real market prices and collateral factors.
The long asset's CF reduces the DSA backing needed (long collateral partially covers the borrow).
As prices diverge from the entry, this number can grow.
The maximum of the two is used as the final utilization, ensuring the most conservative estimate is always applied.
DSA Mechanics
DSA ≠ Long (Standard Case)
The PositionAccount holds two separate vToken positions:
Long vTokens (from leveraged swaps)
DSA vTokens (user's principal)
Principal tracking: suppliedPrincipalVTokens directly maps to the DSA vToken balance. Long collateral balance is simply longVToken.balanceOfUnderlying(positionAccount).
DSA == Long (Shared Market Case)
When the user selects a DSA that is the same token as the long asset (e.g., USDC as both DSA and long), the PositionAccount holds only one vToken balance that represents the sum of both.
The RelativePositionManager separates them using:
When suppliedPrincipalVTokens exceeds totalVTokens (which can happen if the position is partially liquidated), the system syncs suppliedPrincipalVTokens down to totalVTokens and emits RefreshedSuppliedPrincipal. This prevents the system from treating liquidated collateral as still available.
Deactivation in this case redeems from the shared market in a single call, accounting for the treasury fee grossup to avoid over-redemption:
Proportional Close Tolerance
proportionalCloseTolerance (default 100 BPS = 1%) defines the acceptable deviation band for close amounts.
Why it is needed: Interest accrues continuously on the borrow position, and swap outputs are subject to slippage. The close amount derived from closeFractionBps × currentBalance will not match exactly by the time the transaction executes.
Tolerance band for long amounts:
Tolerance bump for 100% closes: For full closes (closeFractionBps = 10000), the repay amount is bumped by the tolerance to ensure that accumulated interest since the close was estimated does not cause a dust leftover:
Any short dust remaining after the repay is validated to be within:
Governance can adjust proportionalCloseTolerance via setProportionalCloseTolerance(). A wider tolerance allows more flexibility but reduces proportionality precision; a narrower tolerance enforces stricter accounting but may cause more reverts due to market movement between estimation and execution.
Flash Loan Integration
Trade uses the existing LeverageStrategiesManager for all flash loan execution. The PositionAccount calls into the LeverageStrategiesManager which uses the Venus Comptroller's flash loan module.
Opening a Position (enterLeverage)
enterLeverage)Closing a Position (exitLeverage)
exitLeverage)Same-Asset Close (exitSingleAssetLeverage)
exitSingleAssetLeverage)When DSA == short (e.g., closing a loss using USDC as both DSA and borrow repayment), no swap is needed:
Liquidation
Trade positions are subject to the standard Venus liquidation mechanism. The PositionAccount is a regular address from the Comptroller's perspective — it enters markets, borrows, and supplies like any other account.
When the Health Factor drops below 1 (i.e., the borrow value exceeds the liquidation threshold-weighted collateral value), third-party liquidators can call liquidateBorrow on the appropriate vToken. This repays part of the debt and seizes a portion of the supplied collateral at a discount.
Post-liquidation behavior:
If DSA == long,
suppliedPrincipalVTokensmay now exceed the actual vToken balance. The next call to_getLongCollateralBalanceor_getSuppliedPrincipalBalancewill detect this and emitRefreshedSuppliedPrincipalto sync the counter down.The position remains
isActive = trueafter liquidation. The user can still manage (close, supply, withdraw) the reduced position.
Pause Mechanism
The contract supports two pause levels:
Partial Pause
activateAndOpenPosition, scalePosition, withdrawPrincipal, deactivatePosition
closeWithProfit, closeWithLoss, supplyPrincipal
Complete Pause
All state-changing operations
None
This design allows governance to freeze risky operations (opening new exposure, withdrawing, deactivating) while keeping defensive operations (closing, adding collateral) available during an incident.
Governance and Access Control
All privileged functions are gated via the Venus AccessControlManager.
setPositionAccountImplementation
Admin
One-time; locked after first call
addDSAVToken
Admin
Adds a new stablecoin to the DSA registry
setDSAVTokenActive
Admin
Enables/disables DSA for new activations
setProportionalCloseTolerance
Admin
Adjusts the close tolerance band
partialPause / partialUnpause
Admin
Toggles partial pause
completePause / completeUnpause
Admin
Toggles complete pause
executePositionAccountCall
Admin
Emergency call forwarder (e.g., asset rescue)
DSA management: When a DSA is set to inactive (setDSAVTokenActive(index, false)), existing positions using that DSA are unaffected. Only new position activations are blocked from selecting that DSA index.
PositionAccount implementation: The EIP-1167 clone implementation is set once and then locked (isPositionAccountImplementationLocked = true). This prevents governance from changing the implementation after positions have been deployed, ensuring users' PositionAccount contracts are immutable.
Security Considerations
Access Control
Only the RelativePositionManager can call PositionAccount methods. All external position operations are gated through this single entrypoint.
All admin functions are controlled by the Venus
AccessControlManager.
Reentrancy
ReentrancyGuardUpgradeableis applied to all state-changing external functions on the RelativePositionManager.
Oracle Dependency
All USD value calculations use the Venus
ResilientOracle. If an oracle price is zero or stale, the relevant function reverts withInvalidOraclePrice.
Flash Loan Safety
The flash loan callback (
executeOperation) on the LeverageStrategiesManager validates that the initiator is the LeverageStrategiesManager itself and that the caller is the Comptroller, preventing unauthorized replay.
Proportional Close Integrity
The tolerance band enforces that close amounts cannot deviate significantly from the intended BPS fraction. This prevents griefing attacks that would allow disproportionate collateral extraction relative to debt repayment.
PositionAccount Immutability
The EIP-1167 clone implementation is locked after the first call to
setPositionAccountImplementation. This means the RelativePositionManager cannot upgrade the PositionAccount logic for existing positions after deployment.
Audits
RelativePositionManager and PositionAccount were audited by CertiK and Quantstamp before mainnet deployment. Audit reports are available in the venus-periphery repository and in the Security & Audits section of the Venus documentation.
Last updated

