Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 188 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

Venus Protocol

Getting Started

Loading...

Loading...

What's New?

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Governance

Loading...

Loading...

Risk

Loading...

Loading...

Loading...

Loading...

Loading...

Tokens

Loading...

Loading...

Loading...

Loading...

Guides

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Technical reference

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Overview

Launched in 2020, Venus Protocol (a.k.a. “Venus”) pushed the edges of decentralized finance through its composition of two pre-existing solutions and deployment on BNB chain, lowering the barrier to entry for millions of new users around the globe. By combining the stablecoin minting facility introduced by Maker and algorithmic money markets developed by Compound, Venus simplified the user experience and provided core capabilities that enabled decentralized finance to flourish in a single application. As a result, Venus found remarkable success and quickly rose to be one of the most widely used decentralized applications in web3.

The latest iteration of Venus Protocol, the most trusted and battle-tested lending and borrowing protocol on the BNB Chain, builds on prior successes and lessons learned to improve in 3 key areas:

  1. Risk management

  2. Decentralization

  3. User experience

In doing so, Venus continues to push the boundaries of what's possible within the realm of decentralized finance.

FAQ

What is Venus Protocol?

Venus Protocol is a trusted decentralized finance lending and borrowing protocol that's deployed on the BNB Chain. Initially launched in 2020, it combines the stablecoin minting facility of Maker and the algorithmic money markets developed by Compound, providing a simplified user experience and core capabilities in a single application.

How do I interact with Venus Protocol?

Interacting with Venus V4 is straightforward. Supply your chosen asset and the amount to start earning interest. Additionally, once you supply assets, you can also borrow against them. Any interest earned from supplying assets can help offset the interest you accrue when borrowing.

Where are my supplied funds stored?

Your supplied funds are stored in a smart contract on the BNB Chain. The contract's code is public, open-source, and has been formally verified and audited by external auditors. You can withdraw your funds on demand or receive Venus Tokens (vTokens) representing your stake. vTokens are as freely tradable as any other cryptographic asset on BNB Chain.

What is the cost of interacting with Venus Protocol?

Transactions on the Venus V4 protocol require BNB Chain fees, which depend on network congestion and the complexity of the transaction.

Is there any risk?

No platform can be considered entirely risk-free. Risks associated with Venus V4 include smart contract risk and liquidation risk. However, every possible step has been taken to minimize these risks, including making the protocol code public and conducting thorough audits.

What are the key areas Venus Protocol V4 aims to improve?

Venus Protocol focuses on improving three main areas:

  • Risk Management: Prioritizing the risk management , Venus introduces new features like Isolated Pools and more sophisticated risk parameters.

  • Decentralization: The governance model has been enhanced by introducing fast-track VIPs, role-based access control, and a fine-grained pause mechanism.

  • User Experience: The latest version offers an enhanced user interface, a more effective reward system, and isolated lending. Future releases for V4 will feature stable rate borrowing and the Venus Prime Soulbound Token, all aimed at providing a smooth user experience.

What is the Resilient Price Oracle?

The Resilient Price Oracle introduced in Venus V4 fetches prices from multiple sources and validates them, providing a more reliable price indicator and protecting against price manipulations. It supports the integration of new price oracles and allows enabling and disabling price oracles per token.

What are Isolated Pools?

Isolated Pools are a new feature in Venus V4, designed to overcome the limitations of a single core pool. Each Isolated Pool is an independent collection of assets with custom risk management configurations. This setup allows users to better manage their risk and earn yield, while also preventing failures in one market from impacting others.

What is the Risk Fund?

In Venus V4, a risk fund is maintained for each pool. A percentage of the protocol's revenue is deposited into this fund, aiming to counterbalance bad debt and prevent potential market insolvencies.

What changes were made to the governance model in Venus V4?

Venus V4 features a new governance model that introduces fast-track Venus Improvement Proposals (VIPs), role-based access control, and a fine-grained pause mechanism. This new model allows for more agile and accurate decision-making, ensuring the protocol remains competitive and secure.

Stable Rate Borrowing

To be released

Overview:

Stable Rate Borrowing is a distinctive feature of the Venus Protocol that provides an alternative to variable interest rate loans. Stable-rate loans set their interest rates at issuance until a rebalancing event occurs. This approach shields users who borrow at a stable rate from being affected by individual actions of other users and large fluctuations in the market.

Rate Determination:

The interest rates for stable and variable rate borrowing are determined based on several calculations involving parameters such as utilization rate, stable loan adoption rate, and total supply. For instance, the stable interest rate will include a base premium plus an additional premium that depends on the stable loan adoption rate.

Model Parameters:

The model parameters involved in the calculations include slopes for the variable interest rate, a base rate per block, the optimal utilization rate (kink), a reserve factor, base premium, and other parameters related to stable loan borrowing.

Rebalancing Conditions:

The fixed rate of a stable loan persists until certain rebalancing conditions are met. These conditions involve the utilization rate and the comparison between the market average borrow rate and the variable borrow rate. The stable rate provides predictability for the borrower but may come at a cost of higher interest rates compared to the variable rate.

Diamond

Core Pool

InterestRateModels

VAI

Comptroller

Technical articles

XVS

Isolated Pools

Facets

Prime

Vaults

Governance

VenusERC4626

Comptroller

E-Mode

Only available on BNB Chain Core Pool.

Overview

The Venus Protocol introduces E-Mode (Efficiency Mode) to the BNB Chain Core Pool, a new feature designed to boost capital efficiency for specific asset pools, such as stablecoins or ETH-based tokens. It also aims to isolate risk within these pools while reusing liquidity from the Core Pool.

E-Mode allows users to activate specialized pools within the Core Pool, each with customized risk settings. By selecting an E-Mode pool, your eligible assets follow optimized parameters for collateral factor (CF) and liquidation threshold (LT), which are increased, while the liquidation incentive (LI) is decreased, making borrowing more efficient and cost-effective while keeping risks contained.

What’s Changed

To support E-Mode, the Core Pool itself has been enhanced with new risk mechanics:

  • Liquidation Threshold (LT) Support – Similar to isolated pools, LT is now used to determine liquidation conditions, separate from CF.

  • Per-Market Liquidation Incentive (LI) – LI is no longer global; each market has its own incentive, configurable by Governance.

  • User-Specific Risk Factors – Effective CF, LT, and LI now depend on the user’s selected E-Mode pool, giving each user a tailored borrowing and collateral profile.

Architecture Overview

E-Mode operates as a lightweight overlay on the Core Pool, enabling per-user risk management without moving funds to separate pools.

  • Core Pool (poolId = 0): The default pool for all users. Supports per-market LIs and LT, even for non-E-Mode users.

  • E-Mode Pools (poolId > 0): Each pool defines a set of assets (e.g., Stablecoin Pool, ETH Pool) with customized CF, LT, and LI for each asset in the pool. Users select a pool to activate its risk parameters.

  • Pool-Market: Markets are tracked per pool, allowing pool-specific overrides while preserving Core Pool compatibility.

This architecture ensures flexibility, backward compatibility, and gas efficiency, while giving users higher borrowing efficiency and better risk isolation.

Impact on Users

  • No Action Needed – Users remain in the Core Pool by default. Their positions continue to function normally without switching to E-Mode.

  • Optional Upgrade – By entering an E-Mode pool, your account will use its risk settings for approved assets.

  • Note: Improved Risk Mechanics – Even without switching, Core Pool users now benefit from per-market liquidation incentives (LI) and liquidation threshold (LT) support, making liquidation calculations and account health evaluations more precise.

Impact on Liquidators

E-Mode introduces more precision and flexibility for liquidators in the Core Pool:

  • Per-Market Liquidation Incentives – Liquidation incentives (LI) are now set on a per-market basis rather than being global. Before liquidating, liquidators should check the LI for each asset. If a user is in an E-Mode pool and uses collateral that isn’t enabled in that pool, the LI for that asset can be zero.

  • Liquidation Thresholds (LT) – LT now determines when accounts can be liquidated, replacing the older CF-based check for liquidations.

  • User-Specific Risk Factors – Effective CF, LT, and LI can vary per user depending on their E-Mode pool, making liquidation decisions more targeted and strategic.

This gives liquidators smarter targeting, higher transparency, and better reward optimization across markets.

How It Works

  1. Default in the Core Pool All users start in the Core Pool and can continue their positions normally.

  2. Select an E-Mode Pool Explore available pools (e.g., Stablecoin) via the Venus App or Venus Lens.

  3. Check Your Borrows Borrowed assets must be approved in the selected pool. Repay any disallowed assets first.

  4. Check Core Pool Fallback Each E-Mode pool has a flag allowCorePoolFallback

For a detailed technical explanation, including implementation and user examples, check out the .

Reward Distributor

Overview

The Venus Reward Distributor allows for the configuration and management of rewards for lenders and borrowers, dependent on the user's activity within the associated markets. The addition of one or more reward distributors to a pool is facilitated through the addRewardsDistributor feature, enhancing the protocol's capability to customize distribution rates on a per-market basis.

In the Venus Protocol V4, the reward system has been upgraded to allow for rewards per market and lending activity, as well as the support for multiple reward tokens. This revamp serves to provide further incentives and yield opportunities for users.

Interest Rate Model

Overview

Venus Protocol offers variable interest rates for markets using two different models: the Jump Rate Model and the Whitepaper Rate Model. Each market operates under one of these models with specifically set risk parameters at the market's inception. Notably, the community can update these parameters through the Governance process. Moreover, some markets feature a stable rate, introduced in Venus V4.

Enable E-mode

Want to try out e-mode?

Head to the Venus dApp () and ensure you are connected to the BNB Chain.

Click on the “E-mode” icon to view current e-mode groups.

Make sure your wallet is connected.

Click “Enable” in the e-mode group you would like to enable. Just like that, enjoy increased LTV on the assets listed in that e-mode group!

Vaults

Vaults within Venus Protocol provide a secure and efficient mechanism for users to stake their tokens, whether XVS or VAI, and earn passive income. This staking process allows users to actively participate in and contribute to the stability and security of the Venus ecosystem, while maximizing returns on their holdings.

Staking in XVS Vault

  1. Navigate to the Venus app (app.venus.io) and connect your BNB Chain Wallet or other supported wallet apps.

  2. On the left side of the screen, click on the 'Vault' tab.

Token Converter

Overview

Protocol revenues, sourced from reserve interests and liquidations, are processed through the module. Once allocated, these underlying tokens are subsequently sent to various Token Converters, each transforming the received income into specific tokens, automating and optimizing this conversion process.

FlashLoanFacet

FlashLoanFacet

This facet contract contains functions for flash loan operations

Solidity API

XVS

Overview

XVS is the native token of Venus Protocol and serves as its governance token. By staking XVS tokens in the vault, users gain voting power proportionate to the amount staked. This voting power enables them to participate in the voting process for Venus Improvement Proposals (VIPs), thereby playing a critical role in the development and evolution of the Venus Protocol.

Furthermore, users who stake their XVS tokens in the vault have the potential to earn yield, creating an incentive for participation in the Venus governance process. This aligns the interests of XVS holders with the overall health and success of the Venus Protocol.

DiamondConsolidated

DiamondConsolidated

This contract contains the functions defined in the different facets of the Diamond, plus the getters to the public variables. This contract cannot be deployed, due to its size. Its main purpose is to allow the easy generation of an ABI and the typechain to interact with the Unitroller contract in a simple way

InterestRateModelLens

InterestRateModelLens

Lens for querying interest rate model simulations

Solidity API

Isolated Pools

Overview

Isolated Pools are made up of separate collections of assets with tailored risk management configurations. This design offers users broader opportunities to manage risk and allocate assets to earn yield. Moreover, it prevents hypothetical failures from affecting the liquidity of the entire protocol as they are confined to isolated markets.

Isolated Pools also offer custom rewards for each market in the pool, incentivizing users accordingly.

Two Kinks Interest Rate Curve

Overview

The 2-Kink Interest Rate Curve introduces a new model to optimize interest rates and utilization across Venus protocol markets. By incorporating two separate "kinks", this model aims to provide more flexible control over market dynamics, enhancing both the predictability and efficiency of APYs (Annual Percentage Yields) for borrowers and suppliers.

This design helps reduce the volatility of APYs during periods of high demand, such as during launchpool events, and encourages greater participation by offering more predictable costs and returns.

Gasless Transactions on zkSync

This guide will walk you through the steps to interact with Venus Protocol on ZKsync without needing ETH to cover gas fees, thanks to the integration of . All transactions will be sponsored, so you can focus on using the protocol without worrying about gas expenses.

Step-by-Step Guide

Reward Distributor Architecture

The Rewards Distributor system is centered around the RewardsDistributor contract. This contract maintains the functionality to configure, track and distribute rewards to users based on their borrow and supply activities within the protocol. Upon initialization, each RewardsDistributor proxy is associated with a specific reward token and Comptroller, from which point the reward token can be disseminated to users that supply or borrow in the corresponding pool.

User Interactions

Users have a range of possible interactions with the Reward Distributor:

  • Supply: Users can supply assets and earn rewards based on the supply speeds set for the reward token.

  • Borrow: Users can borrow assets and earn rewards according to the configured borrow speed of the reward token.

  • Claim Rewards: Users can claim their accrued reward tokens for individual markets, a feature that significantly reduces gas fees and streamlines the reward claiming process.

A new screen will display two options: XVS and VAI vaults. Select the 'XVS' vault.

  • Once you select the XVS vault, a new interface will show. Click the 'Stake' button.

  • A pop-up will appear asking for the amount of XVS you want to stake. Input the desired amount and confirm.

  • After entering the amount, a prompt will ask for the transaction's confirmation in your wallet. Confirm this.

  • Once you've staked your XVS tokens, the interface will show the staked amount, your potential rewards, and other vault statistics.

  • Staking in VAI Vault

    1. Follow the same steps as above to access the 'Vault' tab in the Venus app.

    2. This time, select the 'VAI' vault.

    3. Upon clicking on the 'VAI' vault, you'll see the option to 'Stake'.

    4. Enter the amount of VAI you'd like to stake and confirm the staking action.

    5. Just like with the XVS vault, you'll need to confirm the transaction in your wallet.

    6. After staking, the interface will show the staked amount, potential rewards, and other relevant statistics related to the VAI vault.

    Next Steps and Future of XVS

    The upcoming Venus Prime program adds a new dimension to the utility of XVS tokens. As Venus Protocol continues to innovate:

    • The launch of Venus Prime will provide opportunities for additional yield to committed users, using protocol's revenue instead of just relying on the token supply.

    • The program will introduce unique, non-transferable tokens for eligible participants, adding a new layer of user interaction.

    These developments further emphasize the importance of the XVS token in the ecosystem, providing holders with more ways to earn and participate in the protocol's future.

    Solidity API

    User Pool Tracking: Each user is associated with exactly one pool at a time via userPoolId. Switching pools updates this mapping and triggers the relevant risk rules.

    that determines whether assets not included in the E-Mode pool will use the Core Pool’s risk factors (i.e. CF, LT, LI). If fallback is not allowed, users must exit these markets (i.e., remove such assets as collateral) to ensure they aren’t unintentionally liquidated.
  • Enter E-Mode Eligible assets follow E-Mode risk settings, while the behavior of assets not included in the E-Mode pool depends on the allowCorePoolFallback flag.

  • Enjoy Higher Efficiency Borrow and manage positions with optimized collateral and liquidation rules.

  • full E-Mode technical article
    Example of E-Mode pools - assets highlighted in red are not available for borrowing in the pool
    getSimulationResponse

    Simulate interest rate curve fo a specific interest rate model given a reference borrow amount and reserve factor

    Parameters

    Name
    Type
    Description

    referenceAmountInWei

    uint256

    Borrow amount to use in simulation

    interestRateModel

    address

    Address for interest rate model to simulate

    reserveFactorMantissa

    uint256

    Reserve Factor to use in simulation

    Return Values

    Name
    Type
    Description

    [0]

    struct InterestRateModelLens.SimulationResponse


    struct SimulationResponse {
      uint256[] borrowSimulation;
      uint256[] supplySimulation;
    }
    function getSimulationResponse(uint256 referenceAmountInWei, address interestRateModel, uint256 reserveFactorMantissa) external view returns (struct InterestRateModelLens.SimulationResponse)
    Jump Rate Model

    The Jump Rate Model uses the following formulas to calculate the interest:

    For Borrow rate:

    And, for Supply rate:

    Where,

    The borrow rate employs different formulas when the utilization rate falls into two distinct ranges:

    If u < kink:

    If u > kink:

    Model Parameters

    • a1: Variable interest rate slope1.

    • a2: Variable interest rate slope2.

    • b: Base rate per block (baseRatePerYear / blocksPerYear).

    • kink: Optimal utilization rate, at which the variable interest rate slope shifts from slope1 to slope2.

    • reserve_factor: Part of interest income withdrawn from the protocol, i.e., not distributed to suppliers.

    The utilization rate (u) is defined as:

    Where:

    • borrows: Amount of borrows in the market, in terms of the underlying asset, excluding bad debt.

    • cash: Total amount of the underlying asset owned by the market at a specific time.

    • reserves: Amount of the underlying asset owned by the market but unavailable for borrowers or suppliers, reserved for various uses defined by the protocol's tokenomics.

    • bad_debt: After liquidators repay as much debt as possible, reducing collateral to a minimal amount, the remaining debt is tagged as bad debt. Bad debt doesn’t accrue interest.

    Whitepaper Rate Model

    The Whitepaper Rate Model is simpler, where the borrow rate depends linearly on the utilization:

    For Borrow rate:

    For Supply rate:

    Where,

    borrow_rate(u)=b+a1⋅kink+a1⋅min⁡(0,u−kink)+a2⋅max⁡(0,u−kink)borrow\_rate (u) = b + a_1 \cdot kink + a_1 \cdot \min(0, u-kink) + a_2 \cdot \max(0,u-kink)borrow_rate(u)=b+a1​⋅kink+a1​⋅min(0,u−kink)+a2​⋅max(0,u−kink)
    supply_rate(u)=borrow_rate(u)⋅us⋅(1−reserve_factor)supply\_rate(u) = borrow\_rate(u) \cdot us \cdot (1 - reserve\_factor)supply_rate(u)=borrow_rate(u)⋅us⋅(1−reserve_factor)
    us=borrowscash+borrows−reserves+badDebtus = \frac{borrows}{cash + borrows - reserves + badDebt}us=cash+borrows−reserves+badDebtborrows​
    borrow_rate(u)=a1⋅u+bborrow\_rate(u) = a_1 \cdot u + bborrow_rate(u)=a1​⋅u+b
    borrow_rate(u)=a1⋅kink+a2⋅(u−kink)+bborrow\_rate(u) = a_1 \cdot kink + a_2 \cdot (u-kink) + bborrow_rate(u)=a1​⋅kink+a2​⋅(u−kink)+b
    utilization_rate=(borrows+bad_debt)(cash+borrows+bad_debt−reserves)utilization\_rate = \frac{(borrows + bad\_debt)}{(cash + borrows + bad\_debt - reserves)}utilization_rate=(cash+borrows+bad_debt−reserves)(borrows+bad_debt)​
    borrow_rate(u)=a⋅u+bborrow\_rate (u) = a \cdot u + bborrow_rate(u)=a⋅u+b
    supply_rate(u)=borrow_rate(u)⋅us⋅(1−reserve_factor)supply\_rate(u) = borrow\_rate(u) \cdot us \cdot (1 - reserve\_factor)supply_rate(u)=borrow_rate(u)⋅us⋅(1−reserve_factor)
    us=borrowscash+borrows−reserves+badDebtus = \frac{borrows}{cash + borrows - reserves + badDebt}us=cash+borrows−reserves+badDebtborrows​

    When e-mode is enabled, you can only borrow assets listed in that group. These assets will be marked in the “borrowable” column for your reference.

    Currently, only the Stablecoins e-mode group is enabled. We plan to release BTC and BNB e-mode groups within the next few weeks. Keep following us on X or join our Telegram and Discord groups to be the first to know!

    app.venus.io
    Key Aspects of the Token Converter

    The Token Converter works on four key principles:

    1. Distributed and Autonomous: No centralized management or human interactions needed, ensuring a secure and seamless conversion process.

    2. Efficient: The system is designed to maximize the amount of specific tokens we receive while protecting against potential risks like sandwich attacks.

    3. Streaming: The conversions occur continually, without waiting for scheduled intervals.

    4. Transparent: All conversions are publicly recorded in the blockchain, reinforcing our commitment to transparency.

    Venus Protocol will offer discounts to incentivize these conversions. This incentive will create arbitrage opportunities in the market, and external agents can potentially gain from these opportunities.

    Rational

    Before the Token Converter, token conversions were not as seamless and efficient. Venus Protocol needed a system that could constantly convert the received income into specific tokens, with no room for errors or delays.

    The Token Converter streamlines the conversion process by allowing key elements in the Venus Protocol, such as the XVSVaultConverter and RiskFundConverter, to autonomously offer token conversions. This solution follows the rules of distributed and autonomous systems, removing the need for human intervention.

    Moreover, the introduction of incentives through discounts encourages external agents to take part in the conversion process, thus creating a win-win situation for all. This is in line with the vision of decentralization, where processes are not only transparent but also rewarding for participants.

    Architecture

    The dashed lines represent transactions initiated by external agents (VIP’s, scripts, arbitrage bots, etc.), and the solid lines represent transfers of funds.

    Automatic Income Allocation
    executeFlashLoan

    Executes a flashLoan operation with the requested assets

    Transfers the specified assets to the receiver contract and handles repayment. Supports both full repayment and partial repayment where unpaid amounts become ongoing debt positions.

    Parameters

    Name
    Type
    Description

    onBehalf

    address payable

    The address of the user whose debt position will be created in case of partial repayment

    receiver

    address payable

    The address of the contract that will receive the flashLoan amount and execute the operation

    vTokens

    VToken[]

    The addresses of the vToken assets to be loaned

    underlyingAmounts

    uint256[]

    The amounts of each underlying assets to be loaned


    Isolated Pools Architecture

    The Isolated Pools system is based on the PoolRegistry contract. It maintains a directory of isolated lending pools, allows the creation and registration of new pools, and offers getter methods to fetch pool details.

    To add a new market to an existing lending pool, the PoolRegistry deploys a JumpRateModelV2 or a WhitePaperInterestRateModel contract, deploying the upgradable VToken for the market before gaining the approval of the market's Comptroller.

    Isolated Lending Pools Architecture

    User Actions

    Users can perform the following actions on any market in a pool:

    1. Deposit: Users can deposit an asset, receiving vTokens that correspond to the liquidity deposited. These vTokens accrue interest until they are burned on redeem or liquidated.

    2. Borrow: Users can borrow assets, in exchange for locked collateral.

    3. Redeem: Users can redeem vTokens for the underlying asset based on the exchange rate.

    4. Repay Borrow: Users can repay the borrowed asset and accrued interest.

    2-Kink Interest Rate Model Architecture

    The 2-Kink IR Curve is built into the Interest Rate Models used by Venus markets. It allows for two distinct kinks in the curve, separating the initial utilization phase from the high-utilization phase. This enables better control over borrow and supply rates as utilization increases.

    The curve is defined by:

    • Kink: A utilization threshold where the interest rate curve’s slope changes.

    • Multiplier: The rate at which the interest rate increases before and after the kink, controlling the curve’s steepness.

    • Base Rate: A predefined APY jump at the start of the curve or any kink, providing a step-up in interest rates as utilization increases.

    By using two kinks and base rates, the protocol can more accurately balance supply and borrow demand, especially in markets with varying demand cycles like launchpools.

    Two Kinks Interest Rate Model

    Benefits of 2-Kink IR Curve

    • More Predictable APYs: By introducing a second kink, the interest rate curve allows for smoother transitions in APYs as market utilization changes.

    • Increased Participation: Both borrowers and suppliers benefit from more predictable rates, encouraging greater market participation even during high-demand periods.

    • Optimized Market Efficiency: By reducing sharp spikes in borrow APYs, the 2-Kink IR Curve improves the overall efficiency of Venus markets, ensuring better control over utilization rates and protocol reserves.

    Smart Contract Reference

    • Two Kinks Rate Model contract (for the Core pool on BNB Chain)

    • Two Kinks Rate Model contract (for the Isolated pools)

    • Jump Rate Model contract (used in the Core pool on BNB Chain)

    • Jump Rate Model V2 contract (used in the Isolated pools)

    Step 1: Connect to ZKsync on Venus
    1. Open the Venus app and connect your wallet.

    2. Make sure you are connected to the ZKsync network. If you are not, switch your wallet’s network to ZKsync.

    Selection of ZKsync network

    Step 2: Interact with the Venus Protocol

    In this example, we will approve the use of the ZK market as collateral.

    1. Navigate to the ZK market on Venus.

    2. Click on "Collateral" to enable the use of this market as collateral.

    Interaction with any feature on ZKsync

    Step 3: Sign the Transaction

    1. Instead of sending a typical transaction, you will be prompted to sign a message. This step authorizes Zyfi to pay for the gas fee of the transaction on your behalf.

    2. Sign the message in your wallet. The gas for the transaction will be covered by Zyfi Paymaster, so you don’t need ETH in your wallet.

    3. Once signed, Zyfi processes the transaction, and it is sent to the ZKsync blockchain with gas paid through their vault.

    Sign a message with Rabby, instead of sending a transaction
    Sign a message with Metamask, instead of sending a transaction

    Viewing the Transaction

    You can verify the transaction on the ZKsync Explorer. The transaction will display Zyfi as the Paymaster, covering the gas fees.

    Zyfi Paymaster

    VIPs

    Overview

    Venus Protocol's governance relies on participants locking XVS tokens into a vault to acquire voting power for Venus Improvement Proposals (VIPs). A 48-hour timelock period after voting ensures transparency and protection against malicious proposals. However, the initial model's rigidity prompted the introduction of a new governance structure in Venus V4. This upgraded model incorporates fast-track VIPs, role-based access control, and a fine-grained pause mechanism for enhanced flexibility and timely adjustments.

    Governance Upgrade

    Venus V4 introduces an improved governance structure with the following components:

    • Fast-track and Critical VIPs

    • Role-based access control

    • Fine-grained pause

    Fast-track and Critical Improvement Proposals

    Venus Governance has now categorized VIPs into three types: Normal, Fast-track, and Critical.

    • Normal VIPs encompass significant updates like contract upgrades or changes in access controls.

    • Fast-track VIPs deal with risk parameter adjustments such as interest rates or collateral factors.

    • Critical VIPs are utilized during emergencies demanding an immediate reaction.

    Each VIP type has its unique proposal threshold, timelock, and voting periods, reflecting the potential risk and impact of the proposed changes.

    The initial voting and delay periods for these types are as follows:

    • Normal VIP: 24 hour voting period + 48 hour delay (+ 48 hour delay to execute commands on networks other than BNB Chain)

    • Fast-track VIP: 24 hour voting period + 6 hour delay (+ 6 hour delay to execute commands on networks other than BNB Chain)

    • Critical VIP: 6 hour voting period + 1 hour delay (+ 1 hour delay to execute commands on networks other than BNB Chain)

    Role-based Access Control

    Venus V4 employs a separate Access Control Manager contract that validates access permissions rather than merely verifying the caller as an "admin". This allows certain actions to bypass voting, enabling them to take the fast-track or critical route, or even to be executed directly through a multisig by guardians. It can be particularly useful for implementing borrowing and supply caps, pausing specific market actions, or responding to rapid market fluctuations.

    Fine-grained Pause

    A fine-grained pause mechanism allows the pause guardian to individually halt any action on any market. Unlike previous versions, where the entire protocol was paused for damage control or protection against attacks, the updated model enables guardians to pause individual market actions like supply, borrow, and enabling collateral, offering greater control and flexibility.

    VAI

    Overview

    VAI is the primary stablecoin of the Venus Protocol. It is carefully designed and integrated with a series of stability mechanisms to maintain its peg to 1 USD.

    Stability Fee and Optimised Minting

    VAI sustains its value via a stability fee system. This fee is a charge that users incur when they repay their minted VAI. Calculated on a block-by-block basis, this fee gets added to the user's minted VAI balance. This fee system encourages users to either mint or burn VAI in response to its price fluctuations, thereby contributing to its stability.

    The stability fee is determined through the following formula:

    The baseRate is a fixed rate that users must always pay, while max(0, (1 - currentPriceOfVAI)) * floatingRate is a variable rate that users pay based on outstanding VAI. This incentivizes users to burn or mint VAI according to its price. The variable rate will always be greater or equal to zero, meaning the minimum stability fee will be the base rate.

    Revenue generated from the stability fee serves as a financial cushion during extreme market conditions, such as bad debt scenarios.

    VAIVaultProxy

    VAI Vault Proxy

    Proxy contract for the VAI Vault

    Solidity API

    _setPendingImplementation

    • Admin Functions **


    _acceptImplementation

    Accepts new implementation of VAI Vault. msg.sender must be pendingImplementation

    Return Values

    Name
    Type
    Description

    _setPendingAdmin

    Begins transfer of admin rights. The newPendingAdmin must call _acceptAdmin to finalize the transfer.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _acceptAdmin

    Accepts transfer of admin rights. msg.sender must be pendingAdmin

    Return Values

    Name
    Type
    Description

    Risk Fund and Shortfall Handling

    Overview

    Venus Protocol manages risks of high volatility tokens with isolated pools. Each pool (Isolated Pools and the Core pool) has an associated risk fund receiving a percentage of the pool's income (interest and liquidation bonus) in USDT to prevent insolvency. The specific percentage is defined by the tokenomics of the project. The risk fund also covers bad debt in case of bankruptcy without a liquidator.

    Risk fund

    The risk fund concerns three main contracts:

    • ProtocolShareReserve

    • RiskFund

    • ReserveHelpers

    These three contracts are designed to hold funds that have been accumulated from interest reserves and liquidation incentives, send a portion to the protocol treasury, and send the remainder to the RiskFund contract. When reduceReserves() is called in a vToken contract, all accumulated liquidation fees and interests reserves are sent to the ProtocolShareReserve contract. Once funds are transferred to the ProtocolShareReserve, anyone can call releaseFunds() to transfer 50% to the protocolIncome address and the other 50% to the riskFund contract. Once in the riskFund contract, the tokens can be swapped via PancakeSwap pairs to the convertible base asset, which can be updated by the authorized accounts. When tokens are converted to the convertibleBaseAsset, they can be used in the Shortfall contract to auction off the pool's bad debt. Note that just as each pool is isolated, the risk funds for each pool are also isolated: only the associated risk fund for a pool can be used when auctioning off the bad debt of the pool.

    Shortfall

    When a borrower's shortfall (total borrowed amount converted to USD is greater than the total supplied amount converted to USD) is detected in a market in the Isolated Pools, Venus halts the interest accrual, writes off the borrower's balance, and tracks the bad debt.

    Shortfall is an auction contract designed to auction off the convertibleBaseAsset accumulated in RiskFund. The convertibleBaseAsset is auctioned in exchange for users paying off the pool's bad debt. An auction can be started by anyone once a pool's bad debt has reached a minimum value (see Shortfall.minimumPoolBadDebt()). This value is set and can be changed by the authorized accounts. If the pool’s bad debt exceeds the risk fund plus a 10% incentive, then the auction winner is determined by who will pay off the largest percentage of the pool's bad debt. The auction winner repays the bid percentage of the bad debt in exchange for the entire risk fund. Otherwise, if the risk fund covers the pool's bad debt plus the 10% incentive, then the auction winner is determined by who will take the smallest percentage of the risk fund in exchange for paying off all the pool's bad debt.

    The main configurable (via VIP) parameters in the Shortfall contract , and their initial values, are:

    • minimumPoolBadDebt - Minimum USD bad debt in the pool to allow the initiation of an auction. Initial value set to 1,000 USD

    • waitForFirstBidder - Blocks to wait for first bidder. Initial value sets to 100 blocks

    • nextBidderBlockLimit - Time to wait for next bidder. Initial value set to 100 blocks

    Availability:

    • Shortfall contract will be used only for the markets in the Isolated Pools.

    • The markets in the Core pool don't track the bad debt at the moment, so it cannot be reduced automatically.

    VAIUnitroller

    VAI Unitroller

    This is the proxy contract for the VAIComptroller

    Solidity API

    _setPendingImplementation

    • Admin Functions **


    _acceptImplementation

    Accepts new implementation of comptroller. msg.sender must be pendingImplementation

    Return Values

    Name
    Type
    Description

    _setPendingAdmin

    Begins transfer of admin rights. The newPendingAdmin must call _acceptAdmin to finalize the transfer.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _acceptAdmin

    Accepts transfer of admin rights. msg.sender must be pendingAdmin

    Return Values

    Name
    Type
    Description

    XVSVaultProxy

    XVS Vault Proxy

    XVS Vault Proxy contract

    Solidity API

    _setPendingImplementation

    • Admin Functions **


    _acceptImplementation

    Accepts new implementation of XVS Vault. msg.sender must be pendingImplementation

    Return Values

    Name
    Type
    Description

    _setPendingAdmin

    Begins transfer of admin rights. The newPendingAdmin must call _acceptAdmin to finalize the transfer.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _acceptAdmin

    Accepts transfer of admin rights. msg.sender must be pendingAdmin

    Return Values

    Name
    Type
    Description

    XVSVaultTreasury

    XVSVaultTreasury

    This contract stores XVS received from XVSVaultConverter and funds XVSVault

    Solidity API

    XVS_ADDRESS

    The xvs token address


    xvsVault

    The xvsvault address


    fundXVSVault

    This function transfers funds to the XVS vault

    Parameters

    Name
    Type
    Description

    📅 Events

    • FundsTransferredToXVSStore emits on success

    ⛔️ Access Requirements

    • Restricted by ACM

    ❌ Errors

    • InsufficientBalance is thrown when amount entered is greater than balance

    sweepToken

    This function sweep tokens from the contract

    Parameters

    Name
    Type
    Description

    📅 Events

    • SweepToken emits on success

    ⛔️ Access Requirements

    • Restricted by ACM


    VTreasury

    VTreasury

    Contract for treasury all tokens as fee and transfer to governance

    Solidity API

    fallback

    To receive BNB


    withdrawTreasuryBEP20

    Withdraw Treasury BEP20 Tokens, Only owner call it

    Parameters

    Name
    Type
    Description

    withdrawTreasuryBNB

    Withdraw Treasury BNB, Only owner call it

    Parameters

    Name
    Type
    Description

    Venus interface

    Let's take a quick look at the Venus interface and the features available in each menu of the navigation bar.

    Dashboard

    In the center of the Dashboard interface, you will find the Supply and Borrow markets. You'll also notice a new column called 'Pool' which identifies the pool to which each market belongs. The Supply market allows you to lend your cryptocurrency assets and earn interest on them. You can choose which assets to supply and specify the amount you want to lend. On the other hand, the Borrow market allows you to borrow cryptocurrency assets by using your supplied assets as collateral. You can select the assets you want to borrow and specify the amount you need.

    Account

    The Account interface provides an overview of your supplied and borrowed assets. Here, you can keep track of your balances and monitor the status of your transactions.

    Core Pool

    The Core Pool interface is your hub for exploring all primary markets available. It allows you to click on each market to examine essential metrics such as 'Supply APY', 'Borrow APY', and 'Total Liquidity', among others. This interface centralizes all your lending and borrowing activities within the main markets.

    Pools

    The Pools interface allows you to explore all isolated pools available. You can click on each pool to view all the markets within it. In the markets, you can see various metrics such as 'Supply APY', 'Borrow APY', 'Total Liquidity', and more.

    Vaults

    The Vaults interface allows you to access and manage the vaults associated with Venus Protocol. Vaults are designed to provide users with automated strategies for optimizing their yields and managing their assets more efficiently.

    Swap

    The Swap interface enables you to swap one cryptocurrency for another within the Venus Protocol. You can exchange your assets conveniently and quickly.

    History

    In the History interface, you can review transaction history and track your previous activities on the Protocol.

    Governance

    The Governance interface provides access to Venus Protocol's governance features. Here, users can participate in voting and contribute to decision-making processes that shape the future of the protocol.

    XVS

    The XVS interface displays the current daily reward distribution rate for each of the protocol markets.

    VAI

    The VAI interface is where you can mint and manage the VAI stablecoin. VAI is created on Venus Protocol and is pegged to the value of one USD.

    Borrowing VAI

    Introduction

    This guide provides step-by-step instructions on how to borrow VAI, the stablecoin of Venus Protocol, available exclusively for prime users. Borrowing involves using your account's total core pool collateral to secure the loan, and this tutorial will walk you through the VAI UI to accomplish this.

    Steps for Borrowing VAI

    Step 1: Access VAI Borrowing UI

    Navigate to the Venus Protocol website and select the "VAI" option from the sidebar menu. This will take you to the VAI dashboard, where you can manage your borrowings and repayments.

    Step 2: Connect Your Wallet

    Click on the "Connect wallet" button in the top right corner of the VAI dashboard to connect your wallet. This is necessary to interact with the Venus Protocol and manage your VAI borrowings.

    Step 3: Enter Borrow Amount

    In the "Borrow" tab, enter the amount of VAI you wish to borrow in the provided field. You can also see your maximum borrow limit based on your account's total collateral. Ensure that the amount you wish to borrow does not exceed this limit.

    Step 4: Review and Confirm Borrowing

    After entering the desired amount, review the details of your borrowing transaction, including the collateral used and the borrow limit. Once you've confirmed that everything is correct, click on the "Borrow" button to initiate the transaction.

    A wallet pop-up will appear, asking for your confirmation to proceed with the transaction. Confirm to finalize the borrowing process.

    Repaying VAI Debt

    Step 1: Navigate to Repay Tab

    To repay your VAI debt, access the VAI dashboard again and select the "Repay" tab. This interface allows you to make repayments towards your borrowed VAI.

    Step 2: Enter Repayment Amount

    In the "Repay" tab, enter the amount of VAI you wish to repay. You can choose to repay part of your debt or the entire amount.

    Step 3: Review and Confirm Repayment

    Review your repayment details carefully. Once you are ready, click on the "Repay VAI" button to proceed. Confirm the transaction in your wallet pop-up to complete the repayment process.

    Conclusion

    Borrowing and repaying VAI on Venus Protocol is straightforward with the VAI UI. By following these steps and ensuring you have enough collateral, you can manage your stablecoin needs effectively. Always be mindful of your borrow limits and repayment responsibilities to maintain a healthy financial position within the protocol.

    Native Token Gateway

    The NativeTokenGateway contract serves the purpose of facilitating seamless interaction with Wrapped Native Token markets, even for users who do not possess any Wrapped Native Tokens. It achieves this by allowing users to utilize the native currency in their wallets directly.

    Overview

    The Venus contracts deployed on the new networks do not directly support native currencies. For example on Ethereum instead of a native ether market there is a market for WETH. Wrapped Native Token markets address this limitation by facilitating the conversion of native currency into a format compatible with the ERC-20 standard.

    To streamline user experience and eliminate the need for an additional transaction to convert native tokens into wrapped tokens, wrapping an unwrapping of native tokens is done behind the scenes when users interact with the market.

    Risk Management

    Introduction

    Venus Protocol is deeply committed to ensuring the highest level of security and risk management for our users. This section of the documentation outlines our comprehensive approach to risk management, emphasizing our continuous monitoring practices, partnerships for enhanced security, real-time alert systems, and ongoing risk assessments.

    Capped Oracles

    Some assets, such as Liquid Staking Tokens (LSTs), are closely tied to an underlying asset, often featuring an added growth component.

    The exchange rate between an asset and its underlying is typically sourced from an onchain smart contract, which can be susceptible to manipulation. A capped oracle is a design mechanism that mitigates potential losses from such manipulation by limiting the rate at which the exchange rate is allowed to grow.

    The capped oracle mechanism should be used for any asset whose price is derived through an intermediary token, where the exchange rate between the source asset and the intermediary is fetched onchain and includes a growth component.

    At a high level, the capped oracle determines the maximum allowable exchange rate at the queried block based on a predefined growth rate. It then compares this with the current onchain exchange rate, and if the current rate exceeds the calculated maximum, it caps it to that maximum value.

    Typically, the current maximum exchange rate at a given block is calculated by taking a historical exchange rate from a past block and applying a predefined per-second growth rate up to the current block timestamp. However, since the exchange rate may not grow consistently over time, the historical reference rate is periodically updated to ensure a more accurate and reliable maximum exchange rate.

    The historical reference rate is periodically refreshed through a process called snapshotting. During this process, the new reference rate is set to the lower of the current onchain exchange rate or the maximum rate derived from the previous reference rate, helping maintain a more accurate and robust cap. Before querying an asset’s price from the capped oracle, the consumer should trigger the snapshotting process. If the configured interval has elapsed, a new snapshot will be taken.

    Risk Oracles and Risk Stewards

    Overview

    Venus Protocol incorporates Risk Oracles and Risk Stewards to ensure risk parameters remain up-to-date, resilient, and aligned with real-time market conditions—all while preserving decentralized governance. Previously, Venus relied on manually created VIPs to apply risk updates based on Chaos Labs recommendations. With the introduction of the Risk Steward and its on-chain receiver, this process is now automated through a secure and permissioned mechanism. In the initial phase, only market cap-related parameters—specifically supply caps and borrow caps—will be updated automatically, improving responsiveness and operational efficiency.


    Tokenomics

    Overview

    The Venus Protocol tokenomics have been reevaluated to optimize income distribution and cater to the protocol's present and future needs. of the Venus Protocol revenue distribution model addresses the need and optimizes the allocation between rewards, treasury reserves, a risk fund and BNB burns.

    Import Positions

    Introduction

    This guide provides step-by-step instructions on how to import your supply positions from other DeFi platforms into the Venus Protocol.

    Steps for importing supply positions from other DeFi platforms)

    XVS Bridge

    Introduction

    This guide provides step-by-step instructions on how to bridge XVS tokens from the BNB Chain to the Ethereum network.

    Steps for Bridging XVS from BNB Chain to Ethereum

    function executeFlashLoan(
        address payable onBehalf,
        address payable receiver,
        VToken[] memory vTokens,
        uint256[] memory underlyingAmounts,
        bytes memory param
    ) external

    incentiveBps - Incentive to auction participants. Initial value set to 1000 bps or 10%

    The funds generated in the Core pool, that should be allocated to the risk fund, are temporarily sent to the Venus Treasury contract. With the relase of the Automatic income allocation feature, this income will be sent to the ProtocolShareReserve contract, where there will be distributed following the tokenomics of the project.

  • The funds associated with the Core pool, accumulated in the RiskFund contract, will be used to repay the bad debt of the Core pool via VIP.

  • Chaos Labs Risk Oracle

    The Chaos Labs Risk Oracle is a system designed to continuously analyze market conditions—such as price volatility, liquidity, asset utilization, and liquidation events—and generate risk parameter recommendations tailored to the Venus Protocol.

    Key Benefits:

    • Real-time updates to key parameters like supply and borrow caps

    • Automated adjustments to ensure optimal lending and borrowing rates

    • More responsive risk management with lower latency

    • Reduced operational overhead for the Venus community

    The Risk Oracle makes Venus more adaptable while ensuring parameters remain within safe and governance-approved limits.


    Risk Steward

    A Risk Steward is an on-chain smart contract that executes risk parameter updates on behalf of the protocol, based on recommendations from the Risk Oracle. Venus has introduced this role to bridge off-chain risk intelligence with on-chain execution in a controlled, transparent way.

    Role of the Risk Steward:

    • Reads values from the Risk Oracle during execution

    • Updates only pre-approved risk parameters (e.g., supply caps, borrow caps)

    • Operates within limits set by Venus governance

    • Cannot modify critical protocol settings such as interest rate models, market listings, or governance controls

    This structure ensures faster, automated adjustments without compromising community control.


    How It Works

    1. Data Source: Chaos Labs publishes updated recommendations via the Risk Oracle.

    2. Keeper Role: A Keeper bot observes changes and initiates transactions to update Venus Protocol’s parameters.

    3. Validation: During execution, Venus contracts read and apply new values only if they are within predefined safety bounds.

    4. Challenge Window: Critical updates, which will be introduced in an upcoming phase, will go through governance and can be challenged or vetoed during a defined challenge window before they take effect.

    Governance & Control

    Importantly, this system does not bypass protocol governance. All automated updates happen within constraints defined and approved by the Venus community.

    Any change made through the Risk Oracle follows an optimistic governance model:

    This process preserves decentralization while enabling faster, safer protocol maintenance.


    What’s Next

    Initially, the integration focuses on automating supply and borrow cap updates. Over time, additional parameters may be supported as part of a gradual rollout, always subject to DAO approval and governance-defined constraints.


    Learn More

    • Chaos Labs: Risk Oracles — Real-Time Risk Management for DeFi

    • Venus Community Proposal: Integrate Chaos Labs Risk Oracle

    param

    bytes

    The bytes passed in the executeOperation call

    stabilityFee(%)=baseRate(%)+max⁡(0,(1−currentPriceOfVAI))×floatingRate(%)\text{{stabilityFee}}(\%) = \text{{baseRate}}(\%) + \max(0, (1 - \text{{currentPriceOfVAI}})) \times \text{{floatingRate}}(\%)stabilityFee(%)=baseRate(%)+max(0,(1−currentPriceOfVAI))×floatingRate(%)
    Governance Process

    The capped exchange rate between intervals is constrained by a per-second growth limit. However, since the actual exchange rate may exceed this cap, we inflate the snapshotted exchange rate by a predefined buffer to avoid imposing a hard limit.

    Configuration

    The following configuration needs to be defined when configuring the capped oracle for a token:

    • Annual Growth Rate: This defines the maximum growth in exchange rate per year. Internally this is converted to growth rate per second.

    • Snapshot Interval: After the number of seconds window at which the reference exchange rate is recalculated,

    • Initial Snapshot Exchange Rate and Timestamp: Defines the initial reference exchange rate and the timestamp at which the exchange rate is taken from.

    • Snapshot Gap: Used to define the inflation of the exchange rate at each snapshot.

    Note that all the above variables values can be updated using the governance process after the deployment with the initial values.

    Example

    Let’s walk through an example to understand how the capped oracle functions. Suppose we want to retrieve the exchange rate between wstETH and stETH.

    • Annual Growth Rate: Assume an annual growth rate of 2.9%, based on Lido’s estimated APY. Taking into account Lido compounding period is daily, the estimated APY would be 2.9423% (compounding should be considered when the caps are defined). So, the associated capped oracle could be configured with a maximum annual growth rate of 5%. Internally, this will be converted into a per-second growth rate.

    • Snapshot Interval: The snapshot can be updated once per month to refresh the reference exchange rate.

    • Initial Snapshot: We fetch the current exchange rate and timestamp from the onchain wstETH contract. For instance, the current exchange rate is 1.200101369591475639 and the timestamp is 1744895950. We apply a buffer on top of the current exchange rate: for example 1% of the maximum annual growth rate, that is 1% * 5% = 0.05%. So, the initial snapshot value would be 1.200101369591475639 * 1.0005 = 1.20070142027627137681. This way, the capped oracle won't cap spikes on the wstETH exchange rate just after the initialization.

    • Snapshot Gap: The same concept of the buffer applied to calculate the initial snapshot in the previous step, but to be considered every time the snapshot is automatically updated. This cap could be set to 1.200101369591475639 * 0.0005 = 0.0006, and reviewed periodically.

    Given this initial setup:

    • after 15 days, the maximum exchange rate allowed will be 1.20070142027627137681 * (1 + (0.05 * 15 / 365)) = 1.20316860954764085647

    • after 1 month, the snapshot will be automatically updated. Assuming the exchange rate at that time is 1.20300161856832627043, after applying the snapshot gap, the new maximum exchange rate will be 1.20360161856832627043 (1.20300161856832627043 + 0.0006)

    • after 15 days, the maximum exchange rate allowed will be 1.20360161856832627043 * (1 + (0.05 * 15 / 365)) = 1.20607476713814428156

    Capped Oracle main elements
    Two Kinks Interest Rate Model
    Selection of ZKsync network
    Interaction with any feature on ZKsync
    Sign a message with Rabby, instead of sending a transaction
    Sign a message with Metamask, instead of sending a transaction

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    newPendingAdmin

    address

    New pending admin.

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    newPendingAdmin

    address

    New pending admin.

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    newPendingAdmin

    address

    New pending admin.

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    amountMantissa

    uint256

    Amount to be sent to XVS vault

    tokenAddress

    address

    Address of the asset(token)

    to

    address

    Address to which assets will be transferred

    amount

    uint256

    Amount need to sweep from the contract

    tokenAddress

    address

    The address of treasury token

    withdrawAmount

    uint256

    The withdraw amount to owner

    withdrawAddress

    address

    The withdraw address

    withdrawAmount

    uint256

    The withdraw amount to owner

    withdrawAddress

    address payable

    The withdraw address

    function _setPendingImplementation(address newPendingImplementation) public returns (uint256)
    function _acceptImplementation() public returns (uint256)
    function _setPendingAdmin(address newPendingAdmin) public returns (uint256)
    function _acceptAdmin() public returns (uint256)
    function _setPendingImplementation(address newPendingImplementation) public returns (uint256)
    function _acceptImplementation() public returns (uint256)
    function _setPendingAdmin(address newPendingAdmin) public returns (uint256)
    function _acceptAdmin() public returns (uint256)
    function _setPendingImplementation(address newPendingImplementation) public returns (uint256)
    function _acceptImplementation() public returns (uint256)
    function _setPendingAdmin(address newPendingAdmin) public returns (uint256)
    function _acceptAdmin() public returns (uint256)
    address XVS_ADDRESS
    address xvsVault
    function fundXVSVault(uint256 amountMantissa) external
    function sweepToken(address tokenAddress, address to, uint256 amount) external
    fallback() external payable
    function withdrawTreasuryBEP20(address tokenAddress, uint256 withdrawAmount, address withdrawAddress) external
    function withdrawTreasuryBNB(uint256 withdrawAmount, address payable withdrawAddress) external payable
    User Journey

    The introduction of the NativeTokenGateway contract significantly enhances the user experience when interacting with wrapped native token markets. Unlike before, where users were required to have the wrapped native token to engage with markets, they now have the flexibility to choose between native currency or wrapped version for market interaction.

    If the user opts for native currency, the following functions are executed to facilitate interaction with the protocol:

    Approve Delegate

    The updateDelegate function facilitates the granting or revocation of borrowing and redeeming delegate rights to or from an account. By invoking this function, borrowing delegate rights or redeeming delegate rights can be assigned to a specific address (delegate), enabling them to borrow or redeeming funds on behalf of the User.

    This mechanism provides flexibility and control over borrowing and redeeming activities within the protocol, enhancing the overall efficiency and functionality of the system.

    Interaction with the NativeTokenGateway contract

    Supply (wrapAndSupply)

    • The wrapAndSupply function is invoked sending the native currency, and the execution proceeds as follows:

      • Native currency is wrapped, providing the wrapped token.

      • VWrappedNative tokens are minted on behalf of the user.

      • VWrappedNative tokens are transferred to the user.

    Redeem

    1. redeemUnderlyingAndUnwrap

      • The user approves the NativeTokenGateway contract as the delegate.

      • The redeemUnderlyingAndUnwrap function is called with the amount of underlying tokens to redeem, and the execution proceeds as follows:

        • VWrappedNative tokens are redeemed by the NativeTokenGateway contract on behalf of the user.

        • Received wrapped native tokens are unwrapped to obtain native currency.

        • Native currency is transferred to the user.

    2. redeemAndUnwrap

      • The user approves the NativeTokenGateway contract as the delegate.

      • The redeemAndUnwrap function is called with the amount of VWrappedNative tokens to redeem, and the execution proceeds as follows:

    Borrow (borrowAndUnwrap)

    • The user approves the NativeTokenGateway contract as the delegate.

    • The borrowAndUnwrap function is invoked, and the execution proceeds as follows:

      • Wrapped native tokens are borrowed on behalf of the user.

      • The borrowed wrapped native tokens are unwrapped to obtain native currency.

      • Native currency is transferred to the user.

    Repay (wrapAndRepay)

    • The wrapAndRepay function is invoked sending the native currency, and the execution proceeds as follows:

      • The native currency sent is wrapped, providing the wrapped native.

      • The NativeTokenGateway repays the debt on behalf of the user.

      • Any unused native currency for repayment is returned to the user.

    Multiple Audits Before Deployment
    • Prior to deployment, Venus Protocol undergoes extensive audits conducted by industry-leading security firms. The results of these audits are publicly accessible and have been fully implemented, ensuring a robust and secure framework.

    • Access our detailed audit reports here: Security and Audits.

    Continuous On-Chain Monitoring

    • Venus Protocol has partnered with Chaos Labs, a leader in blockchain security and monitoring. This partnership equips us with sophisticated tools for continuous on-chain monitoring, significantly enhancing our risk control and mitigation strategies.

    • Explore our monitoring dashboard for real-time insights: Chaos Labs Risk Overview.

    Real-Time Alert System

    • To further enhance our risk management, we have implemented a real-time alert system via Telegram. This system provides immediate notifications for critical events such as market high utilization, significant whale movements, and borrow/supply cap utilization.

    • Join our alert channel to stay updated: Chaos Labs Telegram Alerts.

    Dynamic Risk Management

    • In collaboration with Chaos Labs, we continuously analyze market conditions and adjust risk parameters across all pools regularly or anytime there is need for adjustment to mitigate risks due to market conditions. These adjustments are based on comprehensive data analysis and are integral to maintaining the stability and security of the protocol.

    Frontend

    Several security measures have been implemented to mitigate the security risks associated with the frontend app deployed at https://app.venus.io.

    • The Venus Protocol UI is deployed on AWS infrastructure. Additionally, Cloudflare is employed to distribute the web app. The relevant security services in both AWS and Cloudflare are properly configured to detect and mitigate security risks.

    • SPF and DKIM are configured to protect every email sent from a @venus.io account.

    • Web certificates, generated by AWS, are set to auto-renew.

    • Venus nameservers are hosted on Cloudflare, serving as our DNS provider.

    • The Venus Protocol UI utilizes to assess the risk profile associated with web3 addresses. If the risk is deemed high, the connection is disallowed, preventing any interactions with contracts from the UI involving that risky address.

    • Only privileged users have the authority to deploy the open-source code, accessible on Github (https://github.com/VenusProtocol/venus-protocol-interface), to the domain app.venus.io. Additionally, only privileged users are authorized to merge pull requests in the Github repository.

    Conclusion

    The risk management practices at Venus Protocol are designed to provide a secure and stable environment for our users. Our commitment to continuous monitoring, real-time alerts, and dynamic risk adjustments ensure that we are always at the forefront of blockchain security. We encourage our community to explore the provided resources for a deeper understanding of our risk management protocols.

    XVS Vault Base Rewards

    The XVS Staking Vault is an integral component of the Venus ecosystem. It enables governance voting participation and is a prerequisite for Venus Prime eligibility. To incentivize XVS staking, additional rewards will be offered in the form of Base Rewards (previously referred to as Legacy Rewards).

    These rewards will be transferred every six months from the XVS Distributor to the XVS Vault Store, where they will be emitted at a rate of 308.7 XVS per day.

    Revenue Distribution from Protocol Reserves

    Protocol reserves are mainly composed of accumulated borrow fees. The model for revenue allocation from these reserves divides income into three main segments:

    • Treasury Reserve (15%): The treasury reserve is used to fund community-driven initiatives and essential protocol expenses for its ongoing operations.

    • XVS Vault Rewards (20%): This allocation is designated for the buyback of XVS, which is then distributed via vault rewards.

    • Venus Prime Token Program (20%): Used to boost select market APYs with organic rewards for users that qualify.

    • Risk Fund (20%): This fund is established to address potential shortfalls in the protocol, particularly in situations of ineffective or delayed liquidations.

    • BNB Burn (25%): See community proposal .

    Allocation for Additional Revenue Streams

    Other revenue streams include liquidation penalties and potential income generated from future product releases. The revenue distribution for these streams is as follows:

    • Treasury Reserves (35%)

    • XVS Vault Rewards (20%)

    • Risk Fund (20%)

    • BNB Burn (25%)

    The methodology behind these adjustments includes an assessment of the existing tokenomics, past changes, their impact on the ecosystem, and analysis of market dynamics and trends.

    This dual allocation model accounts for the diverse revenue sources within the Venus Protocol ecosystem, ensuring robust and responsive financial management. As the protocol evolves and introduces new products, these models may further be adjusted to optimally serve the Venus community.

    Version 4.1
    Step 1: Connect Your Wallet
    • Click on the "Connect wallet" button in the top right corner of the Venus Bridge interface to connect your wallet.

    If you have supply positions in other DeFi protocols (we currently only support Aave, with more to come soon) for which we can propose a better APY, a modal will automatically appear showing you options to import your positions to the Venus Protocol.

    If you close this modal, it won't be shown to you ever again. You can still access this UI by selecting the "Import" item in the side menu.

    Step 2: Initiate an Import

    • Click on the "Import" button next to any position listed.

    • A confirmation pop-up will appear in your wallet for you to approve the transaction. Note that this transaction is sponsored by the Venus Protocol, therefore it is free of charge.

    Step 3: Confirm and Wait

    • Confirm the transaction in your wallet. The interface will show the transaction as pending, indicating that it is being processed. This may take from a few seconds to a few minutes depending on the current network activity.

    • You can import all your positions one-by-one by repeating the process.

    Step 4: Transaction Completion

    • Once the transaction is complete, the new positions will appear in the "Account" page.

    Step 1: Access the Venus Bridge
    • Navigate to the Venus Protocol and select the "Bridge" option from the sidebar menu. XVS Bridge

    Step 2: Connect Your Wallet

    • Click on the "Connect wallet" button in the top right corner of the Venus Bridge interface to connect your wallet.

    Step 3: Configure the Bridge Transaction

    • From: Ensure "BNB mainnet" is selected in the "From" dropdown menu.

    • To: Select "Ethereum" in the "To" dropdown menu to set the destination network.

    Step 4: Enter the Amount to Bridge

    • Enter the amount of XVS you wish to transfer in the "Amount" field. You can also use the "MAX" button to transfer the total available balance.

    • Check your "Wallet balance" to confirm you have sufficient XVS and BNB for gas fees.

    Step 5: Approve XVS Token

    • Before initiating the transfer, you must give the bridge contract permission to access your XVS tokens. Click on the "Approve XVS" button to do this.

    • A wallet pop-up will request your confirmation for the approval. Confirm to proceed.

    Step 6: Initiate the Transfer

    • After approving XVS token usage, the interface will update to reflect the next step. Click the "Transfer" button (which replaces the "Approve XVS" button after approval) to initiate the bridging process.

    • A confirmation pop-up will appear in your wallet for you to approve the transaction.

    Step 7: Confirm and Wait

    • Confirm the transaction in your wallet. The Venus Bridge interface will show the transaction as pending, indicating that it is being processed. This may take a few minutes.

    Step 8: Transaction Completion

    • Once the transaction is complete, the XVS tokens will be available in your Ethereum wallet.

    Conclusion

    Bridging XVS tokens from BNB Chain to Ethereum is made simple with the Venus Protocol. Remember to approve your tokens for use by the bridge and to check transaction details carefully before confirming to ensure a smooth bridging experience.

    Protocol Math

    Overview

    The contracts under the Venus Protocol employ a system called Exponential.sol. This system uses exponential mathematics to represent fractional quantities with high precision.

    Most numbers in this system are represented by a mantissa, an unsigned integer scaled by a factor of 1 * 10^18. This scaling ensures basic mathematical operations can be performed with a high degree of accuracy.

    vToken and Underlying Decimals

    Prices and exchange rates are adjusted according to the unique decimal scaling of each asset. vTokens, which are BEP-20 tokens, are scaled with 8 decimal places. However, their underlying tokens may have different decimal scaling, which is indicated by a public member called 'decimals'.

    For further details, please refer to the respective token contract addresses.

    Interpreting Exchange Rates

    The exchange rate of vTokens is adjusted based on the decimal difference between the vToken and its underlying asset.

    Here is an example illustrating how to determine the value of one vBUSD in BUSD using the Web3.js JavaScript library.

    As BNB lacks an underlying contract, you must set the 'underlyingDecimals' to 18 when dealing with vBNB.

    To calculate the number of underlying tokens that can be redeemed using vTokens, you should multiply the total amount of vTokens by the previously computed 'oneVTokenInUnderlying' value.

    Calculating Accrued Interest

    Interest rates for each market are updated in any block where there is a change in the ratio of borrowed assets to supplied assets. The magnitude of this change in interest rates depends on the interest rate model smart contract in place for the market, and the degree of change in the aforementioned ratio.

    For a visualization of the current interest rate model applied to each market, refer to the market pages at the .

    The accrual of interest to suppliers and borrowers in a market occurs when any wallet interacts with the market's vToken contract. This interaction could be any of the following functions: mint, redeem, borrow, or repay. A successful execution of any of these functions triggers the accrueInterest method, leading to the addition of interest to the underlying balance of every supplier and borrower in the market. Interest accrues for the current block, as well as any previous blocks where the accrueInterest method was not triggered due to lack of interaction with the vToken contract. Interest only accumulates during blocks where one of the aforementioned methods is invoked on the vToken contract.

    Let's consider an example of supply interest accrual: Alice supplies 1 BNB to the Venus Protocol. At the time of her supply, the supplyRatePerBlock is 37893605 Wei, which equates to 0.000000000037893605 BNB per block. For 3 blocks, no interactions occur with the vBNB contract. On the subsequent 4th block, Bob borrows some BNB. As a result, Alice’s underlying balance is updated to 1.000000000151574420 BNB (calculated by multiplying 37893605 Wei by 4 blocks and adding the original 1 BNB). From this point onwards, the accrued interest on Alice’s underlying BNB balance will be based on the updated value of 1.000000000151574420 BNB, rather than the initial 1 BNB. It is important to note that the supplyRatePerBlock value may alter at any given time.

    Calculating the APY Using Rate Per Block

    The Annual Percentage Yield (APY) for either supplying or borrowing in each market can be computed using the supplyRatePerBlock (for Supply APY) or borrowRatePerBlock (for Borrow APY) values. These rates can be used in the following formula (assuming a daily compound):

    Here is an example of calculating the supply and borrow APY with Web3.js JavaScript:

    Automatic income allocation

    The purpose of this document is to explain the technical details for distributing incomes generated by the Venus Protocol. The distributed incomes are generated from the spread of lending rates (borrow minus supply rates) and liquidations (part of the liquidation incentives). The distribution process for both the Core Pool and Isolated Pools as well as how the different amounts are allocated to different destinations based on specific rules and the approach for near-streaming income distribution are covered.

    Income Distribution Schema

    The Venus Protocol generates income from two main sources:

    • Spread between the borrowing rate and the supply rate

    • Part of the liquidation incentives

    goes into more detail about the distribution schema and desired outcomes.

    The initial distribution excludes VAI funds, which are kept in the VTreasury.

    Streaming Income Distribution

    The Venus Protocol aims to distribute accumulated reserves in the markets automatically and in near-real-time, leveraging transactions executed by users. This approach eliminates the need for external tools to manage the distribution process. The ProtocolShareReserve contract serves as the designated destination for liquidation incomes, allowing for tracking and distribution within the Venus Protocol.

    Core Pool - Spread Income

    Accumulated reserves in the Core Pool markets will be distributed after reaching a specified threshold. The threshold is based on the number of blocks since the last transfer of reserves. This strategy helps socialize part of the cost associated with distribution.

    Core Pook - Liquidation Income

    In the Core Pool, liquidation income is transferred to the Liquidator contract in the form of vTokens. During a liquidation transaction, the Liquidator contract will try to redeem the protocol's portion of the liquidation incentive in vTokens for the underlying tokens. If the redemption process is successful, the underlying tokens will be sent to the ProtocolShareReserve contract. However, if the redemption fails the underlying tokens will be added to a list of pending redemptions and the Liquidator contract will try to redeem the pending redemptions again in subsequent liquidation transactions.

    Isolated Pool - Spread Income

    Distribution of income generated by the interest rate spread in Isolated Pools is socialized and distributed periodically just like in the Core Pool

    Isolated Pool - Liquidation Income

    The Isolated Pools liquidations are managed by the VToken contracts. During a liquidation transaction, the protocol's percentage of the seized amount is transferred directly to the ProtocolShareReserve contract. No other action is required.

    Distribution of Collected Incomes

    The distribution of collected incomes is facilitated by the ProtocolShareReserve contract. It supports WBNB transfers but not BNB transfers. Therefore, BNB needs to be wrapped into WBNB before transferring to the ProtocolShareReserve contract.

    updateAssetsState Function

    The updateAssetsState function enables the transfer of funds to the ProtocolShareReserve contract. After transferring funds to the ProtocolShareReserve contract, the updateAssetsState function is invoked with the following parameters:

    • address comptroller: The Comptroller where the market generated the income.

    • address asset: The asset transferred to the ProtocolShareReserve.

    • IncomeOrigin origin: The origin type, either "spread" or "liquidation."

    Within the updateAssetsState function, the following steps are performed:

    • Calculate the transferred balance, taking into account the previous balance of the asset.

    • Assign the received amount to the appropriate entry (comptroller - asset - schema).

    • Track the total balance of the received asset for future distribution.

    releaseFunds Function

    The releaseFunds function is responsible for distributing the accumulated funds to the different destinations. This function can be invoked by anyone and follows a two-step process:

    1. Transfer the tokens to the destination addresses.

    2. Invoke the updateAssetsState function in the receiver contract.

    VBNBAdmin

    VBNBAdmin contract is the admin of the vBNB vToken. All the other vToken contracts send revenue to PSR directly whereas vBNB sends the reserves to the admin i.e., the vBNBAdmin contract. This pattern is different for vBNB because it's not a upgradable contract.

    Whenever the VBNBAdmin receives BNB from the vBNB contract it converts it to WBNB and then sends it to the Protocol share reserve contract.

    To release the reserves of vBNB contract you need to call the reduceReserves() function of the VBNBAdmin contract.

    JumpModel

    JumpRateModel

    Solidity API

    constructor

    Construct an interest rate model

    Parameters

    Name
    Type
    Description

    utilizationRate

    Calculates the utilization rate of the market: borrows / (cash + borrows - reserves)

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getBorrowRate

    Calculates the current borrow rate per block, with the error code expected by the market

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getSupplyRate

    Calculates the current supply rate per block

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    Submitting a VIP

    Overview

    Venus Protocol's governance model allows XVS token holders to propose and vote on Venus Improvement Proposals (VIPs). Here's a step-by-step guide to help you create and submit a proposal.

    Remember, you need a voting weight of at least 300,000 to submit a proposal.

    Step 1: Visit the Venus Governance Portal

    Navigate to the Venus Governance Portal using your preferred web browser. You can access the portal at .

    Step 2: Connect Your Wallet

    To submit a proposal, you need to connect your wallet by clicking on the "Connect Wallet" button at the top right corner of the screen. A menu will appear listing various wallets that the Venus Governance Portal supports. Select your wallet from the menu and follow the instructions to connect your wallet to the portal.

    Step 3: Create a Proposal

    Now that your wallet is connected, you can create a proposal. Look for the "Create Proposal" button at the top right corner of the screen and click on it.

    This action will open a modal presenting two options - "Upload file" and "Create Manually":

    Step 4: Upload a proposal file

    The fastest way to create a proposal is by importing a VIP file. The import uses a JSON file containing all the information needed to create a VIP, such as the proposal's title, type, actions and parameters.

    Venus makes available a tool to generate VIP files, which you can find . You can also check an example of a valid proposal file . Note that all the fields will be validated according to their requirements and types.

    Step 4.1: Choose a VIP file

    Clicking "Upload file" will lead you to choose the proposal file you want to upload. After uploading the desired file, it will be parsed and validated and any possible errors found will be reported by the interface.

    Step 4.2: Confirm the Proposal

    Once the import is successfully validated, the interface will present all the VIP data for your review:

    If everything looks good, click "Create" at the bottom of the modal to confirm the creation of your VIP.

    Step 5: Create a Proposal Manually

    Proposals can also be created manually by clicking on "Create manually".

    Step 5.1: Choose the Proposal Type

    After clicking the "Create manually" button, a new interface will pop up prompting you to select the proposal type. Select the relevant proposal type for the change you want to propose.

    Step 5.2: Enter Proposal Information

    The next step is to provide detailed information about your proposal. This includes the proposal's title, a brief description, and a link to an off-chain discussion related to your proposal. Ensure the information you provide is clear and concise to facilitate understanding by other community members.

    Step 5.3: Set the Voting Options

    The third screen is where you can specify descriptions for the voting options (for, against, abstain).

    Step 5.4: Specify the Actions

    Next add the actions that will take place if the proposal is approved. An action requires an contract address, function signature and arguments so that the operation can be created correctly.

    Step 5.5: Confirm the Proposal Submission

    Finally, just like after the VIP import, you will be able to review your proposal to ensure all details are accurate. After confirming everything is correct, click the "Submit" button to submit your proposal. You'll see a confirmation prompt on your connected wallet. Confirm the transaction to complete the proposal submission process.

    Congratulations! You've successfully submitted a Venus Improvement Proposal. The Venus community will now review your proposal and vote on it. Remember, your active involvement in Venus Protocol's governance process is crucial for its continued development and success.

    Automatic Income Allocation

    Overview

    This innovation is designed to distribute the incomes generated by Venus Protocol seamlessly, channeling them to different destinations according to specific rules and percentages. This functionality will incorporate incomes generated through various sources, including interest reserves and liquidation incentives, for both the Core pools and Isolated pools. The goal is to distribute these incomes in underlying tokens and not in vTokens, based on the latest protocol tokenomics.

    Key Aspects of Automatic Income Allocation

    • Near-Streaming Distribution: The income will be distributed in a near-streaming fashion, from the different pools to the ProtocolShareReserve contract.

    • Flexible Distribution Rules: The incomes generated by Venus Protocol will be distributed according to two schemas:

      • Schema (PROTOCOL_RESERVES): Applied specifically to income generated by the interest reserves in every Venus market.

    Benefits

    • Efficiency: Automating the income distribution process allows for quicker and more accurate allocation.

    • Transparency: All distributions are recorded on the blockchain, reinforcing Venus Protocol's commitment to clear and open practices.

    • Flexibility: The ability to define specific rules and percentages for different destinations ensures that the distribution aligns with the community's needs and goals.

    Architecture

    The dashed lines represent transactions initiated by external agents (VIP’s, scripts, arbitrage bots, etc.), and the solid lines represent transfers of funds.

    Supplying and borrowing

    In this guide, we will focus on using Venus Protocol to earn interest and borrow assets. If you’re looking for a more technical understanding of what’s happening under the hood, check out .

    Once you’ve created your Web3 wallet on or any other supported wallet App, open the Venus app (). The interface will ask you to connect your Web3 wallet. Connecting your wallet to Venus Protocol enables you to authorize transactions, view balances, and perform other essential actions.

    After successfully connecting your wallet, you will gain access to all the features of the Venus Protocol interface. In the Dashboard menu you will find all the markets. Clicking one of the markets a new modal will pop out, enabling you to interact with the selected market. Just make sure you are under the "Supply" or "Borrow" tab, depending on the desired action.

    XVSStore

    XVS Store

    XVS Store responsible for distributing XVS rewards

    Solidity API

    VAIVault

    VAI Vault

    The VAI Vault is configured for users to stake VAI And receive XVS as a reward.

    Solidity API

    VBNBAdmin

    VBNBAdmin

    This contract is the "admin" of the vBNB market, reducing the reserves of the market, sending them to the ProtocolShareReserve contract, and allowing the executions of the rest of the privileged functions in the vBNB contract (after checking if the sender has the required permissions).

    ComptrollerStorage

    ComptrollerStorage

    Storage layout for the Comptroller contract.

    VWrappedNative tokens are redeemed by the NativeTokenGateway contract on behalf of the user.
  • Received wrapped native tokens are unwrapped to obtain native currency.

  • Native currency is transferred to the user.

  • Chainalysis
    Tokenomics
    https://app.venus.io/governance
    here
    here

    15% to Treasury

  • 20% to XVS Vault rewards

  • 20% to Venus Prime

  • 20% to Risk Fund

  • 25% to BNB Burn

  • Schema (ADDITIONAL_REVENUE): Valid for liquidation and other product developments.

    • 35% to Treasury

    • 20% to XVS Vault rewards

    • 20% to Risk Fund

    • 25% to BNB Burn

  • Integration with Existing Architecture: The Automatic Income Allocation will seamlessly integrate with the existing ProtocolShareReserve contract, ensuring that the incomes are sent to their designated reserves.

  • BNB Chain <> Venus BNB Burn Proposal
    oneVTokenInUnderlying=exchangeRateCurrent1×10(18+underlyingDecimals−vTokenDecimals)oneVTokenInUnderlying = \frac{exchangeRateCurrent}{1 \times 10^{(18 + underlyingDecimals - vTokenDecimals)}}oneVTokenInUnderlying=1×10(18+underlyingDecimals−vTokenDecimals)exchangeRateCurrent​
    underlyingTokens=vTokenAmount×oneVTokenInUnderlyingunderlyingTokens = vTokenAmount \times oneVTokenInUnderlyingunderlyingTokens=vTokenAmount×oneVTokenInUnderlying
    Markets
    Venus app

    baseRatePerYear

    uint256

    The approximate target base APR, as a mantissa (scaled by 1e18)

    multiplierPerYear

    uint256

    The rate of increase in interest rate wrt utilization (scaled by 1e18)

    jumpMultiplierPerYear

    uint256

    The multiplierPerBlock after hitting a specified utilization point

    kink_

    uint256

    The utilization point at which the jump multiplier is applied

    cash

    uint256

    The amount of cash in the market

    borrows

    uint256

    The amount of borrows in the market

    reserves

    uint256

    The amount of reserves in the market (currently unused)

    [0]

    uint256

    The utilization rate as a mantissa between [0, 1e18]

    cash

    uint256

    The amount of cash in the market

    borrows

    uint256

    The amount of borrows in the market

    reserves

    uint256

    The amount of reserves in the market

    [0]

    uint256

    The borrow rate percentage per block as a mantissa (scaled by 1e18)

    cash

    uint256

    The amount of cash in the market

    borrows

    uint256

    The amount of borrows in the market

    reserves

    uint256

    The amount of reserves in the market

    reserveFactorMantissa

    uint256

    The current reserve factor for the market

    [0]

    uint256

    The supply rate percentage per block as a mantissa (scaled by 1e18)

    safeRewardTransfer

    Safely transfer rewards. Only active reward tokens can be sent using this function. Only callable by owner

    Parameters

    Name
    Type
    Description

    token

    address

    Reward token to transfer

    _to

    address

    Destination address of the reward

    _amount

    uint256

    Amount to transfer


    setPendingAdmin

    Allows the admin to propose a new admin Only callable admin

    Parameters

    Name
    Type
    Description

    _admin

    address

    Propose an account as admin of the XVS store


    acceptAdmin

    Allows an account that is pending as admin to accept the role nly calllable by the pending admin


    setNewOwner

    Set the contract owner

    Parameters

    Name
    Type
    Description

    _owner

    address

    The address of the owner to set Only callable admin


    setRewardToken

    Set or disable a reward token

    Parameters

    Name
    Type
    Description

    _tokenAddress

    address

    The address of a token to set as active or inactive

    status

    bool

    Set whether a reward token is active or not


    emergencyRewardWithdraw

    Security function to allow the owner of the contract to withdraw from the contract

    Parameters

    Name
    Type
    Description

    _tokenAddress

    address

    Reward token address to withdraw

    _amount

    uint256

    Amount of token to withdraw


    pause

    Pause vault


    resume

    Resume vault


    deposit

    Deposit VAI to VAIVault for XVS allocation

    Parameters

    Name
    Type
    Description

    _amount

    uint256

    The amount to deposit to vault


    withdraw

    Withdraw VAI from VAIVault

    Parameters

    Name
    Type
    Description

    _amount

    uint256

    The amount to withdraw from vault


    claim

    Claim XVS from VAIVault


    claim

    Claim XVS from VAIVault

    Parameters

    Name
    Type
    Description

    account

    address

    The account for which to claim XVS


    pendingXVS

    View function to see pending XVS on frontend

    Parameters

    Name
    Type
    Description

    _user

    address

    The user to see pending XVS

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    Amount of XVS the user can claim


    updatePendingRewards

    Function that updates pending rewards


    _become

    • Admin Functions **


    setAccessControl

    Sets the address of the access control of this contract

    Parameters

    Name
    Type
    Description

    newAccessControlAddress

    address

    New address for the access control


    Solidity API

    vBNB

    address of vBNB


    WBNB

    address of WBNB contract


    initialize

    Used to initialize non-immutable variables


    setProtocolShareReserve

    PSR setter.

    Parameters

    Name
    Type
    Description

    protocolShareReserve_

    contract IProtocolShareReserve

    Address of the PSR contract

    📅 Events

    • Emits ProtocolShareReserveUpdated event.

    ⛔️ Access Requirements

    • Only owner (Governance)


    reduceReserves

    Reduce reserves of vBNB, wrap them and send them to the PSR contract

    Parameters

    Name
    Type
    Description

    reduceAmount

    uint256

    amount of reserves to reduce

    📅 Events

    • Emits ReservesReduced event.


    setInterestRateModel

    Sets the interest rate model of the vBNB contract

    Parameters

    Name
    Type
    Description

    newInterestRateModel

    address

    Address of the new interest rate model

    ⛔️ Access Requirements

    • Controlled by ACM


    receive

    Invoked when BNB is sent to this contract

    ⛔️ Access Requirements

    • Only vBNB is considered a valid sender


    fallback

    Invoked when called function does not exist in the contract. The function will be executed in the vBNB contract.

    ⛔️ Access Requirements

    • Only owner (Governance)


    Solidity API

    oracle

    Oracle which gives the price of any given asset


    closeFactorMantissa

    Multiplier used to calculate the maximum repayAmount when liquidating a borrow


    liquidationIncentiveMantissa

    Multiplier representing the discount on collateral that a liquidator receives


    accountAssets

    Per-account mapping of "assets you are in"


    markets

    Official mapping of vTokens -> Market metadata


    allMarkets

    A list of all markets


    borrowCaps

    Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.


    minLiquidatableCollateral

    Minimal collateral required for regular (non-batch) liquidations


    supplyCaps

    Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed


    isForcedLiquidationEnabled

    Flag indicating whether forced liquidation enabled for a market


    prime

    Prime token address


    approvedDelegates

    Whether the delegate is allowed to borrow or redeem on behalf of the user


    const vTokenDecimals = 8; // all vTokens have 8 decimal places
    const underlying = new web3.eth.Contract(bep20Abi, busdAddress);
    const vToken = new web3.eth.Contract(vTokenAbi, vBusdAddress);
    const underlyingDecimals = await underlying.methods.decimals().call();
    const exchangeRateCurrent = await vToken.methods.exchangeRateCurrent().call();
    const mantissa = 18 + parseInt(underlyingDecimals) - vTokenDecimals;
    const oneVTokenInUnderlying = exchangeRateCurrent / Math.pow(10, mantissa);
    console.log('1 vBUSD can be redeemed for', oneVTokenInUnderlying, 'BUSD');
    Rate = vToken.supplyRatePerBlock(); // Integer
    Rate = 37893566
    BNB Mantissa = 1 * 10 ^ 18 (BNB has 18 decimal places)
    Blocks Per Day = 80 * 60 * 24 (based on 80 blocks occurring every minute on BNB Chain)
    Days Per Year = 365
    
    APY = (((Rate / BNB Mantissa) * Blocks Per Day) + 1) ^ (Days Per Year - 1) * 100
    const ethMantissa = 1e18;
    const blocksPerDay = 80 * 60 * 24;
    const daysPerYear = 365;
    
    const vToken = new web3.eth.Contract(vBnbAbi, vBnbAddress);
    const supplyRatePerBlock = await vToken.methods.supplyRatePerBlock().call();
    const borrowRatePerBlock = await vToken.methods.borrowRatePerBlock().call();
    const supplyApy = Math.pow(((supplyRatePerBlock / bnbMantissa) * blocksPerDay) + 1, daysPerYear - 1) * 100;
    const borrowApy = Math.pow(((borrowRatePerBlock / bnbMantissa) * blocksPerDay) + 1, daysPerYear - 1) * 100;
    console.log(`Supply APY for BNB ${supplyApy} %`);
    console.log(`Borrow APY for BNB ${borrowApy} %`);
    constructor(uint256 baseRatePerYear, uint256 multiplierPerYear, uint256 jumpMultiplierPerYear, uint256 kink_) public
    function utilizationRate(uint256 cash, uint256 borrows, uint256 reserves) public pure returns (uint256)
    function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) public view returns (uint256)
    function getSupplyRate(uint256 cash, uint256 borrows, uint256 reserves, uint256 reserveFactorMantissa) public view returns (uint256)
    function safeRewardTransfer(address token, address _to, uint256 _amount) external
    function setPendingAdmin(address _admin) external
    function acceptAdmin() external
    function setNewOwner(address _owner) external
    function setRewardToken(address _tokenAddress, bool status) external
    function emergencyRewardWithdraw(address _tokenAddress, uint256 _amount) external
    function pause() external
    function resume() external
    function deposit(uint256 _amount) external
    function withdraw(uint256 _amount) external
    function claim() external
    function claim(address account) external
    function pendingXVS(address _user) public view returns (uint256)
    function updatePendingRewards() public
    function _become(contract VAIVaultProxy vaiVaultProxy) external
    function setAccessControl(address newAccessControlAddress) external
    contract VTokenInterface vBNB
    contract IWBNB WBNB
    function initialize(contract IProtocolShareReserve _protocolShareReserve, address accessControlManager) external
    function setProtocolShareReserve(contract IProtocolShareReserve protocolShareReserve_) external
    function reduceReserves(uint256 reduceAmount) external
    function setInterestRateModel(address newInterestRateModel) public returns (uint256)
    receive() external payable
    fallback(bytes data) external payable returns (bytes)
    struct LiquidationOrder {
      contract VToken vTokenCollateral;
      contract VToken vTokenBorrowed;
      uint256 repayAmount;
    }
    struct AccountLiquiditySnapshot {
      uint256 totalCollateral;
      uint256 weightedCollateral;
      uint256 borrows;
      uint256 effects;
      uint256 liquidity;
      uint256 shortfall;
    }
    struct RewardSpeeds {
      address rewardToken;
      uint256 supplySpeed;
      uint256 borrowSpeed;
    }
    struct Market {
      bool isListed;
      uint256 collateralFactorMantissa;
      uint256 liquidationThresholdMantissa;
      mapping(address => bool) accountMembership;
    }
    enum Action {
      MINT,
      REDEEM,
      BORROW,
      REPAY,
      SEIZE,
      LIQUIDATE,
      TRANSFER,
      ENTER_MARKET,
      EXIT_MARKET
    }
    contract ResilientOracleInterface oracle
    uint256 closeFactorMantissa
    uint256 liquidationIncentiveMantissa
    mapping(address => contract VToken[]) accountAssets
    mapping(address => struct ComptrollerStorage.Market) markets
    contract VToken[] allMarkets
    mapping(address => uint256) borrowCaps
    uint256 minLiquidatableCollateral
    mapping(address => uint256) supplyCaps
    mapping(address => bool) isForcedLiquidationEnabled
    contract IPrime prime
    mapping(address => mapping(address => bool)) approvedDelegates
    Supply Assets to Earn Interest
    1. Connect your Web3 wallet on MetaMask or other supported wallet app to the Venus app (https://app.venus.io).

    2. Navigate to the "Dashboard" menu and choose the asset you want to supply. For example, if you want to supply TRX, click on the TRX market.

    3. Enable the asset. This will prompt a transaction confirmation in your wallet. Remember that a small gas fee applies, so ensure some native tokens (BNB for BNB chain, or ETH for Ethereum, for example) are available in your wallet.

    4. Specify the amount you want to supply. The selected assets are transferred directly from your wallet to Venus Protocol, earning interest immediately. This interest will be automatically added to your Supply Balance.

    Manage your Borrowing Limit

    Your borrowing limit on Venus Protocol is a function of the assets you have supplied. The following steps guide you to manage it:

    1. Navigate to the "Account" section.

    2. Here, you'll find your Borrow Limit on each pool, represented as a percentage of the total value of your supplied assets.

    3. To adjust this limit, you can either supply more assets or repay some of your outstanding loans.

    Borrow Assets on Venus Protocol

    After supplying assets, you can borrow other assets within your borrowing limit:

    1. From the "Dashboard" menu, select the asset you want to borrow.

    2. Input the amount you wish to borrow and confirm the transaction.

    Farm $XVS tokens

    In addition to earning interest on supplied assets, you can also farm $XVS tokens:

    1. In the "Vaults" section, you can stake your XVS or VAI tokens to earn XVS tokens.

    2. Click on 'Stake'. You will be prompted to confirm the transaction in your wallet.

    Lending and Borrowing Example

    Let's assume you supply 1000 TRX to Venus, and the vTRX/TRX rate is 0.0204. You'd receive approximately 49,019 vTRX in return (1000 / 0.0204). If the vTRX/TRX rate increases to 0.0215 after a year, your 49,019 vTRX would be worth 1021.5 TRX (49019 * 0.0215), an increase of 21.5 TRX.

    Remember that these vTokens represent your collateral in Venus Protocol. It's crucial not to trade or transfer them if you have an active loan, as they're required to maintain your borrowing limit.

    WETH

    ETH is the native token for the Ethereum blockchain, used to pay gas fees, for example. WETH is an ERC-20 token representing ETH. Most Web3 apps (including Venus) are compatible with ERC-20 tokens, so it's necessary to convert ETH to WETH.

    The conversion of ETH -> WETH and WETH -> ETH is always available in the WETH token itself, and the exchange rate is always 1:1:

    • If you wrap 1 ETH, you'll receive 1 WETH.

    • If you unwrap 1 WETH, you'll receive 1 ETH.

    Only the gas fee to execute the wrap/unwrap transactions will need to be paid. Each Ethereum network (including L2s) has its own WETH token (see the full list on CoinMarketCap)).

    An easy way to get WETH from ETH is by using Uniswap. For example, on the Ethereum mainnet, the process would be:

    1. Go to the Uniswap page to wrap ETH on Ethereum.

    2. Connect your wallet.

    3. Type the amount of ETH you want to wrap.

    4. Click on Wrap.

    5. Review and accept the transaction in your Web3 wallet.

    6. Remember to add the WETH token to your Web3 wallet to see your WETH balance.

    Wrap ETH at Uniswap

    To unwrap WETH tokens (getting ETH), you can also use Uniswap, switching the input and output currencies.

    Unwrap ETH at Uniswap
    Venus Protocol’s whitepaper
    MetaMask
    https://app.venus.io

    Venus Prime

    Overview

    Venus Protocol is excited to announce Venus Prime, a revolutionary incentive program aimed to bolster user engagement and growth within the protocol. An integral part of Venus Tokenomics v3.1, Venus Prime aims to enhance rewards and promote $XVS staking, focusing on markets including USDT, USDC, BTC and ETH.

    Venus Prime Essentials

    Venus Prime's uniqueness lies in its self-sustaining rewards system, instead of external sources, rewards are derived from the protocol's revenue, fostering a sustainable and ever-growing program.

    Eligible $XVS holders will receive a unique, non-transferable Soulbound Token, which boosts rewards across selected markets.

    Prime Tokens:

    Venus Prime encourages user commitment through two unique Prime Tokens:

    1. Revocable Prime Token:

      • Users need to stake at least 1,000 XVS for 90 days in a row.

      • After these 90 days, users can mint their Prime Token.

    Expected Impact and Launch

    Venus Prime aims to incentivize larger stake sizes and diverse user participation. This is expected to significantly increase the staking of XVS, the Total Value Locked (TVL), and market growth.

    Venus Prime intends to promote user loyalty and the overall growth of the protocol. By endorsing long-term staking, discouraging premature withdrawals, and incentivizing larger stakes, Venus Prime sets a new course in user engagement and liquidity, contributing to Venus Protocol's success.

    Stake your $XVS tokens today to be eligible for Venus Prime, an exciting new venture in the DeFi landscape.

    Technical Reward Details

    Reward Formula: Cobb-Douglas function

    Where:

    • = Rewards for user in market

    • = Protocol Reserve Revenue for market

    • = Proportion to be distributed as rewards

    Qualifiable XVS Staked:

    Qualifiable supply and borrow:

    Note: There will be a limit for the qualifiable supply and borrow amounts, set by the staked XVS limit and the market multiplier.

    User Reward Example:

    Model Parameters

    • = 0.5

    • = 744,164

    • = 8 BTC

    • = 0.2

    User Parameters

    User Parameters
    Token Value
    USD Value

    Qualifiable Staked XVS

    Qualifiable Supply and Borrow

    User Rewards

    Expected Rewards Function

    Rewards in the Venus Prime program will automatically increase as a user increases its XVS Stake, so long as the amount staked and market participation fall within the limits outlined in the "Technical Reward Details" section below.

    The graph above demonstrates the relationship between an increased XVS staked amount and its effect on market rewards, assuming a constant participation of $2.5K USD in the BTC supply market. This helps visualize how an increase in the staked amount influences the APY.

    Diamond Comptroller in the Core pool

    As features continued to be introduced to the Core Pool Comptroller contract, it grew to exceed the maximum allowable size of 24KB. In response to this challenge and to preemptively address similar issues in the future, a multifaceted diamond pattern was implemented.

    The original comptroller was refactored using the EIP-2535 diamond pattern into distinct facets. This restructuring aligns the storage layout with that of the Comptroller proxy, streamlining the contract's organization and enhancing efficiency. As a consequence user interactions now trigger two delegate calls.

    Venus Comptroller - Refactored to EIP 2535

    The previous implementation of Venus used a transparent upgrade proxy delegate pattern. For the diamond proxy we needed a slightly different implementation of fallback function.

    • Comptroller proxy(Unitroller): https://bscscan.com/address/0xfd36e2c2a6789db23113685031d7f16329158384

    • Comptroller implementation before enabling the Diamond Proxy: https://bscscan.com/address/0x909dd16b24cef96c7be13065a9a0eaf8a126ffa5

    The following diagram shows the previous design:

    The Unitroller contract delegated calls to the Comptroller. The Comptroller had the storage layout defined by ComptrollerV12Storage, which extended the UnitrollerAdminStorage.

    EIP - 2535 Overview

    The Diamond Proxy pattern is widely used in Solidity development for its ability to separate concerns and improve code maintainability. It is often used in complex contracts that require multiple facets with shared functionality.

    1. The Diamond Proxy pattern involves creating a "proxy" contract that acts as a single entry point for all functionality shared by multiple contracts. This allows contracts to share functionality without having to duplicate code in each contract.

    2. Each contract that needs to share functionality with the proxy contract is referred to as a "facet." Facets are separate contracts that can be upgraded or modified independently of each other and the proxy contract.

    3. The proxy contract delegates function calls to the correct facet contract based on the function selector. This allows the proxy contract to act as a single entry point for all shared functionality.

    Enabling Venus Integration with the existing Unitroller - Diamond and Transparent proxy combination

    Step 1: The first step was creating the Diamond proxy contract. This contract contains a mapping to hold the addresses of the facet contracts and a fallback function that delegates the function call to the appropriate facet.

    Chained delegate calls are used. This means calldata is delegated from Unitroller to the Diamond contract and then a chained delegate call is made to a specific facet based on the function selector.

    The Diamond contract checks for the facet address in the selectors-to-facet-address mapping (_selectorToFacetAndPosition internal variable) and then makes a delegate call to that facet address. Facets inherit the ComptrollerStorage (ComptrollerV13Storage) to access the state.

    Step 2: Division of the comptroller into multiple facets based on separation of concerns.

    Generally is used with the diamond pattern. Since the Core Pool contracts still use Solidity 0.5.16 this wasn't an option and storage is handled using the same pattern as the original comptroller, by inheriting storage contracts.

    Comptroller storage contains the facet addresses, mapping of the function selectors to the facet address, and mapping of all selectors to the facet address.

    User interaction with new diamond pattern

    Users will continue to interact with the Unitroller proxy contract same as before with one significant difference. Now the Diamond proxy serves as the implementation contract for the Unitroller, and the Comptroller's implementation has been divided into multiple facets. These facets will function as the various components of the Diamond proxy.

    Following a user's interaction with the Unitroller, the delegateCall operation will be directed towards the Diamond proxy. Once the delegateCall reaches the Diamond proxy, it will analyze the function selector and determine the appropriate facet address to which the delegateCall will be forwarded.

    How will new Upgrades work?

    Scenario: A new state variable is to be introduced for an upgrade, which is being used by all or few facets.

    Add a new state variable in the comptrollerStorage by extending the storage to ComptrollerV14Storage just like new state is added to facets by extending the previous storage.

    Scenario: Add a new facet to the Diamond or update the existing facet by add/replace/remove function selectors.

    Deploy the facet with the functions/methods that need to be added to the Comptroller Implementation.

    Execute the diamondCut method(admin access) to add the new facet to the comptrollerStorage.

    To execute the diamondCut through VIP, the cut argument can be generated using the by customizing the generateCutParams to provide the correct actions on the provided function seletors.

    Diamond proxy implementation for Core Pool Comptroller

    The Comptroller of the core pool is divided into 4 facets and 2 parent contracts extended by the facets. Facets will receive the function call through a chained delegateCall from Unitroller, and each facet holds its own responsibility as explained below:

    Facets

    : This facet contains all the external pre-hook functions related to vToken.

    : This facet contains all setter configuration functions.

    : This facet provides market information including account activity in the market. It is also responsible for entering and exiting the market.

    : This facet provides the external functions related to all claims and rewards of the protocol.

    Parent contracts

    : This contract contains functions related to access and checks.

    XVSRewardsHelper: This contract contains the shared functions used by the RewardFacet and PolicyFacet.

    The following diagram shows the inheritance and association relationships among the different contracts:

    Peg Stability Module

    Overview

    The Peg Stability Module (PSM) is a crucial component of the Venus Protocol designed to maintain the value of the VAI stablecoin at $1. It functions similarly to the system provided by MakerDAO for DAI. The PSM contract utilizes two stablecoins: VAI (the target stablecoin) and USDT (used to help maintain the peg).

    Features

    Convert Functionality:

    • Users can exchange VAI and USDT with a "fixed" conversion rate of 1 VAI = $1.

    • Users can send VAI to the PSM and receive USDT if enough USDT is available in the PSM.

    • Users can send USDT to the PSM and receive VAI, provided that the PSM hasn't reached its maximum allowed minted VAI limit.

    No Stability Fee

    The VAI minted through the PSM does not accrue any interest or stability fee.

    Configurable Parameters:

    The PSM contract has three configurable variables set via the Venus Improvement Proposal (VIP):

    • feeIn: Fee charged when users send USDT to the PSM.

    • feeOut: Fee charged when users send VAI to the PSM.

    • maxMintedVAI: The maximum amount of VAI that the PSM can distribute. Conversions that exceed this limit will be reverted.

    Fees Sent to Treasury: The collected fees are sent to the Venus Treasury contract in each operation.

    Integration with Oracle Price: The PSM considers the USD value of the stablecoin to peg VAI to its value accurately.

    Convert Functions

    Function swapStableForVAI

    This function allows users to exchange the paired stablecoin (USDT) for VAI.

    Expected Parameters:

    • receiver: Address of the user who will receive the VAI.

    • amount: The amount of stablecoin (USDT) the sender wants to convert.

    The received stablecoins will be held by the PSM, and the fee specified by feeIn will be sent to the Treasury contract.

    This function returns the amount of VAI transferred to the receiver.

    Function swapVAIForStable

    This function enables users to exchange VAI for the paired stablecoin (USDT).

    Expected Parameters:

    • receiver: Address of the user who will receive the stablecoin.

    • amount: The expected amount of stablecoin (USDT) the user should receive.

    The received VAI will be burnt, and the fee specified by feeOut will be sent to the Treasury contract.

    This function returns the amount of VAI transferred from the sender (burnt + fee).

    Preview Functions

    The PSM also offers preview functions that help users estimate the outcome of convert operations:

    previewSwapVAIForStable(uint256 stableTknAmount)

    Returns the amount of VAI that the sender would transfer (burnt + fee) to receive the specified stablecoin amount.

    previewSwapStableForVAI(uint256 stableTknAmount)

    Returns the amount of VAI that the receiver would receive after executing the swapVAIForStable function with the specified stablecoin amount.

    Integration of the Oracle Price

    To protect the value of VAI and consider the USD value of the paired stablecoin, the PSM integrates with the Resilient Oracle. The following rules are applied:

    swapVAIForStable (the user sends VAI and receives USDT)

    • If the oracle price of the paired stablecoin is below $1, the conversion rate is 1 stablecoin = $1.

    For example if 1 USDT = $0.90

    • Input: The user wishes to receive 1 USDT.

    • Calculation: The conversion rate to consider is max(1, 0.9) => 1 USDT = $1 = 1 VAI.

    • If the oracle price of the paired stablecoin is above $1, the conversion rate is 1 stablecoin = oracle price.

    For example if 1 USDT = $1.1

    • Input: The user desires to receive 10 USDT.

    • Calculation: The conversion rate to consider is max(1, 1.1) => 1 USDT = $1.1 = 1.1 VAI.

    swapStableForVAI (the user sends USDT and receives VAI)

    • If the oracle price of the paired stablecoin is below $1, the conversion rate is 1 stablecoin = oracle price.

    For example if 1 USDT = $0.90

    • Input: The user wishes to send 10 USDT to the PSM.

    • Calculation: The conversion rate to consider is min(1, 0.9) => 10 USDT = $9 = 9 VAI.

    • If the oracle price of the paired stablecoin is above $1, the conversion rate is 1 stablecoin = $1.

    For example if 1 USDT = $1.1

    • 1 USDT = $1.1 (conversion rate according to our oracles)

    • Input: The user wishes to send 10 USDT to the PSM.

    This documentation is designed to be user-friendly and does not cover the technical implementation details of the Peg Stability Module. For technical information, developers and smart contract auditors can refer to the .

    Delegating & Voting

    Overview

    Venus DAO is an autonomous and decentralized organization that functions via smart contracts on a blockchain, meaning it operates without any central authority or control. The purpose of DAOs is to facilitate trustless collaboration and decision-making among members, who can be individuals or entities involved in the organization. Governance within Venus DAO encompasses making decisions, establishing rules, and managing resources.

    It includes the following components:

    1/ Token Holders: DAOs typically have a native token, representing membership and voting rights within the organization. For Venus Protocol, this native token is XVS. Token holders partake in the decision-making process by voting on proposals.

    2/ Proposals: Venus DAO members who stake XVS in the Vault can create proposals, which suggest changes, initiatives, or organizational actions. Proposals can span a variety of topics such as protocol upgrades, funding requests, or changes to the DAO's rules. To propose, one requires "Voting power" of 300,000 XVS. To vote on a proposal, one needs "Voting power" of 600,000 XVS, either individually owned or delegated by other members.

    3/ Voting: Following a proposal's creation, token holders can vote on it. Venus DAO manages the voting process, queuing and voting on protocol updates within 48-hour timelocks. The voting method could entail a simple majority vote, a supermajority, or weighted voting based on each participant's token count, as is the case with Venus Protocol.

    4/ Voting Period: Venus DAO recognizes three Venus Improvement Proposals (VIP) roles: Normal, Fast Track, and Critical. Each VIP role has a unique proposal threshold, timelock, and voting period, which can be configured by Governance. This duration allows token holders ample time to review, discuss, and cast their votes. The votes are tallied once the voting period concludes.

    5/ Execution: After a proposal garners support and votes, all Venus DAO members can execute the VIP directly in the Venus dapp through smart contracts.

    6/ Transparency and Auditability: All Venus DAO transactions and governance activities take place on a public blockchain, enabling transparency and auditability for anyone interested. This level of transparency helps maintain accountability and minimizes potential fraud or manipulation risks.

    It's crucial to understand that DAO governance is an evolving field, with different DAOs adopting unique governance structures and processes. The specific rules and mechanisms are continually refined and adapted to best meet the needs of all Venus DAO members.\

    Delegate Voting Power

    Step 1: Visit the Venus Governance Portal

    Access the Venus governance portal via your browser. The URL is .

    Step 2: Connect Your Wallet

    On the top right corner of the screen, click on the "Connect Wallet" button. Choose your wallet from the dropdown menu and follow the prompts to connect.

    Step 3: Delegate Your Voting Power

    Once your wallet is connected, click on the "Delegate" button in the Governance section. This will open up a new dialogue box.

    Step 4: Enter Your Address

    In the new dialogue box, click on the "Paste your address" field. Your connected wallet address should automatically populate.

    Step 5: Redelegate Your Votes

    Click on the "Redelegate" button. This will submit the address for vote delegation.

    Step 6: Confirm the Transaction

    A confirmation prompt will appear in your connected wallet (for example, MetaMask). Confirm the transaction to complete the voting power delegation process.

    Congratulations, you've now enabled your XVS in the vault to participate in Venus Protocol's governance. Your tokens are now ready to vote on upcoming VIP proposals. Remember, your engagement in the protocol’s decision-making process is vital for its future development and success.

    Vote for a VIP

    Step 7: Select the VIP Proposal

    To vote on a Venus Improvement Proposal (VIP), navigate to the list of active proposals on the Venus Governance Portal. Click on the title of the VIP you wish to vote on. Remember, your voting eligibility requires your address to be delegated.

    Step 8: Cast Your Vote

    After selecting the VIP, you'll see voting options for the proposal. You can choose 'For' to vote in favor of the proposal, 'Against' to vote against it, or 'Abstain' to remain neutral.

    Step 9: Add a Comment

    Before you submit your vote, you have an option to provide a comment explaining the reasoning behind your decision. This step is not mandatory, but it contributes to a more transparent and inclusive voting process.

    Step 10: Submit Your Vote

    Once you've made your decision and optionally left a comment, click the 'Submit Vote' button to cast your vote.

    Congratulations, you've successfully voted on a VIP proposal! Your participation is integral to the development and success of the Venus Protocol. Thank you for your contribution to our community's decision-making process. Remember, every vote counts in shaping the future of Venus Protocol.

    WhitePaperModel

    WhitePaperInterestRateModel

    The parameterized model described in section 2.4 of the original Venus Protocol whitepaper

    Solidity API

    constructor

    Construct an interest rate model

    Parameters

    Name
    Type
    Description

    utilizationRate

    Calculates the utilization rate of the market: borrows / (cash + borrows - reserves)

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getBorrowRate

    Calculates the current borrow rate per block, with the error code expected by the market

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getSupplyRate

    Calculates the current supply rate per block

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    TwoKinksInterestRateModel

    TwoKinksInterestRateModel

    An interest rate model with two different slope increase or decrease each after a certain utilization threshold called kink is reached.

    Solidity API

    Prime storage

    PrimeStorageV1

    Storage for Prime Token

    Solidity API

    Diamond

    Diamond

    This contract contains functions related to facets

    Solidity API

    If a user decides to withdraw XVS and their balance falls below 1000, their Prime Token will be automatically revoked.
  • The limit to the number of revocable Prime tokens is 500 on BNB chain. Source. It can be changed with a VIP.

  • Irrevocable "OG" Prime Token (Phase 2):

    • To be defined

  • ααα = Protocol stake and supply & borrow amplification weight
  • τi​τ_{i}​τi​​ = XVS staked amount for user iii

  • σi\sigma_iσi​ = Sum of qualified supply and borrow balance for user iii

  • ∑j,m​∑_{j,m}​∑j,m​​ = Sum for all users jjj in markets mmm

  • BTC Supply Multiplier = 2

  • XVS Price = $4.0

  • Rewardsi,m=Γm×μ×τiα×σi,m1−α∑j,mτjα×σj,m1−αRewards_{i,m} = \Gamma_m \times \mu \times \frac{\tau_{i}^\alpha \times \sigma_{i,m}^{1-\alpha}}{\sum_{j,m} \tau_{j}^\alpha \times \sigma_{j,m}^{1-\alpha}}Rewardsi,m​=Γm​×μ×∑j,m​τjα​×σj,m1−α​τiα​×σi,m1−α​​
    Rewardsi,mRewards_{i,m}Rewardsi,m​
    iii
    mmm
    Γm\Gamma_mΓm​
    mmm
    μμμ
    τi={min⁡(100000,τi)if τi≥10000otherwise\tau_i = \begin{cases} \min(100000, \tau_i) & \text{if } \tau_i \geq 1000 \\ 0 & \text{otherwise} \end{cases}τi​={min(100000,τi​)0​if τi​≥1000otherwise​
    σi,m=min⁡(τi×borrowMultiplierm,borrowedAmounti,m)+min⁡(τi×supplyMultiplierm,suppliedAmounti,m)\begin{align*} \sigma_{i,m} &= \min(\tau_i \times borrowMultiplier_m, borrowedAmount_{i,m}) \\ &+ \min(\tau_i \times supplyMultiplier_m, suppliedAmount_{i,m}) \end{align*}σi,m​​=min(τi​×borrowMultiplierm​,borrowedAmounti,m​)+min(τi​×supplyMultiplierm​,suppliedAmounti,m​)​
    ααα
    ∑j,BTCτjα×σj,BTC1−α{\sum_{j,BTC} \tau_{j}^\alpha \times \sigma_{j,BTC}^{1-\alpha}}∑j,BTC​τjα​×σj,BTC1−α​
    ΓBTC\Gamma_{BTC}ΓBTC​
    μ\muμ

    Staked XVS

    1,200

    $4,800

    BTC Supply

    0.097

    $2,500

    τi=min(100000, 1200)\tau_i=min(100000,\text{ } 1200)τi​=min(100000, 1200)
    σi,BTC=min($9600,$2500)\sigma_{i,\text{BTC}} = \textit{min}(\text{\$9600}, \text{\$2500})σi,BTC​=min($9600,$2500)
    Rewardsi,BTC=8×0.2×1,2000.5×2,5000.5744,164Rewards_{i, BTC} = 8\times 0.2\times \dfrac{1,200^{0.5}\times 2,500^{0.5}}{744,164}Rewardsi,BTC​=8×0.2×744,1641,2000.5×2,5000.5​
    Rewardsi,BTC= 0.00372Rewards_{i, BTC} = \ 0.00372Rewardsi,BTC​= 0.00372
    User APY Increase=0.003720.097=3.88%\text{User APY Increase} = \dfrac{0.00372}{0.097} = 3.88\%User APY Increase=0.0970.00372​=3.88%
    Please note that the rewards can vary based on the total market participation and the amount of XVS staked, as illustrated by the formula and example above.

    The Diamond Proxy pattern also supports multiple inheritances. This means that each facet can inherit from other contracts, including other facets. This allows for a high degree of code reuse and modular design.

    AppStorage
    facet-cut-params-generator script
    PolicyFacet
    SetterFacet
    MarketFacet
    RewardFacet
    FacetBase
    Diamond - Previous hierarchy of contracts
    Diamond facets
    Diamond - New hierarchy of contracts

    The user needs to send 1 VAI (1 USDT * 1 $/USDT) + fees.

  • Assuming feeOut = 10%, 0.10 VAI will be sent to the treasury, and 1 VAI will be burnt, resulting in a total of 1.1 VAI provided by the user.

  • The fee is calculated considering the "principal" VAI amount that we are to burn (1 VAI = $1).

  • The user needs to send 11 VAI (10 USDT * 1.1 $/USDT) + fees.

  • Assuming feeOut = 10%, 1.1 VAI will be sent to the treasury, and 10 VAI will be burnt, resulting in a total of 12.1 VAI provided by the user.

  • The fee is calculated considering the "principal" VAI amount that we are to burn (11 VAI = $11).

  • The user will receive 9 VAI (10 USDT * 0.9) - fees.

  • Assuming feeIn = 10%, 0.9 VAI will be sent to the treasury, and 8.1 VAI will be sent to the user.

  • The fee is calculated considering the "principal" VAI amount (9 VAI = $9).

  • Calculation: The conversion rate to consider is min(1, 1.1) => 10 USDT = $10 = 10 VAI.

  • The user will receive 10 VAI (10 USDT * 1.0) - fees.

  • Assuming feeIn = 10%, 1 VAI will be sent to the treasury, and 9 VAI will be sent to the user.

  • The fee is calculated considering the "principal" VAI amount (10 VAI = $10).

  • smart contract code
    USD price considered by the Peg Stability Module at Venus
    https://app.venus.io/governance
    Wrap ETH at Uniswap
    Unwrap ETH at Uniswap

    baseRatePerYear

    uint256

    The approximate target base APR, as a mantissa (scaled by 1e18)

    multiplierPerYear

    uint256

    The rate of increase in interest rate wrt utilization (scaled by 1e18)

    cash

    uint256

    The amount of cash in the market

    borrows

    uint256

    The amount of borrows in the market

    reserves

    uint256

    The amount of reserves in the market (currently unused)

    [0]

    uint256

    The utilization rate as a mantissa between [0, 1e18]

    cash

    uint256

    The amount of cash in the market

    borrows

    uint256

    The amount of borrows in the market

    reserves

    uint256

    The amount of reserves in the market

    [0]

    uint256

    The borrow rate percentage per block as a mantissa (scaled by 1e18)

    cash

    uint256

    The amount of cash in the market

    borrows

    uint256

    The amount of borrows in the market

    reserves

    uint256

    The amount of reserves in the market

    reserveFactorMantissa

    uint256

    The current reserve factor for the market

    [0]

    uint256

    The supply rate percentage per block as a mantissa (scaled by 1e18)

    tokens

    Mapping to get prime token's metadata


    totalIrrevocable

    Tracks total irrevocable tokens minted


    totalRevocable

    Tracks total revocable tokens minted


    revocableLimit

    Indicates maximum revocable tokens that can be minted


    irrevocableLimit

    Indicates maximum irrevocable tokens that can be minted


    stakedAt

    Tracks when prime token eligible users started staking for claiming prime token


    markets

    vToken to market configuration


    interests

    vToken to user to user index


    alphaNumerator

    numerator of alpha. Ex: if alpha is 0.5 then this will be 1


    alphaDenominator

    denominator of alpha. Ex: if alpha is 0.5 then this will be 2


    xvsVault

    address of XVS vault


    xvsVaultRewardToken

    address of XVS vault reward token


    xvsVaultPoolId

    address of XVS vault pool id


    isScoreUpdated

    mapping to check if a account's score was updated in the round


    nextScoreUpdateRoundId

    unique id for next round


    totalScoreUpdatesRequired

    total number of accounts whose score needs to be updated


    pendingScoreUpdates

    total number of accounts whose score is yet to be updated


    vTokenForAsset

    mapping used to find if an asset is part of prime markets


    comptroller

    address of core pool comptroller contract


    unreleasedPLPIncome

    unreleased income from PLP that's already distributed to prime holders


    primeLiquidityProvider

    The address of PLP contract


    oracle

    The address of ResilientOracle contract


    _become

    Call _acceptImplementation to accept the diamond proxy as new implementaion

    Parameters

    Name
    Type
    Description

    unitroller

    contract Unitroller

    Address of the unitroller


    diamondCut

    To add function selectors to the facet's mapping

    Parameters

    Name
    Type
    Description

    diamondCut_

    struct IDiamondCut.FacetCut[]

    IDiamondCut contains facets address, action and function selectors


    facetFunctionSelectors

    Get all function selectors mapped to the facet address

    Parameters

    Name
    Type
    Description

    facet

    address

    Address of the facet

    Return Values

    Name
    Type
    Description

    [0]

    bytes4[]

    selectors Array of function selectors


    facetPosition

    Get facet position in the _facetFunctionSelectors through facet address

    Parameters

    Name
    Type
    Description

    facet

    address

    Address of the facet

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    Position of the facet


    facetAddresses

    Get all facet addresses

    Return Values

    Name
    Type
    Description

    [0]

    address[]

    facetAddresses Array of facet addresses


    facetAddress

    Get facet address and position through function selector

    Parameters

    Name
    Type
    Description

    functionSelector

    bytes4

    function selector

    Return Values

    Name
    Type
    Description

    [0]

    struct ComptrollerV13Storage.FacetAddressAndPosition

    FacetAddressAndPosition facet address and position


    facets

    Get all facets address and their function selector

    Return Values

    Name
    Type
    Description

    [0]

    struct Diamond.Facet[]

    facets_ Array of Facet


    constructor(uint256 baseRatePerYear, uint256 multiplierPerYear) public
    function utilizationRate(uint256 cash, uint256 borrows, uint256 reserves) public pure returns (uint256)
    function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) public view returns (uint256)
    function getSupplyRate(uint256 cash, uint256 borrows, uint256 reserves, uint256 reserveFactorMantissa) public view returns (uint256)
    struct Token {
      bool exists;
      bool isIrrevocable;
    }
    struct Market {
      uint256 supplyMultiplier;
      uint256 borrowMultiplier;
      uint256 rewardIndex;
      uint256 sumOfMembersScore;
      bool exists;
    }
    struct Interest {
      uint256 accrued;
      uint256 score;
      uint256 rewardIndex;
    }
    struct PendingReward {
      address vToken;
      address rewardToken;
      uint256 amount;
    }
    mapping(address => struct PrimeStorageV1.Token) tokens
    uint256 totalIrrevocable
    uint256 totalRevocable
    uint256 revocableLimit
    uint256 irrevocableLimit
    mapping(address => uint256) stakedAt
    mapping(address => struct PrimeStorageV1.Market) markets
    mapping(address => mapping(address => struct PrimeStorageV1.Interest)) interests
    uint128 alphaNumerator
    uint128 alphaDenominator
    address xvsVault
    address xvsVaultRewardToken
    uint256 xvsVaultPoolId
    mapping(uint256 => mapping(address => bool)) isScoreUpdated
    uint256 nextScoreUpdateRoundId
    uint256 totalScoreUpdatesRequired
    uint256 pendingScoreUpdates
    mapping(address => address) vTokenForAsset
    address comptroller
    mapping(address => uint256) unreleasedPLPIncome
    address primeLiquidityProvider
    contract ResilientOracleInterface oracle
    struct Facet {
      address facetAddress;
      bytes4[] functionSelectors;
    }
    function _become(contract Unitroller unitroller) public
    function diamondCut(struct IDiamondCut.FacetCut[] diamondCut_) public
    function facetFunctionSelectors(address facet) external view returns (bytes4[])
    function facetPosition(address facet) external view returns (uint256)
    function facetAddresses() external view returns (address[])
    function facetAddress(bytes4 functionSelector) external view returns (struct ComptrollerV13Storage.FacetAddressAndPosition)
    function facets() external view returns (struct Diamond.Facet[])
    MULTIPLIER_PER_BLOCK

    The multiplier of utilization rate per block that gives the slope 1 of the interest rate scaled by EXP_SCALE


    BASE_RATE_PER_BLOCK

    The base interest rate per block which is the y-intercept when utilization rate is 0 scaled by EXP_SCALE


    KINK_1

    The utilization point at which the multiplier2 is applied


    MULTIPLIER_2_PER_BLOCK

    The multiplier of utilization rate per block that gives the slope 2 of the interest rate scaled by EXP_SCALE


    BASE_RATE_2_PER_BLOCK

    The base interest rate per block which is the y-intercept when utilization rate hits KINK_1 scaled by EXP_SCALE


    RATE_1

    The maximum kink interest rate scaled by EXP_SCALE


    KINK_2

    The utilization point at which the jump multiplier is applied


    JUMP_MULTIPLIER_PER_BLOCK

    The multiplier of utilization rate per block that gives the slope 3 of interest rate scaled by EXP_SCALE


    RATE_2

    The maximum kink interest rate scaled by EXP_SCALE


    constructor

    Construct an interest rate model

    Parameters

    Name
    Type
    Description

    baseRatePerYear_

    int256

    The approximate target base APR, as a mantissa (scaled by EXP_SCALE)

    multiplierPerYear_

    int256

    The rate of increase or decrease in interest rate wrt utilization (scaled by EXP_SCALE)

    kink1_

    int256

    The utilization point at which the multiplier2 is applied

    multiplier2PerYear_

    int256

    The rate of increase or decrease in interest rate wrt utilization after hitting KINK_1 (scaled by EXP_SCALE)


    getBorrowRate

    Calculates the current borrow rate per slot (block)

    Parameters

    Name
    Type
    Description

    cash

    uint256

    The amount of cash in the market

    borrows

    uint256

    The amount of borrows in the market

    reserves

    uint256

    The amount of reserves in the market

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    The borrow rate percentage per slot (block) as a mantissa (scaled by EXP_SCALE)


    getSupplyRate

    Calculates the current supply rate per slot (block)

    Parameters

    Name
    Type
    Description

    cash

    uint256

    The amount of cash in the market

    borrows

    uint256

    The amount of borrows in the market

    reserves

    uint256

    The amount of reserves in the market

    reserveFactorMantissa

    uint256

    The current reserve factor for the market

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    The supply rate percentage per slot (block) as a mantissa (scaled by EXP_SCALE)


    utilizationRate

    Calculates the utilization rate of the market: borrows / (cash + borrows - reserves)

    Parameters

    Name
    Type
    Description

    cash

    uint256

    The amount of cash in the market

    borrows

    uint256

    The amount of borrows in the market

    reserves

    uint256

    The amount of reserves in the market

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    The utilization rate as a mantissa between [0, EXP_SCALE]


    Shortfall and auctions

    A set of processes are executed in a market when a shortfall (total borrowed amount converted to USD is greater than the total supplied amount converted to USD) is detected for a borrower to pause the interest accrual on the borrow, write off the borrower's borrow balance and track the market bad debt.

    V represents the total bad debt including the accrued interest on the bad debt. To calculate the accrued interest the borrow index when the bad debt is detected is divided by the initial borrow index and then multiplied by the borrowed amount. For example, if the initial borrow index is 1.2 and when bad debt of 100 USDC is detected the borrow index is 1.5 then the V (total bad debt) becomes 100 * (1.5/1.2) = 125 USDC.

    The calculated total bad debt of the account is written off for the borrower and interest accrual is stopped on the bad debt.

    When the pool's bad debt reaches a minimum amount the risk fund reserve is auctioned off to cover the bad debt (see Shortfall.minimumPoolBadDebt()). Anyone will be allowed to start or restart an auction if the constraints are satisfied:

    • no other auction is in progress for the same pool (Shortfall.auctions(comptrollerAddress).status in (AuctionStatus.NOT_STARTED, AuctionStatus.ENDED))

    • the bad debt accumulated in the pool, in USD, is greater than Shortfall.minimumPoolBadDebt()

    Auction participants receive a maximum 10% incentive (configurable by the community via VIP, see RiskFund.incentiveBps()) for covering the bad debt. Depending on the size of the reserve in the risk fund, either 100% of bad debt or a portion of it is raised.

    N represents the total pool’s bad debt denoted in USD and M represents total risk fund balance in USD. When an auction begins, a starting bid is set to prevent bidders from taking advantage of the auction by opening with an undervalued bid. The highest bidder’s funds are locked, and when the auction closes the market(s) total cash reserve is increased, the bad debt of the market(s) is decreased and the risk fund partially/completely transferred to the winning bidder.

    Auction scenarios

    In scenario 1, X% indicates the percentage of bad debt the bidder is willing to pay and in scenario 2, the Y% indicates the percentage of the risk fund the bidder is willing to seize. During the auction, bidders are only allowed to specify X% or Y% depending on the type of auction.

    A bid will be successful only if the bidder has sufficient funds to cover the bad debt they are bidding for and they make the best offer. When a bid is placed it is transferred to the Shortfall contract, and released if they are out bid. Subsequent bids should be placed within 100 blocks (adjustable via VIP, see Shortfall.nextBidderBlockLimit()) of the previous bid, otherwise anyone (including the winning bidder) can close the auction. If there is no bid for 100 blocks (adjustable via VIP, see Shortfall.waitForFirstBidder()) the auction can be restarted accounting for any changes in the risk fund and bad debt balance.

    The auction process attempts to cover as much market bad debt as possible. In scenario 1, all of the bad debt may not be covered by the auction. In this case, the bad debt not covered will be maintained in the system until a new auction is started.

    Examples

    Let’s take a scenario when bad debt is greater than the total risk fund balance.

    • Bad Debt: Assuming that pool bad debt is 10 BTC and the price of BTC is $20,000. Then, the total bad debt is $200,000. If the incentive is 10% then the final bad debt is $220,000.

    • Risk Fund: Given the risk fund is stored in USDT token, the token risk fund balance is 100,000 USDT and 1 USDT is equal to $1, then the total risk fund balance is $100,000

    • Minimum Bid: In order for a user to bid they have to supply a minimum percentage of bad debt calculated as (100000/220000) * 0.9 = 40.90%


    Scenario when bad debt is less than total risk fund balance

    • Bad Debt: Assuming pool bad debt is 10 BTC and the price of BTC is $20,000. Then, the total bad debt is $200,000. Suppose the incentive is 10% then the final bad debt is $220,000.

    • Risk Fund: Given the risk fund is stored in USDT token, the token risk fund balance is 500,000 USDT and 1 USDT is equal to $1, then the total risk fund balance is $500,000

    • Maximum Bid: Now for a user to bid they have to supply 100% of the bad debt and can claim a maximum of (220000 * 1.1) * 500000 = 48.40% of the risk fund balance.


    Scenario when the auction was started and nobody participated so instead of starting a new auction we need to restart the auction

    • Auction Started: Suppose an auction was started and there was no bidder till 100 blocks. Then in this case the auction is stale and bids cannot be placed.

    • Restart Auction: Now suppose a user wants to restart the auction and/or place a bid then they can restart using:

      • Restart Auction Signature: restartAuction(comtrollerAddress)

    Contributing

    We have a strict policy on how we should commit our work. Following these guidelines will help us to:

    1. Avoid hard to solve merge conflicts. Our workflow favors rebase over merge in feature branches, so there are no complex dependencies between branches. We sacrifice the “full history” in favor of just “meaningful history”, thus avoiding unnecessary diffs.

    2. Make our contracts more secure. It's easy to make a small mistake that would cost millions of dollars to the contract users. We need to peer review our contracts as thoroughly as possible, thus our workflow ensures the process is easy and rewarding for the reviewers.

    ComptrollerLens

    ComptrollerLens Contract

    The ComptrollerLens contract has functions to get the number of tokens that can be seized through liquidation, hypothetical account liquidity and shortfall of an account.

    Solidity API

    RewardFacet

    RewardFacet

    This facet contract provides the external functions related to all claims and rewards of the protocol

    Solidity API

    int256 MULTIPLIER_PER_BLOCK
    int256 BASE_RATE_PER_BLOCK
    int256 KINK_1
    int256 MULTIPLIER_2_PER_BLOCK
    int256 BASE_RATE_2_PER_BLOCK
    int256 RATE_1
    int256 KINK_2
    int256 JUMP_MULTIPLIER_PER_BLOCK
    int256 RATE_2
    constructor(int256 baseRatePerYear_, int256 multiplierPerYear_, int256 kink1_, int256 multiplier2PerYear_, int256 baseRate2PerYear_, int256 kink2_, int256 jumpMultiplierPerYear_) public
    function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view returns (uint256)
    function getSupplyRate(uint256 cash, uint256 borrows, uint256 reserves, uint256 reserveFactorMantissa) public view virtual returns (uint256)
    function utilizationRate(uint256 cash, uint256 borrows, uint256 reserves) public pure returns (uint256)

    baseRate2PerYear_

    int256

    The additional base APR after hitting KINK_1, as a mantissa (scaled by EXP_SCALE)

    kink2_

    int256

    The utilization point at which the jump multiplier is applied

    jumpMultiplierPerYear_

    int256

    The multiplier after hitting KINK_2

    User A Starts Auction: User A notices that the pool’s bad debt is greater than the minimum bad debt required to start an auction, then they can start an auction using this function call:

    • Minimum Pool Bad Debt: You can find the minimum required bad debt for a pool to start an auction using minimumPoolBadDebt state variable and the bad debt of individual markets using the badDebt state variable of the vToken contract.

    • Start Auction Signature: startAuction(comptrollerAddress)

      • Address of the pool’s comptroller.

      • Starting an auction triggers AuctionStarted event which can be monitored to get notifications.

  • User A Places Bid: Now user A sees that the auction has started and wishes to place a bid. In this case, the user will place the minimum bid and try to seize the risk fund balance at the lowest value possible:

    • Block Limit: Note that the first bid has to be placed within 100 blocks from starting the auction, otherwise the auction needs to be restarted.

    • Approval: You need to give approval to the Shortfall contract to transfer the bid amount of funds to itself.

      • To calculate the amount for approval you need to first decide the bid bps. In this case, the minimum bid bps can be read using auctions[comptrollerAddress].startBidBps state variable.

      • In this example, it’s 4090 i.e., 40.90%. So you need to transfer 40.90% of 10 BTC which is 4.9 BTC. This is the approval amount. If there are multiple tokens as part of the bad debt then you have to provide 40.90% of each of the tokens bad debt.

      • You can find the list of markets involved in the bad debt by using auctions[comptrollerAddress].markets variable and then retrieving the underlying token of each of the markets using underlying()

    • Place Bid Signature: placeBid(comptrollerAddress, bidBps, auctionStartBlock)

      • Auction Start Block: This is the block number when the auction was started. You can find this using: auctions[comptrollerAddress].startBlock state variable.

      • Placing a bid triggers BidPlaced

  • User B Places Bid: Now user B sees an opportunity and decides to place a bid. They have to place a bid bigger than 40.90% bid bps to succeed in placing the bid. For example, user B places a bid for 41% to outperform User A’s bid.

    • Refund: User A will immediately receive back the BTC they sent to the Shortfall contract as part of the first bid.

  • User A Places Improved Bid: Now user A sees that User B places a better bid. Then User A can wish to complete with a better bid again. Suppose user A places a new bid for 43%.

  • User A Closed Auction: After placing a bid, User A waits for 100 blocks and sees there are no new bids that outperform their bid then they can close the auction and win it.

    • Close Auction Signature: closeAuction(comptrollerAddress)

    • Risk Fund Transfer: At this point in time all the 100,000 USDT is transferred from the risk fund to user A’s address.

  • User A Starts Auction: Now suppose user A notices that the pool’s bad debt is greater than the minimum bad debt required to start an auction, then they can start an auction.

    • Minimum Pool Bad Debt: You can find the minimum required bad debt for a pool to start an auction using minimumPoolBadDebt state variable and the bad debt of individual markets using badDebt state variable of the vToken contract.

    • Start Auction Signature: startAuction(comptrollerAddress)

      • Address of the pool’s comptroller.

      • Starting an auction triggers AuctionStarted event which can be monitored to get notifications.

  • User A Places Bid: Now user A sees that the auction has started and wishes to place a bid. In this case, the user will place the maximum bid and try to seize the maximum possible risk fund balance by covering 100% of bad debt:

    • Block Limit: Note that the first bid has to be placed within 100 blocks from starting the auction, otherwise it needs to be restarted.

    • Approval: You need to give approval to the Shortfall contract to transfer the bid amount of funds to itself.

      • Amount: You need to transfer 10 BTC i.e., the complete bad debt. This is the approval amount. If there are multiple tokens as part of the bad debt then you have to provide complete bad debt for each token.

      • You can find the list of markets involved in the bad debt using auctions[comptrollerAddress].markets variable and then read the underlying token of each of the markets using underlying() function.

    • Place Bid Signature: placeBid(comptrollerAddress, bidBps, auctionStartBlock)

      • Auction Start Block: This is the block number when the auction was started. You can find this using: auctions[comptrollerAddress].startBidBps state variable.

      • Bid BPS: In this example, the bid bps is 100% which indicates 100% of 48.40% (i.e., 242,000 USDT).

  • User B Places Bid: Now user B sees an opportunity and decides to place a bid. They have to place a bid lower than 100% bid bps to succeed in placing a bid. Image user B places a bid for 95% (i.e., risk fund seize amount is 242000 - (100-95)% = 229900 ) to outperform User A’s bid.

    • Refund: User A will immediately receive back the BTC they sent to the Shortfall contract as part of the first bid.

  • User A Places Improved Bid: Now user A sees that User B places a better bid. Then User A can wish to complete with a better bid again. Suppose user A places a new bid for 94%.

  • User A Closed Auction: After placing a bid, User A waits for 100 blocks and sees there are no new bids that outperform their bid then they can close the auction and win it.

    • Close Auction Signature: closeAuction(comptrollerAddress)

    • Risk Fund Transfer: At this point in time 94% of 242,000 USDT i.e., 227,480 USDT is transferred from the risk fund to user A’s address.

  • Place Bids and Close Auction: Now just like previous steps a user can place bids and close the auction.

    Auction scenarios
    Save newcomers' time. When new developers join the team, they want to know how the code evolved and why certain design decisions were made. Our workflow encourages exhaustive commit messages that describe the reason behind each change.

    Although the policy may seem too restrictive, it is usually quite easy to follow. It may require you to learn git a bit deeper than you're used to — please follow along, we'll show the necessary commands :)

    Configure your git

    By default, git merges the upstream changes into your local branch on pull. This silently spoils your history and may introduce unnecessary merge conflicts that are hard to solve and reason about. We encourage you to turn off this feature by running git config --global pull.ff only.

    Create a feature branch

    1. Prefer to base your feature branches on master. If it is not possible, make sure to not include someone else's commits in your PR later.

    2. Prefer short and descriptive names for branches (good: polynomial-interest-curve, bad: fix-rate).

    3. Use lowercase words separated by dashes (good: xvs-vault, bad: XVSVault).

    4. You may include work type into the branch name (ok: feature/polynomial-interest-curve).

    5. Make sure no-one else works in your feature branch.

    Make commmits

    Commit messages will need to follow a standard format in order to be able to correctly bumpt the next version and format the release. Conventional commits is a nice standard to use for formatting the commit messages. There are different tools available to enforce these messages

    Structure

    Breaking changes

    Breaking changes will result in a major version bump. These can be triggered by placing BREAKING CHANGE or BREAKING CHANGES in the footer of the commit message or by placing an exclamation point after the type. See next section on commit format

    Enforcing commits

    commitlint - Precommit hook with husky ( currently implement in the api repo)

    Type
    Release
    Included in Changelog

    breaking change

    major

    true

    feat

    minor

    true

    build

    false

    false

    ci

    false

    Prettify your history

    Once you have made your changes, it's time to present them to the reviewers. It is quite important that the reviewers only see the relevant up-to-date changes structured by commits.

    1. While you've been working on your feature branch, the master branch has most likely evolved. Rebase your changes on top of master by running git rebase --onto master <parent>, where <parent> is the hash of the commit immediately preceding your first commit. You can find <parent> by looking at the history: git log --oneline.

    2. Your feature branch should have linear history. No merge commits are allowed.

    3. The commits in your PR should not solve the problems introduced in your previous commits. The reviewers often look at the code commit by commit, and they may comment on the problems you later solve. By making sure your commits are self-contained, you free the reviewers of unnecessary work. Use the interactive rebase feature (git rebase -i <parent>) to squash, reorder or drop your commits.

    Notes on force pushing

    When you rewrite your history, GitHub will refuse to accept your changes. This is to protect you from wiping out someone else's contributions. We need to follow certain rules to make sure our history is clean and the others' contributions are intact.

    1. Every feature branch should have one active maintainer. No-one else is allowed to directly commit to your feature branch.

    2. You can safely force-push to your feature branch. If your colleague wants to contribute, ask them to push their changes into a separate branch, and then cherry-pick. If you want to help your colleague, push your changes to a separate branch and let your colleague cherry-pick. This would help you to avoid any potential conflicts stemming from force-pushing.

    3. Always use --force-with-lease and not --force/-f to force-push. Things happen, and someone may violate the “one active maintainer” rule. Force with lease would save you the trouble of recovering someone's work :)

    4. Never force-push to master or any branch that has several maintainers. The only exception to this rule is when a secret (API key, private key, etc.) is accidentially committed, in which case you should immediately wipe it out and notify the security team as soon as possible.

    Make a pull request

    1. Make sure your commit history follows the guidelines written above. Rebase once again if necessary.

    2. If your PR is work in progress, explicitly mark it as WIP.

    Pass the review

    1. During the review, your history does not need to satisfy the criteria above. The reviewers are interested in how you have addressed their comments, so do not squash your fixes with your previous commits during the review. You can use git commit --fixup <target_commit> to make a fix to a specific commit.

    2. Avoid fixing up a fixup :)

    3. After addressing all of the review comments, rebase your work so that the commits are self-contained again. You can use git rebase -i --autosquash to squash the fixup commits into the target commits automatically.

    4. Do not add any new changes to the code after the review (except for squashing and reordering the commits).

    Closing thoughts

    This policy may require some time and effort: writing lenghty commit messages and doing an interactive rebase isn't as straightforward as git commit -am. This pays out quickly, however. When you do git bisect to find a bug, you'd really appreciate descriptive commits instead of just "Update file" or "Some fixes". When you're reviewing a PR, you can limit the mental burden by looking at individual commits instead of diving straight into 40 files changed. When you're a newcomer and wonder why a function you wanted to use suddenly disappeared before you fully understood the code, you'll be happy to see the reason straight in git log. The same goes for when you git blame to understand why a certain line of code is written the way it is.

    If we were to summarize everything written above into just three bullet points, we'd go with:

    • Always describe the reason for your changes in commit messages like you're talking with the 5-year-old.

    • Leave only meaningful changes in your PR history. Git history can't and shouldn't encompass everything, just like your school history textbook.

    • Choose only one person responsible for a feature. Avoid unnecessary interference.

    liquidateCalculateSeizeTokens

    Computes the number of collateral tokens to be seized in a liquidation event

    Parameters

    Name
    Type
    Description

    comptroller

    address

    Address of comptroller

    vTokenBorrowed

    address

    Address of the borrowed vToken

    vTokenCollateral

    address

    Address of collateral for the borrow

    actualRepayAmount

    uint256

    Repayment amount i.e amount to be repaid of total borrowed amount

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    A tuple of error code, and tokens to seize

    [1]

    uint256


    liquidateCalculateSeizeTokens

    Computes the number of collateral tokens to be seized in a liquidation event

    Parameters

    Name
    Type
    Description

    borrower

    address

    Address of borrower whose collateral is being seized

    comptroller

    address

    Address of comptroller

    vTokenBorrowed

    address

    Address of the borrowed vToken

    vTokenCollateral

    address

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    A tuple of error code, and tokens to seize

    [1]

    uint256


    liquidateVAICalculateSeizeTokens

    Computes the number of VAI tokens to be seized in a liquidation event

    Parameters

    Name
    Type
    Description

    comptroller

    address

    Address of comptroller

    vTokenCollateral

    address

    Address of collateral for vToken

    actualRepayAmount

    uint256

    Repayment amount i.e amount to be repaid of the total borrowed amount

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    A tuple of error code, and tokens to seize

    [1]

    uint256


    getHypotheticalAccountLiquidity

    Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow A snapshot of the account is taken and the total borrow amount of the account is calculated

    Parameters

    Name
    Type
    Description

    comptroller

    address

    Address of comptroller

    account

    address

    Address of the borrowed vToken

    vTokenModify

    contract VToken

    Address of collateral for vToken

    redeemTokens

    uint256

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    Returns a tuple of error code, liquidity, and shortfall

    [1]

    uint256

    [2]

    uint256


    claimVenus

    Claim all the xvs accrued by holder in all markets and VAI

    Parameters

    Name
    Type
    Description

    holder

    address

    The address to claim XVS for


    claimVenus

    Claim all the xvs accrued by holder in the specified markets

    Parameters

    Name
    Type
    Description

    holder

    address

    The address to claim XVS for

    vTokens

    contract VToken[]

    The list of markets to claim XVS in


    claimVenus

    Claim all xvs accrued by the holders

    Parameters

    Name
    Type
    Description

    holders

    address[]

    The addresses to claim XVS for

    vTokens

    contract VToken[]

    The list of markets to claim XVS in

    borrowers

    bool

    Whether or not to claim XVS earned by borrowing

    suppliers

    bool


    claimVenusAsCollateral

    Claim all the xvs accrued by holder in all markets, a shorthand for claimVenus with collateral set to true

    Parameters

    Name
    Type
    Description

    holder

    address

    The address to claim XVS for


    _grantXVS

    Transfer XVS to the recipient

    Parameters

    Name
    Type
    Description

    recipient

    address

    The address of the recipient to transfer XVS to

    amount

    uint256

    The amount of XVS to (possibly) transfer


    seizeVenus

    Seize XVS rewards allocated to holders

    Parameters

    Name
    Type
    Description

    holders

    address[]

    Addresses of the XVS holders

    recipient

    address

    Address of the XVS token recipient

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    The total amount of XVS tokens seized and transferred to recipient


    claimVenus

    Claim all xvs accrued by the holders

    Parameters

    Name
    Type
    Description

    holders

    address[]

    The addresses to claim XVS for

    vTokens

    contract VToken[]

    The list of markets to claim XVS in

    borrowers

    bool

    Whether or not to claim XVS earned by borrowing

    suppliers

    bool


    getXVSVTokenAddress

    Returns the XVS vToken address

    Return Values

    Name
    Type
    Description

    [0]

    address

    The address of XVS vToken


    Risk Stewards

    Overview

    The Risk Stewards system introduces a secure and modular mechanism for automatically updating borrow and supply caps in the Venus Protocol. In the earlier model, these risk parameters were modified manually via governance proposals (VIPs). This new architecture eliminates manual intervention by enabling fully on-chain, automated updates.

    In this updated model, Chaos Labs provides risk parameter updates through their on-chain Risk Oracle. These updates are delivered directly to dedicated steward contracts, such as MarketCapsRiskSteward, which are responsible for applying the changes to the protocol.

    All updates are executed through a central router contract, RiskStewardReceiver

    Liquidator

    Solidity API

    <type>[optional scope]: <description>
    
    [optional body]
    
    [optional footer(s)]
    struct AccountLiquidityLocalVars {
      uint256 sumCollateral;
      uint256 sumBorrowPlusEffects;
      uint256 vTokenBalance;
      uint256 borrowBalance;
      uint256 exchangeRateMantissa;
      uint256 oraclePriceMantissa;
      struct ExponentialNoError.Exp weightedFactor;
      struct ExponentialNoError.Exp exchangeRate;
      struct ExponentialNoError.Exp oraclePrice;
      struct ExponentialNoError.Exp tokensToDenom;
    }
    function liquidateCalculateSeizeTokens(address comptroller, address vTokenBorrowed, address vTokenCollateral, uint256 actualRepayAmount) external view returns (uint256, uint256)
    function liquidateCalculateSeizeTokens(address borrower, address comptroller, address vTokenBorrowed, address vTokenCollateral, uint256 actualRepayAmount) external view returns (uint256, uint256)
    function liquidateVAICalculateSeizeTokens(address comptroller, address vTokenCollateral, uint256 actualRepayAmount) external view returns (uint256, uint256)
    function getHypotheticalAccountLiquidity(address comptroller, address account, contract VToken vTokenModify, uint256 redeemTokens, uint256 borrowAmount, enum WeightFunction weightingStrategy) external view returns (uint256, uint256, uint256)
    function claimVenus(address holder) public
    function claimVenus(address holder, contract VToken[] vTokens) public
    function claimVenus(address[] holders, contract VToken[] vTokens, bool borrowers, bool suppliers) public
    function claimVenusAsCollateral(address holder) external
    function _grantXVS(address recipient, uint256 amount) external
    function seizeVenus(address[] holders, address recipient) external returns (uint256)
    function claimVenus(address[] holders, contract VToken[] vTokens, bool borrowers, bool suppliers, bool collateral) public
    function getXVSVTokenAddress() external view returns (address)
    function.
    event which can be monitored.

    Placing a bid triggers BidPlaced event which can be monitored.

    false

    fix

    patch

    true

    refactor

    patch

    false

    test

    false

    false

    Address of collateral for the borrow

    actualRepayAmount

    uint256

    Repayment amount i.e amount to be repaid of total borrowed amount

    Number of vTokens being redeemed

    borrowAmount

    uint256

    Amount borrowed

    weightingStrategy

    enum WeightFunction

    The weighting strategy to use: - WeightFunction.USE_COLLATERAL_FACTOR to use collateral factor - WeightFunction.USE_LIQUIDATION_THRESHOLD to use liquidation threshold

    Whether or not to claim XVS earned by supplying

    Whether or not to claim XVS earned by supplying

    collateral

    bool

    Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall

    vBnb

    Address of vBNB contract.


    comptroller

    Address of Venus Unitroller contract.


    vaiController

    Address of VAIUnitroller contract.


    wBNB

    Address of wBNB contract


    constructor

    Constructor for the implementation contract. Sets immutable variables.

    Parameters

    Name
    Type
    Description

    comptroller_

    address

    The address of the Comptroller contract

    vBnb_

    address payable

    The address of the VBNB

    wBNB_

    address

    The address of wBNB


    initialize

    Initializer for the implementation contract.

    Parameters

    Name
    Type
    Description

    treasuryPercentMantissa_

    uint256

    Treasury share, scaled by 1e18 (e.g. 0.2 * 1e18 for 20%)

    accessControlManager_

    address

    address of access control manager

    protocolShareReserve_

    address

    The address of the protocol share reserve contract


    restrictLiquidation

    An admin function to restrict liquidations to allowed addresses only.

    Parameters

    Name
    Type
    Description

    borrower

    address

    The address of the borrower


    unrestrictLiquidation

    An admin function to remove restrictions for liquidations.

    Parameters

    Name
    Type
    Description

    borrower

    address

    The address of the borrower


    addToAllowlist

    An admin function to add the liquidator to the allowedLiquidatorsByAccount mapping for a certain borrower. If the liquidations are restricted, only liquidators from the allowedLiquidatorsByAccount mapping can participate in liquidating the positions of this borrower.

    Parameters

    Name
    Type
    Description

    borrower

    address

    The address of the borrower

    liquidator

    address


    removeFromAllowlist

    An admin function to remove the liquidator from the allowedLiquidatorsByAccount mapping of a certain borrower. If the liquidations are restricted, this liquidator will not be able to liquidate the positions of this borrower.

    Parameters

    Name
    Type
    Description

    borrower

    address

    The address of the borrower

    liquidator

    address


    liquidateBorrow

    Liquidates a borrow and splits the seized amount between protocol share reserve and liquidator. The liquidators should use this interface instead of calling vToken.liquidateBorrow(...) directly. Checks force VAI liquidation first; vToken should be address of vaiController if vaiDebt is greater than threshold For BNB borrows msg.value should be equal to repayAmount; otherwise msg.value should be zero.

    Parameters

    Name
    Type
    Description

    vToken

    address

    Borrowed vToken

    borrower

    address

    The address of the borrower

    repayAmount

    uint256

    The amount to repay on behalf of the borrower

    vTokenCollateral

    contract IVToken

    The collateral to seize


    setTreasuryPercent

    Sets the new percent of the seized amount that goes to treasury. Should be less than or equal to comptroller.liquidationIncentiveMantissa().sub(1e18).

    Parameters

    Name
    Type
    Description

    newTreasuryPercentMantissa

    uint256

    New treasury percent (scaled by 10^18).


    setProtocolShareReserve

    Sets protocol share reserve contract address

    Parameters

    Name
    Type
    Description

    protocolShareReserve_

    address payable

    The address of the protocol share reserve contract


    reduceReserves

    Reduce the reserves of the pending accumulated reserves


    setMinLiquidatableVAI

    Sets the threshold for minimum amount of vaiLiquidate

    Parameters

    Name
    Type
    Description

    minLiquidatableVAI_

    uint256

    New address for the access control


    setPendingRedeemChunkLength

    Length of the pendingRedeem array to be consider while redeeming in Liquidation transaction

    Parameters

    Name
    Type
    Description

    newLength_

    uint256

    Length of the chunk


    pauseForceVAILiquidate

    Pause Force Liquidation of VAI


    resumeForceVAILiquidate

    Resume Force Liquidation of VAI


    contract IVBNB vBnb
    contract IComptroller comptroller
    contract IVAIController vaiController
    address wBNB
    constructor(address comptroller_, address payable vBnb_, address wBNB_) public
    function initialize(uint256 treasuryPercentMantissa_, address accessControlManager_, address protocolShareReserve_) external virtual
    function restrictLiquidation(address borrower) external
    function unrestrictLiquidation(address borrower) external
    function addToAllowlist(address borrower, address liquidator) external
    function removeFromAllowlist(address borrower, address liquidator) external
    function liquidateBorrow(address vToken, address borrower, uint256 repayAmount, contract IVToken vTokenCollateral) external payable
    function setTreasuryPercent(uint256 newTreasuryPercentMantissa) external
    function setProtocolShareReserve(address payable protocolShareReserve_) external
    function reduceReserves() external
    function setMinLiquidatableVAI(uint256 minLiquidatableVAI_) external
    function setPendingRedeemChunkLength(uint256 newLength_) external
    function pauseForceVAILiquidate() external
    function resumeForceVAILiquidate() external
    , which ensures:
    • Only pre-approved steward contracts are allowed to execute logic

    • Updates adhere to protocol-defined rules such as:

      • Debounce periods between consecutive updates

      • Maximum allowable percentage change in parameters

      • Access control enforced through Venus’s AccessControlManager

    This architecture enables faster response to market dynamics while maintaining the safety and integrity of the protocol’s core risk parameters.


    Contracts and Responsibilities

    1. RiskStewardReceiver.sol

    Purpose

    The RiskStewardReceiver contract acts as the central entry point for processing on-chain risk parameter updates in the Venus Protocol. It integrates directly with the Chaos Labs Risk Oracle, pulling risk recommendations (like borrow/supply caps) and forwarding them to the appropriate RiskSteward contract (e.g., MarketCapsRiskSteward) for enforcement.

    Its key role is to:

    • Validate, deduplicate, and throttle risk updates,

    • And delegate the actual update execution to the appropriate steward contract responsible for enforcing specific risk parameter types.

    This contract enables a modular and secure pipeline for processing real-time risk recommendations on-chain.


    Key Responsibilities

    • Oracle Integration: Directly reads data from the IRiskOracle, which provides structured RiskParameterUpdate records.

    • Per-Type Configuration: Maintains a riskParameterConfigs mapping to register:

      • Which updateType is supported,

      • Which steward contract should handle it,

      • What debounce period (minimum time between updates) is enforced.

    • Validation Checks Before Processing: Before an update is executed, the contract validates that:

      • The update type is active (ConfigNotActive)

      • The update is not expired (UpdateIsExpired)

    • Processing Updates: Provides two ways to trigger an update:

      1. processUpdateById(updateId)

      2. processUpdateByParameterAndMarket(updateType, market)

      Both functions:

    • State Tracking:

      • lastProcessedTime: Tracks last update per (market + updateType) to enforce debounce period

      • processedUpdates: Marks updates that have already been processed, preventing replay

    • Governance and Controls:

      • Uses AccessControlledV8 to restrict who can:

        • Set or modify risk configs

        • Pause or unpause the contract


    2. MarketCapsRiskSteward.sol

    The MarketCapsRiskSteward contract is responsible for processing supply cap and borrow cap updates for Venus markets. These updates originate from the RiskStewardReceiver, which itself receives on-chain recommendations from the Chaos Labs Risk Oracle.

    This contract does not fetch or validate updates directly. Instead, it:

    • Receives validated updates delegated by the RiskStewardReceiver

    • Performs delta checks to ensure caps are within allowed bounds

    • Writes new cap values into the correct pool comptroller (either Core or Isolated)

    • Emits events for transparency and downstream indexing


    Key Responsibilities

    • Parameter Enforcement Applies updates only for:

      • supplyCap

      • borrowCap

    • Source Validation Ensures updates can only be executed by the trusted RiskStewardReceiver. → Any direct call from an external or malicious contract is rejected (OnlyRiskStewardReceiver).

    • Delta Bounding Before updating any cap, the new value is validated against the previous cap. The change is only allowed if it’s within the maxDeltaBps (basis points) threshold. → Ensures the system remains stable and avoids drastic risk shifts (UpdateNotInRange).

    • Governance Access AccessControlledV8 is used to restrict who can:

      • Set the maxDeltaBps

      • Initialize the contract


    End-to-End Flow: Market Cap Update via Risk Stewards

    This example walks through a complete end-to-end flow where Chaos Labs updates a borrow cap for a market using the on-chain risk oracle, and the change is processed securely through the steward contracts.

    Roles

    Role
    Description

    Chaos Labs

    Publishes risk parameter updates on-chain via a Risk Oracle

    Keeper Bot

    External off-chain agent responsible for calling the RiskStewardReceiver to apply updates

    RiskStewardReceiver

    Central processor that validates updates and routes them to the correct steward

    MarketCapsRiskSteward

    Applies validated supply/borrow cap updates to the appropriate pool comptroller


    Example Scenario

    Chaos Labs recommends updating the borrow cap for the USDC market (vUSDC) from 5,000,000 to 6,000,000 tokens.


    Step-by-Step Execution

    1. Chaos Labs Publishes an Update On-Chain

    Chaos Labs publishes the following to the on-chain Risk Oracle contract:

    This update is stored in the oracle contract and made available via getUpdateById(updateId).


    2. Keeper Bot Detects the Update and Calls processUpdateById

    A Keeper Bot regularly polls the Risk Oracle and calls:


    3. RiskStewardReceiver Validates the Update

    Upon receiving the call, RiskStewardReceiver performs strict validations:

    • ✅ Checks that the update is the latest from the oracle for the given market and type

    • ✅ Validates the update is active in config (ConfigNotActive)

    • ✅ Verifies it is not expired (timestamp + 1 day > now) (UpdateIsExpired)

    • ✅ Ensures it is not already processed (ConfigAlreadyProcessed)

    • ✅ Ensures debounce interval has passed for the (market + updateType) pair (UpdateTooFrequent)

    If any check fails, the transaction reverts with the corresponding error.


    4. Update is Routed to MarketCapsRiskSteward

    Once the update passes all validations, the RiskStewardReceiver uses the updateType to determine which RiskSteward contract should handle it, and delegates the update to MarketCapsRiskSteward:

    Here, the steward performs:

    • ✅ Validates that the msg.sender is RiskStewardReceiver (OnlyRiskStewardReceiver)

    • ✅ Confirms that updateType is either supplyCap or borrowCap (UnsupportedUpdateType)

    • ✅ Retrieves the current cap from the comptroller and validates that the new cap change is within the allowed delta range defined by maxDeltaBps:

    • ✅ Writes the new cap into the pool comptroller:

    • ✅ Emits BorrowCapUpdated(market, newCap) for downstream indexing

    • ✅ Applies the update to the pool’s comptroller, by directly making a call to the appropriate setter function: comptroller.setMarketSupplyCaps(newSupplyCapMarkets, newSupplyCaps)


    5. Update State is Committed

    Once the steward call completes:

    • The update ID is marked as processed

    • The (market + updateType) debounce timer is updated with the current block time

    • RiskParameterUpdated(updateId) is emitted


    Failure Scenarios

    Scenario
    Failure Trigger
    Result

    Keeper calls too late (e.g. after 24h)

    UpdateIsExpired

    Revert

    Keeper tries again for same ID

    ConfigAlreadyProcessed

    Revert

    Another update was already applied for the same market+type

    UpdateIsExpired

    Revert

    Debounce timer has not passed

    UpdateTooFrequent


    Risk Stewards

    Limitations

    While the Risk Steward system enables secure and automated updates to certain risk parameters, there are important limitations to keep in mind:

    1. Bypasses On-Chain Governance

    This architecture allows updates (e.g., supply and borrow caps) to be applied automatically, without going through the formal governance process.

    • Critical parameters such as collateral factors, liquidation thresholds, and reserve factors are intentionally excluded.

    • These parameters are considered sensitive and must be proposed and approved through governance (via Venus Improvement Proposals or VIPs) to ensure proper transparency and community review.

    2. No Cross-Chain Initiation Support

    The current design supports only same-chain update processing.

    • Updates on a specific chain can only be processed if a Risk Oracle is deployed and supported on that chain..

    • For operational efficiency and monitoring, it would be beneficial to register or reflect these updates on BNB Chain, where monitoring systems and automation (such as keeper bots) are primarily active.

    Prime tokens

    Only available on BNB chain

    Overview

    This technical article explains implementation details of the Venus Prime program. The overview of the Venus Prime program can be checked .

    VenusERC4626 Vaults

    Overview

    Venus Protocol introduces native ERC-4626 vaults, bringing standardized, composable yield vaults to the Venus ecosystem. This integration represents a significant advancement in making Venus's yield-bearing markets more accessible and composable within the broader DeFi ecosystem.

    Key Benefits:

    PSM

    Peg Stability Contract.

    Contract for swapping stable token for VAI token and vice versa to maintain the peg stability between them.

    Solidity API

    {
      "updateId": 101,
      "market": "0x...vUSDC",
      "updateType": "borrowCap",
      "newValue": 6000000,
      "timestamp": 1721036000,
      "additionalData": "<encoded underlyingAddress/chainId>"
    }
    riskStewardReceiver.processUpdateById(101);
            IRiskSteward(riskParameterConfigs[update.updateType].riskSteward).processUpdate(update);

    The update has not already been processed (ConfigAlreadyProcessed)

  • The debounce period since the last update has passed (UpdateTooFrequent)

  • Fetch the update from the risk oracle

  • Validate its status

  • Delegate the update execution to the configured IRiskSteward contract

  • Can be paused to halt all update processing using OpenZeppelin’s PausableUpgradeable

  • Revert

    Chaos Labs sets too large a delta

    UpdateNotInRange

    Revert

    Cap type is misspelled

    UnsupportedUpdateType

    Revert

    Non-receiver tries to call steward

    OnlyRiskStewardReceiver

    Revert

    Risk Stewards
    Rewards

    (Main explanation of Prime rewards)

    Qualifiable supply and borrow amounts limits are set by the staked XVS limit and the market multiplier. The USD values of the tokens and the USD value of XVS will be taken into account to calculate these caps. The following pseudocode shows how σi,m\sigma_{i,m}σi,m​ is calculated considering the caps:

    Significance of α

    A higher α value increases the weight of stake contributions when determining rewards and decreases the weight of supply/borrow contributions. The value of α is between 0-1 (both excluded).

    A default weight of 0.5 has been evaluated as a good ratio and is not likely to be changed. A higher value would only be needed if Venus wanted to attract more XVS stake from the Prime token holders at the expense of supply/borrow rewards.

    Here is an example to show how the score is impacted based on the value of α:

    Implementation of the rewards in solidity

    rewardIndex and sumOfMembersScore are global variables in supported markets used when calculating rewards. sumOfMembersScore represents the current sum of all the Prime token holders score and rewardIndex needs to be updated whenever a user’s staked XVS or supply/borrow changes.

    Whenever a user’s supply/borrow or XVS Vault balance changes we will recalculate the rewards accrued and add them to their account:

    • In Comptroller (specifically in the PolicyFacet), after executing any operation that could impact the Prime score or interest, we accrue the interest and update the score for the Prime user by calling accrueInterestAndUpdateScore.

    • In the XVSVault, after depositing or requesting a withdrawal, the function xvsUpdated is invoked, to review the requirements of Prime holders.

    This is how we will calculate the user rewards:

    Then we will update the userRewardIndex (interests[market][account]) to their current global values.

    Income collection and distribution

    Every market in Venus (including Isolated Lending markets) contributes to the rewards that the Prime contract will distribute, following the protocol tokenomics. The following diagram shows the current implementation for the flow of funds.

    Rewards will be distributed to Prime users only in USDT, USDC, BTC and ETH tokens. Other tokens will have to be converted to the tokens used for rewarding users in Prime. This conversion should follow a configurable (via VIP) distribution table, that initially will be:

    Prime market
    Distribution

    USDT

    40%

    USDC

    30%

    ETH

    25%

    BTC

    5%

    For example:

    • The CAKE market generates 1,000 CAKE of total income

    • 10% of the CAKE total income should be allocated to Prime → 100 CAKE (following the protocol tokenomics)

    • We should convert 100 CAKE to USDC, USDT, BTC and ETH, because in Prime the rewards are defined in these tokens

    • The conversion should follow the previous table:

      • 40 CAKE should be converted to USDT

      • 30 CAKE should be converted to USDC

      • 25 CAKE should be converted to ETH

      • 5 CAKE should be converted to BTC

    Interest reserves (part of the protocol income) from Isolated Pools and the Core Pool markets are sent to the PSR (Protocol Share Reserve) contract. Based on the configuration, a percentage of income from all markers is reserved for Prime token holders. The interest reserves will be sent to the PSR periodically (currently every 6 hours, but this can be changed by the community via VIP).

    The PSR has a function releaseFunds that needs to be invoked to release the funds to the destination contracts. We have SingleTokenConverter contracts which receive income from the PSR and convert them to Prime supported reward tokens.

    Each SingleTokenConverter sends funds to PrimeLiquidityProvider contract which releases the funds to Prime contract. Distribution speeds for each of the reward token is configured in the PrimeLiquidityProvider contract and based on those speeds Prime distributes rewards.

    If a user tries to claim their rewards and the Prime contract doesn’t have enough funds, then we trigger the release of funds from PrimeLiquidityProvider to Prime contract in the same transaction i.e., in the claimInterest function.

    The following diagram shows the integration of the SingleTokenConverter contracts with the Prime contracts:

    More information about income collection and distribution can be found here.

    Update cap multipliers and alpha

    Market multipliers and alpha can be updated at anytime and then need to be propagated to all users. Changes will be gradually applied to users as they borrow/supply assets and their individual scores are recalculated. This strategy has limitations because the scores will be wrong in aggregate until all Prime users have interacted with the markets.

    To mitigate this issue, Venus will supply a script that will use the permission-less function updateScores to update the scores of all users. This script won’t pause market and Prime contracts. The scores will need to be updated in multiple transactions because a single transaction will run out of gas trying to update all scores.

    As markets won't be paused, there could be inconsistencies due to user supply/borrow transactions in between updating scores transactions. These inconsistencies will be very minor compared to letting it update gradually when users will borrow/supply.

    There are two main objectives for creating this script:

    • If the Venus community wants to update all users scores when multipliers or alpha are changed then we have an immediate option.

    • After minting Prime tokens if the Venus community decides to add an existing market to the Prime token program then users scores need to be updated in order for them to being receiving rewards. The scores cannot be applied gradually in this case as the first Prime users in the market will receive disproportionally large rewards until the rest of the users in the market have their scores updated. A script to quickly update score for all users in a market will prevent this scenario.

    There is a variable named totalScoreUpdatesRequired to track how many score updates are pending. This is for tracking purposes and visible to the community.

    Calculate APR associated with a Prime market and user

    The goal is to offer a view function that allows the Venus UI to show an estimation of the APR associated with the Prime token and the borrow/supply position of a user.

    The steps to perform this calculation are:

    1. Fetch the income per block from PrimeLiquidityProvider

    2. Calculate the user yearly income by multiplying (1) with blocks per year

    3. Calculate the user score and total sum of scores for the market. This we can calculate the total rewards aloocation for the user for an year.

    4. Calculate the capped supply and borrow of the user for the market

    5. Calculate the ratio of allocation of the rewards based on capped supply and borrow of the user

    6. Now borrow and supply APR of user can be calculated based on ratio of capped borrow and supply of the user.

    Example:

    1. Income per block 0.00003 USDT

    2. Income per year is 10512000 blocks/year * 0.00003 = 315.36 USDT

    3. Assuming the user score for USDT: 3, and the sum of scores for USDT: 10, then we would have 94.608 USDT (yearly income for this user, generated by Prime)

    4. Assuming the user has the following positions:

      1. borrow: 30 USDT. Let's say it's capped at 15 USDT, so we'll consider 15 USDT

      2. supply: 10 USDT. Let's say it's also capped at 15 USDT, so we'll consider 10 USDT

    5. Allocating the rewards (94.608 USDT), considering these capped versions, we would have:

      1. borrow: 94.608 * 15/25 = 56.76 USDT

      2. supply: 94.608 * 10/25 = 37.84 USDT

    6. Calculating the APR with these allocations, we would have:

      1. borrow: 56.76/30 = 1.89 = 189%

      2. supply: 37.84/10 = 3.78 = 378%

    Only the supply and borrow amounts below the cap generate Prime rewards. The supply and borrow amounts above the cap do not generate extra rewards. In the example, if the user supplies more USDT, they won't generate more rewards (because the supply amount to be considered is capped at 15 USDT). Therefore the supply APR would decrease if they supply more USDT.

    Bootstrap liquidity for the Prime program

    There will be bootstrap liquidity available for the Prime program. This liquidity:

    • should be uniformly distributed over a period of time, configurable via VIP

    • is defined by the tokens enabled for the Prime program

    These requirements will be enforced with the PrimeLiquidityProvider contract:

    • The Prime contract has a reference to the PrimeLiquidityProvider contract

    • The Prime contract will transfer to itself the available liquidity from the PrimeLiquidityProvider as soon as it’s needed when a user claims interests, to reduce the number of transfers

    • The Prime contract takes into account the tokens available in the PrimeLiquidityProvider contract, when the interests are accrued and the estimated APR calculated

    Regarding the PrimeLiquidityProvider:

    • The PrimeLiquidityProvider contract maintains a speed per token (see tokenDistributionSpeeds, with the number of tokens to release each block), and the needed indexes, to release the required funds per block

    • Anyone can send tokens to the PrimeLiquidityProvider contract

    • Only accounts authorized via ACM will be able to change the tokenDistributionSpeeds attribute

    • The PrimeLiquidityProvider provides a view function to get the available funds that could be transferred for a specific token, taking into account:

      • the current block number

      • the speed associated with the token

    • The PrimeLiquidityProvider provides a function to transfer the available funds to the Prime contract.

    Pause claimInterest

    There is a feature flag to enable/disable the function claimInterest. When this feature is paused, no users will be able to invoke this function.

    The OpenZeppelin PausableUpgradeable contract is used. Only the claimInterest function is under control of this pause mechanism.

    here
  • Full ERC-4626 Compliance – Interoperable with DeFi primitives (DAOs, aggregators, etc.)

  • Native Venus Yield Integration – Auto-compounding via vTokens

  • Gas-Optimized Architecture – Beacon proxy pattern for efficient deployments, so all vaults share the same implementation contract.

  • Secure & Upgradeable – Governance-controlled upgrades and reward management

  • Understanding ERC-4626

    ERC-4626 is a tokenized vault standard designed to unify how yield-bearing assets are deposited, managed, and withdrawn in DeFi protocols. It builds on the ERC-20 token standard and introduces a consistent interface for vaults that accept a specific asset (like USDC) and issue shares representing ownership in the vault.

    The primary goal of ERC-4626 is standardization—allowing developers to integrate with vaults without needing to understand their internal mechanics. Functions like deposit, withdraw, mint, and redeem, follow predictable behaviors across all compliant contracts.

    In essence, ERC-4626 makes it easier for users to earn yield on their assets and for protocols to plug into vaults in a reliable, composable way—enhancing both usability and interoperability across the DeFi ecosystem.

    Reference: https://eips.ethereum.org/EIPS/eip-4626

    The implementation of the Venus ERC-4626 vaults consists of two core smart contracts:

    1. VenusERC4626Factory.sol - The factory contract for deploying standardized vaults

    • Deploys individual vaults for individual vTokens via BeaconProxy

    • Ensures deterministic addresses using CREATE2

    • Managed by Venus Governance

    2. VenusERC4626.sol - The vault logic implementing ERC-4626 functionality

    • ERC-4626-compliant mint, deposit, redeem, and withdraw functions

    • Integrates with Venus vToken interest accrual

    • Handles reward distribution (e.g., XVS)

    Architecture

    VenusERC4626Factory.sol: The Vault Factory

    Architecture Overview

    The factory contract implements a sophisticated deployment system using OpenZeppelin's upgradeability patterns:

    Core Components

    Beacon Proxy System

    • UpgradeableBeacon: Stores the current implementation address.

    • BeaconProxy: Proxy delegates to beacon implementation.

    • CREATE2: Deterministic deployment with fixed salt for beacon proxies.

    Benefits:

    • Single implementation contract shared by all vaults.

    • Gas-efficient deployments.

    • Centralized upgrade capability.

    PoolRegistry Integration

    This ensures:

    • Only legitimate Venus vTokens can create vaults.

    • Proper asset/vToken pairing.

    • Compliance with Venus's risk parameters.

    Key Features

    • Deterministic Deployment: Uses a constant salt to enable deterministic address generation for ERC-4626 vault proxies.

    • Upgradeable Architecture: Utilizes a beacon proxy pattern to support upgradeability of all deployed vaults via a single beacon.

    • Vault Tracking: Maintains a mapping createdVaults of vTokens to their corresponding deployed ERC-4626 vaults.

    • Reward Routing: Allows configuration of a centralized reward recipient for all vaults and supports liquidity mining incentives.

    • Permissioned Admin: Restricts administrative operations (e.g., setting reward recipient, max loops) via Access Control Manager (ACM).

    Events

    • CreateERC4626 (event): Emitted when a new ERC-4626 vault is created for a vToken.

    • RewardRecipientUpdated (event): Emitted when the reward recipient address is updated.

    Constants

    • SALT (bytes32): Constant salt used for deterministic deployment of vaults.

    State variables

    • beacon (UpgradeableBeacon): Stores the address of the beacon contract holding the ERC-4626 vault implementation.

    • poolRegistry (PoolRegistryInterface): Reference to the Venus Pool Registry contract.

    • rewardRecipient (address): Address designated to receive liquidity mining rewards.

    • createdVaults (mapping(address => ERC4626Upgradeable)): Maps vTokens to their deployed ERC-4626 vault instances.

    Functions

    • initialize(): Initializes the factory with core configuration.

    • createERC4626(address vToken): Creates a new ERC-4626 vault for the specified vToken.

    • computeVaultAddress(address vToken): Returns the predicted address of a vault for a specific vToken.

    • setRewardRecipient(address newRecipient): Updates the address receiving reward distributions (ACM-restricted).

    • setMaxLoopsLimit(uint256 loopsLimit): Configures the maximum allowed loop iterations (ACM-restricted).

    Security Considerations

    1. Access Controls

    • Admin-Only Functions (via AccessControlledV8):

      • setRewardRecipient()

      • setMaxLoopsLimit()

      • upgradeBeacon() (for emergency fixes)

    2. Input Validation

    • ensureNonzeroAddress() prevents invalid configurations.

    Attack Surface Mitigation

    Threat Vector

    Mitigation Strategy

    Reentrancy

    nonReentrant modifiers

    Invalid vTokens

    PoolRegistry validation

    Governance attacks

    ACM with timelocks

    Upgrade risks

    Beacon ownership controls


    VenusERC4626.sol: The Vault Implementation

    Core Architecture

    The VenusERC4626 contract serves as an ERC-4626 compliant wrapper around Venus's yield-bearing vTokens. It inherits from multiple OpenZeppelin and Venus-specific base contracts to provide a secure, feature-rich implementation:

    Key Features

    • ERC-4626 Compliant: Fully compliant with the ERC-4626 Tokenized Vault standard, enabling integrations with yield aggregators and frontends.

    • vToken Wrapping: Provides tokenized access to underlying vTokens with proportional interest accrual.

    • Dual-Stage Initialization: Separates base contract setup and access/reward configuration for modular deployment.

    • Reward Claiming: Allows vaults to claim accrued rewards and direct them to a predefined recipient.

    • Failsafes and Admin Tools: Includes recovery mechanisms, such as sweepToken, and loop control for security and operational safety.

    Key Inherited Functionality:

    • ERC4626Upgradeable: Uses OpenZeppelin's 4626 contract as the base implementation of the ERC-4626 standard.

    • AccessControlledV8: Venus role-based access control system.

    • ReentrancyGuardUpgradeable: Protection against reentrancy attacks.

    • MaxLoopsLimitHelper: Prevents gas exhaustion in loops.

    Events

    • ClaimRewards (event): Emitted when rewards are claimed and distributed.

    • RewardRecipientUpdated (event): Emitted when the reward recipient address is updated.

    • SweepToken (event): Emitted when ERC-20 tokens are swept from the contract.

    State variables

    • vToken (VToken): The underlying Venus vToken being wrapped.

    • comptroller (IComptroller): The Comptroller contract associated with the vToken.

    • rewardRecipient (address): Address designated to receive reward tokens.

    Functions

    Core ERC-4626 Functions

    • deposit(uint256 assets, address receiver): Deposits assets and mints shares to the receiver.

    • mint(uint256 shares, address receiver): Mints exact shares by depositing required assets.

      • Note - It can mint slightly fewer shares than requested, because vToken.mint rounds down.

    • withdraw(uint256 assets, address receiver, address owner): Withdraws exact assets and burns shares from the owner.

      • Note - Receiver can receive slightly more assets than requested, because VToken.redeemUnderlying rounds up

    • redeem(uint256 shares, address receiver, address owner): Redeems exact shares and transfers assets to the receiver.

    • totalAssets(): Returns the total underlying assets held by the vault.

    Initialization

    • initialize(address vToken_): Initializes the vault with the target vToken (first-stage init).

    • initialize2(address accessControlManager_, address rewardRecipient_, uint256 loopsLimit_): Second-stage initialization with access control, reward recipient, and loop limit.

    Reward Management

    • claimRewards(): Claims all available rewards and sends them to the recipient.

    • setRewardRecipient(address newRecipient): Updates the reward recipient address (ACM-restricted).

    Admin Functions

    • sweepToken(IERC20Upgradeable token): Allows the owner to recover any ERC-20 tokens that were mistakenly sent to the vault.

    • setMaxLoopsLimit(uint256 loopsLimit): Configures the maximum loop iterations (ACM-restricted).

    Error Codes

    • VenusError(uint256 errorCode): Generic error returned from Venus protocol operations.

    • ERC4626__ZeroAmount(string operation): Thrown when a zero amount is provided during an operation.

    • ERC4626__DepositMoreThanMax(): Error triggered when a deposit exceeds the maximum limit.

    • ERC4626__MintMoreThanMax(): Error triggered when a mint exceeds the maximum limit.

    • ERC4626__WithdrawMoreThanMax(): Error triggered when a withdrawal exceeds the maximum limit.

    • ERC4626__RedeemMoreThanMax(): Error triggered when a redeem exceeds the maximum limit.

    Deposit Flow

    1. Validates input parameters.

    2. Calculates shares to mint.

    3. Transfers assets from the user.

    4. Mints vTokens via Venus Protocol.

    5. Issues vault shares to the receiver.

    Example

    Scenario: Alice deposits 100 USDC.

    Result:

    • Alice gets 100 vault shares.

    • Vault holds 100 vUSDC (earning yield).

    Withdrawal Flow

    1. Validates input parameters.

    2. Calculates shares to burn.

    3. Redeems underlying assets from Venus.

    4. Transfers assets to the receiver.

    5. Burns vault shares.

    Example

    Scenario: Alice withdraws 50 USDC (after interest accrual).

    Result

    Alice receives 50 USDC.

    • Vault burns shares adjusted for interest (e.g., 48.54 shares at a 1.03 exchange rate).

    Security Features

    1. Reentrancy Protection:

      • All state-changing functions use the nonReentrant modifier.

      • Critical Venus operations (mint/redeem) are atomic.

    2. Input Validation:

      • Zero-address checks are performed via ensureNonzeroAddress.

      • Zero-amount validation for all operations.

      • Explicit error codes for Venus operations.

    3. Access Control:

      • Sensitive functions are protected by Venus's ACM.

      • The reward recipient can only be changed by authorized accounts.


    BASIS_POINTS_DIVISOR

    The divisor used to convert fees to basis points.


    MANTISSA_ONE

    The mantissa value representing 1 (used for calculations).


    ONE_DOLLAR

    The value representing one dollar in the stable token.


    VAI

    VAI token contract.


    STABLE_TOKEN_ADDRESS

    The address of the stable token contract.


    oracle

    The address of ResilientOracle contract wrapped in its interface.


    venusTreasury

    The address of the Venus Treasury contract.


    feeIn

    The incoming stableCoin fee. (Fee for swapStableForVAI).


    feeOut

    The outgoing stableCoin fee. (Fee for swapVAIForStable).


    vaiMintCap

    The maximum amount of VAI that can be minted through this contract.


    vaiMinted

    The total amount of VAI minted through this contract.


    isPaused

    A flag indicating whether the contract is currently paused or not.


    initialize

    Initializes the contract via Proxy Contract with the required parameters.

    Parameters

    Name
    Type
    Description

    accessControlManager_

    address

    The address of the AccessControlManager contract.

    venusTreasury_

    address

    The address where fees will be sent.

    oracleAddress_

    address

    The address of the ResilientOracle contract.

    feeIn_

    uint256


    swapVAIForStable

    Swaps VAI for a stable token.

    Parameters

    Name
    Type
    Description

    receiver

    address

    The address where the stablecoin will be sent.

    stableTknAmount

    uint256

    The amount of stable tokens to receive.

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    The amount of VAI received and burnt from the sender.


    swapStableForVAI

    Swaps stable tokens for VAI with fees.

    Parameters

    Name
    Type
    Description

    receiver

    address

    The address that will receive the VAI tokens.

    stableTknAmount

    uint256

    The amount of stable tokens to be swapped.

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    Amount of VAI minted to the sender.


    pause

    Pause the PSM contract.


    resume

    Resume the PSM contract.


    setFeeIn

    Set the fee percentage for incoming swaps.

    Parameters

    Name
    Type
    Description

    feeIn_

    uint256

    The new fee percentage for incoming swaps.


    setFeeOut

    Set the fee percentage for outgoing swaps.

    Parameters

    Name
    Type
    Description

    feeOut_

    uint256

    The new fee percentage for outgoing swaps.


    setVenusTreasury

    Set the address of the Venus Treasury contract.

    Parameters

    Name
    Type
    Description

    venusTreasury_

    address

    The new address of the Venus Treasury contract.


    setOracle

    Set the address of the ResilientOracle contract.

    Parameters

    Name
    Type
    Description

    oracleAddress_

    address

    The new address of the ResilientOracle contract.


    previewSwapVAIForStable

    Calculates the amount of VAI that would be burnt from the user.

    Parameters

    Name
    Type
    Description

    stableTknAmount

    uint256

    The amount of stable tokens to be received after the swap.

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    The amount of VAI that would be taken from the user.


    previewSwapStableForVAI

    Calculates the amount of VAI that would be sent to the receiver.

    Parameters

    Name
    Type
    Description

    stableTknAmount

    uint256

    The amount of stable tokens provided for the swap.

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    The amount of VAI that would be sent to the receiver.


    Contracts Overview

    Venus Protocol contracts are divided in these repositories:

    • isolated-pools: Contains core contracts for isolated lending, including logic for supplying, borrowing, liquidations, pool and market deployments, and interest rate models.

    • oracle: This repo has contracts for oracles that we support as well as logic for validating prices returned from those oracles.

    • : The core protocol is located in this repo. It contains logic central to lending and borrowing of the core pool.

    • : The contracts used for proposing, voting and executing changes are kept in the `governance-contracts repo.

    • : The contracts use to bridge XVS to different networks.

    Isolated Pools Contracts

    There are 2 categories of isolated pools contracts:

    • Pool

    • Risk Management

    Pool

    Pool contracts can be divided into 4 categories:

    • Configuration

    • Logic

    • Miscellaneous

    Configuration

    Configuration contracts are used to deploy, configure, and manage pools.

    Creating and managing pools is done by the . It can add markets to pools, update pool metadata, and return pool information.

    Logic contracts

    The contract is the central contract for each lending pool. It contains functionality central to borrowing activity in the pool like supplying and borrowing assets and liquidations. Configuration values for the pool such as the liquidation incentive, close factor, and collateral factor can also be set and retrieved from the comptroller. Account liquidity and positions can also be retrieved from the comptroller.

    in isolated lending play an identical role as vTokens in the Core Pool. They represent a users supplied tokens to the protocol and can be redeemed (burned) for those tokens.

    Miscellaneous contracts

    Isolated Pools use additional contracts such as lenses, rewards, ect.

    Users are rewarded for borrowing and lending activities with a reward tokens. The manages these distributions using a configurable rate.

    To make querying pool data easier, Isolated Pools contains a that queries and formats pool data. These calls can be gas intensive so as a general rule of thumb this contract should not be used in transactions.

    Risk Management

    Lending comes with the inherent risk that borrows will not be able to repay their loan, which is a threat to the protocol's insolvency. Venus mitigates this risk with a . A percentage of protocol revenues is transferred to the RiskFund as it is accrued. When bad debt is detected, this fund can be auctioned off and used to cover the bad debt.

    When bad deb is auctioned off the contract is responsible for running the action and paying the winner.

    The acts as a treasury where each isolated pool can transfer their revenue.

    Oracle Contracts

    Venus Protocol implements secondary, primary and pivot oracles to create a validation and fallback strategy that avoids creating a single point of a failure by relying on a single source for prices. The contract is responsible for fetching and validating prices for a given vToken and managing which oracles are used for a particular vToken.

    Oracles

    is the primary oracle. If a token isn't support by Chainlink then prices will be fetched from a secondary oracle.

    is used in the Classic model (Chainlink-compatible interface) as a pivot oracle to validate prices returned by main and fallback oracles.

    contract is responsible for fetching token prices from the Binance oracle. It is used as a secondary oracle.

    is used as a pivot oracle to validate prices returned by primary and secondary oracles.

    Venus Protocol

    Venus Protocol contracts can be grouped as follows:

    • Lending

    • Tokens

    • Vault

    • Lens

    Lending Contracts

    At the heart of the Core Pool is the comptroller. The latest version is . The comptroller is responsible for listing markets, managing user's positions in markets, liquidations, and emitting rewards. It contains setters and getters for market configuration variables such as collateral factor, close factor, and liquidation incentive. Lending actions can be be paused globally or per market from the comptroller.

    Each market gets deployed with an interest rate model. The uses a linear curve to determine interest rates based on supply and demand of the asset until it reaches the kink after which there is a sharp increase in rates.

    Another interest rate model that can be deployed with markets is the . It is similar to the JumpRateModel except it doesn't include a kink. Instead it contains a fixed base rate.

    When a borrow becomes insolvent it may be liquidated. The handles this process. When a borrow is liquidated the seized amount is split between the liquidator and the

    Revenue earned by the protocol is kept in the .

    Token Contracts

    XVS is an important token in the Venus ecosystem because it powers Venus governance. The token contract defines a lockable BEP20 token with additional methods that enable voting and vote delegation. To vote, a user must first lock their XVS in the vault.

    is the Venus stable coin that can be minted against collateral. Users who mint VAI are charged a fee based on the outstanding supply and price of VAI to keep its value pegged at $1. The controls the amount of VAI a user is allowed to mint which is determined by the collateral a user has provided and their liquidity.

    When a user supplies a token to the protocol, vTokens are minted to represent their supply. The contract contains methods that support lending activities for the asset including lending, borrowing and liquidating

    Vault Contracts

    XVS Vault

    XVS can be locked in the to earn XVS and enable voting. Each XVS locked gives the locking address one vote to use or delegate.

    VAI Vault

    VAI staked in the earn XVS. Staking rewards are accumulated daily.

    Misc Contracts

    ComptrollerLens

    The contains methods for fetching the liquidity of an account and the amount of tokens that can be seized for a repayable amount

    SnapshotLens

    The contains methods for getting the details of account for a specific market or all markets where an account is active.

    VenusLens

    Protocol level data is made available through the . It contains getters related to XVS distribution, governance, and markets.

    Governance Contracts

    There are three main Governance contracts:

    • GovernorBravoDelegate

    • AccessControlManager

    • Timelock

    GovernorBravoDelegate

    The core logic for governance proposals is in the contract. It enables submitting proposals, moving proposals through time-gated stages, canceling and executing proposals as well as voting logic. The voting threshold as well as timelocks are set on this contract.

    AccessControlManager

    To enhance security of the protocol, Venus Protocol uses the to grant accounts access to call specific functions on contracts. This contract is responsible for granting and revoking those permissions. It also provides a getter to check if an address is allowed to call a specific function.

    Timelock Once a proposal has succeeded its execution is managed by the contract. The Timelock can place the proposal in a queue for execution and execute the proposal. It also enables canceling the proposal.

    Liquidations

    This is a step-by-step guide on how to perform liquidations on the Venus Protocol. Liquidations involve seizing collateral from under-collateralized accounts to repay outstanding debts. The instructions are targeted towards developers or bots that aim to automate the liquidation process.

    Account Liquidity Calculations

    Venus Protocol uses two calculations to determine account liquidity: Collateral Factor (CF) and Liquidation Threshold (LT).

    Collateral Factor (CF)

    Collateral Factor is the percentage of the supplied funds that can be used to cover a loan. Comptroller.getAccountLiquidity in the Core Pool and Comptroller.getBorrowingPower in Isolated Pools return the liquidity or an account. They use the Resilient Oracle to retrieve the value of the asset and the collateral factor for the market to determine the percentage of supply can be used as collateral. Relying on getBorrowingPower is not sufficient for identifying accounts in need of liquidation on Isolated Pools.

    Liquidation Threshold (LT)

    The Liquidation Threshold represents the point at which an account becomes under-collateralized, triggering the possibility of liquidation. In the Core Pool this is the same as the collateral factor. In Isolated Pools, the LT can be retrieved with Comptroller.getAccountLiquidity.

    Liquidators often use external monitoring systems or other strategies to accurately identify under-collateralized accounts.

    Iterating over all accounts and checking the CF and LT for every account is extremely inefficient.

    Instead, liquidators should rely on off-chain computations and maintain an off-chain mapping for accounts and balances. Using functions like vTokenBalancesAll and vTokenUnderlyingPriceAll from PoolLens can help retrieve balances and prices efficiently for multiple vTokens associated with an account.

    By combining the information obtained from these functions, one can accurately identify under-collateralized accounts that are suitable for liquidation.

    Minimum Liquidatable Collateral

    The Comptroller.minLiquidatableCollateral variable represents the minimal collateral in USD required for regular (non-batch) liquidations. Accounts with collateral below this threshold may not be eligible for non-batch liquidations. It's defined in USD value (18 decimals scale).

    Finding Under-Collateralized Accounts

    The first step to performing a liquidation is to identify under-collateralized accounts. Here's a suggested approach to finding under-collateralized accounts:

    1. Create a record of account balances: To identify under-collateralized accounts efficiently, liquidators can maintain an off-chain mapping of accounts and balances by indexing market events to detect new positions and update existing ones:

      • Mint: Event emitted when tokens are minted.

      • Redeem: Event emitted when tokens are redeemed.

    Consider using a subgraph to index these events.

    1. Get account balances: Use the vTokenBalancesAll function provided by PoolLens (VenusLens on the Core Pool) to retrieve supply and borrow balances for multiple vTokens associated with an account. This function takes an array of vTokens and the account address as parameters.

    2. Get underlying asset prices: Use the vTokenUnderlyingPriceAll function provided by the PoolLens (VenusLens on the Core Pool) to retrieve the underlying asset prices for multiple vTokens. This function takes an array of vTokens as a parameter.

    3. Calculate liquidity shortfall: With the supply and borrow balances obtained from step 2 and the underlying asset prices from step 3, calculate the liquidity shortfall for each account. This can be done by taking the scalar product of the balances and prices and comparing them against the LT values.

    By following this approach, you can efficiently identify under-collateralized accounts based on the CF and LT calculations.

    Please note that the functions mentioned above are provided by PoolLens and may require integration within your liquidation bot. Additionally, it's important to stay updated with any changes or updates to Venus Protocol that may impact the process of finding under-collateralized accounts.

    Performing the Liquidation

    Once an under-collateralized account has been identified, the liquidation process can be initiated using either liquidateBorrow , liquidateAccount or healAccount function. liquidateBorrow is provided by the relevant vToken contract (Liquidator contract on the Core Pool) whereas liquidateAccount and healAccount are provided in Comptroller. Here's an overview of the steps involved:

    Please note that healAccount is an extension of the liquidation mechanism to address handling of bad debt and offseting it with protocol revenue/fees. On the other hand, liquidateAccount allows batches of liquidations in a single transaction. In both cases, the total collateral must be lower than the threshold Comptroller.minLiquidatableCollateral. Those two functions are only available in Isolated Pools. For Core Pool liquidateBorrow function provided by Liquidator contract is the only available mechanism to perform liquidations.

    1. Calculate the liquidation amount: Determine the amount of debt to be repaid and the collateral to be seized. This is typically calculated by examining the borrower's debt balance, the market's collateral factor, and any discounts or liquidation incentives offered.

    2. When performing the liquidation, there are 3 different types of liquidations that can be called, taking in mind the collateral, minimum liquidatable collateral and solvency of the account:

    • Collateral > minLiquidatableCollateral --> liquidateBorrow(): Call the liquidateBorrow function on the relevant vToken contract. This function requires several parameters, including the borrower's address, the liquidator's address, the amount of debt to be repaid, and the collateral to be seized. Refer to the vToken contract documentation for specific details on the function's required parameters.

    Example

    Given:

    • Collateral Factor: 50%

    • Close Factor: 50%

    • Collateral < minLiquidatableCollateral && account is solvent --> liquidateAccount(): this function liquidates all borrows of the borrower.

    Example

    • Collateral Factor: 50%

    • Liquidation Threshold: 60%

    • Collateral < minLiquidatableCollateral && account is insolvent --> healAccount(): this function seizes all the remaining collateral from the borrower, requires the person initiating the liquidation (msg.sender) to repay the borrower's existing debt, and treats any remaining debt as bad debt. The sender has to repay a certain percentage of the debt, computed as collateral / (borrows * liquidationIncentive)

    Example

    • Collateral Factor: 50%

    • Liquidation Threshold: 60%

    1. Handle liquidation results: After invoking liquidateBorrow, monitor the transaction's success and handle any resulting events or errors. Successful liquidations will transfer the seized collateral to the liquidator's address and repay the debt from the borrower's account.

    Please note that the liquidation process involves complex calculations and requires a deep understanding of Venus Protocol. It's essential to thoroughly test and validate your liquidation bot before deploying it in a production environment. Additionally, keep track of any changes or updates to the Venus Protocol that may impact the liquidation process.

    Forced liquidations

    Usually, accounts are only eligible to be liquidated if they are under-collateralized, as described in the previous sections. An exception is if "forced liquidations" are enabled for a market or an individual account in a market. In this case, borrow positions can be liquidated in that market even when the health rate of the account is greater than 1 (i.e. when the account is sufficiently collateralized). Additionally, the close factor check is ignored, allowing the liquidation of 100% of the debt in one transaction.

    This feature is based on the implementation done by Compound V2 . Compound V2 allows "forced liquidations" on markets as soon as the Collateral factor is zero, the Reserve factor is 100% and the borrows are paused. Venus defines a feature flag to enable/disable "forced liquidations", configurable directly via VIP, not based on other parameters. Compound community talked about this feature in .

    On Venus, forced liquidations can be enabled either for an entire market (all borrow positions in the market can be forcefully liquidated), or for individual accounts in a market (only the borrows of a particular account can be forcefully liquidated in the market).

    To check if forced liquidations are enabled for an entire market, the function Comptroller.isForcedLiquidationEnabled(address vToken) can be called on the Comptroller contract of the pool with the address of the market. To check if forced liquidations are enabled for an individual account in the market, the function Comptroller.isForcedLiquidationEnabledForUser(address borrower, address vToken) can be used, providing the account and market address as arguments.

    Availability: Forced Liquidations for entire markets are available in the Core pool since , in the Isolated pools since . Forced Liquidations for individual accounts are available only in the Core pool since .

    Example

    Given:

    • vUSDT collateral factor: 80%

    • 1 USDT = 1 BUSD = 1 USDC = $1 (for simplicity)

    Force VAI Debt First

    This feature is disabled. Liquidators will have to change their codebase to consider the forced sequence of liquidations when there is a VAI debt. After having the confirmation from the main Liquidators that they have adapted their code, a VIP will be proposed to enable this feature.

    In the previous section, liquidations are carried out on all accounts without taking into consideration specific amounts of VAI debt. The forceVAILiquidate feature enhances the liquidation process by forcing liquidations of borrowers with VAI debt greater than minLiquidatableVAI. Forcing VAI liquidations allows the protocol to better manage risk and prevent potential losses due to excessive VAI debt accumulation.

    For borrowers with outstanding VAI debt, the force VAI liquidation first includes checks to ensure that only eligible accounts are liquidated before starting the liquidation process.

    Checks

    1. Check that VAI liquidations are not paused in Comptroller.

    2. The forceVAILiquidate flag is set to true.

    3. Verify whether the borrower's VAI debt is greater than the minimum amount of liquidatable VAI (initially 1,000 VAI).

    If the above conditions are true then the protocol checks that the current vToken sent to be liquidated is VAI, otherwise the liquidation fails.

    Example 1

    Given:

    • this feature is enabled

    • a user is eligible to be liquidated with the following debt:

    Example 2

    Given:

    • this feature is enabled

    • a user eligible to be liquidated with the following debts:

    Automatic Income Allocation

    In the Core Pool, liquidation income is transferred to the Liquidator contract in the form of vTokens. During a liquidation transaction, the Liquidator contract will try to redeem the protocol's portion of the liquidation incentive in vTokens for the underlying tokens. If the redemption process is successful, the underlying tokens will be sent to the ProtocolShareReserve contract. However, if the redemption fails the underlying tokens will be added to a list of pending redemptions and the Liquidator contract will try to redeem the pending redemptions again in subsequent liquidation transactions.

    Distributing Seized Amount

    The seized collateral is distributed between the Liquidator and the ProtocolShareReserve contract:

    1. Liquidator's Share:

      • The Liquidator receives a designated portion of the collateral as an incentive.

    2. ProtocolShareReserve contract's Share:

    Redemption Handling

    The Liquidator contract attempts to redeem the protocol's portion of the liquidation incentive in underlying tokens for the VTokens:

    1. Successful Redemption:

      • If the redemption is successful, the underlying tokens are sent to the ProtocolShareReserve contract.

    2. Failed Redemption:

    Pending Redemption Management

    Subsequent liquidation transactions leverage the list of pending redemptions: during each liquidation, the Liquidator contract attempts to redeem pending VTokens for their underlying tokens, and send these underlying tokens to the ProtocolShareReserve contract.

    Prime liquidity provider

    PrimeLiquidityProvider

    PrimeLiquidityProvider is used to fund Prime

    Solidity API

    borrowUSDCap = toUSD(xvsBalanceOfUser * marketBorrowMultipler)
    supplyUSDCap = toUSD(xvsBalanceOfUser * marketSupplyMultipler)
    borrowUSD = toUSD(borrowTokens)
    supplyUSD = toUSD(supplyTokens)
    
    // borrow side
    if (borrowUSD < borrowUSDCap) {
      borrowQVL = borrowTokens
    else {
      borrowQVL = borrowTokens * borrowUSDCap/borrowUSD
    }
    
    // supply side
    if (supplyUSD < supplyUSDCap) {
      supplyQVL = supplyTokens
    else {
      supplyQVL = supplyTokens * supplyUSDCap/supplyUSD
    }
    
    return borrowQVL + supplyQVL
    User A:
    Stake: 200
    Supply/Borrow: 500
    
    User B:
    Stake: 100
    Supply/Borrow: 1000
    
    If alpha is 0.7 then:
    user A score: 263.2764409
    user B score: 199.5262315
    
    If alpha is 0.3 then:
    user A score: 379.8288965
    user B score: 501.1872336
    // every time accrueInterest is called. delta is interest per score
    delta = totalIncomeToDistribute / sumOfMembersScore;
    rewardIndex += delta;
    rewards = (rewardIndex - userRewardIndex) * scoreOfUser;
    contract VenusERC4626Factory is AccessControlledV8, MaxLoopsLimitHelper {
        UpgradeableBeacon public beacon;
        mapping(address vToken => ERC4626Upgradeable vault) public createdVaults;
    
        function createERC4626(address vToken) external returns (ERC4626Upgradeable) {
            // Deployment logic...
        }
    }
    function createERC4626(address vToken) external {
        // Validate vToken is registered in PoolRegistry
        if (vToken != poolRegistry.getVTokenForAsset(comptroller, underlying)) {
            revert VenusERC4626Factory__InvalidVToken();
        }
        // Proceed with deployment...
    }
    contract VenusERC4626 is
        ERC4626Upgradeable,
        AccessControlledV8,
        MaxLoopsLimitHelper,
        ReentrancyGuardUpgradeable {
        // Implementation...
    }
    function deposit(uint256 assets, address receiver)
        public
        override
        nonReentrant
        returns (uint256)
    {
        // Input validation
        if (assets == 0) revert ERC4626__ZeroAmount("deposit");
        if (assets > maxDeposit(receiver)) revert ERC4626__DepositMoreThanMax();
    
        // Process deposit
        uint256 shares = previewDeposit(assets);
        _deposit(_msgSender(), receiver, assets, shares);
    
        return shares;
    }
    function withdraw(uint256 assets, address receiver, address owner)
        public
        override
        nonReentrant
        returns (uint256)
    {
        // Input validation
        if (assets == 0) revert ERC4626__ZeroAmount("withdraw");
        if (assets > maxWithdraw(owner)) revert ERC4626__WithdrawMoreThanMax();
    
        // Process withdrawal
        uint256 shares = previewWithdraw(assets);
        beforeWithdraw(assets); // Redeems from Venus
        _withdraw(_msgSender(), receiver, owner, assets, shares);
    
        return shares;
    }
    enum FeeDirection {
      IN,
      OUT
    }
    uint256 BASIS_POINTS_DIVISOR
    uint256 MANTISSA_ONE
    uint256 ONE_DOLLAR
    contract IVAI VAI
    address STABLE_TOKEN_ADDRESS
    contract ResilientOracleInterface oracle
    address venusTreasury
    uint256 feeIn
    uint256 feeOut
    uint256 vaiMintCap
    uint256 vaiMinted
    bool isPaused
    function initialize(address accessControlManager_, address venusTreasury_, address oracleAddress_, uint256 feeIn_, uint256 feeOut_, uint256 vaiMintCap_) external
    function swapVAIForStable(address receiver, uint256 stableTknAmount) external returns (uint256)
    function swapStableForVAI(address receiver, uint256 stableTknAmount) external returns (uint256)
    function pause() external
    function resume() external
    function setFeeIn(uint256 feeIn_) external
    function setFeeOut(uint256 feeOut_) external
    function setVenusTreasury(address venusTreasury_) external
    function setOracle(address oracleAddress_) external
    function previewSwapVAIForStable(uint256 stableTknAmount) external view returns (uint256)
    function previewSwapStableForVAI(uint256 stableTknAmount) external view returns (uint256)

    The percentage of fees to be applied to a stablecoin -> VAI swap.

    feeOut_

    uint256

    The percentage of fees to be applied to a VAI -> stablecoin swap.

    vaiMintCap_

    uint256

    The cap for the total amount of VAI that can be minted.

    venus-protocol
    governance-contracts
    token-bridge
    PoolRegistry
    PoolRegistry
    Comptroller
    Comptroller
    vToken
    vTokens
    RewardsDistributor
    RewardsDistributor
    PoolLens
    lens
    RiskFund
    RiskFund
    Shortfall
    Shortfall
    ProtocolShareReserve
    ProtocolShareReserve
    ResilientOracle
    ResilientOracle
    ChainlinkOracle
    ChainLinkOracle
    RedStoneOracle
    RedstoneOracle
    BinanceOracle
    BinanceOracle
    PythOracle
    PythOracle
    Comptroller
    Comptroller
    JumpRateModel
    JumpRateModel
    WhitePaperInterestRateModel
    WhitePaperInterestRateModel
    Liquidator
    Liquidator
    treasury
    VTreasury
    VTreasury
    XVS
    XVS
    VAI
    VAI
    VAIController
    vTokens
    VToken
    XVSVault
    VAIVault
    ComptrollerLens
    SnapshotLens
    VenusLens
    GovernorBraveDelegate
    AccessControlManager
    Timelock

    Borrow: Event emitted when underlying is borrowed.

  • RepayBorrow: Event emitted when a borrow is repaid. By listening to these events, liquidators can track changes in positions and update the balances of users accordingly.

  • Liquidation Threshold: 60%

  • Borrow Amount: $13,000

  • Collateral Amount: $20,000

  • Liquidation Incentive: 110%

  • Protocol Share Percentage: 5%

  • The borrowed amount is $1,000 above the liquidation threshold ($12,000), therefore the position is eligible for liquidation. Liquidation can be called with a repayment of up to $6,500 (borrow amount * close factor). Let's assume the liquidator initiates the liquidation process with a repayment amount of $1,000 Let's Calculate the Collateral Seized Amount (the amount that is seized from the borrower's collateral):

    Collateral Seized Amount = Repayment Amount * Liquidation Incentive

    Collateral Seized Amount = $1,000 * 1.1

    Collateral Seized Amount = $1,100

    Therefore, if the borrowed asset value reaches $13,000 and the repayment amount is $1,000, the total collateral seized will be $1,100 considering the liquidation incentive of 10%. In order to calculate what amount the liquidator will get we need to consider treasuryPercentMantissa (in the Core pool) or protocolSeizeShareMantissa (in the Isolated pools). This variable (Protocol Share Percentage) sets the percentage of the collateral seized that will go to the protocol. Let's assume that the protocol shares for liquidations is 5% and calculate the liquidator received amount:

    Liquidator Receive Amount = Collateral Seized - Protocol Shares

    Protocol Shares = (Collateral Seized / Liquidation Incentive) * Protocol Share Percentage

    Protocol Shares = ($1,100 / 1.1) * 0.05 = $50

    Liquidator Receive Amount = $1,100 - $50 = $1,050

    In conclusion, the liquidator will provide $1,000 for the liquidation. After the liquidation, the liquidator will receive $1,050 and the rest $50 will go to the protocol.

    Min Liquidatable Collateral: $100
  • Borrow Amount: $60

  • Collateral Amount: $90

  • Position is already eligible for liquidation since Borrow Amount >= $54. We should call liquidateAccount() because collateral < $100 and account is solvent.

    Min Liquidatable Collateral: $100
  • Borrow Amount: $90

  • Collateral Amount: $60

  • Position is eligible for liquidation and collateral is < $100, but the account is insolvent, so we need to call healAccount() to ensure that the remaining debt ($30) is treated as bad debt for the protocol.

    Close factor: 50%

  • Liquidation incentive: 10%

  • User with the following positions:

    • Supply: 500 USDT

    • Borrow: 200 BUSD

    • Borrow: 100 USDC

  • The health rate for this user would be (500 * 0.8) / (200 + 100) = 1.33. So, in normal circumstances, this user is not eligible to be liquidated.

    Now, let’s say we enable the forced liquidations in the BUSD market (via VIP). Then:

    • Anyone will be allowed to liquidate the BUSD position of the previous user. Moreover, the close factor limit won’t be taken into account. So, the following liquidation would be doable:

      • Repay amount: 200 BUSD

      • Collateral market to seize: USDT

    • By doing this liquidation, 220 USDT (repay amount + liquidation incentive) would be seized from the user’s collateral.

    • After the liquidation, the global position of our user would be:

      • Supply: 280 USDT (500 USDT - 220 USDT seized during the liquidation)

      • Borrow: 0 BUSD

      • Borrow: 100 USDC

    • So, the new health rate would be (280 * 0.8 / 100) = 2.24. They will be still ineligible for regular liquidations

    • Because the forced liquidation is not enabled in the USDC market, the USDC debt cannot be liquidated (because the health rate is greater than 1).

    2,000 VAI

  • 5,000 USDT

  • Liquidators will be required to liquidate the VAI position first because it is greater than minLiquidatableVAI. If they try to liquidate first the USDT position, the liquidation transaction will be reverted.

  • 500 VAI

  • 5,000 USDT

  • Liquidators will be allowed to liquidate first the VAI position or the USDT position. Both liquidations will work because the VAI debt is less than minLiquidatableVAI

    The remaining portion of the collateral is sent to the ProtocolShareReserve contract.
  • Conversion (if applicable):

    • BNB:

      • If the seized collateral is BNB, it is converted to Wrapped BNB (wBNB) before sending it to the ProtocolShareReserve contract.

    • Other VTokens:

      • For other VTokens, the underlying tokens are redeemed and transferred to the ProtocolShareReserve contract.

  • If the redemption fails due to insufficient liquidity or other reasons, the VTokens representing the pending redemption are added to a list for later processing.
    here
    this post
    VIP-172
    VIP-186
    VIP-210
    the last time those tokens were released
    Flow of funds related to Prime
    Integration of the SingleTokenConverter contracts with the Prime contracts
    Flow of funds related to ERC4626 wrappers
    Flow of funds related to ERC4626 wrapper
    Flow of funds related to ERC4626 wrappers
    DEFAULT_MAX_DISTRIBUTION_SPEED

    The default max token distribution speed


    prime

    Address of the Prime contract


    tokenDistributionSpeeds

    The rate at which token is distributed (per block)


    maxTokenDistributionSpeeds

    The max token distribution speed for token


    lastAccruedBlock

    The rate at which token is distributed to the Prime contract


    tokenAmountAccrued

    The token accrued but not yet transferred to prime contract


    initialize

    PrimeLiquidityProvider initializer

    Parameters

    Name
    Type
    Description

    accessControlManager_

    address

    AccessControlManager contract address

    tokens_

    address[]

    Array of addresses of the tokens

    distributionSpeeds_

    uint256[]

    New distribution speeds for tokens

    maxDistributionSpeeds_

    uint256[]

    ❌ Errors

    • Throw InvalidArguments on different length of tokens and speeds array


    initializeTokens

    Initialize the distribution of the token

    Parameters

    Name
    Type
    Description

    tokens_

    address[]

    Array of addresses of the tokens to be intialized

    ⛔️ Access Requirements

    • Only Governance


    pauseFundsTransfer

    Pause fund transfer of tokens to Prime contract

    ⛔️ Access Requirements

    • Controlled by ACM


    resumeFundsTransfer

    Resume fund transfer of tokens to Prime contract

    ⛔️ Access Requirements

    • Controlled by ACM


    setTokensDistributionSpeed

    Set distribution speed (amount of token distribute per block)

    Parameters

    Name
    Type
    Description

    tokens_

    address[]

    Array of addresses of the tokens

    distributionSpeeds_

    uint256[]

    New distribution speeds for tokens

    ⛔️ Access Requirements

    • Controlled by ACM

    ❌ Errors

    • Throw InvalidArguments on different length of tokens and speeds array


    setMaxTokensDistributionSpeed

    Set max distribution speed for token (amount of maximum token distribute per block)

    Parameters

    Name
    Type
    Description

    tokens_

    address[]

    Array of addresses of the tokens

    maxDistributionSpeeds_

    uint256[]

    New distribution speeds for tokens

    ⛔️ Access Requirements

    • Controlled by ACM

    ❌ Errors

    • Throw InvalidArguments on different length of tokens and speeds array


    setPrimeToken

    Set the prime token contract address

    Parameters

    Name
    Type
    Description

    prime_

    address

    The new address of the prime token contract

    📅 Events

    • Emits PrimeTokenUpdated event

    ⛔️ Access Requirements

    • Only owner


    setMaxLoopsLimit

    Set the limit for the loops can iterate to avoid the DOS

    Parameters

    Name
    Type
    Description

    loopsLimit

    uint256

    Limit for the max loops can execute at a time

    📅 Events

    • Emits MaxLoopsLimitUpdated event on success

    ⛔️ Access Requirements

    • Controlled by ACM


    releaseFunds

    Claim all the token accrued till last block

    Parameters

    Name
    Type
    Description

    token_

    address

    The token to release to the Prime contract

    📅 Events

    • Emits TokenTransferredToPrime event

    ❌ Errors

    • Throw InvalidArguments on Zero address(token)

    • Throw FundsTransferIsPaused is paused

    • Throw InvalidCaller if the sender is not the Prime contract


    sweepToken

    A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to user

    Parameters

    Name
    Type
    Description

    token_

    contract IERC20Upgradeable

    The address of the ERC-20 token to sweep

    to_

    address

    The address of the recipient

    amount_

    uint256

    The amount of tokens needs to transfer

    📅 Events

    • Emits SweepToken event

    ⛔️ Access Requirements

    • Only Governance

    ❌ Errors

    • Throw InsufficientBalance if amount_ is greater than the available balance of the token in the contract


    getEffectiveDistributionSpeed

    Get rewards per block for token

    Parameters

    Name
    Type
    Description

    token_

    address

    Address of the token

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    speed returns the per block reward


    accrueTokens

    Accrue token by updating the distribution state

    Parameters

    Name
    Type
    Description

    token_

    address

    Address of the token

    📅 Events

    • Emits TokensAccrued event


    getBlockNumber

    Get the latest block number

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    blockNumber returns the block number


    Token Converters

    Only available on BNB chain, Ethereum and Arbitrum

    The supports making conversions using flash swaps on Pancake Swap to fund the conversion.

    The shows how to interact with the converters and can be used as a base to build advanced conversion strategies.

    VenusERC4626

    VenusERC4626

    Overview

    VenusERC4626 is an upgradeable, ERC4626-compliant vault that wraps a Venus vToken, enabling standard ERC4626 vault interactions with the Venus Protocol. It manages deposits, withdrawals, minting, redeeming, and reward distribution, with additional access control and loop limit protections.

    uint256 DEFAULT_MAX_DISTRIBUTION_SPEED
    address prime
    mapping(address => uint256) tokenDistributionSpeeds
    mapping(address => uint256) maxTokenDistributionSpeeds
    mapping(address => uint256) lastAccruedBlock
    mapping(address => uint256) tokenAmountAccrued
    function initialize(address accessControlManager_, address[] tokens_, uint256[] distributionSpeeds_, uint256[] maxDistributionSpeeds_, uint256 loopsLimit_) external
    function initializeTokens(address[] tokens_) external
    function pauseFundsTransfer() external
    function resumeFundsTransfer() external
    function setTokensDistributionSpeed(address[] tokens_, uint256[] distributionSpeeds_) external
    function setMaxTokensDistributionSpeed(address[] tokens_, uint256[] maxDistributionSpeeds_) external
    function setPrimeToken(address prime_) external
    function setMaxLoopsLimit(uint256 loopsLimit) external
    function releaseFunds(address token_) external
    function sweepToken(contract IERC20Upgradeable token_, address to_, uint256 amount_) external
    function getEffectiveDistributionSpeed(address token_) external view returns (uint256)
    function accrueTokens(address token_) public
    function getBlockNumber() public view virtual returns (uint256)

    loopsLimit_

    uint256

    Maximum number of loops allowed in a single transaction

    Overview

    The Venus Protocol generates income in various underlying tokens from interest and liquidation fees, that are then sent to the ProtocolShareReserve contract. The ProtocolShareReserve contract disburses these earnings to number of destinations. The distributions to the converter contracts are listed next.

    BNB Chain

    Converter
    Accepts
    Interest Reserves (%)
    Liquidation Income (%)

    RiskFundConverter

    USDT

    20%

    20%

    XVSVaultConverter

    XVS

    20%

    20%

    USDTPrimeConverter

    USDT

    11%

    Ethereum Chain

    Converter
    Accepts
    Interest Reserves (%)
    Liquidation Income (%)

    RiskFundConverter

    USDT

    0%

    0%

    XVSVaultConverter

    XVS

    20%

    20%

    USDTPrimeConverter

    USDT

    1.2%

    Arbitrum One

    Converter
    Accepts
    Interest Reserves (%)
    Liquidation Income (%)

    XVSVaultConverter

    XVS

    20%

    20%

    USDTPrimeConverter

    USDT

    5%

    0%

    USDCPrimeConverter

    USDC

    5%

    XVSVaultConverter and every Prime converter are instances of SingleTokenConverter contract.

    RiskFundConverter and SingleTokenConverter convert incoming earnings into specific tokens, with RiskFundConverter converting them into RiskFund's convertible base asset and SingleTokenConverters converting them into their baseAsset. Each time a conversion is completed, the resulting tokens are sent to their respective destination addresses.

    The following diagram illustrates the flow of funds between contracts and its architecture:

    Integration of Token Converters in the Venus protocol
    • The transfer of funds to and from the ProtocolShareReserve contract are initiated by external agents (permissionless).

    • The transfers of funds from the Token Converters to their destinations are performed on each conversion. The conversions are performed by external agents (permissionless).

    • The transfer of XVS from the XVSVaultTreasury to the XVSVault will be performed via VIP.

    RiskFundConverter and SingleTokenConverters possess the ability to "facilitate" token conversions for the income they receive, obtaining the desired tokens (base asset) by relying on oracle prices as reference points to accept conversions that external agents will carry out.

    Venus encourages these conversions by providing incentives that create arbitrage opportunities in the market, with the expectation that external agents will seize these opportunities.

    The diagram below illustrates the connection between income harvesting (the process by which Venus transfers income to the ProtocolShareReserve), distribution (application of the protocol's Tokenomics-defined rules), and conversion (acquiring the required base assets).

    Relationship among the harvesting, distribution, and converting of income

    Token Converters Destinations

    • RiskFund already includes the integration with the Shortfall contract. The USDT received in the conversions will be auctioned off in the Shortfall contract.

    • XVSVaultTreasury accumulates the XVS received in the conversions. Those XVS will be sent to the XVSVault eventually via VIP, which will update also the APR in the XVSVault.

    • PrimeLiquidityProvider accumulates and distributes them according to the speeds configured via VIP.

    AbstractTokenConverter

    AbstractTokenConverter contract provides required features to configure and convert desired assets. The RiskFundConverter and the SingleTokenConverters extend this abstract contract (that could also be extended by other contracts in the future because it provides these features agnostically).

    Configuration of conversions

    There will be one configuration per pair tokenAddressIn / tokenAddressOut. Only authorized contracts (Governance) will be able to add or update these configurations. The configuration for a conversion includes:

    • tokenAddressIn and tokenAddressOut: address of the token accepted by the converter in the conversion, and the address of the token sent to the user/wallet from the converter in the conversion

    • incentive: percentage used to increase the amount finally sent to the user (see below).

    • conversionAccess:

      • NONE: Conversion is disabled for the pair

      • ALL: Conversion is enabled for private conversion and users

      • ONLY_FOR_CONVERTERS: Conversion is enabled only for private conversion (see more about private conversions below)

    For example, in the XVSVaultConverter there would be a configuration entry with these values:

    • tokenAdressIn: XVS token address (the converter accepts XVS)

    • tokenAddressOut: BTCB token address (the converter offers BTCB)

    • incentive: 0 (initially there won't be any incentive)

    • conversionAccess: ALL (everyone can perform conversions of XVS for BTCB in the XVSVaultConverter)

    Incentives

    To incentivize conversions we allow an increase in the final amount sent out from the converter contract.

    Example:

    • Given:

      • Conversion rate provided by the oracle: 1 XVS = 5 USDC

      • Incentive: 10%

    • If the user sends 1 XVS to the contract, they will receive 5.5 USDC (5 USDC base + 0.5 USDC applying the incentive).

    The incentive is applied on the base out amount calculated using the conversion rate, which is based on oracle prices. Incentives will be defined using normal VIP’s, following the Governance mechanism. Each pair of tokens can have a different incentive value. Bigger incentives can be set for converting tokens with lower liquidity, for example.

    Interaction with the Token Converter contracts

    Get Amount Out

    View function getAmountOut(uint256 amountInMantissa, address tokenAddressIn, address tokenAddressOut) returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa), to request the amount of tokenAddressOut tokens that a sender would receive providing amountInMantissa tokens of tokenAddressIn.

    Where:

    • Params:

      • amountInMantissa: the amount of tokenAddressIn tokens the sender would provide to perform the conversion. It is defined in terms of the mantissa of tokenAddressIn

      • tokenAddressIn: the address of the token provided by the sender to get tokens of tokenAddressOut

      • tokenAddressOut: the address of the token to get after the conversion

    • Returned values:

      • amountConvertedMantissa: the amount of tokenAddressIn that would ultimately be transferred from the sender to the contract. This will be the lesser of the converter's liquidity (available with balanceOf(address token)) or amountConvertedMantissa.

      • amountOutMantissa

    Internally, this function uses:

    • the oracle to calculate the conversion rate to apply

    • the configuration for the pair tokenAddressIn / tokenAddressOut, to apply the right discount

    There must be a ConversionConfig entry for the pair tokenAddressIn / tokenAddressOut. Otherwise, the transaction is reverted.

    The convert functions use this view to calculate how many tokens must be transferred.

    Example:

    • Given:

      • There is a configuration entry for the pair tokenAddressIn / tokenAddressOut: XVS/USDC. That means, the contract accepts conversions where the sender sends XVS to the contract, and the contract sends USDC to the sender. This would be a possible configuration in the XVSVaultConverter contract.

      • Current liquidity: 100 USDC

      • Current conversion rate, given by the oracle: 1 XVS = 5 USDC

      • Configured discount: 1%

    • Invocation 1: getAmountOut(15 * 10^18, address(XVS), address(USDC))

      • It means: how many USDC would the sender receive if they would provide 15 XVS to the contract

      • Response:

    • Invocation 2: getAmountOut(25 * 10^18, address(XVS), address(USDC))

      • How many USDC would the sender receive if they provided 25 XVS to the contract?

      • In this case, there isn’t enough liquidity to convert 100% of the input amount (25 XVS would be 126.25 USDC), so 100% of the liquidity will be the amountOutMantissa, and this function (getAmountOut) calculates the input amount needed to “cover” that amount (taking into account the discount).

    Get Amount In

    View function getAmountIn(uint256 amountOutMantissa, address tokenAddressIn, address tokenAddressOut) returns (uint256 amountInMantissa, uint256 amountConvertedMantissa), to request the amount of tokenAddressIn tokens that a sender should send to the contract, to receive amountOutMantissa tokens of tokenAddressOut.

    Where:

    • Parameters:

      • amountOutMantissa: the amount of tokenAddressOut tokens the sender would like to receive in the conversion. It is defined in terms of the mantissa of tokenAddressOut

      • tokenAddressIn: the address of the token provided by the sender to get tokens of tokenAddressOut

      • tokenAddressOut: the address of the token to get after the conversion

    • Returned values:

      • amountInMantissa: the amount of tokenAddressIn tokens that the sender has to send to the contract to receive amountConvertedMantissa tokens of tokenAddressOut

      • amountConvertedMantissa

    Example:

    • Invocation 1: getAmountIn(40 * 10^18, address(XVS), address(USDC))

      • Response:

        • amountInMantissa: $8 * 10^{18}$ (XVS)

        • amountConvertedMantissa: $40 * 10^{18}$ (USDC), equal to the amountOutMantissa param

    • Invocation 2: getAmountIn(120 * 10^18, address(XVS), address(USDC))

      • Response:

        • amountInMantissa: $20 * 10^{18}$ (XVS)

    Conversions Fixing the Amount In

    Function convertExactTokens(uint256 amountInMantissa, uint256 amountOutMinMantissa, address tokenAddressIn, address tokenAddressOut, address to).

    Where:

    • amountInMantissa: the number of tokens (tokensAddressIn) the sender wants to convert

      • It’s defined in the mantissa of the tokenAddressIn Example: -amountOutMinMantissa: the minimum amount of tokenAddressOut tokens the sender is willing to receive in the conversion. It’s defined in the mantissa of the tokenAddressOut.

      • If the amount that would finally be transferred to to is less than amountOutMinMantissa, the transaction is reverted

    • tokenAddressIn: the address of the token provided by the sender to perform the conversion. For instance, in the XVSVaultConverter and in the RiskFundConverter there will be configurations to accept XVS and USDT token addresses respectively

    • tokenAddressOut: the address of the token the sender wants to receive with the execution of the conversion

    • to: the address where the tokens of tokenAddressOut should be sent

    The received tokens (amountInMantissa) are transferred, in the same transaction, to the destination address. The destination address is configured as a storage attribute in the AbstractTokenConverter contract.

    If the received amount is less than amountInMantissa or the transferred out amount is less than the expected one, the transaction is reverted because we don’t support tokens with fees on transferring in this function.

    There must be a ConversionConfig entry for the pair tokenAddressIn / tokenAddressOut. Otherwise, the transaction will be reverted.

    What if there is not enough liquidity?

    • The contract will send to to 100% of the available liquidity, and it will only transfer from the sender the needed amount to cover the conversion (that will be less than the amountInMantissa) It must satisfy the constraint of sending more than amountOutMinMantissa

    • See the second invocation example in the section Get amount out

    Conversions Fixing the Amount Out

    Function convertForExactTokens(uint256 amountInMaxMantissa, uint256 amountOutMantissa, address tokenAddressIn, address tokenAddressOut, address to).

    Where:

    • amountInMaxMantissa: the maximum amount of tokenAddressIn tokens that the sender wants to convert. If the needed amount is greater than this param, the transaction is reverted

    • amountOutMantissa: the exact amount of tokenAddressOut tokens that the sender wants to receive in the conversion

    • tokenAddressIn: the address of the token that the sender is providing to complete the conversion

    • tokenAddressOut: the address of the token that the sender wants to receive in the conversion

    • to: the address where the tokens of tokenAddressOut should be sent

    The received tokens (amountInMantissa) are transferred, in the same transaction, to the destination address. The destination address is configured as a storage attribute in the AbstractTokenConverter contract.

    If the received or the transferred out amounts are less than the required amounts, the transaction is reverted, because we don’t support tokens with fees on transferring in this function.

    There must be a ConversionConfig entry for the pair tokenAddressIn / tokenAddressOut. Otherwise, the transaction will be reverted.

    This implementation of this function can use the getAmountIn function internally because the same liquidity check is needed. If the amountConvertedMantissa amount is less than the param amountOutMantissa, the transaction is reverted. This constraint is similar to checking that the liquidity of tokenAddressOut is less than amountOutMantissa.

    Private Conversion

    Private Conversions aims to maximize the conversion of tokens received from the ProtocolShareReserve contract (to any converter) among existing converters in the same ConverterNetwork contract. This is done to preserve incentives and reduce the dependency on users to perform conversions. Converters will autonomously carry out Private Conversions whenever funds are received from ProtocolShareReserve. No incentives will be provided during this process.

    The following diagram illustrates the flow of private conversion.

    Sequence diagram for private conversions

    RiskFundConverter

    The RiskFundConverter contract extends the AbtractTokenConverter contract. It maintains a distribution of assets per comptroller and assets. ProtocolShareReserve sends the RiskFund's share of income to this contract which will convert the assets and send them to the RiskFund contract.

    SingleTokenConverter

    The SingleTokenConverter contract extends the AbtractTokenConverter contract. ProtocolShareReserve distributes the income share among various SingleTokenConverter contracts, such as the USDTPrimeConverter contract. This particular contract facilitates the conversion of assets to its base asset and subsequently sends them to their designated destination address.

    Users can convert tokens through these contracts(RiskFundConverter and SingleTokenConverters) and receive the converted tokens along with an incentive. A conversion config for the tokenAddressIn / tokenAddressOut pair is necessary for a successful conversion; otherwise, the conversion will revert.

    XVSVaultTreasury

    One instance of XVSVaultTreasury is configured as the destination address in the XVSVaultConverter. This treasury is used to fund the XVSVault.

    ConverterNetwork

    This contract contains the list of all the converters and will provide valid converters which can perform conversions. Converters will interact with this contract to get the list of other converters open for Private Conversions.

    Venus CLI
    Token Converter Bot

    Solidity API

    State Variables

    • NO_ERROR (uint256, internal constant): Error code representing no errors in Venus operations.

    • vToken (VToken, public): The Venus vToken associated with this ERC4626 vault.

    • comptroller (IComptroller, public): The Venus Comptroller contract responsible for market operations.

    • rewardRecipient (address, public): The address that receives rewards distributed by the Venus Protocol.


    Events

    • ClaimRewards(uint256 amount, address indexed rewardToken) Emitted when rewards are claimed.

      • amount: The amount of reward tokens claimed.

      • rewardToken: The address of the reward token claimed.

    • RewardRecipientUpdated(address indexed oldRecipient, address indexed newRecipient) Emitted when the reward recipient address is updated.

      • oldRecipient: The previous reward recipient address.

      • newRecipient: The new reward recipient address.

    • SweepToken(address indexed token, address indexed receiver, uint256 amount) Emitted when tokens are swept from the contract.

      • token: The token address.

      • receiver: The receiver address.


    Errors

    • VenusERC4626__VenusError(uint256 errorCode) Thrown when a Venus protocol call returns an error.

      • errorCode: The error code returned by Venus.

    • ERC4626__DepositMoreThanMax() Thrown when a deposit exceeds the maximum allowed.

    • ERC4626__MintMoreThanMax() Thrown when a mint operation exceeds the maximum allowed.

    • ERC4626__WithdrawMoreThanMax() Thrown when a withdrawal exceeds the maximum available assets.

    • ERC4626__RedeemMoreThanMax() Thrown when a redemption exceeds the maximum redeemable shares.

    • ERC4626__ZeroAmount(string operation) Thrown when attempting an operation with a zero amount.

      • operation: The name of the operation (e.g., "deposit", "withdraw", "mint", "redeem").

    Constructor

    • @custom:oz-upgrades-unsafe-allow constructor Disables initializers for the upgradeable contract pattern.


    Functions

    initialize

    Initializes the VenusERC4626 vault with the associated vToken address.

    Parameters

    Name
    Type
    Description

    vToken_

    address

    The vToken associated with the vault, representing the yield-bearing asset.

    Notes

    • Only the vToken address is set in this function.

    • initialize2 must be called to complete the configuration.


    initialize2

    Completes the configuration of the VenusERC4626 vault by setting additional attributes.

    Parameters

    Name
    Type
    Description

    accessControlManager_

    address

    The address of the access control manager contract.

    rewardRecipient_

    address

    The initial recipient of rewards.

    loopsLimit_

    uint256

    The maximum number of loops for certain operations to enhance security.

    vaultOwner_

    address

    The address of the vault owner.

    Notes

    • Can only be called once.

    • Use with caution to avoid misconfiguration.


    setMaxLoopsLimit

    Sets the maximum number of loops for certain operations.

    Parameters

    Name
    Type
    Description

    loopsLimit

    uint256

    The new maximum loops limit to be set.

    Events

    • Emits MaxLoopsLimitUpdated on success.

    Access

    • Controlled by the Access Control Manager (ACM).


    setRewardRecipient

    Sets a new recipient for rewards distributed by the Venus Protocol.

    Parameters

    Name
    Type
    Description

    newRecipient

    address

    The address of the new reward recipient.

    Events

    • Emits RewardRecipientUpdated on success.

    Access

    • Controlled by the ACM.


    sweepToken

    Sweeps the specified token from the contract and sends it to the contract owner.

    Parameters

    Name
    Type
    Description

    token

    IERC20Upgradeable

    Address of the token.

    Events

    • Emits SweepToken on success.

    Access

    • Only the owner.


    claimRewards

    Claims rewards from all reward distributors associated with the vToken and transfers them to the reward recipient.

    Notes

    • Iterates through all reward distributors fetched from the comptroller, claims rewards, and transfers them if available.


    deposit

    Deposits assets into the vault, minting corresponding shares to the receiver.

    Parameters

    Name
    Type
    Description

    assets

    uint256

    The amount of assets to deposit.

    receiver

    address

    The address to receive shares.

    Returns

    Name
    Type
    Description

    shares

    uint256

    Amount of shares minted.

    Notes

    • Overrides ERC4626Upgradeable deposit.

    • Includes non-reentrant protection and custom Venus logic.


    mint

    Mints new shares of the vault, allocating the corresponding amount of assets to the receiver.

    Parameters

    Name
    Type
    Description

    shares

    uint256

    The amount of shares to mint.

    receiver

    address

    The address to receive shares.

    Returns

    Name
    Type
    Description

    assets

    uint256

    Amount of assets deposited.

    Notes

    • Overrides ERC4626Upgradeable mint.

    • Includes non-reentrant protection and custom Venus logic.


    withdraw

    Withdraws assets from the vault, burning the corresponding amount of shares from the owner's balance.

    Parameters

    Name
    Type
    Description

    assets

    uint256

    The amount of assets to withdraw.

    receiver

    address

    The address to receive assets.

    owner

    address

    The address whose shares are burned.

    Returns

    Name
    Type
    Description

    shares

    uint256

    Amount of shares burned.

    Notes

    • Overrides ERC4626Upgradeable withdraw.

    • Includes non-reentrant protection and custom Venus logic.


    redeem

    Redeems shares of the vault, returning the corresponding amount of assets to the receiver.

    Parameters

    Name
    Type
    Description

    shares

    uint256

    The amount of shares to redeem.

    receiver

    address

    The address to receive assets.

    owner

    address

    The address whose shares are redeemed.

    Returns

    Name
    Type
    Description

    assets

    uint256

    Amount of assets returned.

    Notes

    • Overrides ERC4626Upgradeable redeem.

    • Includes non-reentrant protection and custom Venus logic.


    totalAssets

    Returns the total amount of assets managed by the vault, including both deposited assets and accrued rewards.

    Returns

    Name
    Type
    Description

    assets

    uint256

    Total assets managed by the vault.

    Notes

    • Overrides ERC4626Upgradeable totalAssets.


    maxDeposit

    Returns the maximum deposit allowed, based on Venus supply caps.

    Parameters

    Name
    Type
    Description

    account

    address

    The address of the account.

    Returns

    Name
    Type
    Description

    amount

    uint256

    Maximum assets that can be deposited.

    Notes

    • Returns 0 if minting is paused or the supply cap has been reached.


    maxMint

    Returns the maximum amount of shares that can be minted.

    Parameters

    Name
    Type
    Description

    account

    address

    The address of the account.

    Returns

    Name
    Type
    Description

    shares

    uint256

    Maximum shares that can be minted.

    Notes

    • Derived from the maximum deposit amount converted to shares.


    maxWithdraw

    Returns the maximum amount of assets that can be withdrawn.

    Parameters

    Name
    Type
    Description

    receiver

    address

    The address of the account withdrawing.

    Returns

    Name
    Type
    Description

    amount

    uint256

    Maximum assets that can be withdrawn.

    Notes

    • This value is limited by the available cash in the vault.


    maxRedeem

    Returns the maximum amount of shares that can be redeemed.

    Parameters

    Name
    Type
    Description

    receiver

    address

    The address of the account redeeming.

    Returns

    Name
    Type
    Description

    shares

    uint256

    Maximum shares that can be redeemed.

    Notes

    • Limited by the available cash in the vault.

    VAIController

    VAI Comptroller

    This is the implementation contract for the VAIUnitroller proxy

    Solidity API

    INITIAL_VAI_MINT_INDEX

    Initial index used in interest computations


    CORE_POOL_ID

    poolId for core Pool


    mintVAI

    The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance. The amount minted must be less than the user's Account Liquidity and the mint vai limit.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    repayVAI

    The repay function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Before repaying VAI, users must first approve VAIController to access their VAI balance.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    repayVAIBehalf

    The repay on behalf function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower). Before repaying VAI, the payer must first approve VAIController to access their VAI balance.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    liquidateVAI

    The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setComptroller

    Sets a new comptroller

    Return Values

    Name
    Type
    Description

    setPrimeToken

    Set the prime token contract address

    Parameters

    Name
    Type
    Description

    setVAIToken

    Set the VAI token contract address

    Parameters

    Name
    Type
    Description

    toggleOnlyPrimeHolderMint

    Toggle mint only for prime holder

    Return Values

    Name
    Type
    Description

    getMintableVAI

    Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setTreasuryData

    Update treasury data

    Parameters

    Name
    Type
    Description

    getVAIRepayRate

    Gets yearly VAI interest rate based on the VAI price

    Return Values

    Name
    Type
    Description

    getVAIRepayRatePerBlock

    Get interest rate per block

    Return Values

    Name
    Type
    Description

    getVAIMinterInterestIndex

    Get the last updated interest index for a VAI Minter

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getVAIRepayAmount

    Get the current total VAI a user needs to repay

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getVAICalculateRepayAmount

    Calculate how much VAI the user needs to repay

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    accrueVAIInterest

    Accrue interest on outstanding minted VAI


    setAccessControl

    Sets the address of the access control of this contract

    Parameters

    Name
    Type
    Description

    setBaseRate

    Set VAI borrow base rate

    Parameters

    Name
    Type
    Description

    setFloatRate

    Set VAI borrow float rate

    Parameters

    Name
    Type
    Description

    setReceiver

    Set VAI stability fee receiver address

    Parameters

    Name
    Type
    Description

    setMintCap

    Set VAI mint cap

    Parameters

    Name
    Type
    Description

    getVAIAddress

    Return the address of the VAI token

    Return Values

    Name
    Type
    Description

    FlashLoan

    Overview

    Venus Protocol has natively integrated a sophisticated flash loan mechanism directly into its Core Pool, enabling users to borrow assets without collateral, provided the loan is repaid within the same transaction. This feature unlocks powerful DeFi strategies including arbitrage, self-liquidation, and portfolio rebalancing, while maintaining the protocol's security and capital efficiency.

    The system is designed for seamless integration with existing Venus markets, offering a trustless and composable foundation for advanced financial operations.

    function initialize(address vToken_) public initializer
    function initialize2(address accessControlManager_, address rewardRecipient_, uint256 loopsLimit_, address vaultOwner_) public
    function setMaxLoopsLimit(uint256 loopsLimit) external
    function setRewardRecipient(address newRecipient) external
    function sweepToken(IERC20Upgradeable token) external onlyOwner
    function claimRewards() external
    function deposit(uint256 assets, address receiver) public override nonReentrant returns (uint256)
    function mint(uint256 shares, address receiver) public override nonReentrant returns (uint256)
    function withdraw(uint256 assets, address receiver, address owner) public override nonReentrant returns (uint256)
    function redeem(uint256 shares, address receiver, address owner) public override nonReentrant returns (uint256)
    function totalAssets() public view virtual override returns (uint256)
    function maxDeposit(address account) public view virtual override returns (uint256)
    function maxMint(address account) public view virtual override returns (uint256)
    function maxWithdraw(address receiver) public view virtual override returns (uint256)
    function maxRedeem(address receiver) public view virtual override returns (uint256)

    amount: The amount swept.

    ONLY_FOR_USERS: Conversion is enabled only for users
    : the amount of
    tokenAddressOut
    tokens that the sender would receive in that transaction if they provide
    amountInMantissa
    tokens of
    tokenAddressIn
    . It is defined in terms of the mantissa of
    tokenAddressOut
    .
    amountConvertedMantissa: $ 15 * 10^{18} $ There is enough liquidity of USDC to use 100% of the provided amount
  • amountOutMantissa: $(15 * (5/1) * 10^{18}) * 1.01 = 75.75 * 10^{18}$. That is 75.75 USDC.

    Where:

    • 15 is the input amount

    • 1,01 is the application of the discount

    • 5/1 is the conversion rate given by the oracles

  • Response:

    • amountConvertedMantissa: $((100 / 1,01) / 5) * 10^{18}$ = 19.80$ Where:

      • 100 is the liquidity of USDC in the contract

      • 1,01 is the application of the discount

      • 5 is the conversion rate given by the oracles

      • 19.80 is the amount of XVS needed to review the available liquidity

    • amountOutMantissa: 100 * 10^18. That is 100 USDC

    : the amount of
    tokenAddressOut
    tokens that would ultimately be transferred from the contract to the sender if the user sends
    amountInMantissa
    tokens of
    tokenAddressIn
    to the contract. This will be the lesser of the available liquidity or the requested amount to receive.
    amountConvertedMantissa: $100 * 10^{18}$ (USDC), different from the amountOutMantissa param because there is not enough liquidity

    0%

    USDCPrimeConverter

    USDC

    6%

    0%

    BTCBPrimeConverter

    BTCB

    1%

    0%

    ETHPrimeConverter

    ETH

    2%

    0%

    WBNBBurnConverter

    WBNB

    25%

    25%

    0%

    USDCPrimeConverter

    USDC

    1.2%

    0%

    WBTCPrimeConverter

    WBTC

    0.6%

    0%

    WETHPrimeConverter

    WETH

    17.0%

    0%

    0%

    WBTCPrimeConverter

    WBTC

    3%

    0%

    WETHPrimeConverter

    WETH

    7%

    0%

    the Prime funds
    Integration of Token Converters in the Venus Protocol
    Diagram showing the relationship among the harvesting, distribution, and converting of income
    Sequence diagram for private conversions

    mintVAIAmount

    uint256

    The amount of the VAI to be minted.

    [0]

    uint256

    0 on success, otherwise an error code

    amount

    uint256

    The amount of VAI to be repaid.

    [0]

    uint256

    Error code (0=success, otherwise a failure, see ErrorReporter.sol)

    [1]

    uint256

    Actual repayment amount

    borrower

    address

    The account to repay the debt for.

    amount

    uint256

    The amount of VAI to be repaid.

    [0]

    uint256

    Error code (0=success, otherwise a failure, see ErrorReporter.sol)

    [1]

    uint256

    Actual repayment amount

    borrower

    address

    The borrower of vai to be liquidated

    repayAmount

    uint256

    The amount of the underlying borrowed asset to repay

    vTokenCollateral

    contract VTokenInterface

    The market in which to seize collateral from the borrower

    [0]

    uint256

    Error code (0=success, otherwise a failure, see ErrorReporter.sol)

    [1]

    uint256

    Actual repayment amount

    [0]

    uint256

    uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)

    prime_

    address

    The new address of the prime token contract

    vai_

    address

    The new address of the VAI token contract

    [0]

    uint256

    uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)

    minter

    address

    The account to check mintable VAI

    [0]

    uint256

    Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)

    [1]

    uint256

    Mintable amount (with 18 decimals)

    newTreasuryGuardian

    address

    New Treasury Guardian address

    newTreasuryAddress

    address

    New Treasury Address

    newTreasuryPercent

    uint256

    New fee percentage for minting VAI that is sent to the treasury

    [0]

    uint256

    uint256 Yearly VAI interest rate

    [0]

    uint256

    uint256 Interest rate per bock

    minter

    address

    Address of VAI minter

    [0]

    uint256

    uint256 Returns the interest rate index for a minter

    account

    address

    The address of the VAI borrower

    [0]

    uint256

    (uint256) The total amount of VAI the user needs to repay

    borrower

    address

    The address of the VAI borrower

    repayAmount

    uint256

    The amount of VAI being returned

    [0]

    uint256

    Amount of VAI to be burned

    [1]

    uint256

    Amount of VAI the user needs to pay in current interest

    [2]

    uint256

    Amount of VAI the user needs to pay in past interest

    newAccessControlAddress

    address

    New address for the access control

    newBaseRateMantissa

    uint256

    the base rate multiplied by 10**18

    newFloatRateMantissa

    uint256

    the VAI float rate multiplied by 10**18

    newReceiver

    address

    the address of the VAI fee receiver

    _mintCap

    uint256

    the amount of VAI that can be minted

    [0]

    address

    The address of VAI

    Key Features and Technical Architecture
    • Multi-Asset Support – Borrow single or multiple assets in a single atomic transaction, enabling complex strategies across different markets without intermediate steps.

    • Adaptive Repayment Logic:

      • Instant Full Repayment: Repay the full principal plus flashLoan fees to complete the transaction (standard flash loan model).

      • Partial Repayment Conversion: If a user has existing supplied collateral and repays partially, the outstanding balance automatically converts to a traditional borrow position secured by their collateral, preventing liquidation and failed transactions.

    • Streamlined Fee Mechanism:

      • A single configurable flashLoanFeeMantissa determines the total cost of the loan.

      • The protocol's share (flashLoanProtocolShare) is automatically calculated and routed to the Protocol Share Reserve, ensuring proper incentive alignment for the ecosystem.

    • Robust Security Model:

      • Governance Controlled: Critical parameters (fee structure, activation) are managed through Venus's governance system.

      • Upgradeable Design: Built using modular architecture for future improvements and maintenance.

      • Non-Custodial: Funds never leave the protocol's control during the transaction, eliminating counterparty risk.

    This architecture positions Venus as a capital-efficient platform for both simple flash loans and sophisticated multi-step strategies, all while maintaining the protocol's security guarantees and economic sustainability.


    Understanding Flash Loans

    A flash loan is an uncollateralized loan that must be initiated and repaid within the boundaries of a single atomic transaction. This atomicity is enforced by the blockchain itself; if the borrowed amount plus fees is not returned to the protocol by the end of the transaction, the entire operation reverts as if it never happened. This mechanism eliminates credit risk for the protocol while granting users unprecedented capital efficiency.

    The Venus Innovation: Flexible Repayment & Debt Conversion

    Venus Protocol significantly enhances the basic flash loan model by introducing a partial repayment system, adding a crucial layer of flexibility and user safety.

    1. Instant Full Repayment (Classic Model): The borrower repays the entire principal plus the accrued fee within the transaction. This is the standard flash loan model used for strategies like arbitrage and liquidation, where the profit is guaranteed to cover the cost.

    2. Partial Repayment & Automatic Debt Conversion (Venus Model): This is a unique fail-safe mechanism. The user must repay at least the flash loan fee; otherwise, the transaction will revert. However, if a borrower repays the fee but cannot fully repay the principal and has existing supplied collateral on Venus, the protocol does not force a full revert. Instead, the unpaid principal shortfall is automatically converted into a standard borrow position against the user's existing collateral. This prevents immediate liquidation from a failed flash loan and allows for more complex, multi-block strategy planning. Crucially, for users with no collateral, full repayment of both principal and fee remains mandatory. Any shortfall will cause the transaction to revert, protecting the protocol from unsecured debt.

    Example: A Practical Use Case

    Let's imagine a user, Alice, who has supplied 10 ETH as collateral on Venus.

    1. Objective: Alice uses a flash loan to perform a complex arbitrage trade that she expects will take several transactions to complete.

    2. Action: She takes a flash loan of 100,000 USDC.

    3. Outcome A (Success): Her arbitrage is successful within the single transaction. She repays the 100,000 USDC plus a 0.09% fee (90 USDC). The transaction completes, and she keeps her profit.

    4. Outcome B (Partial Success - Venus's Advantage):

      • Her strategy only partially works. By the end of the transaction, she has only generated 80,000 USDC, leaving a shortfall of 20,000 USDC plus the fee.

      • On another protocol, her transaction would revert, she'd lose her gas fees, and potentially miss her profit opportunity.

      • On Venus, because she has 10 ETH as collateral and she has repaid the flashLoan fee amount, the protocol does not revert. Instead, it automatically converts the 20,000 USDC shortfall into a standard borrow position against her 10 ETH. Her flash loan is settled, and she now has a regular debt to manage over time, potentially still allowing her to profit from the 80,000 USDC she successfully generated.

    5. Outcome C (Failure):

      • Her strategy fails completely. She is only able to repay 50 USDC of the 90 USDC fee, leaving both a fee shortfall and the full principal unpaid.

      • In this scenario, the transaction will revert. The protocol's safety mechanism triggers because the user must repay at least the full flash loan fee, regardless of their collateral position. This protects the protocol from accumulating bad debt.

    This innovative approach makes Venus flash loans both more powerful and more accessible, enabling a wider range of financial strategies while maintaining robust protocol security.


    Core Smart Contracts

    1. FlashLoanFacet.sol – FlashLoan Execution & Validation

    Handles core flash loan operations including:

    • Asset transfers

    • Fee calculations

    • Repayment logic

    • Event emissions

    Key Function

    Explanation: This function serves as the main entry point for initiating both single or multi-asset flash loans. It orchestrates the complete flash loan lifecycle through a phased approach: validating request parameters, transferring multiple assets, executing the user's custom logic via a callback, and enforcing repayment with fee distribution. The entire operation is atomic; if any condition fails (e.g., insufficient repayment or unauthorized access), the transaction reverts, ensuring protocol safety.

    Step-by-Step Workflow:

    1. Validation & Initial Checks

    • Array Integrity: Ensures the vTokens and underlyingAmounts arrays are non-empty and of identical length to prevent parameter mismatches.

    • Asset Checks: For each vToken, verifies that:

      • The vToken is listed.

      • Flash loans are enabled for the asset (isFlashLoanEnabled()).

      • The requested loan amount is non-zero.

    • Authorization:

      • Initiator Authorization: Validates that the initiating contract (msg.sender) is pre-authorized (authorizedFlashLoan[msg.sender]) by the protocol to execute flash loans. This ensures only whitelisted, secure contracts can perform these operations.

      • Delegate Authorization: If the flash loan is executed on behalf of another user (onBehalf), it additionally validates that the initiator is an approved delegate (approvedDelegates[onBehalf][msg.sender]) for that specific user. This enables delegated trading strategies while maintaining security.

    • Address Validation: Ensures the receiver contract is a non-zero address.

    2. Phased Execution

    The core logic is delegated to an internal function that structures the process into three distinct phases:

    Phase 1: Pre-Transfer Setup & Asset Disbursement

    • Fee Calculation: Computes the total fee and protocol fee for each asset using the vToken's fee parameters.

    • Asset Transfer: Calls transferOutUnderlying on each vToken contract to disburse the underlying assets to the receiver contract.

    • Balance Snapshot: Records the cash balance of each vToken market after transfer for subsequent repayment verification.

    Phase 2: User Logic Execution

    • Callback Invocation: Calls executeOperation on the receiver contract, passing the loan details (assets, amounts, fees, initiator, onBehalf) and the param data. This is where the user's custom strategy (e.g., arbitrage, liquidation) is executed.

    • Approval Tracking: Returns an array (tokensApproved) indicating whether the receiver approved each asset for repayment transfer.

    Phase 3: Repayment Handling & Settlement

    • Repayment Processing: For each asset, handles repayment based on the receiver's approval and the amount transferred back:

      • Full Repayment: If the receiver approved and transferred the full amount (principal + fees), the loan is settled.

      • Debt Conversion: If the receiver did not approve or only partially repaid(atleast the fees), the shortfall is converted into a standard borrow position for the onBehalf (requires existing collateral).

    • Fee Distribution: Routes the protocol's share of fees to the Protocol Share Reserve (PSR) and credits supplier fees to the respective vToken markets.

    • Balance Verification: Ensures the final vToken balances reflect the correct repayment amounts, reverting if discrepancies are detected.

    3. Event Emission

    • Upon successful completion, a FlashLoanExecuted event is emitted, logging the receiver address, the vTokens involved, and the amounts loaned.

    Critical Security Features:

    • Non-Reentrancy: The function and its internal phases are protected against reentrancy attacks (implied by nonReentrant modifier or equivalent checks).

    • Atomicity: The entire operation succeeds or reverts entirely, preventing partial state changes.

    • Authorization Enforcement: Strict access control ensures only whitelisted initiators can trigger flash loans.

    • Collateral Checks: For debt conversion, the initiator must have sufficient collateral to cover the converted borrow position; otherwise, the transaction reverts.


    2. SetterFacet.sol - Setter Functions For Flashloan

    This file contains administrative functions to manage flash loan permissions.

    Functions

    setWhiteListFlashLoanAccount

    Explanation: This function is a central access control mechanism. In its initial phase, flash loans might be permissioned to prevent unknown or potentially malicious contracts from using the system until it's battle-tested. This function allows the admin or governance approved address to explicitly grant or revoke permission for a specific address (account) to call the executeFlashLoan function.

    • Whitelisting (_isWhiteListed = true) : Adds the account to a mapping of allowed addresses. This account can now initiate flash loans for itself.

    • Blacklisting/Removing (_isWhiteListed = false) : Removes the account from the whitelist, revoking its permission to initiate flash loans.

    This is a temporary measure often used during a phased rollout before opening the system to permissionless access.


    3. VToken.sol – Asset Transfer & Fee Calculation

    Manages the underlying asset transfers, flash loan fee calculations, and creation of debt positions.

    Key Functions

    1.transferOutUnderlyingFlashLoan

    Explanation: This function is the work horse for moving assets during flash loan operations. When FlashLoanFacet.sol calls this during a flash loan, it performs several critical actions:

    1. Authorization Check: Ensures only the Comptroller contract can call this function.

    2. Flash Loan State Management: Sets the flashLoanAmount to track the active flashloan and prevents concurrent flash loans.

    3. Asset Transfer: Performs the low-level transfer of the underlying asset to the receiver address.

    4. Event Emission: Emits TransferOutUnderlyingFlashLoan event for tracking.


    2. calculateFlashLoanFee

    Explanation: This function computes the cost of a flash loan by calculating the total fee and the protocol's share. It uses fixed-point arithmetic to ensure precision in fee calculations, which is critical for maintaining protocol economics and ensuring accurate revenue distribution between suppliers and the protocol.

    1. Total Fee Calculation : Multiplies the loan amount by the global flashLoanFeeMantissa (a scaled value, e.g., 0.09% represented as 9e14).

    2. Protocol Fee Allocation : Calculates the protocol's portion by multiplying the totalFee by flashLoanProtocolShare (a scaled value representing the protocol's percentage share).


    3. transferInUnderlyingFlashLoan

    Explanation: This function handles the repayment phase of flash loans with enhanced parameter validation. When called by the Comptroller, it performs several critical operations:

    1. Authorization Check: Ensures only the Comptroller contract can call this function.

    2. Asset Collection: Transfers the repayment amount from the receiver contract to the vToken.

    3. Repayment Validation: Validates that the actual transferred amount meets the minimum fee requirement.

    4. Protocol Fee Distribution: Automatically transfers the protocol fee portion to the Protocol Share Reserve.

    5. State Management: Resets the flashLoanAmount to 0, completing the flash loan cycle.

    6. Event Emission: Emits TransferInUnderlyingFlashLoan event with detailed repayment information.


    3. setFlashLoanEnabled

    Explanation: An administrative function that allows governance to explicitly enable or disable flash loan functionality for a specific vToken market. Unlike a toggle function, this takes a boolean parameter to set the exact desired state, preventing accidental state changes. This would be used to disable flash loans if a vulnerability is suspected in a particular asset's market or to enable them after security verification.


    4. setFlashLoanFeeMantissa

    Explanation: This governance-controlled function updates the core economic parameters for flash loans. It allows the protocol to adjust both the total fee charged for flash loans and how that fee is distributed between the protocol treasury and liquidity suppliers. These parameters directly impact the protocol's revenue generation and the attractiveness of providing liquidity.

    1. flashLoanFeeMantissa_ : This is the total fee rate charged for flash loans (scaled by 1e18).

    2. flashLoanProtocolShare_ : This is the percentage of the total fee allocated to the Protocol Share Reserve (scaled by 1e18).


    5. getCash

    Explanation: This function provides cash balance reporting with modified behavior during active flash loan operations. During normal operations, it returns the actual underlying token balance held by the vToken contract. However, during active flash loans (flashLoanAmount > 0), it returns the reduced cash balance reflecting funds temporarily transferred out.

    The protocol now internally uses _getCashPriorWithFlashLoan() which returns getCashPrior() + flashLoanAmount to calculate total available liquidity including active flash loans. This design ensures accurate accounting while maintaining protocol stability through consistent interest rate and exchange rate calculations.


    4. Flash Loan Receiver Standards

    There is a standardized interface for contracts wishing to receive and handle flash loans from Venus Protocol:

    1. IFlashLoanReceiver - Multi-Asset Standard

    Purpose: For complex strategies requiring multiple assets in a single flash loan operation.

    Interface: IFlashLoanReceiver

    Key Parameters:

    • vTokens: Array of VToken addresses borrowed

    • amounts: Corresponding amounts for each asset

    • premiums: Fee amounts for each asset

    • initiator: Address that initiated the flash loan

    • onBehalf: Address whose debt position will be used for any unpaid balance

    • param: Custom encoded data for strategy execution

    Return Value:

    • success: Success status (must return true for transaction to complete)

    • repayAmounts: Array of actual repayment amounts for each asset

    Base Contract: FlashLoanReceiverBase

    • Provides immutable Comptroller reference

    • Inherited by multi-asset receiver contracts

    • Ensures protocol governance integration

    Use Cases: Cross-protocol arbitrage, multi-asset liquidations, complex portfolio rebalancing.

    Core Requirements for the Standard

    Receiver Contracts Must:

    1. Receive Assets: Acknowledge and handle the received flash-loaned assets.

    2. Execute Strategy: Perform intended operations (arbitrage, liquidation, etc.)

    3. Ensure Repayment: Ensure sufficient funds are available and approved for repayment:

      • Must approve at least the fee amount to each vToken contract

      • Return actual repayment amounts in the repayAmounts array

      • For partial repayment: unpaid balance becomes debt against onBehalf address

    4. Return Success: Return true to signal successful operation.

    5. Handle Reversion: If operation fails, return false or revert to unwind the entire transaction.

    Critical Security Note: The entire flash loan transaction is atomic. If executeOperation returns false or reverts, the entire transaction reverts, ensuring protocol safety while allowing complex strategies to fail gracefully.


    Key Events

    • TransferOutUnderlyingFlashLoan - Emitted on successful transfer of amount to receiver during flash loan initiation.

    • TransferInUnderlyingFlashLoan - Emitted on successful transfer of repayment amount from receiver to vToken.

    • FlashLoanExecuted – Emitted after a flash loan is executed successfully.

    • FlashLoanStatusChanged – Emitted when flash loan status is changed for a market.

    • IsAccountFlashLoanWhitelisted – Emitted when trying to set whitelist flashloan account.


    Key Errors

    • FlashLoanNotEnabled - Thrown if flash loan is not enabled for the asset.

    • InvalidAmount - Thrown when the requested flash loan amount is zero.

    • SenderNotAuthorizedForFlashLoan - Thrown when the sender is not authorized to use flash loan.

    • NoAssetsRequested - Thrown if no assets are requested for the flash loan.

    • InvalidFlashLoanParams - Thrown if the flash loan params are invalid.

    • ExecuteFlashLoanFailed - Thrown when executeOperation on the receiver contract fails.

    • NotEnoughRepayment - Thrown if the repayment amount is less than the required total fee.

    • FailedToCreateDebtPosition - Thrown when failing to create a debt position.

    • InvalidComptroller - Thrown if the caller is not the Comptroller contract.

    • FlashLoanAlreadyActive - Thrown if a flash loan is already in progress.

    • NotAnApprovedDelegate - Thrown when the sender is not an approved delegate for the onBehalf address.

    • MarketNotListed - Thrown when trying to flash loan from a market that is not listed in the core pool.

    • InsufficientRepayment - Thrown when the actual transferred amount is less than the required total fee.


    Example FlashLoan Flow: Alice's Arbitrage

    User: Alice (has 10 ETH collateral on Venus)

    Goal: Arbitrage 100,000 USDC between DEXs

    1. Full Repayment (Successful Trade)

    1. Request: Alice's ArbitrageContract calls executeFlashLoan() requesting 100000 USDC.

    2. Transfer: Venus sends 100,000 USDC to Alice's contract + calculates fee (e.g., 90 USDC)

    3. Execution:

      • Venus calls executeOperation() on Alice's contract

      • Contract performs arbitrage (buy low, sell high)

      • Profits 100,200 USDC

      • Approves full repayment of 100,090 USDC

    4. Repayment: Venus pulls the approved 100,090 USDC

    5. Result: Alice keeps 110 USDC profit. Transaction completes.

    2. Partial Repayment (Failed Trade → Debt Conversion)

    1. Request: Alice's ArbitrageContract calls executeFlashLoan() requesting 100000 USDC.

    2. Transfer: Venus sends 100,000 USDC + calculates fee (90 USDC)

    3. Execution:

      • Arbitrage fails due to slippage → only gets 99,500 USDC

      • Approves partial repayment of 99,500 USDC

    4. Debt Conversion:

      • Venus pulls 99,500 USDC

      • Shortfall detected: 590 USDC (100,090 required - 99,500 paid)

      • Converts shortfall into a borrow position against Alice's 10 ETH collateral

    5. Result: Transaction does not revert. Alice now owes 590 USDC to Venus.

    3. Fee Not Paid (Critical Failure → Transaction Reverts)

    1. Request: Alice's ArbitrageContract calls executeFlashLoan() requesting 100,000 USDC.

    2. Transfer: Venus sends 100,000 USDC + calculates fee (90 USDC)

    3. Execution:

      • Arbitrage fails completely → only gets 50 USDC

      • Approves insufficient amount of 50 USDC (less than the 90 USDC fee)

    4. Validation Failure:

      • Venus attempts to pull funds but detects fee shortfall

      • Protocol requires at minimum the full flash loan fee to be repaid 5 Result: Transaction reverts completely. No debt conversion occurs. Alice loses gas fees but protocol remains secure.

    Key Mechanism

    • Full Repayment: Strategy must profit enough to cover principal + fees.

    • Partial Repayment: Unique Venus feature. Requires existing collateral and atleast fees repayment.

    • Fee Not Paid: Transaction always reverts - critical safety mechanism.

    • No Collateral? Full repayment mandatory; otherwise transaction reverts.

    • Auto-Conversion: Shortfall automatically becomes secured debt, preventing liquidation.


    Conclusion

    Venus Protocol’s flash loan implementation provides a secure, composable, and flexible foundation for advanced DeFi strategies. It enables atomic transactions, multi-asset borrowing, and deep composability with Venus and other DeFi protocols.

    uint256 INITIAL_VAI_MINT_INDEX
    uint96 CORE_POOL_ID
    function mintVAI(uint256 mintVAIAmount) external returns (uint256)
    function repayVAI(uint256 amount) external returns (uint256, uint256)
    function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256)
    function liquidateVAI(address borrower, uint256 repayAmount, contract VTokenInterface vTokenCollateral) external returns (uint256, uint256)
    function _setComptroller(contract ComptrollerInterface comptroller_) external returns (uint256)
    function setPrimeToken(address prime_) external
    function setVAIToken(address vai_) external
    function toggleOnlyPrimeHolderMint() external returns (uint256)
    struct AccountAmountLocalVars {
      uint256 oErr;
      enum CarefulMath.MathError mErr;
      uint256 sumSupply;
      uint256 marketSupply;
      uint256 sumBorrowPlusEffects;
      uint256 vTokenBalance;
      uint256 borrowBalance;
      uint256 exchangeRateMantissa;
      uint256 oraclePriceMantissa;
      struct ExponentialNoError.Exp exchangeRate;
      struct ExponentialNoError.Exp oraclePrice;
      struct ExponentialNoError.Exp tokensToDenom;
    }
    function getMintableVAI(address minter) public view returns (uint256, uint256)
    function _setTreasuryData(address newTreasuryGuardian, address newTreasuryAddress, uint256 newTreasuryPercent) external returns (uint256)
    function getVAIRepayRate() public view returns (uint256)
    function getVAIRepayRatePerBlock() public view returns (uint256)
    function getVAIMinterInterestIndex(address minter) public view returns (uint256)
    function getVAIRepayAmount(address account) public view returns (uint256)
    function getVAICalculateRepayAmount(address borrower, uint256 repayAmount) public view returns (uint256, uint256, uint256)
    function accrueVAIInterest() public
    function setAccessControl(address newAccessControlAddress) external
    function setBaseRate(uint256 newBaseRateMantissa) external
    function setFloatRate(uint256 newFloatRateMantissa) external
    function setReceiver(address newReceiver) external
    function setMintCap(uint256 _mintCap) external
    function getVAIAddress() public view virtual returns (address)
    function executeFlashLoan(
        address payable onBehalf,
        address payable receiver,
        VToken[] memory vTokens,
        uint256[] memory underlyingAmounts,
        bytes memory param
    ) external nonReentrant {
        // Validation, asset transfer, fee calculation, repayment logic...
    }
    function setWhiteListFlashLoanAccount(address account, bool _isWhiteListed) external;
    function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant;
    function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256);
    function transferInUnderlyingFlashLoan(
        address payable from,
        uint256 repaymentAmount,
        uint256 totalFee,
        uint256 protocolFee
    ) external nonReentrant returns (uint256);
    function setFlashLoanEnabled(bool enabled) external returns (uint256);
    function setFlashLoanFeeMantissa(
        uint256 flashLoanFeeMantissa_,
        uint256 flashLoanProtocolShare_
    ) external returns (uint256);
    function getCash() external view override returns (uint);
        function executeOperation(
            VToken[] calldata vTokens,
            uint256[] calldata amounts,
            uint256[] calldata premiums,
            address initiator,
            address onBehalf,
            bytes calldata param
        ) external returns (bool success, uint256[] memory repayAmounts);

    Omnichain Governance

    System Overview

    Omnichain Governance is designed to facilitate the execution of VIP across multiple blockchain networks, integrating with the Access Control Manager (ACM) and LayerZero communication protocol. It extends the governance model proposed by LayerZero.

    Key features

    1. VIP Types and Delays:

      • Provides three VIP options: Normal, Fast-track, and Critical.

      • Delays can be configured prior to remote execution on destination networks.

      • Normal VIPs have the greatest delays, whereas Critical VIPs have the smallest delays, indicating their urgency and importance.

    Detailed breakdown

    1. Proposing and Voting:

      • Proposers send VIPs with BNB Chain commands and remote commands.

      • Voting takes place on the BNB Chain utilizing existing governance contracts.

      • Proposals are validated and approved according to predetermined criteria and threshold.

    Detailed overview of remote proposal execution (step-by-step)

    1. Proposing a remote VIP on BNB Chain

    • A proposer submits a VIP through the existing governance mechanism on the BNB Chain.

    • The must VIP include a command invoking the OmnichainProposalSender::execute function which will send the remote VIP payload.

    • The execute function takes four arguments:

    1. Eligibility checks and limits

    Before sending the remote execution message, the system verifies eligibility based on predefined thresholds and limits. These restrictions ensure responsible resource allocation and prevent potential misuse.

    1. Remote proposal ID generation

    It's crucial to understand that the proposal ID for the remote execution on the destination network differs from the initial VIP ID proposed on the BNB Chain. This remote proposal ID starts from 1.

    1. Message relay based on outcome

    • Success: If the eligibility checks and limits are met, the encoded message (payload) is relayed across chains using the LayerZero bridge.

    • Failure: If the checks fail, the system handles the situation differently based on the cause:

      • Insufficient Gas: The retryExecute function is used to attempt redelivering the message with potentially adjusted gas fees.

    1. Receiving and Queuing on the Destination Network

    • Upon successful reception by the destination network's executor contract (OmnichainGovernanceExecutor), the remote proposal enters a "Queued" state.

    • This queuing process applies additional eligibility checks specific to the receiving network, ensuring compliance with its governance rules and thresholds of commands limits.

    1. Delay mechanism and execution

    • Once the configured delay for the remote proposal type (Normal, Fast-track, Critical) elapses, the proposal becomes eligible for execution.

    • Any user can then trigger the execution of the queued commands on the destination network.

    1. Ownership and Access Control

    • OmnichainProposalSender (BNB Chain):

      • Owned by: NormalTimelock contract on the BNB Chain.

      • Authorized callers: Timelocks (Normal, Critical, Fast-track) are authorized to call the execute function on this contract.

    Potential Failures and Retry Options

    • If a VIP fails to send the proposal from source chain (BNB Chain) to destination network, the message will be saved and can be retried with the retryExecute function. This mechanism allows for the redelivery of the message with potentially adjusted gas fees to ensure successful execution.

    • In case where the VIP fails to send the proposal from source chain (BNB Chain) to destination network due to non-retryable conditions and funds are stuck in the OmnichainProposalSender contract, funds can be withdrawn by invoking the fallbackWithdraw function. This ensures that funds are not permanently locked in the contract due to failed execution attempts.

    Contracts overview

    Contract 1: BaseOmnichainControllerSrc

    Functionality

    This contract serves as the framework for secure omnichain (cross-chain) communication. Its primary responsibilities include managing daily command limits and enabling pausing of controlled message transmission across chains.

    Key features

    1. Access Control Integration: Integrates an AccessControlManager contract to enforce access control for critical functions. This ensures that only authorised entities can execute commands, enhancing security.

    2. Daily Command Limits: Establishes a per-chain limit on the number of commands that can be sent within a 24-hour window. This feature prevents potential abuse and maintains system stability.

    3. Pausable: Implements a pausing mechanism, inherited from the OpenZeppelin Pausable contract. This functionality allows the contract owner to temporarily halt omnichain communication if necessary.

    Architecture

    • Inheritance: Extends the functionalities of the Ownable and Pausable contracts from OpenZeppelin, inheriting ownership management and pausing capabilities.

    State variables

    • accessControlManager (address): Stores the address of the AccessControlManager contract.

    • chainIdToMaxDailyLimit (mapping): Maps chain IDs to their corresponding daily command limits.

    • chainIdToLast24HourCommandsSent (mapping): Tracks the number of commands sent within the last 24 hours for each chain.

    Events

    • SetMaxDailyLimit (event): Emitted when the daily command limit for a chain is modified.

    • NewAccessControlManager (event): Triggered when the address of the AccessControlManager is updated.

    Functions

    • constructor(address accessControlManager_): Initializes the contract with the address of the AccessControlManager.

    • setMaxDailyLimit(uint16 chainId_, uint256 limit_): Sets the maximum daily command limit for a specific chain ID. Requires permission from the AccessControlManager.

    Contract 2: OmnichainProposalSender

    Functionality

    This contract facilitates cross-chain message transmission triggered by governor proposals on the main (BNB) chain. It sends proposal execution data to designated remote chains for processing.

    Key features

    • LayerZero Integration: Utilises the LayerZero communication protocol for efficient and reliable cross-chain message delivery.

    • Remote Chain Management: Allows defining trusted remote contracts (receivers) on other chains using setTrustedRemoteAddress.

    • Failed Message Handling: Stores the execution hashes of failed messages to facilitate resending or clearing them in case of insufficient fees or other issues.

    Architecture

    • Inheritance: Inherits functionalities from both the ReentrancyGuard and BaseOmnichainControllerSrc contracts, providing reentrancy protection and foundational omnichain communication capabilities.

    State variables

    • proposalCount (uint256): Tracks the total number of remote proposals.

    • storedExecutionHashes (mapping): Stores the execution hashes of failed messages for retry or clearing purposes.

    • LZ_ENDPOINT (ILayerZeroEndpoint): Interface for interacting with the LayerZero communication protocol.

    Events

    • SetTrustedRemoteAddress (event): Triggered when a trusted remote address is set for a remote chain.

    • TrustedRemoteRemoved (event): Emitted when a trusted remote address is removed from storage.

    • ExecuteRemoteProposal (event): Indicates the execution of a proposal on a remote chain.

    Functions

    • constructor(ILayerZeroEndpoint lzEndpoint_, address accessControlManager_): Initializes the contract with the LayerZero endpoint and the address of the AccessControlManager.

    • estimateFees(uint16 remoteChainId_, bytes calldata payload_, bytes calldata adapterParams_) : Estimates LayerZero fees for cross-chain message delivery based on payload and adapter parameters.

    Contract 3: BaseOmnichainControllerDest

    Functionality

    This contract serves as the base for the Omnichain controller destination contract. It provides functionality related to daily command limits and pausing.

    State variables

    • maxDailyReceiveLimit (uint256): Maximum daily limit for receiving commands from BNB Chain.

    • last24HourCommandsReceived (uint256): Total received commands within the last 24-hour window from BNB Chain.

    • last24HourReceiveWindowStart (uint256): Timestamp when the last 24-hour window started from BNB Chain.

    Events

    • SetMaxDailyReceiveLimit (event): Emitted when the maximum daily limit for receiving commands from BNB Chain is modified.

    Functions

    • constructor(address endpoint_): Initializes the contract with the LayerZero endpoint address.

    • setMaxDailyReceiveLimit(uint256 limit_): Sets the maximum daily limit for receiving commands. Only callable by the contract owner.

    • pause(): Triggers the paused state of the controller. Only callable by the contract owner.

    Contract 4: OmnichainGovernanceExecutor

    Functionality

    This contract executes proposal transactions sent from the main chain. It controls LayerZero configuration and implements a non-blocking behavior.

    State variables

    • GUARDIAN (address): A privileged role that can cancel any proposal.

    • srcChainId (uint16): Stores the layerzero endpoint ID.

    • lastProposalReceived (uint256): Last proposal count received.

    Events

    • ProposalReceived (event): Emitted when a proposal is received.

    • ProposalQueued (event): Emitted when a proposal is queued.

    • ProposalExecuted (event): Emitted when a proposal is executed.

    Functions

    • constructor(address endpoint_, address guardian_, uint16 srcChainId_): Initialises the contract with the LayerZero endpoint address, guardian address, and source chain ID.

    • setSrcChainId(uint16 srcChainId_): Updates the source layerzero endpoint ID. Only callable by the contract owner.

    • addTimelocks(ITimelock[] memory timelocks_): Adds Timelocks to the ProposalTimelocks mapping. Only callable by the contract owner.

    Contract 5: OmnichainExecutorOwner

    Functionality

    The OmnichainExecutorOwner contract serves as a governance and access control mechanism for managing the OmnichainGovernanceExecutor contract. It allows the owner to control the functions that can be executed on the OmnichainGovernanceExecutor contract, upsert function signatures into a registry, and transfer ownership of the OmnichainGovernanceExecutor contract.

    State variables

    • OMNICHAIN_GOVERNANCE_EXECUTOR (immutable):

      • This variable holds the address of the OmnichainGovernanceExecutor contract and is immutable once initialized.

    • functionRegistry (mapping):

    Events

    • FunctionRegistryChanged (event):

      • This event is emitted when a function is added or removed from the function registry.

      • It provides information about the function signature and whether it is active (added) or inactive (removed).

    Functions

    • constructor(address omnichainGovernanceExecutor_):

      • Initializes the contract with the address of the OmnichainGovernanceExecutor contract.

      • This constructor ensures that the provided address is not zero.

    Contract 6: TimelockV8

    Functionality

    The TimelockV8 contract is a Solidity V8 implementation of a timelock mechanism designed to execute transactions with a delay. It incorporates additional features such as setting a delay period, accepting pending admins, and queuing, executing, and canceling transactions. This contract ensures that specific transactions can only be executed after a predefined period, enhancing security and providing governance control.

    Key features

    • Delayed Transaction Execution: Allows transactions to be queued with an associated delay period before execution.

    • Admin Management: Supports the transition of admin roles by accepting pending admin proposals.

    • Transaction Queueing: Provides functionality to queue transactions for future execution, ensuring timely processing.

    • Transaction Execution: Executes queued transactions after the specified delay period has elapsed, subject to admin authorisation.

    Events

    • NewAdmin (event): Signals the acceptance of a new admin account.

    • NewPendingAdmin (event): Indicates the proposal of a new admin account.

    • NewDelay (event): Notifies when the delay period for transaction execution is updated.

    Constants

    • DEFAULT_GRACE_PERIOD: Default grace period for executing queued transactions (14 days).

    • DEFAULT_MINIMUM_DELAY: Default minimum delay period for queuing transactions (1 hour).

    • DEFAULT_MAXIMUM_DELAY: Default maximum delay period for queuing transactions (30 days).

    State variables

    • admin (address): Stores the address of the current admin authorised to manage the timelock.

    • pendingAdmin (address) : Stores the address of the proposed admin awaiting acceptance.

    • delay (uint256) : Specifies the delay period for executing queued transactions.

    Functions

    • setDelay(uint256 delay_): Allows the admin to set the delay period for transaction execution.

    • acceptAdmin(): Enables the pending admin to accept the admin role.

    • setPendingAdmin(address pendingAdmin_): Allows to propose a new admin account via proposal or admin.

    Inter-chain communication:

    • LayerZero provides secure and reliable cross-chain messaging for remote execution commands.

  • Bridging:

    • Works with a bridge solution to deliver messages to destination networks.

    • Enables smooth interoperability between the BNB Chain and other supported networks.

    • Bridge configurations are flexible to accommodate various networks.

  • Guardian account:

    • Authorized by the ACM to revoke orders before they are executed on the target network.

    • Serves as a fail-safe mechanism, preventing unauthorized or incorrect commands from being performed.

  • Command limits and pausing:

    • Allows you to establish daily command restrictions for destination networks.

    • Adds pause/resume functionality for execution to temporarily halt operations in case of an emergency.

  • Remote Execution Flow:

    • Commands for destination networks generate a "Remote VIPs payload”

    • The payload is routed to the destination network using the bridge solution.

  • Delay Mechanism:

    • Remote execution has two delays: bridge delay and executor delay.

    • Bridge delay is the time it takes for the bridge to propagate a message to the target network, which is commonly measured in minutes.

    • Executor delay is the duration between the message's arrival on the target network and its execution, which is customizable dependent on VIP type (Normal, Fast-track, or Critical)

  • Execution and Expiry:

    • User-triggered execution occurs once both delays have passed, signaling the destination network's readiness to perform the orders via Timelock.

    • The Guardian account can cancel orders before they are executed, offering a safeguard against malicious or erroneous acts.

    • "Remote VIPs" become "Expired" if no execution happens within a set grace period, avoiding stale or outdated commands from being executed.

  • Command Restrictions:

    • VIPs can only include one set of commands per destination network to prevent duplication and conflicts.

    • Duplicate commands for the same network within a VIP are not permitted, ensuring consistent and reliable execution.

  • Executor-Side Features:

    • Sets a daily limit on the number of commands received per network.

    • Implements pause/resume functionality for the execute function in the target governance contract, enabling administrators to manage the system's operational state effectively.

  • chainID: Identifies the destination network for the remote execution (endpointId according to LayerZero).

  • payload: Encoded data (off-chain) containing the specific commands to be executed on the target network.

  • adapterParams: The params used to specify the custom amount of gas required for the execution on the destination encoded as (ethers.utils.solidityPack(['uint16','uint256'],[1, gasValue])).

  • zroPaymentAddress_: The address of the ZRO token holder who would pay for the transaction.

  • Logical Error or Check Failure: The fallbackWithdraw function removes the message from the queue, preventing further retries if the failure stems from inherent logic errors or failed eligibility checks.

    OmnichainGovernanceExecutor (destination network):
    • Owned by: OmnichainExecutorOwner contract. This owner performs Access Control Manager (ACM) checks before allowing any function calls on this contract.

  • TimelockV8:

    • Owned by: OmnichainGovernanceExecutor contract. This ownership grants TimelockV8 the authority to perform specific actions like queuing, canceling, and executing remote proposals.

  • If a proposal's queueing fails on the destination network due to insufficient gas, the message will be saved and can be retried with the retryMessage function.
  • If a proposal's queueing fails on the destination network due to reasons such as reaching caps or other constraints, the message will be saved and can be retried with the retryMessage function. This provides flexibility in addressing various failure scenarios and ensures that execution attempts are made until successful.

  • If a proposal's queueing fails on the destination network because the contract has been paused, the message will be saved and can be retried with the retryMessage function after the contract has been unpaused.

  • chainIdToLast24HourWindowStart (mapping): Records the timestamp when the last 24-hour window for a chain began.

  • chainIdToLastProposalSentTimestamp (mapping): maintains the timestamp of the last proposal sent to a specific chain to prevent sending multiple proposals within the same block.

  • pause()
    : Triggers the paused state, halting omnichain communication. Requires
    AccessControlManager
    permission.
  • unpause(): Resumes omnichain communication from the paused state. Requires AccessControlManager permission.

  • setAccessControlManager(address accessControlManager_): Updates the address of the AccessControlManager contract. Only callable by the contract owner.

  • isEligibleToSend(uint16 dstChainId, uint256 noOfCommands_): Checks if sending the specified number of commands to the given chain is permissible based on daily limits and time windows.

  • ensureAllowed(string memory functionSig): Ensures the caller has permission to execute a specific function, leveraging the AccessControlManager.

  • Security Measures: Enforces access control using the AccessControlManager for critical functions.

    trustedRemoteLookup (mapping): Maps remote chain IDs to trusted remote contract addresses for message transmission.

    ClearPayload (event): Signals the successful clearing of a previously failed message.

  • StorePayload (event): Records the storage of an execution hash for a failed message, along with relevant details.

  • FallbackWithdraw (event): Indicates a fallback withdrawal of funds in case of failed messages.

  • execute(uint16 remoteChainId_, bytes calldata payload_, bytes calldata adapterParams_)
    : Sends a message to execute a remote proposal, storing execution hashes if the message fails.
  • retryExecute(...): Resends a previously failed message with potentially additional fees, ensuring reentrancy protection.

  • fallbackWithdraw(...): Allows the owner to withdraw funds in case of failed messages.

  • setTrustedRemoteAddress(uint16 remoteChainId_, bytes calldata newRemoteAddress_): Sets the remote message receiver address for a specified remote chain, requiring AccessControlManager permission.

  • setConfig(uint16 version_, uint16 chainId_, uint256 configType_, bytes calldata config_): Sets the configuration of the LayerZero messaging library, controlled by the AccessControlManager.

  • setSendVersion(uint16 version_): Sets the messaging library version, with permission from the AccessControlManager.

  • getConfig(uint16 version_, uint16 chainId_, uint256 configType_): Retrieves the configuration of the LayerZero messaging library.

  • unpause(): Triggers the resume state of the controller. Only callable by the contract owner.

  • renounceOwnership(): Overrides the renounceOwnership function to prevent accidental renouncement of ownership.

  • _isEligibleToReceive(uint256 noOfCommands_): Checks the eligibility to receive commands based on the daily limit and updates the state accordingly.

  • proposals (mapping): Official record of all proposals ever proposed.

  • proposalTimelocks (mapping): Mapping containing Timelock addresses for each proposal type.

  • queued (mapping): Represents the queue state of a proposal.

  • ReceivePayloadFailed (event): Emitted when a payload receive fails.

  • ProposalCanceled (event): Emitted when a proposal is canceled.

  • TimelockAdded (event): Emitted when a Timelock is added.

  • SetSrcChainId (event): Emitted when the source layer zero endpoint ID is updated.

  • SetTimelockPendingAdmin (event): Emitted when pending admin of Timelock is updated.

  • NewGuardian (event): Emitted when guardian of OmnichainGovernanceExecutor is updated.

  • execute(uint256 proposalId_) : Executes a queued proposal if the ETA has passed.

  • cancel(uint256 proposalId_): Cancels a proposal if the sender is the guardian and the proposal is not executed.

  • state(uint256 proposalId_): Gets the state of a proposal.

  • _blockingLzReceive(...) and _nonblockingLzReceive(...): Process LayerZero receive requests, with blocking and non-blocking behaviour respectively.

  • _queue(uint256 proposalId_): Queues a proposal for execution.

  • _queueOrRevertInternal(...): Checks for a unique proposal and queues it or reverts if already queued.

  • setTimelockPendingAdmin(address pendingAdmin_, uint8 proposalType_): Sets the new pending admin of the Timelock.

  • setGuardian(address newGuardian): Sets the new guardian of the OmnichainGovernanceExecutor.

  • This mapping stores the function signatures along with their corresponding 4-byte hash values.

  • It allows the contract owner to register which functions are permitted to be executed on the OmnichainGovernanceExecutor contract.

  • initialize(address accessControlManager_):

    • Initializes the contract with the address of the access control manager.

    • This function sets up access control for the contract.

  • fallback(bytes calldata data_):

    • Acts as a fallback function that is invoked when a called function does not exist in the contract.

    • It checks if the function signature exists in the function registry and if the caller has permission to execute it.

    • Then it forwards the function call to the OmnichainGovernanceExecutor contract.

    • If the call fails, it reverts with an error message.

  • upsertSignature(string[] calldata signatures_, bool[] calldata active_):

    • Allows the owner to upsert (add or remove) function signatures into the function registry.

    • The owner can specify whether each function signature should be added (true) or removed (false).

    • This function ensures that input arrays have the same length.

    • It emits the FunctionRegistryChanged event for each function signature that is added or removed.

  • transferBridgeOwnership(address newOwner_):

    • Transfers the ownership of the OmnichainGovernanceExecutor contract from this contract to a new owner.

    • This function is controlled by the access control manager to ensure that only authorized entities can transfer ownership.

    • It ensures that the new owner address is not zero before transferring ownership.

  • renounceOwnership():

    • Overrides the renounceOwnership function from the parent contract to provide an empty implementation.

    • This prevents accidental renouncement of ownership, as ownership renouncement is handled through the transferBridgeOwnership function.

  • Transaction Cancellation: Allows cancellation of queued transactions before execution, providing flexibility and control.

  • CancelTransaction (event): Broadcasts the cancellation of a queued transaction.

  • ExecuteTransaction (event): Broadcasts the execution of a queued transaction.

  • QueueTransaction (event): Broadcasts the queuing of a new transaction for future execution.

  • queueTransaction(...): Queues a transaction for future execution after a specified delay.

  • cancelTransaction(...): Cancels a queued transaction before execution.

  • executeTransaction(...): Executes a queued transaction after the delay period has elapsed.

  • Omnichain Governance VIP states
    Omnichain Governance contracts

    E-Mode

    Only available on BNB Chain Core Pool.

    Overview

    The Venus Protocol Core Pool on BNB Chain has been enhanced with E-Mode (Efficiency Mode), a feature designed to provide users with greater capital efficiency when lending and borrowing. E-Mode introduces specialized pools of assets—such as correlated ones—each with its own customized risk parameters.

    When a user activates an E-Mode pool, their borrowing is restricted to assets within that pool but with higher collateral factors (CF) and liquidation thresholds (LT) compared to the default Core Pool. A lower liquidation incentive (LI) is also applied, reducing the penalty at liquidation and making borrowing within E-Mode more efficient.

    This allows users to unlock more borrowing power while keeping risk contained within the pool.

    Unlike isolated pools, which fully segregate assets into separate environments, E-Mode keeps everything within the Core Pool. Users do not need to transfer assets to benefit from different risk profiles. Instead, they can simply activate an E-Mode pool, gaining higher efficiency while maintaining their existing positions. This design balances capital optimization with contained risk management, making E-Mode a powerful extension of the Core Pool.

    Key Benefits of E-Mode

    • Increased Borrowing Power: Higher CF and LT enable users to leverage more borrowing capacity in E-Mode pools.

    • Reduced Liquidation Penalties: Lower LI minimizes losses during volatile market conditions.

    • Seamless Integration: No asset transfers are required; all operations remain in the Core Pool.

    • Risk Isolation: Borrowing limits prevent cross-pool exposure, reducing systemic risks.

    Potential Risks and Considerations

    • Borrow Restrictions: Users must ensure existing borrows align with the target pool's allowed assets.

    • VAI Incompatibility: Users with VAI debt cannot enter E-Mode, ensuring stablecoin-specific isolation.

    • Parameter Changes: Governance updates (e.g., lowering CF) can impact the user positions.

    • Core Pool Fallback Behavior: Controlled by a per-pool flag

    Comptroller Changes for E-Mode in Core Pool

    The introduction of E-Mode in the Venus Core Pool on BNB Chain required significant enhancements to the Comptroller contract. These changes enable fine-grained risk management while preserving the existing Core Pool functionality. Below is a summary of the major updates:

    Change
    Description
    Impact

    The implementation extends the Comptroller contract to support:

    • Pool-specific risk configurations.

    • User-driven pool selection.

    • Refined, pool-based risk management.

    All of this is achieved while maintaining backward compatibility with the Core Pool’s legacy operations.

    Implementation Details

    1. Markets Mapping

    The core data structure for tracking markets has been upgraded to handle multiple pools efficiently.

    Previously: Address as index

    Now: bytes32 as index

    • Core Pool (poolId = 0): The PoolMarketId is the vToken address left-padded to 32 bytes, preserving storage layout for compatibility.

    • E-Mode Pools (poolId > 0): The key is constructed by combining the poolId (uint96, shifted left by 160 bits) with the vToken address (uint160).

    This approach ensures:

    • No collisions between pool-market pairs.

    • Pool-specific overrides (e.g., CF/LT/LI).

    • Backward compatibility is preserved through updated getter functions, which return Core Pool values when called with only a vToken address, while maintaining the same function signatures.

    2. Market Struct

    The Market struct now includes fields to support LT, per-market LI, and pool-specific borrowing rules:

    • accountMembership: Stored only in Core Pool entries, since borrows and collateral are tracked globally across all pools. In E-Mode entries, this mapping remains empty for structural consistency, reducing storage overhead.

    • isBorrowAllowed: A pool-level flag that Governance can toggle, overriding global borrow caps for E-Mode restrictions.

    3. Pool Tracking

    Pools are defined and managed via a dedicated mapping for metadata and asset lists:

    • lastPoolId tracks the latest assigned poolId (0 is reserved for Core).

    • Pools hold metadata, a list of associated vTokens, and the allowCorePoolFallback flag (default: false).

    Governance Workflow: New pools are created via createPool(string calldata label), which assigns the next poolId and initializes the PoolData with allowCorePoolFallback = false by default. Governance can update this behavior via setAllowCorePoolFallback(uint96 poolId, bool allowed). This allows for easy expansion to new pools like "ETH Correlated" or "BNB Derivatives" while choosing the desired fallback behavior.

    4. User Pool Selection

    Each user is associated with exactly one pool at a time, simplifying state management:

    • Defaults to 0 (Core Pool).

    • Switching updates userPoolId with proper validations.

    This ensures all collateral and borrowing operations are evaluated within the context of the user’s active pool. Edge Case Handling: If a user's pool is disabled by Governance, their userPoolId is automatically reset to 0, triggering a fallback event.

    5. Pool Markets Configuration

    Governance configures E-Mode via a suite of administrative functions:

    • Add/Remove: addPoolMarkets and removePoolMarket manage vTokens in non-Core pools.

    • Borrow Control: setIsBorrowAllowed toggles borrowing eligibility.

    • Risk Parameters: Setters for CF, LT, and LI support poolId for E-Mode and address-only for Core.

    Example Setters:

    E-Mode: User Journey

    1. Default State

    • Every user starts in the Core Pool (poolId = 0).

    • Core Pool applies standard parameters (lower CF/LT, higher LI).

    • If the user never switches pools, nothing changes—ensuring zero disruption for legacy users.

    2. Explore Available Pools

    Users can discover available E-Mode pools using:

    • Venus Lens: By calling the getAllPoolsData function to fetch pool data directly from the Comptroller. This returns supported E-Mode pools and their vTokens along with parameters such as CF, LT, LI, and borrow permissions.

    • Venus App UI: A user-friendly interface that displays the same information without requiring direct blockchain queries.

    3. Validate Compatibility

    • Before switching, make sure all your borrowed assets are supported as borrowable assets in the E-Mode pool you want to enter.

    • If any borrowed asset is not allowed in the target pool, the enterPool transaction will revert on: hasValidPoolBorrows() check.

    4. Enter the Pool

    • Call: enterPool(uint96 poolId)

    • Comptroller checks:

      • Pool exists and user isn’t already in it.

      • Borrow compatibility (hasValidPoolBorrows

    5. Post-Entry Impacts

    • Borrowing: Restricted to markets marked isBorrowAllowed in chosen pool.

    • Collateral:

      • Pool assets use pool CF/LT/LI.

    Common Scenarios

    Borrowed Asset Not Allowed

    • Example: A user has borrowed BTCB and tries to enter the Stablecoins Pool.

    • BTCB is not part of that pool, so it is not listed as borrowable.

    • Result: enterPool fails with IncompatibleBorrowedAssets.

    Mixed Collateral

    • Users can provide collateral outside of the E-Mode pool’s listed assets if the pool’s allowCorePoolFallback flag is set to true.

    • If allowCorePoolFallback = true: Non-pool assets use Core Pool parameters (CF, LT, LI). Since Core Pool LI is typically higher, liquidators may target these assets first during liquidation.

    • If allowCorePoolFallback = false (default): Non-pool collateral

    Example: In the Stablecoins Pool, a user supplies USDC + UNI:

    • USDC → CF/LT/LI from E-Mode (e.g., LI = 5%).

    • UNI →

      • If allowCorePoolFallback = true: CF/LT/LI from Core Pool (e.g., LI = 10%).

    Switching Back to Core

    • Switching back is allowed only if the account remains healthy under Core Pool’s stricter parameters.

    • Example: In Stablecoins Pool, a user is safe with CF = 0.90. Switching back to Core Pool with CF = 0.60 may immediately create a shortfall → reverts with LiquidityCheckFailed.

    • Important scenario:

    Governance Changes

    Governance has significant control over pool configurations, which can directly affect user positions:

    1. Borrow Restrictions:

      • Governance can set isBorrowAllowed = false for a market.

      • Existing borrows remain, but new borrows are blocked.

      • This behaves similarly to setting the borrow cap to 0 in the Core Pool.

    Rule of Risk Factor Selection:

    • If a parameter (CF, LT, LI) is defined in the active E-Mode pool, that value is used.

    • If Governance sets a value to 0 in the pool (e.g., CF = 0), the 0 applies — it does not fall back to Core.

    • If the asset is not included in the E-Mode pool:

    Effect on User on Switching Into E-Mode

    To see how E-Mode changes borrowing power, liquidation, and borrow restrictions, let’s follow a single user journey. This example uses hypothetical parameters to illustrate key mechanics.

    Pool Setup

    Asset
    Core Pool CF
    Core Pool LT
    Core Pool LI
    E-Mode CF
    E-Mode LT
    E-Mode LI
    E-Mode Borrow Allowed?

    Step 1: Alex in Core Pool

    • Supplies: $1,000 USDC

    • Borrows: $500 DAI

    Liquidity Calculation:

    • Liquidity = $100, Shortfall = $0 → safe

    Step 2: Attempting to Enter Stablecoins E-Mode

    Alex wants to switch to the Stablecoins Pool.

    • Borrowed DAI is not allowed in the target pool (isBorrowAllowed = false).

    • Comptroller checks fail → transaction reverts with IncompatibleBorrowedAssets.

    This demonstrates borrow restrictions in E-Mode: existing borrows in disallowed markets prevent entering the pool.

    Step 3: Adjusting Position and Entering

    • Alex repays $500 DAI → no active borrows.

    • Calls enterPool(stablecoinPoolId) → succeeds.

    Liquidity Calculation in E-Mode:

    Effect of E-Mode Activation:

    • Collateral Factor (CF) for USDC increases from 60% → 90%

    • Liquidation Incentive (LI) for USDC decreases from 10% → 5%

    • Can borrow USDC (allowed), but cannot borrow DAI (isBorrowAllowed = false).

    Step 4: Borrowing in E-Mode

    • Alex borrows $500 USDC

    • Borrowing DAI fails (restricted by pool-level isBorrowAllowed)

    Liquidity Calculation after borrow:

    Step 5: Switching Back to Core

    Suppose Alex borrowed up to $850 USDC in E-Mode.

    Core Pool Borrow Limit:

    To switch safely, Alex can either:

    1. Add collateral → $500 more USDC → new Core borrow limit = 1500 × 0.6 = 900 → liquidity = 900 - 850 = 50 → switch succeeds.

    2. Repay debt → reduce borrow ≤ $600 → liquidity ≥ 0 → switch succeeds.

    Liquidator Considerations in E-Mode

    The introduction of E-Mode in the Core Pool on BNB Chain also changes how liquidators must evaluate accounts and select assets for liquidation. To remain effective and profitable, liquidators need to adapt to the updated mechanics and new getter functions.

    1. Per-Market Liquidation Incentives (LI)

    • The Core Pool no longer uses a global LI.

    • Each market now has its own per-market liquidation incentive, configurable by Governance.

    • Impact: Liquidators must always query the market’s specific LI before deciding which collateral to seize, since incentives may differ significantly between assets.

    • Strategy: Prioritize assets with higher LI when selecting which collateral to liquidate for maximum profit.

    2. Liquidation Thresholds (LT) in Core Pool

    • The Core Pool now supports Liquidation Thresholds (LT), just like isolated pools.

    • Unlike Collateral Factors (CF), which only define borrow limits, LT determines liquidation conditions.

    • Impact: Liquidators must check account health against LT rather than CF.

    • Recommended Function

    3. Effective Risk Factor Queries

    Because E-Mode overrides Core parameters with pool-specific ones, the protocol provides new getters to return the effective factors for any user and market.

    • Get Effective LTV (Collateral Factor or LT depending on weighting):

      • Use weightingStrategy = 0 to fetch the effective CF.

      • Use weightingStrategy = 1 to fetch the effective LT.


    TL;DR: E-Mode in Venus BNB Chain Core Pool

    Efficiency Boost: E-Mode lets you use higher Collateral Factors (CF) and Liquidation Thresholds (LT), plus lower Liquidation Incentives (LI), for some set of assets (e.g., stablecoins).

    Borrow Limits: You can only borrow from pool-approved assets (isBorrowAllowed = true). If you have borrows in non-approved assets, you can't enter; new borrows are blocked to keep risks isolated.

    How Risk Factors Are Chosen:

    • In E-Mode Pool: Use the pool's CF/LT/LI values (even if set to 0).

    • If the asset isn't in your pool:

      • If allowCorePoolFallback = true: Use Core Pool values.

    Liquidator Notes:

    • Core Pool now uses per-market LI (no global incentive). Liquidators should always fetch the effective liquidation incentive for each user’s market, as markets associated with different E-Mode pools may have different LI values. Additionally, assets outside the E-Mode pool that do not contribute to borrowing power may have LI = 0, even if supplied as collateral.

    • Liquidation Threshold (LT) replaces CF as the trigger for liquidations—use getAccountLiquidity for checks.

    • Use new getters to fetch effective parameters considering pool overrides:

    VenusLens

    VenusLens

    Introduction

    The read only functions on the VenusLens contract provide a view into: - metadata of vToken - daily XVS rewards for an account - account balance for a single vToken - account balances for all vTokens in an account - underlying price of a vToken - underlying prices for a set of vTokens - get liquidity and shortfall of an account - get user's vote history - get proposal details for a set of proposals - get account XVS balance, total votes, and delegated votes - get historical voting balance for a user - get pending XVS Rewards for an account

    Solidity API

    BLOCKS_PER_DAY

    Blocks Per Day


    VTOKEN_ACTIONS

    Total actions available on VToken


    MarketData

    Holds full market information for a single vToken within a specific pool (excluding the Core Pool)


    PoolWithMarkets

    Struct representing a pool (excluding the Core Pool) and its associated markets


    vTokenMetadata

    Query the metadata of a vToken by its address

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    vTokenMetadataAll

    Get VTokenMetadata for an array of vToken addresses

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getDailyXVS

    Get amount of XVS distributed daily to an account

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    vTokenBalances

    Get the current vToken balance (outstanding borrows) for an account

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    vTokenBalancesAll

    Get the current vToken balances (outstanding borrows) for all vTokens on an account

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    vTokenUnderlyingPrice

    Get the price for the underlying asset of a vToken

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    vTokenUnderlyingPriceAll

    Query the underlyingPrice of an array of vTokens

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getAccountLimits

    Query the account liquidity and shortfall of an account

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getXVSBalanceMetadata

    Query the XVSBalance info of an account

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getXVSBalanceMetadataExt

    Query the XVSBalance extended info of an account

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getVenusVotes

    Query the voting power for an account at a specific list of block numbers

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    pendingRewards

    Calculate the total XVS tokens pending and accrued by a user account

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getAllPoolsData

    Returns all pools (excluding the Core Pool) along with their associated market data

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getMarketsDataByPool

    Retrieves full market data for all vTokens in a specific pool (excluding the Core Pool)

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    ❌ Errors

    • PoolDoesNotExist Reverts if the given pool ID does not exist

    • InvalidOperationForCorePool Reverts if called on the Core Pool (poolId = 0)


    XVS Bridge

    This documentation provides detailed instructions and explanations for using the XVS Cross-Chain Bridge. The bridge allows users to transfer tokens between different blockchain networks, including the and multiple destination chains. The supported networks are as follows:

    vToken

    contract VToken

    The address of the vToken to fetch VTokenMetadata

    [0]

    struct VenusLens.VTokenMetadata

    VTokenMetadata struct with vToken supply and borrow information.

    vTokens

    contract VToken[]

    Array of vToken addresses to fetch VTokenMetadata

    [0]

    struct VenusLens.VTokenMetadata[]

    Array of structs with vToken supply and borrow information.

    account

    address payable

    Address of account to fetch the daily XVS distribution

    comptrollerAddress

    address

    Address of the comptroller proxy

    [0]

    uint256

    Amount of XVS distributed daily to an account

    vToken

    contract VToken

    Address of the token to check the balance of

    account

    address payable

    Account address to fetch the balance of

    [0]

    struct VenusLens.VTokenBalances

    VTokenBalances with token balance information

    vTokens

    contract VToken[]

    Addresses of the tokens to check the balance of

    account

    address payable

    Account address to fetch the balance of

    [0]

    struct VenusLens.VTokenBalances[]

    VTokenBalances Array with token balance information

    vToken

    contract VToken

    address of the vToken

    [0]

    struct VenusLens.VTokenUnderlyingPrice

    response struct with underlyingPrice info of vToken

    vTokens

    contract VToken[]

    Array of vToken addresses

    [0]

    struct VenusLens.VTokenUnderlyingPrice[]

    array of response structs with underlying price information of vTokens

    comptroller

    contract ComptrollerInterface

    Address of comptroller proxy

    account

    address

    Address of the account to query

    [0]

    struct VenusLens.AccountLimits

    Struct with markets user has entered, liquidity, and shortfall of the account

    xvs

    contract IXVS

    XVS contract address

    account

    address

    Account address

    [0]

    struct VenusLens.XVSBalanceMetadata

    Struct with XVS balance and voter details

    xvs

    contract IXVS

    XVS contract address

    comptroller

    contract ComptrollerInterface

    Comptroller proxy contract address

    account

    address

    Account address

    [0]

    struct VenusLens.XVSBalanceMetadataExt

    Struct with XVS balance and voter details and XVS allocation

    xvs

    contract IXVS

    XVS contract address

    account

    address

    Address of the account

    blockNumbers

    uint32[]

    Array of blocks to query

    [0]

    struct VenusLens.VenusVotes[]

    Array of VenusVotes structs with block number and vote count

    holder

    address

    Account to query pending XVS

    comptroller

    contract ComptrollerInterface

    Address of the comptroller

    [0]

    struct VenusLens.RewardSummary

    Reward object contraining the totalRewards and pending rewards for each market

    comptroller

    contract ComptrollerInterface

    The Comptroller contract to query

    poolsData

    struct VenusLens.PoolWithMarkets[]

    An array of PoolWithMarkets structs, each containing pool info and its markets

    poolId

    uint96

    The pool ID to fetch data for

    comptroller

    contract ComptrollerInterface

    The address of the Comptroller contract

    result

    struct VenusLens.MarketData[]

    An array of MarketData structs containing detailed market info for the given pool

  • Governance Flexibility: Pool parameters can be dynamically adjusted via Venus Governance proposals.

  • allowCorePoolFallback
    (defaults to
    false
    ).
    • If true: Assets not included in the E-Mode pool use Core Pool risk parameters (CF, LT, LI).

    • If false: Assets not included in the E-Mode pool have no risk factors applied (effectively CF = 0 and LI = 0), so users are recommended to exit such markets before switching into that E-Mode pool.

    Fallback Control: setAllowCorePoolFallback(uint96 poolId, bool allowed) controls whether non-pool assets use Core Pool risk parameters.

    ).
  • VAI check: Users with outstanding VAI debt or active minting positions cannot switch into E-Mode.

  • Liquidity check: Runs _getAccountLiquidity with new pool’s CF/LT.

    • ❌ If shortfall > 0 (would become liquidatable), tx reverts.

  • On success:

    • userPoolId updated

    • PoolSelected event emitted

  • Non-pool assets behavior depends on allowCorePoolFallback:
    • If true: Non-pool assets use Core parameters (typically lower CF, higher LI).

    • If false (default): Non-pool assets have no applicable risk factors in the selected E-Mode pool (effectively CF = 0 and LI = 0).

  • Liquidation:

    • Pool assets → more efficient (lower LI).

    • Non-pool assets → liquidators prefer them due to higher LI.

  • VAI: Minting and repayment only possible in Core Pool.

  • Even if an asset is included in a pool, Governance can set isBorrowAllowed = false. In this case, supplying the asset as collateral is fine, but new borrows of that asset are restricted.
    does not contribute to borrowing power
    . CF, LT, and LI are treated as
    0
    in the E-Mode context. Users are strongly recommended to
    exit these markets
    before or immediately after switching to E-Mode to avoid unnecessary seizure risk for these assets during liquidations.
    If
    allowCorePoolFallback = false
    : CF/LT/LI = 0 → does not contribute to borrowing power.
    If a user is close to liquidation in Core Pool, they may switch into an E-Mode pool (with higher CF/LT) to immediately improve their account health and avoid liquidation.
  • However, if they attempt to switch back to Core, the stricter parameters would again make them liquidatable, so the transaction reverts.

  • This ensures users cannot bypass liquidation risk by cycling between pools.

  • When borrow cap set to 0, no additional borrows are possible, but existing borrows are unaffected.

  • Market Removal from E-Mode:

    • If Governance removes a market from an E-Mode pool, the market’s risk factors instantly revert to its Core Pool values.

    • This is effectively the same as updating CF, LT, or LI parameters via a VIP.

    • Users need to monitor VIP proposals to anticipate changes.

  • Disabling Core Pool Fallback:

    • Governance can disable Core Pool fallback for a pool.

    • Assets outside the E-Mode pool will no longer use Core Pool parameters, which can affect user health.

    • Such changes are implemented only after complete risk analysis and with advanced notice to users so they can adjust their positions safely.

  • Disabling an E-Mode Pool:

    • Governance can disable an entire E-Mode pool by setting the isActive flag to false.

    • When this happens, all users in the disabled pool automatically fall back to Core Pool parameters.

    • Users who remain in a disabled E-Mode pool cannot initiate new borrows and are encouraged to either return to the Core Pool or switch to another active E-Mode pool.

  • If allowCorePoolFallback = true: Use the asset's Core Pool CF/LT/LI.

  • If allowCorePoolFallback = false: Treat CF/LT/LI as 0 for that asset in E-Mode; users are recommended to exit such markets.

  • If the pool is disabled, users automatically fall back to Core Pool parameters.

  • DAI

    60%

    65%

    10%

    90%

    93%

    5%

    No

    UNI

    50%

    55%

    12%

    N/A (Fallback to Core)

    N/A

    N/A

    N/A

    :

    This function has been updated to use LT internally when computing liquidity and shortfall.

    Get Effective Liquidation Incentive (LI):

    If allowCorePoolFallback = false (default): Treat CF/LT/LI as 0; exit such markets.
  • Pool Disabled: Falls back to Core Pool parameters.

  • getEffectiveLtvFactor(account, vToken, 0) → effective CF

  • getEffectiveLtvFactor(account, vToken, 1) → effective LT

  • getEffectiveLiquidationIncentive(account, vToken) → effective LI

  • Liquidation Threshold (LT) Support in Core Pool

    The Core Pool now supports Liquidation Thresholds, similar to isolated pools. LT allows borrowing limits (CF) and liquidation conditions (LT) to be defined separately, improving risk control.

    Enables more precise liquidity calculations, separating borrow caps from liquidation triggers for better user safety.

    Per-Market Liquidation Incentives (LI)

    The global LI has been replaced with per-market LIs, enabling Governance to assign asset-specific liquidation rewards based on risk.

    Liquidators receive tailored incentives, optimizing protocol security and efficiency for high-risk vs. low-risk assets.

    Unified Pool-Market Mapping

    The existing markets mapping has been replaced with _poolMarkets, a flexible structure keyed by a new PoolMarketId type (bytes32), which uniquely identifies each pool-market pair while maintaining backward compatibility for existing market getters.

    Supports multiple pools without storage conflicts, allowing pool-specific overrides while maintaining legacy access.

    USDC

    60%

    65%

    10%

    90%

    93%

    5%

    Borrow Limit=1000×0.6=600\text{Borrow Limit} = 1000 \times 0.6 = 600Borrow Limit=1000×0.6=600
    Liquidity=Borrow Limit−Total Borrow=600−500=100\text{Liquidity} = \text{Borrow Limit} - \text{Total Borrow} = 600 - 500 = 100Liquidity=Borrow Limit−Total Borrow=600−500=100
    Shortfall=0(since liquidity ≥ 0)\text{Shortfall} = 0 \quad (\text{since liquidity ≥ 0})Shortfall=0(since liquidity ≥ 0)
    Borrow Limit=1000×0.9=900\text{Borrow Limit} = 1000 \times 0.9 = 900Borrow Limit=1000×0.9=900
    Liquidity=900−0=900\text{Liquidity} = 900 - 0 = 900Liquidity=900−0=900
    Shortfall=0(safe)\text{Shortfall} = 0 \quad (\text{safe})Shortfall=0(safe)
    Borrow Limit=1000×0.9=900\text{Borrow Limit} = 1000 \times 0.9 = 900Borrow Limit=1000×0.9=900
    Liquidity=900−500=400\text{Liquidity} = 900 - 500 = 400Liquidity=900−500=400
    Shortfall=0(safe)\text{Shortfall} = 0 \quad (\text{safe})Shortfall=0(safe)
    Borrow Limit=1000×0.6=600\text{Borrow Limit} = 1000 \times 0.6 = 600Borrow Limit=1000×0.6=600
    Liquidity=600−850=−250\text{Liquidity} = 600 - 850 = -250Liquidity=600−850=−250
    Shortfall=250(tx reverts)\text{Shortfall} = 250 \quad (\text{tx reverts})Shortfall=250(tx reverts)

    Yes

    uint256 BLOCKS_PER_DAY
    uint256 VTOKEN_ACTIONS
    struct VenusMarketState {
      uint224 index;
      uint32 block;
    }
    struct VTokenMetadata {
      address vToken;
      uint256 exchangeRateCurrent;
      uint256 supplyRatePerBlock;
      uint256 borrowRatePerBlock;
      uint256 reserveFactorMantissa;
      uint256 totalBorrows;
      uint256 totalReserves;
      uint256 totalSupply;
      uint256 totalCash;
      bool isListed;
      uint256 collateralFactorMantissa;
      address underlyingAssetAddress;
      uint256 vTokenDecimals;
      uint256 underlyingDecimals;
      uint256 venusSupplySpeed;
      uint256 venusBorrowSpeed;
      uint256 dailySupplyXvs;
      uint256 dailyBorrowXvs;
      uint256 pausedActions;
    }
    struct VTokenBalances {
      address vToken;
      uint256 balanceOf;
      uint256 borrowBalanceCurrent;
      uint256 balanceOfUnderlying;
      uint256 tokenBalance;
      uint256 tokenAllowance;
    }
    struct VTokenUnderlyingPrice {
      address vToken;
      uint256 underlyingPrice;
    }
    struct AccountLimits {
      contract VToken[] markets;
      uint256 liquidity;
      uint256 shortfall;
    }
    struct XVSBalanceMetadata {
      uint256 balance;
      uint256 votes;
      address delegate;
    }
    struct XVSBalanceMetadataExt {
      uint256 balance;
      uint256 votes;
      address delegate;
      uint256 allocated;
    }
    struct VenusVotes {
      uint256 blockNumber;
      uint256 votes;
    }
    struct ClaimVenusLocalVariables {
      uint256 totalRewards;
      uint224 borrowIndex;
      uint32 borrowBlock;
      uint224 supplyIndex;
      uint32 supplyBlock;
    }
    struct PendingReward {
      address vTokenAddress;
      uint256 amount;
    }
    struct RewardSummary {
      address distributorAddress;
      address rewardTokenAddress;
      uint256 totalRewards;
      struct VenusLens.PendingReward[] pendingRewards;
    }
    struct MarketData {
      uint96 poolId;
      string poolLabel;
      address vToken;
      bool isListed;
      uint256 collateralFactor;
      bool isVenus;
      uint256 liquidationThreshold;
      uint256 liquidationIncentive;
      bool isBorrowAllowed;
    }
    struct PoolWithMarkets {
      uint96 poolId;
      string label;
      struct VenusLens.MarketData[] markets;
    }
    function vTokenMetadata(contract VToken vToken) public returns (struct VenusLens.VTokenMetadata)
    function vTokenMetadataAll(contract VToken[] vTokens) external returns (struct VenusLens.VTokenMetadata[])
    function getDailyXVS(address payable account, address comptrollerAddress) external returns (uint256)
    function vTokenBalances(contract VToken vToken, address payable account) public returns (struct VenusLens.VTokenBalances)
    function vTokenBalancesAll(contract VToken[] vTokens, address payable account) external returns (struct VenusLens.VTokenBalances[])
    function vTokenUnderlyingPrice(contract VToken vToken) public view returns (struct VenusLens.VTokenUnderlyingPrice)
    function vTokenUnderlyingPriceAll(contract VToken[] vTokens) external view returns (struct VenusLens.VTokenUnderlyingPrice[])
    function getAccountLimits(contract ComptrollerInterface comptroller, address account) public view returns (struct VenusLens.AccountLimits)
    function getXVSBalanceMetadata(contract IXVS xvs, address account) external view returns (struct VenusLens.XVSBalanceMetadata)
    function getXVSBalanceMetadataExt(contract IXVS xvs, contract ComptrollerInterface comptroller, address account) external returns (struct VenusLens.XVSBalanceMetadataExt)
    function getVenusVotes(contract IXVS xvs, address account, uint32[] blockNumbers) external view returns (struct VenusLens.VenusVotes[])
    function pendingRewards(address holder, contract ComptrollerInterface comptroller) external view returns (struct VenusLens.RewardSummary)
    function getAllPoolsData(contract ComptrollerInterface comptroller) external view returns (struct VenusLens.PoolWithMarkets[] poolsData)
    function getMarketsDataByPool(uint96 poolId, contract ComptrollerInterface comptroller) public view returns (struct VenusLens.MarketData[] result)
    function getEffectiveLiquidationIncentive(
        address account,
        address vToken
    ) external view returns (uint256);
    mapping(address => Market) public markets;
    type PoolMarketId is bytes32;
    mapping(PoolMarketId => Market) public _poolMarkets;
    struct Market {
        bool isListed;
        uint256 collateralFactorMantissa;
        mapping(address => bool) accountMembership;
        bool isVenus;
        uint256 liquidationThresholdMantissa;
        uint256 liquidationIncentiveMantissa;
        uint96 poolId;
        bool isBorrowAllowed;
    }
    struct PoolData {
        string label;               // e.g., "Stablecoins"
        address[] vTokens;          // Markets in this pool
        bool allowCorePoolFallback; // If true, non-pool assets use Core Pool CF/LT/LI; if false, CF/LT/LI treated as 0
    }
    
    mapping(uint96 => PoolData) public pools;
    
    uint96 public lastPoolId;
    mapping(address => uint96) public userPoolId;
    // E-Mode setter
    function setCollateralFactor(uint96 poolId, VToken vToken, uint256 newCollateralFactorMantissa, uint256 newLiquidationThresholdMantissa) external returns (uint256);
    
    // Core Pool setter
    function setCollateralFactor(VToken vToken, uint256 newCollateralFactorMantissa, uint256 newLiquidationThresholdMantissa) external returns (uint256);
    enum WeightFunction {
        USE_COLLATERAL_FACTOR,        // 0
        USE_LIQUIDATION_THRESHOLD     // 1
    }
    
    function getEffectiveLtvFactor(
        address account,
        address vToken,
        WeightFunction weightingStrategy
    ) external view returns (uint256);
    function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);

    Ethereum

  • opBNB

  • Optimism

  • ZKsync

  • Supported Transfer Paths

    The bridge supports transfers between all network pairs, providing users with enhanced flexibility and interoperability across blockchain ecosystems.

    The system consists of multiple contracts, including XVSBridgeAdmin, XVSProxySrc, XVSProxyDest, and XVS token contracts.

    The functionality of the bridge relies on LayerZero for the seamless transfer of XVS tokens across different networks. Consequently, the security and integrity of the token on each network are subject to potential vulnerabilities inherent in the bridging mechanism. It is essential to note that these risks are a general characteristic of integrating with network bridges and do not stem from any particular weaknesses within the token implementation.

    1. Getting Started

    To start using the XVS Cross-Chain Bridge, follow these steps:

    1.1. Approving XVS Tokens

    Before transferring XVS tokens, you need to approve the Bridge contract on the BNB chain to spend XVS tokens on your behalf. Follow these steps:

    1. Call the approve function of the XVS token contract with the following parameters:

      • _spender: Address of the Bridge contract on the BNB chain.

      • _amount: Amount of XVS tokens to approve for transfer.

    1.2. Estimating Transaction Fees

    To estimate the transaction fees required to send XVS tokens to the destination chain, call the estimateSend function of the Bridge contract with the following parameters:

    • _dstChainId: Destination chain ID, defined by LayerZero (e.g., Ethereum virtual chain ID (101))

    • _toAddress: Receiver address on the destination chain

    • _amount: Amount of XVS tokens you want to send, defined with 18 decimals

    • _useZro: false (indicating that you are not paying in LayerZero ZRO tokens)

    • _adapterParams: 0x000100000000000000000000000000000000000000000000000000000000000493E0 (ethers.utils.solidityPack(['uint16','uint256'],[1, gasValue]) the gas value should be greater then minDestGas which is set to 300k).

    2. Transferring Tokens

    The actual token transfer is performed using the sendFrom function of the Bridge contract. Follow these steps:

    2.1. Sending Tokens

    1. Call the sendFrom function of the Bridge contract with the following parameters::

      • _from: Your address on the BNB chain

      • _dstChainId: Destination chain ID defined by LayerZero (e.g., Ethereum virtual chain ID (101))

      • _toAddress: The address on the destination chain where you want to receive the XVS tokens

      • _amount: Amount of XVS tokens you want to send, defined with 18 decimals

      • _callParams: ["RefundGasAddress", "ZROaddress", "adapterParams"]

        • RefundGasAddress: Address where you want to receive a refund for excessive gas sent. It can be the sender's address.

        • ZROaddress: 0x0000000000000000000000000000000000000000 (indicating that you are not paying in ZRO tokens)

    3. Receiving Tokens on the Destination Chain

    When you send XVS tokens to the destination chain using the bridge, the tokens will be minted by the Bridge contract to the receiver's address on the destination chain.

    4. Transferring Tokens Back to the BNB chain

    To transfer XVS tokens back to the BNB chain, follow a similar process as mentioned in the earlier send section. You don't need to approve the Bridge contract on the destination chain to spend XVS tokens on your behalf. The tokens will be burned on the destination chain on your behalf and unlocked and transferred to the receiver's address on the BNB chain.

    To transfer XVS tokens between destination chains, such as from Ethereum to opBNB, the process remains similar to the earlier send section. You don't need to approve the Bridge contract on the destination chain to spend XVS tokens on your behalf. The tokens will be burned on the one destination chain (Ethereum) and minted on the other destination chain (opBNB).

    5. Monitoring Transaction Status

    After initiating a token transfer, you should wait for the transaction to confirm. This process may take a few minutes. Once the transaction confirms, you will receive the bridged XVS tokens on the destination chain. You can use LayerZero scan to monitor your cross-chain transactions.

    6. Security and Risks

    6.1. Ownership Transfer

    • Use the transferOwnership method in the XVSBridgeAdmin contract to transfer ownership of the admin contract.

    • Use the transferBridgeOwnership method to transfer ownership of the Bridge contract from one contract to another.

    • Ownership control is crucial in case of emergencies or security issues.

    • The owner of the XVSBridgeAdmin contract will be initially the Guardian, but it will be transferred to Governance as soon as the MultichainGovernance module is deployed.

    6.2. Pause and Resume

    • The Bridge includes a pause and unpause mechanism. Use the pause method to halt the contract's functionality and unpause to resume.

    • Pausing is a security measure to prevent further transactions during emergencies or potential attacks.

    • XVS Cross-chain messages that attempt to mint or release tokens to the receiver can be received by the destination Bridge contract. These messages will fail, but they can be retried once the destination Bridge Contract has been unpaused.

    6.3. Limit the Amount of XVS Transfers

    • Example: Limit the maximum XVS transfer to USD 1,000 in one transaction and USD 100,000 in one day. These limits can be adjusted using VIPs.

    6.4. Transfer Delays

    • Configurable delay after XVS transfers to the target network by specifying a minimum number of blocks in the LayerZero endpoint configuration.

    6.5. Token Controller Contract

    • Token Controller contract within the XVS token deployed on the target network to blacklist addresses, preventing them from transferring or receiving XVS. Integrated with the ACM.

    6.6. Cap on Token Minting

    • Cap on the amount of tokens that can be minted in the destination target network. This feature can be integrated in Token Controller.

    6.7. Mitigation Plans for Mint Cap Reached

    • If XVS become stuck between bridges due to exceeding the mint cap, the system will extend the mint cap via VIP. The failed message will be retried.

    6.8. Bridge Model

    • The XVSProxyOFTDest contract serves as the Bridge model. It will be authorized to mint and burn XVS in the destination chain. Limits on these actions will be set by Governance or the Guardian.

    • While the initial deployment involves one Bridge contract per network, the system is designed to support several bridges simultaneously, providing users with flexibility.

    • The system's architecture allows for the deployment of multiple bridges within the same network, offering users the option to choose different bridges for their transactions. This flexibility ensures efficient and diverse token bridging capabilities.

      Example of Bridging in Case of Multiple Active Bridges:

    6.9. Bridge Replacement Scenario

    In the event that a Bridge contract needs replacement, such as due to a security risk, the following steps will be taken:

    1. Pause the Bridge:

      • Temporarily pause the Bridge contract to prevent further transactions.

    2. Token Evaluation:

      • Evaluate whether pausing the XVS token is necessary during the replacement process.

    3. Migrate MinterToMintedAmount:

      • Move the minterToMintedAmount value to a different Bridge contract address using the migrateMintedTokens function.

    4. Reduce MintCap:

      • Reduce the mintCap to zero for the Bridge contract address with security issues.

    These steps ensure a secure and systematic replacement of a Bridge contract, maintaining the integrity of the token. Simultaneously, on the BNB chain, the locked XVS will be transferred and locked in the other Bridge contract, ensuring a fix total supply of XVS.

    6.10. Default Downtime

    • Currently, the Bridge relies on a single relayer, the default by LayerZero, to generate proofs and submit them to target chains. While this configuration is functional, it's important to be aware of the potential implications. If the relayer goes offline or encounters problems, there's no immediate backup to maintain bridge functionality, potentially delaying or preventing transactions. In the event of unforeseen downtime affecting the default LayerZero relayer, a wallet can be authorized to temporarily generate proofs and submit them on the target network on behalf of the relayer. This authorization is granted only in exceptional circumstances via VIP.

    7. Contract Details

    Here, we provide more details about the key contracts used in the XVS Cross-chain Bridge:

    7.1. XVSBridgeAdmin

    • XVSBridgeAdmin is the admin contract for the bridge, ensuring proper setup.

    • It contains a functionRegistry mapping for function signatures, allowing the contract to call corresponding methods in destination contracts after ensuring access control permissions.

    • Ownership transfers for XVSBridgeAdmin and Bridge can be executed via the transferOwnership and transferBridgeOwnership methods respectively.

    7.2. XVSProxySrc

    • XVSProxySrc extends the BaseOFTV2 contract and includes custom logic for token transfers.

    • It overrides the _debitFrom and _creditTo functions, checking transaction limits and user eligibility.

    • It enforces transaction limits, tracks 24-hour window limits, and allows whitelisting of users.

    • XVSProxySrc can be paused and resumed in emergencies.

    7.3. XVSProxyDest

    • XVSProxyDest is similar to XVSProxySrc but with specific differences.

    • Transaction limits are enforced primarily for outbound amounts only in the source chain.

    • It overrides the debitFrom function to include custom logic for checking transaction limits in USD and performs an external call to the XVS token contract to burn tokens from the sender.

    • It overrides the creditTo function to trigger an external call to the XVS token contract to mint tokens for the receiver.

    • When sending tokens from the destination chain to the BNB chain, it burns user tokens, with the burning logic residing in the XVS token contract.

    • When receiving tokens from the BNB chain (to the Destination Chain), it mints tokens for the receiver, with the minting logic residing in the XVS token contract.

    7.4. XVS Token

    • The XVS token contract is deployed on destination chains, and it is used within the XVSProxyDest contract.

    • The XVS token follows the ERC20 standard and extends the TokenController ownable contract, which contains all controlling mechanisms of the XVS.

    • It is responsible for setting minting limits for the minter (in this case, the remote Bridge contract).

    • When receiving transactions and tokens from the source chain's Bridge contract, an external call is made to mint tokens for the receiver.

    • When sending tokens to the source chain's Bridge contract, an external call is made from the Bridge contract to burn tokens from the sender.

    • Offers a blacklisting feature to prevent certain users from receiving, transferring and bridging XVS tokens.

    • integration is used for setting minting caps and blacklisting, and these settings can be configured via VIPs or Guardian.

    8. Additional Features

    In addition to the core functionality, the XVS Cross-chain Bridge includes additional features to enhance its capabilities:

    8.1. Oracle Integration

    • The contract incorporates an oracle integration through the ResilientOracleInterface. It allows the contract to fetch price data for the token using the getPrice function.

    8.2. Whitelist Mechanism

    • The contract implements a whitelist mechanism to skip checks on transaction limits for whitelisted addresses. The whitelist mapping is used to track whitelisted addresses. The setWhitelist function allows adding or removing addresses from the whitelist.

    8.3. Transaction Limits

    • The contract introduces transaction limits for both sending and receiving transactions, based on a daily and single transaction basis. The limits are defined using chainIdToMaxSingleTransactionLimit, chainIdToMaxDailyLimit, chainIdToMaxSingleReceiveTransactionLimit, and chainIdToMaxDailyReceiveLimit.

    • Single Send Limit (source network in the first column, destination network in the first row)

      BNB
      opBNB
      Arbitrum
      Ethereum
      ZKsync
      Optimism
      Base
    • Daily Send Limit (source network in the first column, destination network in the first row)

      BNB
      opBNB
      Arbitrum
      Ethereum
      ZKsync
      Optimism
      Base
    • Single Receive Limit = Single Send Limit + 2%

    • Daily Receive Limit = Daily Send Limit + 2%

    Note: The additional 2% provides a margin to account for potential price fluctuations during the processing of bridging transactions.

    8.4. Pause and Unpause Mechanism

    • The contract incorporates a pause and unpause mechanism using the Pausable library. The pause and unpause functions can be used to halt and resume the contract's functionality, respectively.

    9. Possible Failures of Bridging XVS Tokens

    9.1. Sending XVS tokens from the source chain

    • The oracle temporarily fails due to reasons including being paused by the owner, incorrect address configuration, or price validation failures.

    • The transfer amount exceeds the single or daily sending transaction limit.

    • The transfer amount is too small, becoming zero after removing dust.

    • The sender is blacklisted by the XVS token.

    • The destination bridge is not configured as a trusted remote.

    9.2. Receiving XVS tokens on the destination chain

    • The oracle temporarily fails due to reasons including being paused by the owner, incorrect address configuration, or price validation failures.

    • The transfer amount exceeds the single or daily receiving transaction limit.

    • The recipient is blacklisted by the XVS token.

    • The minting cap on the destination bridge is exceeded.

    Retry Mechanism for Failed Transactions

    In the event of a failed transaction, follow the below step-by-step process using block explorers and the retryMessage function to retry transactions on the respective blockchain. Here's a detailed guide:

    1. Identify the Failed Transaction:

      • Use LayerZero scan to identify the failed transaction within the target network by providing the transaction hash from the source network where the transaction was initiated.

    2. Examine the MessageFailed Log:

      • Access the emitted events of the failed transaction and specifically examine the log. This log contains essential function parameters needed for the retry.

    3. Extract Function Parameters:

      • From the MessageFailed log, extract the following essential function parameters:

        • _srcChainId

    4. Construct a RetryMessage:

      • In the event of a transaction failure on the BNB chain, invoke the retryMessage function of the XVSProxyOFTSrc contract on the BNB chain. Use the parameters extracted from the MessageFailed log for this operation. Conversely, if the transaction fails on any network other than BNB chain, invoke the retryMessage function of the XVSProxyOFTDest contract on that network.

    BNB chain
    Arbitrum
    Base
    BNB

    adapterParams: 0x000100000000000000000000000000000000000000000000000000000000000493E0 (ethers.utils.solidityPack(['uint16','uint256'],[1, gasValue]) the gas value should be greater then minDestGas which is set to 300k).

    $20,000

    -

    $20,000

    $20,000

    $20,000

    $20,000

    Ethereum

    $100,000

    $10,000

    $20,000

    -

    $20,000

    $20,000

    $20,000

    ZKsync

    $20,000

    $20,000

    $20,000

    $20,000

    -

    $20,000

    $20,000

    Optimism

    $20,000

    $20,000

    $20,000

    $20,000

    $20,000

    -

    $20,000

    Base

    $20,000

    $20,000

    $20,000

    $20,000

    $20,000

    $20,000

    -

    $1,000,000

    $100,000

    $100,000

    $100,000

    opBNB

    $50,000

    -

    $100,000

    $50,000

    $100,000

    $100,000

    $100,000

    Arbitrum

    $100,000

    $100,000

    -

    $100,000

    $100,000

    $100,000

    $100,000

    Ethereum

    $1,000,000

    $50,000

    $100,000

    -

    $100,000

    $100,000

    $100,000

    ZKsync

    $100,000

    $100,000

    $100,000

    $100,000

    -

    $100,000

    $100,000

    Optimism

    $100,000

    $100,000

    $100,000

    $100,000

    $100,000

    -

    $100,000

    Base

    $100,000

    $100,000

    $100,000

    $100,000

    $100,000

    $100,000

    -

    _srcAddress
  • _nonce

  • _payload

  • BNB

    -

    $10,000

    $20,000

    $100,000

    $20,000

    $20,000

    $20,000

    opBNB

    $10,000

    -

    $20,000

    $10,000

    $20,000

    $20,000

    $20,000

    Arbitrum

    BNB

    -

    $50,000

    ACM
    MessageFailed
    Assets bridging from src chain to dest chain
    Assets bridging from dest chain to src chain
    Risks and security

    $20,000

    $100,000

    1. Initial Setup:
       - Bridge Contract A (BridgeA) has a minterToMintedAmount of 100 XVS.
       - User A holds all 100 XVS minted by BridgeA.
    
    2. Separate Bridge Contract B Setup:
       - Bridge Contract B (BridgeB) has a separate minterToMintedAmount of 50 XVS.
       - User B holds all 50 XVS minted by BridgeB.
    
    3. User B Bridges Off Tokens Using Bridge A:
       - User B decides to use BridgeA to bridge off his 50 XVS.
       - After the successful bridging process, BridgeA's minterToMintedAmount is now 50, reflecting the XVS burned by User B through this BridgeA.
    
    4. User A Bridges Off Tokens Using Both Bridges:
       - Now, User A intends to bridge off his 100 XVS, splitting them between BridgeA and BridgeB.
       - User A uses BridgeA for 50 XVS and BridgeB for the remaining 50 XVS.

    XVSVault

    XVS Vault

    The XVS Vault allows XVS holders to lock their XVS to recieve voting rights in Venus governance and are rewarded with XVS.

    Solidity API

    pause

    Pauses vault


    resume

    Resume vault


    poolLength

    Returns the number of pools with the specified reward token

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    add

    Add a new token pool

    Parameters

    Name
    Type
    Description

    set

    Update the given pool's reward allocation point

    Parameters

    Name
    Type
    Description

    setRewardAmountPerBlock

    Update the given reward token's amount per block

    Parameters

    Name
    Type
    Description

    setWithdrawalLockingPeriod

    Update the lock period after which a requested withdrawal can be executed

    Parameters

    Name
    Type
    Description

    deposit

    Deposit XVSVault for XVS allocation

    Parameters

    Name
    Type
    Description

    claim

    Claim rewards for pool

    Parameters

    Name
    Type
    Description

    executeWithdrawal

    Execute withdrawal to XVSVault for XVS allocation

    Parameters

    Name
    Type
    Description

    requestWithdrawal

    Request withdrawal to XVSVault for XVS allocation

    Parameters

    Name
    Type
    Description

    getEligibleWithdrawalAmount

    Get unlocked withdrawal amount

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getRequestedAmount

    Get requested amount

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getWithdrawalRequests

    Returns the array of withdrawal requests that have not been executed yet

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    pendingReward

    View function to see pending XVSs on frontend

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    updatePool

    Update reward variables of the given pool to be up-to-date

    Parameters

    Name
    Type
    Description

    getUserInfo

    Get user info with reward token address and pid

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    pendingWithdrawalsBeforeUpgrade

    Gets the total pending withdrawal amount of a user before upgrade

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    delegate

    Delegate votes from msg.sender to delegatee

    Parameters

    Name
    Type
    Description

    delegateBySig

    Delegates votes from signatory to delegatee

    Parameters

    Name
    Type
    Description

    getCurrentVotes

    Gets the current votes balance for account

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getPriorVotes

    Determine the xvs stake balance for an account

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _become

    • Admin Functions **


    setAccessControl

    Sets the address of the access control of this contract

    Parameters

    Name
    Type
    Description

    Prime token

    Prime

    Prime Token is used to provide extra rewards to the users who have staked a minimum of MINIMUM_STAKED_XVS XVS in the XVSVault for STAKING_PERIOD days

    PolicyFacet

    PolicyFacet

    This facet contract contains all the external pre-hook functions related to vToken

    Solidity API

    _lockPeriod

    uint256

    A period between withdrawal request and a moment when it's executable

    r

    bytes32

    Half of the ECDSA signature pair

    s

    bytes32

    Half of the ECDSA signature pair

    rewardToken

    address

    Reward token address

    [0]

    uint256

    Number of pools that distribute the specified token as a reward

    _rewardToken

    address

    Reward token address

    _allocPoint

    uint256

    Number of allocation points assigned to this pool

    _token

    contract IBEP20

    Staked token

    _rewardPerBlock

    uint256

    _rewardToken

    address

    Reward token address

    _pid

    uint256

    Pool index

    _allocPoint

    uint256

    Number of allocation points assigned to this pool

    _rewardToken

    address

    Reward token address

    _rewardAmount

    uint256

    Number of allocation points assigned to this pool

    _rewardToken

    address

    Reward token address

    _pid

    uint256

    Pool index

    _newPeriod

    uint256

    New lock period

    _rewardToken

    address

    The Reward Token Address

    _pid

    uint256

    The Pool Index

    _amount

    uint256

    The amount to deposit to vault

    _account

    address

    The account for which to claim rewards

    _rewardToken

    address

    The Reward Token Address

    _pid

    uint256

    The Pool Index

    _rewardToken

    address

    The Reward Token Address

    _pid

    uint256

    The Pool Index

    _rewardToken

    address

    The Reward Token Address

    _pid

    uint256

    The Pool Index

    _amount

    uint256

    The amount to withdraw from the vault

    _rewardToken

    address

    The Reward Token Address

    _pid

    uint256

    The Pool Index

    _user

    address

    The User Address

    withdrawalAmount

    uint256

    Amount that the user can withdraw

    _rewardToken

    address

    The Reward Token Address

    _pid

    uint256

    The Pool Index

    _user

    address

    The User Address

    [0]

    uint256

    Total amount of requested but not yet executed withdrawals (including both executable and locked ones)

    _rewardToken

    address

    The Reward Token Address

    _pid

    uint256

    The Pool Index

    _user

    address

    The User Address

    [0]

    struct XVSVaultStorageV1.WithdrawalRequest[]

    An array of withdrawal requests

    _rewardToken

    address

    Reward token address

    _pid

    uint256

    Pool index

    _user

    address

    User address

    [0]

    uint256

    Reward the user is eligible for in this pool, in terms of _rewardToken

    _rewardToken

    address

    Reward token address

    _pid

    uint256

    Pool index

    _rewardToken

    address

    Reward token address

    _pid

    uint256

    Pool index

    _user

    address

    User address

    amount

    uint256

    Deposited amount

    rewardDebt

    uint256

    Reward debt (technical value used to track past payouts)

    pendingWithdrawals

    uint256

    Requested but not yet executed withdrawals

    _rewardToken

    address

    The Reward Token Address

    _pid

    uint256

    The Pool Index

    _user

    address

    The address of the user

    beforeUpgradeWithdrawalAmount

    uint256

    Total pending withdrawal amount in requests made before the vault upgrade

    delegatee

    address

    The address to delegate votes to

    delegatee

    address

    The address to delegate votes to

    nonce

    uint256

    The contract state required to match the signature

    expiry

    uint256

    The time at which to expire the signature

    v

    uint8

    account

    address

    The address to get votes balance

    [0]

    uint96

    The number of current votes for account

    account

    address

    The address of the account to check

    blockNumber

    uint256

    The block number to get the vote balance at

    [0]

    uint96

    The balance that user staked

    newAccessControlAddress

    address

    New address for the access control

    Initial reward per block, in terms of _rewardToken

    The recovery byte of the signature

    function pause() external
    function resume() external
    function poolLength(address rewardToken) external view returns (uint256)
    function add(address _rewardToken, uint256 _allocPoint, contract IBEP20 _token, uint256 _rewardPerBlock, uint256 _lockPeriod) external
    function set(address _rewardToken, uint256 _pid, uint256 _allocPoint) external
    function setRewardAmountPerBlock(address _rewardToken, uint256 _rewardAmount) external
    function setWithdrawalLockingPeriod(address _rewardToken, uint256 _pid, uint256 _newPeriod) external
    function deposit(address _rewardToken, uint256 _pid, uint256 _amount) external
    function claim(address _account, address _rewardToken, uint256 _pid) external
    function executeWithdrawal(address _rewardToken, uint256 _pid) external
    function requestWithdrawal(address _rewardToken, uint256 _pid, uint256 _amount) external
    function getEligibleWithdrawalAmount(address _rewardToken, uint256 _pid, address _user) external view returns (uint256 withdrawalAmount)
    function getRequestedAmount(address _rewardToken, uint256 _pid, address _user) external view returns (uint256)
    function getWithdrawalRequests(address _rewardToken, uint256 _pid, address _user) external view returns (struct XVSVaultStorageV1.WithdrawalRequest[])
    function pendingReward(address _rewardToken, uint256 _pid, address _user) external view returns (uint256)
    function updatePool(address _rewardToken, uint256 _pid) external
    function getUserInfo(address _rewardToken, uint256 _pid, address _user) external view returns (uint256 amount, uint256 rewardDebt, uint256 pendingWithdrawals)
    function pendingWithdrawalsBeforeUpgrade(address _rewardToken, uint256 _pid, address _user) public view returns (uint256 beforeUpgradeWithdrawalAmount)
    function delegate(address delegatee) external
    function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external
    function getCurrentVotes(address account) external view returns (uint96)
    function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96)
    function _become(contract XVSVaultProxy xvsVaultProxy) external
    function setAccessControl(address newAccessControlAddress) external
    Solidity API

    BLOCKS_PER_YEAR

    total blocks per year


    WBNB

    address of WBNB contract


    VBNB

    address of VBNB contract


    MINIMUM_STAKED_XVS

    minimum amount of XVS user needs to stake to become a prime member


    MAXIMUM_XVS_CAP

    maximum XVS taken in account when calculating user score


    STAKING_PERIOD

    number of days user need to stake to claim prime token


    initialize

    Prime initializer

    Parameters

    Name
    Type
    Description

    xvsVault_

    address

    Address of XVSVault

    xvsVaultRewardToken_

    address

    Address of XVSVault reward token

    xvsVaultPoolId_

    uint256

    Pool id of XVSVault

    alphaNumerator_

    uint128

    ❌ Errors

    • Throw InvalidAddress if any of the address is invalid


    getPendingRewards

    Returns boosted pending interest accrued for a user for all markets

    Parameters

    Name
    Type
    Description

    user

    address

    the account for which to get the accrued interests

    Return Values

    Name
    Type
    Description

    pendingRewards

    struct PrimeStorageV1.PendingReward[]

    the number of underlying tokens accrued by the user for all markets


    updateScores

    Update total score of multiple users and market

    Parameters

    Name
    Type
    Description

    users

    address[]

    accounts for which we need to update score

    📅 Events

    • Emits UserScoreUpdated event

    ❌ Errors

    • Throw NoScoreUpdatesRequired if no score updates are required

    • Throw UserHasNoPrimeToken if user has no prime token


    updateAlpha

    Update value of alpha

    Parameters

    Name
    Type
    Description

    _alphaNumerator

    uint128

    numerator of alpha. If alpha is 0.5 then numerator is 1

    _alphaDenominator

    uint128

    denominator of alpha. If alpha is 0.5 then denominator is 2

    📅 Events

    • Emits AlphaUpdated event

    ⛔️ Access Requirements

    • Controlled by ACM


    updateMultipliers

    Update multipliers for a market

    Parameters

    Name
    Type
    Description

    market

    address

    address of the market vToken

    supplyMultiplier

    uint256

    new supply multiplier for the market, scaled by 1e18

    borrowMultiplier

    uint256

    new borrow multiplier for the market, scaled by 1e18

    📅 Events

    • Emits MultiplierUpdated event

    ⛔️ Access Requirements

    • Controlled by ACM

    ❌ Errors

    • Throw MarketNotSupported if market is not supported


    setStakedAt

    Update staked at timestamp for multiple users

    Parameters

    Name
    Type
    Description

    users

    address[]

    accounts for which we need to update staked at timestamp

    timestamps

    uint256[]

    new staked at timestamp for the users

    📅 Events

    • Emits StakedAtUpdated event for each user

    ⛔️ Access Requirements

    • Controlled by ACM

    ❌ Errors

    • Throw InvalidLength if users and timestamps length are not equal


    addMarket

    Add a market to prime program

    Parameters

    Name
    Type
    Description

    market

    address

    address of the market vToken

    supplyMultiplier

    uint256

    the multiplier for supply cap. It should be converted to 1e18

    borrowMultiplier

    uint256

    the multiplier for borrow cap. It should be converted to 1e18

    📅 Events

    • Emits MarketAdded event

    ⛔️ Access Requirements

    • Controlled by ACM

    ❌ Errors

    • Throw MarketAlreadyExists if market already exists

    • Throw InvalidVToken if market is not valid


    setLimit

    Set limits for total tokens that can be minted

    Parameters

    Name
    Type
    Description

    _irrevocableLimit

    uint256

    total number of irrevocable tokens that can be minted

    _revocableLimit

    uint256

    total number of revocable tokens that can be minted

    📅 Events

    • Emits MintLimitsUpdated event

    ⛔️ Access Requirements

    • Controlled by ACM

    ❌ Errors

    • Throw InvalidLimit if any of the limit is less than total tokens minted


    setMaxLoopsLimit

    Set the limit for the loops can iterate to avoid the DOS

    Parameters

    Name
    Type
    Description

    loopsLimit

    uint256

    Number of loops limit

    📅 Events

    • Emits MaxLoopsLimitUpdated event on success

    ⛔️ Access Requirements

    • Controlled by ACM


    issue

    Directly issue prime tokens to users

    Parameters

    Name
    Type
    Description

    isIrrevocable

    bool

    are the tokens being issued

    users

    address[]

    list of address to issue tokens to

    ⛔️ Access Requirements

    • Controlled by ACM


    xvsUpdated

    Executed by XVSVault whenever user's XVSVault balance changes

    Parameters

    Name
    Type
    Description

    user

    address

    the account address whose balance was updated


    accrueInterestAndUpdateScore

    accrues interes and updates score for an user for a specific market

    Parameters

    Name
    Type
    Description

    user

    address

    the account address for which to accrue interest and update score

    market

    address

    the market for which to accrue interest and update score


    claim

    For claiming prime token when staking period is completed


    burn

    For burning any prime token

    Parameters

    Name
    Type
    Description

    user

    address

    the account address for which the prime token will be burned

    ⛔️ Access Requirements

    • Controlled by ACM


    togglePause

    To pause or unpause claiming of interest

    ⛔️ Access Requirements

    • Controlled by ACM


    claimInterest

    For user to claim boosted yield

    Parameters

    Name
    Type
    Description

    vToken

    address

    the market for which claim the accrued interest

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    amount the amount of tokens transferred to the msg.sender


    claimInterest

    For user to claim boosted yield

    Parameters

    Name
    Type
    Description

    vToken

    address

    the market for which claim the accrued interest

    user

    address

    the user for which to claim the accrued interest

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    amount the amount of tokens transferred to the user


    getAllMarkets

    Retrieves an array of all available markets

    Return Values

    Name
    Type
    Description

    [0]

    address[]

    an array of addresses representing all available markets


    claimTimeRemaining

    fetch the numbers of seconds remaining for staking period to complete

    Parameters

    Name
    Type
    Description

    user

    address

    the account address for which we are checking the remaining time

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    timeRemaining the number of seconds the user needs to wait to claim prime token


    calculateAPR

    Returns supply and borrow APR for user for a given market

    Parameters

    Name
    Type
    Description

    market

    address

    the market for which to fetch the APR

    user

    address

    the account for which to get the APR

    Return Values

    Name
    Type
    Description

    supplyAPR

    uint256

    supply APR of the user in BPS

    borrowAPR

    uint256

    borrow APR of the user in BPS


    estimateAPR

    Returns supply and borrow APR for estimated supply, borrow and XVS staked

    Parameters

    Name
    Type
    Description

    market

    address

    the market for which to fetch the APR

    user

    address

    the account for which to get the APR

    borrow

    uint256

    hypothetical borrow amount

    supply

    uint256

    Return Values

    Name
    Type
    Description

    supplyAPR

    uint256

    supply APR of the user in BPS

    borrowAPR

    uint256

    borrow APR of the user in BPS


    accrueInterest

    Distributes income from market since last distribution

    Parameters

    Name
    Type
    Description

    vToken

    address

    the market for which to distribute the income

    ❌ Errors

    • Throw MarketNotSupported if market is not supported


    getInterestAccrued

    Returns boosted interest accrued for a user

    Parameters

    Name
    Type
    Description

    vToken

    address

    the market for which to fetch the accrued interest

    user

    address

    the account for which to get the accrued interest

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    interestAccrued the number of underlying tokens accrued by the user since the last accrual


    mintAllowed

    Checks if the account should be allowed to mint tokens in the given market

    Parameters

    Name
    Type
    Description

    vToken

    address

    The market to verify the mint against

    minter

    address

    The account which would get the minted tokens

    mintAmount

    uint256

    The amount of underlying being supplied to the market in exchange for tokens

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)


    mintVerify

    Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    vToken

    address

    Asset being minted

    minter

    address

    The address minting the tokens

    actualMintAmount

    uint256

    The amount of the underlying asset being minted

    mintTokens

    uint256


    redeemAllowed

    Checks if the account should be allowed to redeem tokens in the given market

    Parameters

    Name
    Type
    Description

    vToken

    address

    The market to verify the redeem against

    redeemer

    address

    The account which would redeem the tokens

    redeemTokens

    uint256

    The number of vTokens to exchange for the underlying asset in the market

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)


    redeemVerify

    Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    vToken

    address

    Asset being redeemed

    redeemer

    address

    The address redeeming the tokens

    redeemAmount

    uint256

    The amount of the underlying asset being redeemed

    redeemTokens

    uint256


    borrowAllowed

    Checks if the account should be allowed to borrow the underlying asset of the given market

    Parameters

    Name
    Type
    Description

    vToken

    address

    The market to verify the borrow against

    borrower

    address

    The account which would borrow the asset

    borrowAmount

    uint256

    The amount of underlying the account would borrow

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)


    borrowVerify

    Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    vToken

    address

    Asset whose underlying is being borrowed

    borrower

    address

    The address borrowing the underlying

    borrowAmount

    uint256

    The amount of the underlying asset requested to borrow


    repayBorrowAllowed

    Checks if the account should be allowed to repay a borrow in the given market

    Parameters

    Name
    Type
    Description

    vToken

    address

    The market to verify the repay against

    payer

    address

    The account which would repay the asset

    borrower

    address

    The account which borrowed the asset

    repayAmount

    uint256

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)


    repayBorrowVerify

    Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    vToken

    address

    Asset being repaid

    payer

    address

    The address repaying the borrow

    borrower

    address

    The address of the borrower

    actualRepayAmount

    uint256


    liquidateBorrowAllowed

    Checks if the liquidation should be allowed to occur

    Parameters

    Name
    Type
    Description

    vTokenBorrowed

    address

    Asset which was borrowed by the borrower

    vTokenCollateral

    address

    Asset which was used as collateral and will be seized

    liquidator

    address

    The address repaying the borrow and seizing the collateral

    borrower

    address


    liquidateBorrowVerify

    Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    vTokenBorrowed

    address

    Asset which was borrowed by the borrower

    vTokenCollateral

    address

    Asset which was used as collateral and will be seized

    liquidator

    address

    The address repaying the borrow and seizing the collateral

    borrower

    address


    seizeAllowed

    Checks if the seizing of assets should be allowed to occur

    Parameters

    Name
    Type
    Description

    vTokenCollateral

    address

    Asset which was used as collateral and will be seized

    vTokenBorrowed

    address

    Asset which was borrowed by the borrower

    liquidator

    address

    The address repaying the borrow and seizing the collateral

    borrower

    address


    seizeVerify

    Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    vTokenCollateral

    address

    Asset which was used as collateral and will be seized

    vTokenBorrowed

    address

    Asset which was borrowed by the borrower

    liquidator

    address

    The address repaying the borrow and seizing the collateral

    borrower

    address


    transferAllowed

    Checks if the account should be allowed to transfer tokens in the given market

    Parameters

    Name
    Type
    Description

    vToken

    address

    The market to verify the transfer against

    src

    address

    The account which sources the tokens

    dst

    address

    The account which receives the tokens

    transferTokens

    uint256

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)


    transferVerify

    Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    vToken

    address

    Asset being transferred

    src

    address

    The account which sources the tokens

    dst

    address

    The account which receives the tokens

    transferTokens

    uint256


    getBorrowingPower

    Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface

    Parameters

    Name
    Type
    Description

    account

    address

    The account get liquidity for

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    (possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)

    [1]

    uint256

    [2]

    uint256


    getAccountLiquidity

    Determine the current account liquidity wrt liquidation threshold requirements

    Parameters

    Name
    Type
    Description

    account

    address

    The account get liquidity for

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    (possible error code (semi-opaque), account liquidity in excess of liquidation threshold requirements, account shortfall below liquidation threshold requirements)

    [1]

    uint256

    [2]

    uint256


    getHypotheticalAccountLiquidity

    Determine what the account liquidity would be if the given amounts were redeemed/borrowed

    Parameters

    Name
    Type
    Description

    account

    address

    The account to determine liquidity for

    vTokenModify

    address

    The market to hypothetically redeem/borrow in

    redeemTokens

    uint256

    The number of tokens to hypothetically redeem

    borrowAmount

    uint256

    Return Values

    Name
    Type
    Description

    [0]

    uint256

    (possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)

    [1]

    uint256

    [2]

    uint256


    _setVenusSpeeds

    Set XVS speed for a single market

    Parameters

    Name
    Type
    Description

    vTokens

    contract VToken[]

    The market whose XVS speed to update

    supplySpeeds

    uint256[]

    New XVS speed for supply

    borrowSpeeds

    uint256[]

    New XVS speed for borrow


    SetterFacet

    SetterFacet

    This facet contract contains all the configurational setter functions

    Solidity API

    setPriceOracle

    Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setPriceOracle

    Sets a new price oracle for the comptroller

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setCloseFactor

    Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setCloseFactor

    Sets the closeFactor used when liquidating borrows

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setAccessControl

    Sets the address of the access control of this contract

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setCollateralFactor

    Sets the collateral factor and liquidation threshold for a market in the Core Pool only.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setLiquidationIncentive

    Sets the liquidation incentive for a market in the Core Pool only.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setCollateralFactor

    Sets the collateral factor and liquidation threshold for a market in the specified pool.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setLiquidationIncentive

    Sets the liquidation incentive for a market in the specified pool.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setLiquidatorContract

    Update the address of the liquidator contract

    Parameters

    Name
    Type
    Description

    _setPauseGuardian

    Admin function to change the Pause Guardian

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setMarketBorrowCaps

    Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface

    Parameters

    Name
    Type
    Description

    _setMarketBorrowCaps

    Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert

    Parameters

    Name
    Type
    Description

    setMarketSupplyCaps

    Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface

    Parameters

    Name
    Type
    Description

    _setMarketSupplyCaps

    Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert

    Parameters

    Name
    Type
    Description

    _setProtocolPaused

    Set whole protocol pause/unpause state

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setActionsPaused

    Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface

    Parameters

    Name
    Type
    Description

    _setActionsPaused

    Pause/unpause certain actions

    Parameters

    Name
    Type
    Description

    _setVAIController

    Sets a new VAI controller

    Return Values

    Name
    Type
    Description

    _setVAIMintRate

    Set the VAI mint rate

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setMintedVAIOf

    Set the minted VAI amount of the owner

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setTreasuryData

    Set the treasury data.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setVenusVAIVaultRate

    Set the amount of XVS distributed per block to VAI Vault

    Parameters

    Name
    Type
    Description

    _setVAIVaultInfo

    Set the VAI Vault infos

    Parameters

    Name
    Type
    Description

    setPrimeToken

    Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setPrimeToken

    Sets the prime token contract for the comptroller

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setForcedLiquidation

    Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface

    Parameters

    Name
    Type
    Description

    _setForcedLiquidation

    Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity

    Parameters

    Name
    Type
    Description

    _setForcedLiquidationForUser

    Enables forced liquidations for user's borrows in a certain market. If forced liquidation is enabled, user's borrows in the market may be liquidated regardless of the account liquidity. Forced liquidation may be enabled for a user even if it is not enabled for the entire market.

    Parameters

    Name
    Type
    Description

    setWhiteListFlashLoanAccount

    Explanation: This function grants or revokes an account's permission to use the protocol's flash loan feature, enforcing access control and address validation.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setXVSToken

    Set the address of the XVS token

    Parameters

    Name
    Type
    Description

    _setXVSVToken

    Set the address of the XVS vToken

    Parameters

    Name
    Type
    Description

    setPoolActive

    updates active status for a specific pool (excluding the Core Pool)

    Parameters

    Name
    Type
    Description

    📅 Events

    • PoolActiveStatusUpdated Emitted after the pool active status is updated.

    ❌ Errors

    • InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.

    • PoolDoesNotExist Reverts if the target pool ID does not exist.


    setIsBorrowAllowed

    Updates the isBorrowAllowed flag for a market in a pool.

    Parameters

    Name
    Type
    Description

    📅 Events

    • BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.

    ❌ Errors

    • PoolDoesNotExist Reverts if the pool ID is invalid.

    • MarketConfigNotFound Reverts if the market is not listed in the pool.


    MarketFacet

    MarketFacet

    This facet contract contains functions regarding markets

    Solidity API

    isComptroller

    Indicator that this is a Comptroller contract (for inspection)


    getAssetsIn

    Returns the vToken markets an account has entered in the Core Pool

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getAllMarkets

    Return all of the markets

    Return Values

    Name
    Type
    Description

    liquidateCalculateSeizeTokens

    Calculate number of tokens of collateral asset to seize given an underlying amount

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    liquidateCalculateSeizeTokens

    Calculate number of tokens of collateral asset to seize given an underlying amount

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    liquidateVAICalculateSeizeTokens

    Calculate number of tokens of collateral asset to seize given an underlying amount

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    checkMembership

    Returns whether the given account has entered the specified vToken market in the Core Pool

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    isMarketListed

    Checks whether the given vToken market is listed in the Core Pool (poolId = 0)

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    enterMarkets

    Add assets to be included in account liquidity calculation

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    unlistMarket

    Unlists the given vToken market from the Core Pool (poolId = 0) by setting isListed to false

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    exitMarket

    Removes asset from sender's account liquidity calculation

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    supportMarket

    Alias to _supportMarket to support the Isolated Lending Comptroller Interface

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _supportMarket

    Adds the given vToken market to the Core Pool (poolId = 0) and marks it as listed

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    updateDelegate

    Grants or revokes the borrowing or redeeming delegate rights to / from an account If allowed, the delegate will be able to borrow funds on behalf of the sender Upon a delegated borrow, the delegate will receive the funds, and the borrower will see the debt on their account Upon a delegated redeem, the delegate will receive the redeemed amount and the approver will see a deduction in his vToken balance

    Parameters

    Name
    Type
    Description

    enterPool

    Allows a user to switch to a new pool (e.g., e-mode ).

    Parameters

    Name
    Type
    Description

    📅 Events

    • PoolSelected Emitted after a successful pool switch.

    ❌ Errors

    • PoolDoesNotExist The specified pool ID does not exist.

    • AlreadyInSelectedPool The user is already in the target pool.

    • IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.

    • LiquidityCheckFailed The user's liquidity is insufficient after switching pools.


    createPool

    Creates a new pool with the given label.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    📅 Events

    • PoolCreated Emitted after successfully creating a new pool.

    ❌ Errors

    • EmptyPoolLabel Reverts if the provided label is an empty string.


    addPoolMarkets

    Batch initializes market entries with basic config.

    Parameters

    Name
    Type
    Description

    📅 Events

    • PoolMarketInitialized Emitted after successfully initializing a market in a pool.

    ❌ Errors

    • ArrayLengthMismatch Reverts if poolIds and vTokens arrays have different lengths or if the length is zero.

    • InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.

    • PoolDoesNotExist Reverts if the target pool ID does not exist.


    removePoolMarket

    Removes a market (vToken) from the specified pool.

    Parameters

    Name
    Type
    Description

    📅 Events

    • PoolMarketRemoved Emitted after a market is successfully removed from a pool.

    ❌ Errors

    • InvalidOperationForCorePool Reverts if called on the Core Pool.

    • PoolMarketNotFound Reverts if the market is not listed in the pool.


    getCollateralFactor

    Get the core pool collateral factor for a vToken

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getLiquidationThreshold

    Get the core pool liquidation threshold for a vToken

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getLiquidationIncentive

    Get the core pool liquidation Incentive for a vToken

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getEffectiveLtvFactor

    Returns the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getEffectiveLiquidationIncentive

    Get the Effective liquidation Incentive for a given account and market

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getPoolVTokens

    Returns the full list of vTokens for a given pool ID.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    ❌ Errors

    • PoolDoesNotExist Reverts if the given pool ID do not exist.

    • InvalidOperationForCorePool Reverts if called on the Core Pool.


    markets

    Returns the market configuration for a vToken in the core pool (poolId = 0).

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    poolMarkets

    Returns the market configuration for a vToken from _poolMarkets.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    ❌ Errors

    • PoolDoesNotExist Reverts if the given pool ID do not exist.


    hasValidPoolBorrows

    Returns true if the user can switch to the given target pool, i.e., all markets they have borrowed from are also borrowable in the target pool.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    uint256 BLOCKS_PER_YEAR
    address WBNB
    address VBNB
    uint256 MINIMUM_STAKED_XVS
    uint256 MAXIMUM_XVS_CAP
    uint256 STAKING_PERIOD
    function initialize(address xvsVault_, address xvsVaultRewardToken_, uint256 xvsVaultPoolId_, uint128 alphaNumerator_, uint128 alphaDenominator_, address accessControlManager_, address primeLiquidityProvider_, address comptroller_, address oracle_, uint256 loopsLimit_) external
    function getPendingRewards(address user) external returns (struct PrimeStorageV1.PendingReward[] pendingRewards)
    function updateScores(address[] users) external
    function updateAlpha(uint128 _alphaNumerator, uint128 _alphaDenominator) external
    function updateMultipliers(address market, uint256 supplyMultiplier, uint256 borrowMultiplier) external
    function setStakedAt(address[] users, uint256[] timestamps) external
    function addMarket(address market, uint256 supplyMultiplier, uint256 borrowMultiplier) external
    function setLimit(uint256 _irrevocableLimit, uint256 _revocableLimit) external
    function setMaxLoopsLimit(uint256 loopsLimit) external
    function issue(bool isIrrevocable, address[] users) external
    function xvsUpdated(address user) external
    function accrueInterestAndUpdateScore(address user, address market) external
    function claim() external
    function burn(address user) external
    function togglePause() external
    function claimInterest(address vToken) external returns (uint256)
    function claimInterest(address vToken, address user) external returns (uint256)
    function getAllMarkets() external view returns (address[])
    function claimTimeRemaining(address user) external view returns (uint256)
    function calculateAPR(address market, address user) external view returns (uint256 supplyAPR, uint256 borrowAPR)
    function estimateAPR(address market, address user, uint256 borrow, uint256 supply, uint256 xvsStaked) external view returns (uint256 supplyAPR, uint256 borrowAPR)
    function accrueInterest(address vToken) public
    function getInterestAccrued(address vToken, address user) public returns (uint256)
    function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256)
    function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external
    function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256)
    function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external
    function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256)
    function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external
    function repayBorrowAllowed(address vToken, address payer, address borrower, uint256 repayAmount) external returns (uint256)
    function repayBorrowVerify(address vToken, address payer, address borrower, uint256 actualRepayAmount, uint256 borrowerIndex) external
    function liquidateBorrowAllowed(address vTokenBorrowed, address vTokenCollateral, address liquidator, address borrower, uint256 repayAmount) external view returns (uint256)
    function liquidateBorrowVerify(address vTokenBorrowed, address vTokenCollateral, address liquidator, address borrower, uint256 actualRepayAmount, uint256 seizeTokens) external
    function seizeAllowed(address vTokenCollateral, address vTokenBorrowed, address liquidator, address borrower, uint256 seizeTokens) external returns (uint256)
    function seizeVerify(address vTokenCollateral, address vTokenBorrowed, address liquidator, address borrower, uint256 seizeTokens) external
    function transferAllowed(address vToken, address src, address dst, uint256 transferTokens) external returns (uint256)
    function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external
    function getBorrowingPower(address account) external view returns (uint256, uint256, uint256)
    function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256)
    function getHypotheticalAccountLiquidity(address account, address vTokenModify, uint256 redeemTokens, uint256 borrowAmount) external view returns (uint256, uint256, uint256)
    function _setVenusSpeeds(contract VToken[] vTokens, uint256[] supplySpeeds, uint256[] borrowSpeeds) external

    numerator of alpha. If alpha is 0.5 then numerator is 1. alphaDenominator_ must be greater than alphaNumerator_, alphaDenominator_ cannot be zero and alphaNumerator_ cannot be zero

    alphaDenominator_

    uint128

    denominator of alpha. If alpha is 0.5 then denominator is 2. alpha is alphaNumerator_/alphaDenominator_. So, 0 < alpha < 1

    accessControlManager_

    address

    Address of AccessControlManager

    primeLiquidityProvider_

    address

    Address of PrimeLiquidityProvider

    comptroller_

    address

    Address of Comptroller

    oracle_

    address

    Address of Oracle

    loopsLimit_

    uint256

    Maximum number of loops allowed in a single transaction

    hypothetical supply amount

    xvsStaked

    uint256

    hypothetical staked XVS amount

    The number of tokens being minted

    The number of tokens being redeemed

    The amount of the underlying asset the account would repay

    The amount of underlying being repaid

    borrowerIndex

    uint256

    The address of the borrower

    repayAmount

    uint256

    The amount of underlying being repaid

    The address of the borrower

    actualRepayAmount

    uint256

    The amount of underlying being repaid

    seizeTokens

    uint256

    The amount of collateral token that will be seized

    The address of the borrower

    seizeTokens

    uint256

    The number of collateral tokens to seize

    The address of the borrower

    seizeTokens

    uint256

    The number of collateral tokens to seize

    The number of vTokens to transfer

    The number of vTokens to transfer

    The amount of underlying to hypothetically borrow

    newOracle

    contract ResilientOracleInterface

    The new price oracle to set

    [0]

    uint256

    uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)

    newOracle

    contract ResilientOracleInterface

    The new price oracle to set

    [0]

    uint256

    uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)

    newCloseFactorMantissa

    uint256

    New close factor, scaled by 1e18

    [0]

    uint256

    uint256 0=success, otherwise will revert

    newCloseFactorMantissa

    uint256

    New close factor, scaled by 1e18

    [0]

    uint256

    uint256 0=success, otherwise will revert

    newAccessControlAddress

    address

    New address for the access control

    [0]

    uint256

    uint256 0=success, otherwise will revert

    vToken

    contract VToken

    The market to set the factor on

    newCollateralFactorMantissa

    uint256

    The new collateral factor, scaled by 1e18

    newLiquidationThresholdMantissa

    uint256

    The new liquidation threshold, scaled by 1e18

    [0]

    uint256

    uint256 0=success, otherwise a failure. (See ErrorReporter for details)

    vToken

    address

    The market to set the liquidationIncentive for

    newLiquidationIncentiveMantissa

    uint256

    New liquidationIncentive scaled by 1e18

    [0]

    uint256

    uint256 0=success, otherwise a failure. (See ErrorReporter for details)

    poolId

    uint96

    The ID of the pool.

    vToken

    contract VToken

    The market to set the factor on

    newCollateralFactorMantissa

    uint256

    The new collateral factor, scaled by 1e18

    newLiquidationThresholdMantissa

    uint256

    [0]

    uint256

    uint256 0=success, otherwise a failure. (See ErrorReporter for details)

    poolId

    uint96

    The ID of the pool.

    vToken

    address

    The market to set the liquidationIncentive for

    newLiquidationIncentiveMantissa

    uint256

    New liquidationIncentive scaled by 1e18

    [0]

    uint256

    uint256 0=success, otherwise a failure. (See ErrorReporter for details)

    newLiquidatorContract_

    address

    The new address of the liquidator contract

    newPauseGuardian

    address

    The address of the new Pause Guardian

    [0]

    uint256

    uint256 0=success, otherwise a failure. (See enum Error for details)

    vTokens

    contract VToken[]

    The addresses of the markets (tokens) to change the borrow caps for

    newBorrowCaps

    uint256[]

    The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed

    vTokens

    contract VToken[]

    The addresses of the markets (tokens) to change the borrow caps for

    newBorrowCaps

    uint256[]

    The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed

    vTokens

    contract VToken[]

    The addresses of the markets (tokens) to change the supply caps for

    newSupplyCaps

    uint256[]

    The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed

    vTokens

    contract VToken[]

    The addresses of the markets (tokens) to change the supply caps for

    newSupplyCaps

    uint256[]

    The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed

    state

    bool

    The new state (true=paused, false=unpaused)

    [0]

    bool

    bool The updated state of the protocol

    markets_

    address[]

    Markets to pause/unpause the actions on

    actions_

    enum Action[]

    List of action ids to pause/unpause

    paused_

    bool

    The new paused state (true=paused, false=unpaused)

    markets_

    address[]

    Markets to pause/unpause the actions on

    actions_

    enum Action[]

    List of action ids to pause/unpause

    paused_

    bool

    The new paused state (true=paused, false=unpaused)

    [0]

    uint256

    uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)

    newVAIMintRate

    uint256

    The new VAI mint rate to be set

    [0]

    uint256

    uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)

    owner

    address

    The address of the account to set

    amount

    uint256

    The amount of VAI to set to the account

    [0]

    uint256

    The number of minted VAI by owner

    newTreasuryGuardian

    address

    The new address of the treasury guardian to be set

    newTreasuryAddress

    address

    The new address of the treasury to be set

    newTreasuryPercent

    uint256

    The new treasury percent to be set

    [0]

    uint256

    uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)

    venusVAIVaultRate_

    uint256

    The amount of XVS wei per block to distribute to VAI Vault

    vault_

    address

    The address of the VAI Vault

    releaseStartBlock_

    uint256

    The start block of release to VAI Vault

    minReleaseAmount_

    uint256

    The minimum release amount to VAI Vault

    _prime

    contract IPrime

    The new prime token contract to be set

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    _prime

    contract IPrime

    The new prime token contract to be set

    [0]

    uint256

    uint 0=success, otherwise a failure (see ErrorReporter.sol for details)

    vTokenBorrowed

    address

    Borrowed vToken

    enable

    bool

    Whether to enable forced liquidations

    vTokenBorrowed

    address

    Borrowed vToken

    enable

    bool

    Whether to enable forced liquidations

    borrower

    address

    The address of the borrower

    vTokenBorrowed

    address

    Borrowed vToken

    enable

    bool

    Whether to enable forced liquidations

    account

    address

    The account to whitelist or remove

    _isWhiteListed

    bool

    True to whitelist, false to remove

    None

    xvs_

    address

    The address of the XVS token

    xvsVToken_

    address

    The address of the XVS vToken

    poolId

    uint96

    id of the pool to update

    active

    bool

    true to enable, false to disable

    poolId

    uint96

    The ID of the pool.

    vToken

    address

    The address of the market (vToken).

    borrowAllowed

    bool

    The new borrow allowed status.

    The new liquidation threshold, scaled by 1e18

    InactivePool The user is trying to enter inactive pool.

    MarketNotListedInCorePool Reverts if the market is not listed in the core pool.
  • MarketAlreadyListed Reverts if the given market is already listed in the specified pool.

  • InactivePool Reverts if attempted to add markets to an inactive pool.

  • liquidationIncentiveMantissa

    uint256

    The max liquidation incentive allowed for this market, in mantissa.

    marketPoolId

    uint96

    The pool ID this market belongs to.

    isBorrowAllowed

    bool

    Whether borrowing is allowed in this market.

    liquidationIncentiveMantissa

    uint256

    The liquidation incentive allowed for this market, in mantissa.

    marketPoolId

    uint96

    The pool ID this market belongs to.

    isBorrowAllowed

    bool

    Whether borrowing is allowed in this market.

    account

    address

    The address of the account to query

    [0]

    contract VToken[]

    assets A dynamic array of vToken markets the account has entered

    [0]

    contract VToken[]

    The list of market addresses

    vTokenBorrowed

    address

    The address of the borrowed vToken

    vTokenCollateral

    address

    The address of the collateral vToken

    actualRepayAmount

    uint256

    The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens

    [0]

    uint256

    (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)

    [1]

    uint256

    borrower

    address

    Address of borrower whose collateral is being seized

    vTokenBorrowed

    address

    The address of the borrowed vToken

    vTokenCollateral

    address

    The address of the collateral vToken

    actualRepayAmount

    uint256

    [0]

    uint256

    (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)

    [1]

    uint256

    vTokenCollateral

    address

    The address of the collateral vToken

    actualRepayAmount

    uint256

    The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens

    [0]

    uint256

    (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)

    [1]

    uint256

    account

    address

    The address of the account to check

    vToken

    contract VToken

    The vToken to check

    [0]

    bool

    True if the account is in the asset, otherwise false

    vToken

    contract VToken

    The vToken Address of the market to check

    [0]

    bool

    listed True if the (Core Pool, vToken) market is listed, otherwise false

    vTokens

    address[]

    The list of addresses of the vToken markets to be enabled

    [0]

    uint256[]

    Success indicator for whether each corresponding market was entered

    market

    address

    The address of the market (vToken) to unlist

    [0]

    uint256

    uint256 0=success, otherwise a failure (See enum Error for details)

    vTokenAddress

    address

    The address of the asset to be removed

    [0]

    uint256

    Whether or not the account successfully exited the market

    vToken

    contract VToken

    The address of the market (token) to list

    [0]

    uint256

    uint256 0=success, otherwise a failure. (See enum Error for details)

    vToken

    contract VToken

    The address of the vToken market to list in the Core Pool

    [0]

    uint256

    uint256 0=success, otherwise a failure. (See enum Error for details)

    delegate

    address

    The address to update the rights for

    approved

    bool

    Whether to grant (true) or revoke (false) the borrowing or redeeming rights

    poolId

    uint96

    The ID of the pool the user wants to enter.

    label

    string

    name for the pool (must be non-empty).

    [0]

    uint96

    poolId The incremental unique identifier of the newly created pool.

    poolIds

    uint96[]

    Array of pool IDs.

    vTokens

    address[]

    Array of market (vToken) addresses.

    poolId

    uint96

    The ID of the pool from which the market should be removed.

    vToken

    address

    The address of the market token to remove.

    vToken

    address

    The address of the vToken to get the collateral factor for

    [0]

    uint256

    The collateral factor for the vToken, scaled by 1e18

    vToken

    address

    The address of the vToken to get the liquidation threshold for

    [0]

    uint256

    The liquidation threshold for the vToken, scaled by 1e18

    vToken

    address

    The address of the vToken to get the liquidation Incentive for

    [0]

    uint256

    liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18

    account

    address

    The account whose pool is used to determine the market's risk parameters.

    vToken

    address

    The address of the vToken market.

    weightingStrategy

    enum WeightFunction

    The weighting strategy to use: - WeightFunction.USE_COLLATERAL_FACTOR to use collateral factor - WeightFunction.USE_LIQUIDATION_THRESHOLD to use liquidation threshold

    [0]

    uint256

    factor The effective loan-to-value factor, scaled by 1e18.

    account

    address

    The account whose pool is used to determine the market's risk parameters

    vToken

    address

    The address of the vToken market

    [0]

    uint256

    The liquidation Incentive for the vToken, scaled by 1e18

    poolId

    uint96

    The ID of the pool whose vTokens are being queried.

    [0]

    address[]

    An array of vToken addresses associated with the pool.

    vToken

    address

    The address of the vToken whose market configuration is to be fetched.

    isListed

    bool

    Whether the market is listed and enabled.

    collateralFactorMantissa

    uint256

    The maximum borrowable percentage of collateral, in mantissa.

    isVenus

    bool

    Whether this market is eligible for VENUS rewards.

    liquidationThresholdMantissa

    uint256

    poolId

    uint96

    The ID of the pool whose market configuration is being queried.

    vToken

    address

    The address of the vToken whose market configuration is to be fetched.

    isListed

    bool

    Whether the market is listed and enabled.

    collateralFactorMantissa

    uint256

    The maximum borrowable percentage of collateral, in mantissa.

    isVenus

    bool

    Whether this market is eligible for XVS rewards.

    liquidationThresholdMantissa

    uint256

    account

    address

    The address of the user attempting to switch pools.

    targetPoolId

    uint96

    The pool ID the user wants to switch into.

    [0]

    bool

    bool True if the switch is allowed, otherwise False.

    The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens

    The threshold at which liquidation is triggered, in mantissa.

    The threshold at which liquidation is triggered, in mantissa.

    function setPriceOracle(contract ResilientOracleInterface newOracle) external returns (uint256)
    function _setPriceOracle(contract ResilientOracleInterface newOracle) external returns (uint256)
    function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256)
    function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256)
    function _setAccessControl(address newAccessControlAddress) external returns (uint256)
    function setCollateralFactor(contract VToken vToken, uint256 newCollateralFactorMantissa, uint256 newLiquidationThresholdMantissa) external returns (uint256)
    function setLiquidationIncentive(address vToken, uint256 newLiquidationIncentiveMantissa) external returns (uint256)
    function setCollateralFactor(uint96 poolId, contract VToken vToken, uint256 newCollateralFactorMantissa, uint256 newLiquidationThresholdMantissa) external returns (uint256)
    function setLiquidationIncentive(uint96 poolId, address vToken, uint256 newLiquidationIncentiveMantissa) external returns (uint256)
    function _setLiquidatorContract(address newLiquidatorContract_) external
    function _setPauseGuardian(address newPauseGuardian) external returns (uint256)
    function setMarketBorrowCaps(contract VToken[] vTokens, uint256[] newBorrowCaps) external
    function _setMarketBorrowCaps(contract VToken[] vTokens, uint256[] newBorrowCaps) external
    function setMarketSupplyCaps(contract VToken[] vTokens, uint256[] newSupplyCaps) external
    function _setMarketSupplyCaps(contract VToken[] vTokens, uint256[] newSupplyCaps) external
    function _setProtocolPaused(bool state) external returns (bool)
    function setActionsPaused(address[] markets_, enum Action[] actions_, bool paused_) external
    function _setActionsPaused(address[] markets_, enum Action[] actions_, bool paused_) external
    function _setVAIController(contract VAIControllerInterface vaiController_) external returns (uint256)
    function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256)
    function setMintedVAIOf(address owner, uint256 amount) external returns (uint256)
    function _setTreasuryData(address newTreasuryGuardian, address newTreasuryAddress, uint256 newTreasuryPercent) external returns (uint256)
    function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external
    function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external
    function setPrimeToken(contract IPrime _prime) external returns (uint256)
    function _setPrimeToken(contract IPrime _prime) external returns (uint256)
    function setForcedLiquidation(address vTokenBorrowed, bool enable) external
    function _setForcedLiquidation(address vTokenBorrowed, bool enable) external
    function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external
    function setWhiteListFlashLoanAccount(address account, bool _isWhiteListed) external 
    function _setXVSToken(address xvs_) external
    function _setXVSVToken(address xvsVToken_) external
    function setPoolActive(uint96 poolId, bool active) external
    function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external
    function isComptroller() public pure returns (bool)
    function getAssetsIn(address account) external view returns (contract VToken[])
    function getAllMarkets() external view returns (contract VToken[])
    function liquidateCalculateSeizeTokens(address vTokenBorrowed, address vTokenCollateral, uint256 actualRepayAmount) external view returns (uint256, uint256)
    function liquidateCalculateSeizeTokens(address borrower, address vTokenBorrowed, address vTokenCollateral, uint256 actualRepayAmount) external view returns (uint256, uint256)
    function liquidateVAICalculateSeizeTokens(address vTokenCollateral, uint256 actualRepayAmount) external view returns (uint256, uint256)
    function checkMembership(address account, contract VToken vToken) external view returns (bool)
    function isMarketListed(contract VToken vToken) external view returns (bool)
    function enterMarkets(address[] vTokens) external returns (uint256[])
    function unlistMarket(address market) external returns (uint256)
    function exitMarket(address vTokenAddress) external returns (uint256)
    function supportMarket(contract VToken vToken) external returns (uint256)
    function _supportMarket(contract VToken vToken) external returns (uint256)
    function updateDelegate(address delegate, bool approved) external
    function enterPool(uint96 poolId) external
    function createPool(string label) external returns (uint96)
    function addPoolMarkets(uint96[] poolIds, address[] vTokens) external
    function removePoolMarket(uint96 poolId, address vToken) external
    function getCollateralFactor(address vToken) external view returns (uint256)
    function getLiquidationThreshold(address vToken) external view returns (uint256)
    function getLiquidationIncentive(address vToken) external view returns (uint256)
    function getEffectiveLtvFactor(address account, address vToken, enum WeightFunction weightingStrategy) external view returns (uint256)
    function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256)
    function getPoolVTokens(uint96 poolId) external view returns (address[])
    function markets(address vToken) external view returns (bool isListed, uint256 collateralFactorMantissa, bool isVenus, uint256 liquidationThresholdMantissa, uint256 liquidationIncentiveMantissa, uint96 marketPoolId, bool isBorrowAllowed)
    function poolMarkets(uint96 poolId, address vToken) public view returns (bool isListed, uint256 collateralFactorMantissa, bool isVenus, uint256 liquidationThresholdMantissa, uint256 liquidationIncentiveMantissa, uint96 marketPoolId, bool isBorrowAllowed)
    function hasValidPoolBorrows(address account, uint96 targetPoolId) public view returns (bool)

    VToken

    Venus's vToken Contract

    Abstract base for vTokens

    Solidity API

    transfer

    Transfer amount tokens from msg.sender to dst

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    transferFrom

    Transfer amount tokens from src to dst

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    approve

    Approve spender to transfer up to amount from src

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    balanceOfUnderlying

    Get the underlying balance of the owner

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    totalBorrowsCurrent

    Returns the current total borrows plus accrued interest

    Return Values

    Name
    Type
    Description

    borrowBalanceCurrent

    Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    seize

    Transfers collateral tokens (this market) to the liquidator.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _setPendingAdmin

    Begins transfer of admin rights. The newPendingAdmin must call _acceptAdmin to finalize the transfer.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _acceptAdmin

    Accepts transfer of admin rights. msg.sender must be pendingAdmin

    Return Values

    Name
    Type
    Description

    _setReserveFactor

    accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh

    Return Values

    Name
    Type
    Description

    setAccessControlManager

    Sets the address of the access control manager of this contract

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    _reduceReserves

    Accrues interest and reduces reserves by transferring to protocol share reserve

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    allowance

    Get the current allowance from owner for spender

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    balanceOf

    Get the token balance of the owner

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getAccountSnapshot

    Get a snapshot of the account's balances, and the cached exchange rate

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    supplyRatePerBlock

    Returns the current per-block supply interest rate for this vToken

    Return Values

    Name
    Type
    Description

    borrowRatePerBlock

    Returns the current per-block borrow interest rate for this vToken

    Return Values

    Name
    Type
    Description

    getCash

    Get cash balance of this vToken in the underlying asset

    Return Values

    Name
    Type
    Description

    setReduceReservesBlockDelta

    Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve

    Parameters

    Name
    Type
    Description

    setProtocolShareReserve

    Sets protocol share reserve contract address

    Parameters

    Name
    Type
    Description

    initialize

    Initialize the money market

    Parameters

    Name
    Type
    Description

    exchangeRateCurrent

    Accrue interest then return the up-to-date exchange rate

    Return Values

    Name
    Type
    Description

    accrueInterest

    Applies accrued interest to total borrows and reserves


    _setComptroller

    Sets a new comptroller for the market

    Return Values

    Name
    Type
    Description

    _setInterestRateModel

    Accrues interest and updates the interest rate model using _setInterestRateModelFresh

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    exchangeRateStored

    Calculates the exchange rate from the underlying to the VToken

    Return Values

    Name
    Type
    Description

    borrowBalanceStored

    Return the borrow balance of account based on stored data

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    transferOutUnderlyingFlashLoan

    Transfers the underlying asset to the specified address for flash loan operations.

    Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying asset and tracks the flash loan amount.

    Parameters

    Name
    Type
    Description

    transferInUnderlyingFlashLoan

    Transfers the underlying asset from the specified address for flash loan repayment.

    Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying asset for flash loan repayment and handles protocol fee distribution to the protocol share reserve.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    calculateFlashLoanFee

    Calculates the total fee and protocol fee for a flash loan amount. Reverts if flash loans are disabled.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setFlashLoanEnabled

    Sets flash loan status for the market. Governance-restricted.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    setFlashLoanFeeMantissa

    Updates the flash loan fee parameters. Governance-restricted.

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    struct MintLocalVars {
      enum CarefulMath.MathError mathErr;
      uint256 exchangeRateMantissa;
      uint256 mintTokens;
      uint256 totalSupplyNew;
      uint256 accountTokensNew;
      uint256 actualMintAmount;
    }
    struct RedeemLocalVars {
      enum CarefulMath.MathError mathErr;
      uint256 exchangeRateMantissa;
      uint256 redeemTokens;
      uint256 redeemAmount;
      uint256 totalSupplyNew;
      uint256 accountTokensNew;
    }
    struct BorrowLocalVars {
      enum CarefulMath.MathError mathErr;
      uint256 accountBorrows;
      uint256 accountBorrowsNew;
      uint256 totalBorrowsNew;
    }
    struct RepayBorrowLocalVars {
      enum TokenErrorReporter.Error err;
      enum CarefulMath.MathError mathErr;
      uint256 repayAmount;
      uint256 borrowerIndex;
      uint256 accountBorrows;
      uint256 accountBorrowsNew;
      uint256 totalBorrowsNew;
      uint256 actualRepayAmount;
    }

    symbol_

    string

    EIP-20 symbol of this token

    decimals_

    uint8

    EIP-20 decimal precision of this token

    dst

    address

    The address of the destination account

    amount

    uint256

    The number of tokens to transfer

    [0]

    bool

    Whether or not the transfer succeeded

    src

    address

    The address of the source account

    dst

    address

    The address of the destination account

    amount

    uint256

    The number of tokens to transfer

    [0]

    bool

    Whether or not the transfer succeeded

    spender

    address

    The address of the account which may transfer tokens

    amount

    uint256

    The number of tokens that are approved (type(uint256).max means infinite)

    [0]

    bool

    Whether or not the approval succeeded

    owner

    address

    The address of the account to query

    [0]

    uint256

    The amount of underlying owned by owner

    [0]

    uint256

    The total borrows with interest

    account

    address

    The address whose balance should be calculated after updating borrowIndex

    [0]

    uint256

    The calculated balance

    liquidator

    address

    The account receiving seized collateral

    borrower

    address

    The account having collateral seized

    seizeTokens

    uint256

    The number of vTokens to seize

    [0]

    uint256

    uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).

    newPendingAdmin

    address payable

    New pending admin.

    [0]

    uint256

    uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).

    [0]

    uint256

    uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).

    [0]

    uint256

    uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).

    newAccessControlManagerAddress

    address

    New address for the access control

    [0]

    uint256

    uint 0=success, otherwise will revert

    reduceAmount_

    uint256

    Amount of reduction to reserves

    [0]

    uint256

    uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).

    owner

    address

    The address of the account which owns the tokens to be spent

    spender

    address

    The address of the account which may transfer tokens

    [0]

    uint256

    The number of tokens allowed to be spent (type(uint256).max means infinite)

    owner

    address

    The address of the account to query

    [0]

    uint256

    The number of tokens owned by owner

    account

    address

    Address of the account to snapshot

    [0]

    uint256

    (possible error, token balance, borrow balance, exchange rate mantissa)

    [1]

    uint256

    [2]

    uint256

    [3]

    uint256

    [0]

    uint256

    The supply interest rate per block, scaled by 1e18

    [0]

    uint256

    The borrow interest rate per block, scaled by 1e18

    [0]

    uint256

    The quantity of underlying asset owned by this contract

    newReduceReservesBlockDelta_

    uint256

    block difference value

    protcolShareReserve_

    address payable

    The address of protocol share reserve contract

    comptroller_

    contract ComptrollerInterface

    The address of the Comptroller

    interestRateModel_

    contract InterestRateModelV8

    The address of the interest rate model

    initialExchangeRateMantissa_

    uint256

    The initial exchange rate, scaled by 1e18

    name_

    string

    [0]

    uint256

    Calculated exchange rate scaled by 1e18

    [0]

    uint256

    uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).

    newInterestRateModel_

    contract InterestRateModelV8

    The new interest rate model to use

    [0]

    uint256

    uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).

    [0]

    uint256

    Calculated exchange rate scaled by 1e18

    account

    address

    The address whose balance should be calculated

    [0]

    uint256

    The calculated balance

    to

    address payable

    The address to which the underlying asset is transferred

    amount

    uint256

    The amount of the underlying asset to transfer

    from

    address payable

    The address from which the underlying asset is transferred

    repaymentAmount

    uint256

    The amount of the underlying asset to transfer

    totalFee

    uint256

    The total fee amount for the flash loan

    protocolFee

    uint256

    The protocol fee amount to be transferred to the protocol share reserve

    [0]

    uint256

    The actual amount transferred in

    amount

    uint256

    The amount of the flash loan

    [0]

    uint256

    The total fee for the flash loan

    [1]

    uint256

    The portion of the total fees that goes to the protocol share reserve

    enabled

    bool

    True to enable flash loans, false to disable

    [0]

    uint256

    Status code (e.g., success/failure)

    flashLoanFeeMantissa_

    uint256

    New flash loan fee (scaled by 1e18)

    flashLoanProtocolShare_

    uint256

    New protocol fee share (scaled by 1e18)

    [0]

    uint256

    Status code (e.g., success/failure)

    EIP-20 name of this token

    function transfer(address dst, uint256 amount) external returns (bool)
    function transferFrom(address src, address dst, uint256 amount) external returns (bool)
    function approve(address spender, uint256 amount) external returns (bool)
    function balanceOfUnderlying(address owner) external returns (uint256)
    function totalBorrowsCurrent() external returns (uint256)
    function borrowBalanceCurrent(address account) external returns (uint256)
    function seize(address liquidator, address borrower, uint256 seizeTokens) external returns (uint256)
    function _setPendingAdmin(address payable newPendingAdmin) external returns (uint256)
    function _acceptAdmin() external returns (uint256)
    function _setReserveFactor(uint256 newReserveFactorMantissa_) external returns (uint256)
    function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint256)
    function _reduceReserves(uint256 reduceAmount_) external virtual returns (uint256)
    function allowance(address owner, address spender) external view returns (uint256)
    function balanceOf(address owner) external view returns (uint256)
    function getAccountSnapshot(address account) external view returns (uint256, uint256, uint256, uint256)
    function supplyRatePerBlock() external view returns (uint256)
    function borrowRatePerBlock() external view returns (uint256)
    function getCash() external view returns (uint256)
    function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external
    function setProtocolShareReserve(address payable protcolShareReserve_) external
    function initialize(contract ComptrollerInterface comptroller_, contract InterestRateModelV8 interestRateModel_, uint256 initialExchangeRateMantissa_, string name_, string symbol_, uint8 decimals_) public
    function exchangeRateCurrent() public returns (uint256)
    function accrueInterest() public virtual returns (uint256)
    function _setComptroller(contract ComptrollerInterface newComptroller) public returns (uint256)
    function _setInterestRateModel(contract InterestRateModelV8 newInterestRateModel_) public returns (uint256)
    function exchangeRateStored() public view returns (uint256)
    function borrowBalanceStored(address account) public view returns (uint256)
    function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external
    function transferInUnderlyingFlashLoan(
        address payable from,
        uint256 repaymentAmount,
        uint256 totalFee,
        uint256 protocolFee
    ) external returns (uint256)
    function calculateFlashLoanFee(uint256 amount)
        public
        view
        returns (uint256, uint256);
    function setFlashLoanEnabled(bool enabled) external returns (uint256)
    function setFlashLoanFeeMantissa(
        uint256 flashLoanFeeMantissa_,
        uint256 flashLoanProtocolShare_
    )
        external
        returns (uint256);

    Comptroller

    Comptroller

    The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating, and seizing done by the vToken contract. Each pool has one Comptroller checking these interactions across markets. When a user interacts with a given market by one of these main actions, a call is made to a corresponding hook in the associated Comptroller, which either allows or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow, as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation.

    The Comptroller also includes two functions liquidateAccount() and healAccount(), which are meant to handle accounts that do not exceed the minLiquidatableCollateral for the Comptroller:

    • healAccount(): This function is called to seize all of a given user’s collateral, requiring the msg.sender repay a certain percentage of the debt calculated by collateral/(borrows*liquidationIncentive). The function can only be called if the calculated percentage does not exceed 100%, because otherwise no badDebt would be created and liquidateAccount() should be used instead. The difference in the actual amount of debt and debt paid off is recorded as badDebt for each market, which can then be auctioned off for the risk reserves of the associated pool.

    Solidity API

    enterMarkets

    Add assets to be included in account liquidity calculation; enabling them to be used as collateral

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    📅 Events

    • MarketEntered is emitted for each market on success

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • ActionPaused error is thrown if entering any of the markets is paused

    • MarketNotListed error is thrown if any of the markets is not listed


    updateDelegate

    Grants or revokes the borrowing delegate rights to / from an account If allowed, the delegate will be able to borrow funds on behalf of the sender Upon a delegated borrow, the delegate will receive the funds, and the borrower will see the debt on their account

    Parameters

    Name
    Type
    Description

    📅 Events

    • DelegateUpdated emits on success

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • ZeroAddressNotAllowed is thrown when delegate address is zero


    exitMarket

    Removes asset from sender's account liquidity calculation; disabling them as collateral

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    📅 Events

    • MarketExited is emitted on success

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • ActionPaused error is thrown if exiting the market is paused

    • NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market

    • MarketNotListed error is thrown when the market is not listed

    • InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency


    preMintHook

    Checks if the account should be allowed to mint tokens in the given market

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • ActionPaused error is thrown if supplying to this market is paused

    • MarketNotListed error is thrown when the market is not listed

    • SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting


    mintVerify

    Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    preRedeemHook

    Checks if the account should be allowed to redeem tokens in the given market

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • ActionPaused error is thrown if withdrawals are paused in this market

    • MarketNotListed error is thrown when the market is not listed

    • InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency

    • SnapshotError is thrown if some vToken fails to return the account's supply and borrows


    redeemVerify

    Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    repayBorrowVerify

    Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    liquidateBorrowVerify

    Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    seizeVerify

    Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    transferVerify

    Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    preBorrowHook

    disable-eslint


    borrowVerify

    Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.

    Parameters

    Name
    Type
    Description

    preRepayHook

    Checks if the account should be allowed to repay a borrow in the given market

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • ActionPaused error is thrown if repayments are paused in this market

    • MarketNotListed error is thrown when the market is not listed


    preLiquidateHook

    Checks if the liquidation should be allowed to occur

    Parameters

    Name
    Type
    Description

    ❌ Errors

    • ActionPaused error is thrown if liquidations are paused in this market

    • MarketNotListed error is thrown if either collateral or borrowed token is not listed

    • TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor

    • MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations


    preSeizeHook

    Checks if the seizing of assets should be allowed to occur

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • ActionPaused error is thrown if seizing this type of collateral is paused

    • MarketNotListed error is thrown if either collateral or borrowed token is not listed

    • ComptrollerMismatch error is when seizer contract or seized asset belong to different pools


    preTransferHook

    Checks if the account should be allowed to transfer tokens in the given market

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • ActionPaused error is thrown if withdrawals are paused in this market

    • MarketNotListed error is thrown when the market is not listed

    • InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency

    • SnapshotError is thrown if some vToken fails to return the account's supply and borrows


    healAccount

    Seizes all the remaining collateral, makes msg.sender repay the existing borrows, and treats the rest of the debt as bad debt (for each market). The sender has to repay a certain percentage of the debt, computed as collateral / (borrows * liquidationIncentive).

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • CollateralExceedsThreshold error is thrown when the collateral is too big for healing

    • SnapshotError is thrown if some vToken fails to return the account's supply and borrows

    • PriceError is thrown if the oracle returns an incorrect price for some asset


    liquidateAccount

    Liquidates all borrows of the borrower. Callable only if the collateral is less than a predefined threshold, and the account collateral can be seized to cover all borrows. If the collateral is higher than the threshold, use regular liquidations. If the collateral is below the threshold, and the account is insolvent, use healAccount.

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Not restricted

    ❌ Errors

    • CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation

    • InsufficientCollateral error is thrown when there is not enough collateral to cover the debt

    • SnapshotError is thrown if some vToken fails to return the account's supply and borrows

    • PriceError is thrown if the oracle returns an incorrect price for some asset


    setCloseFactor

    Sets the closeFactor to use when liquidating borrows

    Parameters

    Name
    Type
    Description

    📅 Events

    • Emits NewCloseFactor on success

    ⛔️ Access Requirements

    • Controlled by AccessControlManager


    setCollateralFactor

    Sets the collateralFactor for a market

    Parameters

    Name
    Type
    Description

    📅 Events

    • Emits NewCollateralFactor when collateral factor is updated

    • and NewLiquidationThreshold when liquidation threshold is updated

    ⛔️ Access Requirements

    • Controlled by AccessControlManager

    ❌ Errors

    • MarketNotListed error is thrown when the market is not listed

    • InvalidCollateralFactor error is thrown when collateral factor is too high

    • InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor

    • PriceError is thrown when the oracle returns an invalid price for the asset


    setLiquidationIncentive

    Sets liquidationIncentive

    Parameters

    Name
    Type
    Description

    📅 Events

    • Emits NewLiquidationIncentive on success

    ⛔️ Access Requirements

    • Controlled by AccessControlManager


    supportMarket

    Add the market to the markets mapping and set it as listed

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Only PoolRegistry

    ❌ Errors

    • MarketAlreadyListed is thrown if the market is already listed in this pool


    setMarketBorrowCaps

    Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Controlled by AccessControlManager


    setMarketSupplyCaps

    Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Controlled by AccessControlManager


    setActionsPaused

    Pause/unpause specified actions

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Controlled by AccessControlManager


    setMinLiquidatableCollateral

    Set the given collateral threshold for non-batch liquidations. Regular liquidations will fail if the collateral amount is less than this threshold. Liquidators should use batch operations like liquidateAccount or healAccount.

    Parameters

    Name
    Type
    Description

    ⛔️ Access Requirements

    • Controlled by AccessControlManager


    addRewardsDistributor

    Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor contracts with the same rewardToken, and there could be overlaping among them considering the last reward block

    Parameters

    Name
    Type
    Description

    📅 Events

    • Emits NewRewardsDistributor with distributor address

    ⛔️ Access Requirements

    • Only Governance


    setPriceOracle

    Sets a new price oracle for the Comptroller

    Parameters

    Name
    Type
    Description

    📅 Events

    • Emits NewPriceOracle on success

    ❌ Errors

    • ZeroAddressNotAllowed is thrown when the new oracle address is zero


    setMaxLoopsLimit

    Set the for loop iteration limit to avoid DOS

    Parameters

    Name
    Type
    Description

    setPrimeToken

    Sets the prime token contract for the comptroller

    Parameters

    Name
    Type
    Description

    setForcedLiquidation

    Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity

    Parameters

    Name
    Type
    Description

    getAccountLiquidity

    Determine the current account liquidity with respect to liquidation threshold requirements

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getBorrowingPower

    Determine the current account liquidity with respect to collateral requirements

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getHypotheticalAccountLiquidity

    Determine what the account liquidity would be if the given amounts were redeemed/borrowed

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getAllMarkets

    Return all of the markets

    Return Values

    Name
    Type
    Description

    isMarketListed

    Check if a market is marked as listed (active)

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getAssetsIn

    Returns the assets an account has entered

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    checkMembership

    Returns whether the given account is entered in a given market

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    liquidateCalculateSeizeTokens

    Calculate number of tokens of collateral asset to seize given an underlying amount

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    ❌ Errors

    • PriceError if the oracle returns an invalid price


    getRewardsByMarket

    Returns reward speed given a vToken

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    getRewardDistributors

    Return all reward distributors for this pool

    Return Values

    Name
    Type
    Description

    isComptroller

    A marker method that returns true for a valid Comptroller contract

    Return Values

    Name
    Type
    Description

    updatePrices

    Update the prices of all the tokens associated with the provided account

    Parameters

    Name
    Type
    Description

    actionPaused

    Checks if a certain action is paused on a market

    Parameters

    Name
    Type
    Description

    Return Values

    Name
    Type
    Description

    liquidateAccount(): This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation incentive. Otherwise, the pool will incur bad debt, in which case the function healAccount() should be used instead. This function skips the logic verifying that the repay amount does not exceed the close factor.

    SnapshotError is thrown if some vToken fails to return the account's supply and borrows

  • PriceError is thrown if the oracle returns an incorrect price for some asset

  • PriceError is thrown if the oracle returns an incorrect price for some asset

    borrowerIndex

    uint256

    actualRepayAmount

    uint256

    The amount of underlying being repaid

    seizeTokens

    uint256

    The amount of collateral token that will be seized

    seizeTokens

    uint256

    The number of collateral tokens to seize

    skipLiquidityCheck

    bool

    Allows the borrow to be liquidated regardless of the account liquidity

  • InsufficientShortfall is thrown when trying to liquidate a healthy account

  • SnapshotError is thrown if some vToken fails to return the account's supply and borrows

  • PriceError is thrown if the oracle returns an incorrect price for some asset

  • PriceError is thrown if the oracle returns an incorrect price for some asset

  • vTokens

    address[]

    The list of addresses of the vToken markets to be enabled

    [0]

    uint256[]

    errors An array of NO_ERROR for compatibility with Venus core tooling

    delegate

    address

    The address to update the rights for

    allowBorrows

    bool

    Whether to grant (true) or revoke (false) the rights

    vTokenAddress

    address

    The address of the asset to be removed

    [0]

    uint256

    error Always NO_ERROR for compatibility with Venus core tooling

    vToken

    address

    The market to verify the mint against

    minter

    address

    The account which would get the minted tokens

    mintAmount

    uint256

    The amount of underlying being supplied to the market in exchange for tokens

    vToken

    address

    Asset being minted

    minter

    address

    The address minting the tokens

    actualMintAmount

    uint256

    The amount of the underlying asset being minted

    mintTokens

    uint256

    vToken

    address

    The market to verify the redeem against

    redeemer

    address

    The account which would redeem the tokens

    redeemTokens

    uint256

    The number of vTokens to exchange for the underlying asset in the market

    vToken

    address

    Asset being redeemed

    redeemer

    address

    The address redeeming the tokens

    redeemAmount

    uint256

    The amount of the underlying asset being redeemed

    redeemTokens

    uint256

    vToken

    address

    Asset being repaid

    payer

    address

    The address repaying the borrow

    borrower

    address

    The address of the borrower

    actualRepayAmount

    uint256

    vTokenBorrowed

    address

    Asset which was borrowed by the borrower

    vTokenCollateral

    address

    Asset which was used as collateral and will be seized

    liquidator

    address

    The address repaying the borrow and seizing the collateral

    borrower

    address

    vTokenCollateral

    address

    Asset which was used as collateral and will be seized

    vTokenBorrowed

    address

    Asset which was borrowed by the borrower

    liquidator

    address

    The address repaying the borrow and seizing the collateral

    borrower

    address

    vToken

    address

    Asset being transferred

    src

    address

    The account which sources the tokens

    dst

    address

    The account which receives the tokens

    transferTokens

    uint256

    vToken

    address

    Asset whose underlying is being borrowed

    borrower

    address

    The address borrowing the underlying

    borrowAmount

    uint256

    The amount of the underlying asset requested to borrow

    vToken

    address

    The market to verify the repay against

    borrower

    address

    The account which would borrowed the asset

    vTokenBorrowed

    address

    Asset which was borrowed by the borrower

    vTokenCollateral

    address

    Asset which was used as collateral and will be seized

    borrower

    address

    The address of the borrower

    repayAmount

    uint256

    vTokenCollateral

    address

    Asset which was used as collateral and will be seized

    seizerContract

    address

    Contract that tries to seize the asset (either borrowed vToken or Comptroller)

    liquidator

    address

    The address repaying the borrow and seizing the collateral

    borrower

    address

    vToken

    address

    The market to verify the transfer against

    src

    address

    The account which sources the tokens

    dst

    address

    The account which receives the tokens

    transferTokens

    uint256

    user

    address

    account to heal

    borrower

    address

    the borrower address

    orders

    struct ComptrollerStorage.LiquidationOrder[]

    an array of liquidation orders

    newCloseFactorMantissa

    uint256

    New close factor, scaled by 1e18

    vToken

    contract VToken

    The market to set the factor on

    newCollateralFactorMantissa

    uint256

    The new collateral factor, scaled by 1e18

    newLiquidationThresholdMantissa

    uint256

    The new liquidation threshold, scaled by 1e18

    newLiquidationIncentiveMantissa

    uint256

    New liquidationIncentive scaled by 1e18

    vToken

    contract VToken

    The address of the market (token) to list

    vTokens

    contract VToken[]

    The addresses of the markets (tokens) to change the borrow caps for

    newBorrowCaps

    uint256[]

    The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.

    vTokens

    contract VToken[]

    The addresses of the markets (tokens) to change the supply caps for

    newSupplyCaps

    uint256[]

    The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.

    marketsList

    contract VToken[]

    Markets to pause/unpause the actions on

    actionsList

    enum ComptrollerStorage.Action[]

    List of action ids to pause/unpause

    paused

    bool

    The new paused state (true=paused, false=unpaused)

    newMinLiquidatableCollateral

    uint256

    The new min liquidatable collateral (in USD).

    _rewardsDistributor

    contract RewardsDistributor

    Address of the RewardDistributor contract to add

    newOracle

    contract ResilientOracleInterface

    Address of the new price oracle to set

    limit

    uint256

    Limit for the max loops can execute at a time

    _prime

    contract IPrime

    Address of the Prime contract

    vTokenBorrowed

    address

    Borrowed vToken

    enable

    bool

    Whether to enable forced liquidations

    account

    address

    The account get liquidity for

    error

    uint256

    Always NO_ERROR for compatibility with Venus core tooling

    liquidity

    uint256

    Account liquidity in excess of liquidation threshold requirements,

    shortfall

    uint256

    Account shortfall below liquidation threshold requirements

    account

    address

    The account get liquidity for

    error

    uint256

    Always NO_ERROR for compatibility with Venus core tooling

    liquidity

    uint256

    Account liquidity in excess of collateral requirements,

    shortfall

    uint256

    Account shortfall below collateral requirements

    account

    address

    The account to determine liquidity for

    vTokenModify

    address

    The market to hypothetically redeem/borrow in

    redeemTokens

    uint256

    The number of tokens to hypothetically redeem

    borrowAmount

    uint256

    error

    uint256

    Always NO_ERROR for compatibility with Venus core tooling

    liquidity

    uint256

    Hypothetical account liquidity in excess of collateral requirements,

    shortfall

    uint256

    Hypothetical account shortfall below collateral requirements

    [0]

    contract VToken[]

    markets The list of market addresses

    vToken

    contract VToken

    vToken Address for the market to check

    [0]

    bool

    listed True if listed otherwise false

    account

    address

    The address of the account to pull assets for

    [0]

    contract VToken[]

    A list with the assets the account has entered

    account

    address

    The address of the account to check

    vToken

    contract VToken

    The vToken to check

    [0]

    bool

    True if the account is in the market specified, otherwise false.

    vTokenBorrowed

    address

    The address of the borrowed vToken

    vTokenCollateral

    address

    The address of the collateral vToken

    actualRepayAmount

    uint256

    The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens

    error

    uint256

    Always NO_ERROR for compatibility with Venus core tooling

    tokensToSeize

    uint256

    Number of vTokenCollateral tokens to be seized in a liquidation

    vToken

    address

    The vToken to get the reward speeds for

    rewardSpeeds

    struct ComptrollerStorage.RewardSpeeds[]

    Array of total supply and borrow speeds and reward token for all reward distributors

    [0]

    contract RewardsDistributor[]

    Array of RewardDistributor addresses

    [0]

    bool

    Always true

    account

    address

    Address of the account to get associated tokens with

    market

    address

    vToken address

    action

    enum ComptrollerStorage.Action

    Action to check

    [0]

    bool

    paused True if the action is paused otherwise false

    The number of tokens being minted

    The number of tokens being redeemed

    The amount of underlying being repaid

    The address of the borrower

    The address of the borrower

    The number of vTokens to transfer

    The amount of underlying being repaid

    The address of the borrower

    The number of vTokens to transfer

    The amount of underlying to hypothetically borrow

    function enterMarkets(address[] vTokens) external returns (uint256[])
    function updateDelegate(address delegate, bool allowBorrows) external
    function exitMarket(address vTokenAddress) external returns (uint256)
    function preMintHook(address vToken, address minter, uint256 mintAmount) external
    function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external
    function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external
    function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external
    function repayBorrowVerify(address vToken, address payer, address borrower, uint256 actualRepayAmount, uint256 borrowerIndex) external
    function liquidateBorrowVerify(address vTokenBorrowed, address vTokenCollateral, address liquidator, address borrower, uint256 actualRepayAmount, uint256 seizeTokens) external
    function seizeVerify(address vTokenCollateral, address vTokenBorrowed, address liquidator, address borrower, uint256 seizeTokens) external
    function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external
    function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external
    function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external
    function preRepayHook(address vToken, address borrower) external
    function preLiquidateHook(address vTokenBorrowed, address vTokenCollateral, address borrower, uint256 repayAmount, bool skipLiquidityCheck) external
    function preSeizeHook(address vTokenCollateral, address seizerContract, address liquidator, address borrower) external
    function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external
    function healAccount(address user) external
    function liquidateAccount(address borrower, struct ComptrollerStorage.LiquidationOrder[] orders) external
    function setCloseFactor(uint256 newCloseFactorMantissa) external
    function setCollateralFactor(contract VToken vToken, uint256 newCollateralFactorMantissa, uint256 newLiquidationThresholdMantissa) external
    function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external
    function supportMarket(contract VToken vToken) external
    function setMarketBorrowCaps(contract VToken[] vTokens, uint256[] newBorrowCaps) external
    function setMarketSupplyCaps(contract VToken[] vTokens, uint256[] newSupplyCaps) external
    function setActionsPaused(contract VToken[] marketsList, enum ComptrollerStorage.Action[] actionsList, bool paused) external
    function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external
    function addRewardsDistributor(contract RewardsDistributor _rewardsDistributor) external
    function setPriceOracle(contract ResilientOracleInterface newOracle) external
    function setMaxLoopsLimit(uint256 limit) external
    function setPrimeToken(contract IPrime _prime) external
    function setForcedLiquidation(address vTokenBorrowed, bool enable) external
    function getAccountLiquidity(address account) external view returns (uint256 error, uint256 liquidity, uint256 shortfall)
    function getBorrowingPower(address account) external view returns (uint256 error, uint256 liquidity, uint256 shortfall)
    function getHypotheticalAccountLiquidity(address account, address vTokenModify, uint256 redeemTokens, uint256 borrowAmount) external view returns (uint256 error, uint256 liquidity, uint256 shortfall)
    function getAllMarkets() external view returns (contract VToken[])
    function isMarketListed(contract VToken vToken) external view returns (bool)
    function getAssetsIn(address account) external view returns (contract VToken[])
    function checkMembership(address account, contract VToken vToken) external view returns (bool)
    function liquidateCalculateSeizeTokens(address vTokenBorrowed, address vTokenCollateral, uint256 actualRepayAmount) external view returns (uint256 error, uint256 tokensToSeize)
    function getRewardsByMarket(address vToken) external view returns (struct ComptrollerStorage.RewardSpeeds[] rewardSpeeds)
    function getRewardDistributors() external view returns (contract RewardsDistributor[])
    function isComptroller() external pure returns (bool)
    function updatePrices(address account) public
    function actionPaused(address market, enum ComptrollerStorage.Action action) public view returns (bool)

    Resilient Price Oracle

    Overview

    In its previous version, Venus was fully reliant on the Chainlink price oracle for fetching prices. This dependence, while generally reliable, created a single point of failure. An erroneous or stale price could, without a secondary mechanism for validation, pose threats such as unwarranted liquidations or inflated borrowing.

    In light of these risks, Venus V4 introduces the Resilient Price Oracle, a more robust system capable of pulling data from multiple sources for cross-validation. The Resilient Oracle is equipped with an algorithm to verify prices between two or more sources, providing a safeguard in cases where the primary source proves unreliable or fails.

    Furthermore, the improved oracle infrastructure supports the integration of new price oracles in real-time and permits the enabling and disabling of price oracles per token.

    Key Features

    Resilient Price Feeds

    The Resilient Price Feeds replace the single source price provider used in the Comptroller contract with a more robust and reliable solution. This new component not only fetches asset prices from various on-chain sources but also includes a fallback mechanism to protect the protocol from oracle failures. Presently, this feature incorporates Chainlink, RedStone, Pyth Network and Binance oracles, with the possibility of adding more in the future.

    Governance Configurations

    The Resilient Price Feeds system can be configured by the Venus governance via Venus Improvement Proposals (VIPs). These configurations include pause and resume functionalities for the oracle, price feed configurations, and fixed price settings, among others.

    Safety Measures

    In implementing the Resilient Price Oracle, several safety measures have been adopted to ensure the security and continuity of the Venus Protocol:

    • Price Continuity: Asset prices pre and post upgrade were validated in a simulated environment to ensure consistency.

    • Testnet Deployment: The oracles have been deployed and tested in the Venus Protocol testnet environment.

    • Auditing: The code has been audited by OpenZeppelin, Peckshield, Certik, and Hacken.

    Correlated Token Oracles

    For correlated tokens, like Liquid Staked Tokens (LST), best practice suggests oracles quote first smart contracts to get the exchange rate between the correlated assets, and then multiply that by the USD market price of the second token to complete the calculation.

    In Venus we use dedicated oracles for each LST asset in order to calculate the price as follows:

    • convert the LST to the underlying tokens (using the exchange rate provided by the LST contracts)

    • convert the underlying token calculated in the previous step to USD, using a “traditional” oracle based on market price

    The current list of correlated token oracles in Venus is:

    • AnkrBNBOracle. It returns the USD price of the token, converting on-chain from ankrBNB to BNB using the exchange rate from the ankrBNB contract.

    • BNBxOracle. It returns the USD price of the token, converting on-chain from BNBx to BNB using the exchange rate from the contract.

    • eBTCAccountantOracle (instance of EtherfiAccountantOracle

    Assumption on Liquid Staked Tokens

    WeETHOracle and WstETHOracle assume a 1:1 price ratio between the LST and the underlying asset (e.g. 1 ETH = 1 stETH). The primary risks associated with this approach involve smart contract vulnerabilities and counterparty risks that could impact the redemption processes of the LSTs. In cases of substantial counterparty risk, particularly if the underlying tokens are not redeemable against the LSTs, the direct smart contract pricing might become unreliable. Here's our plan to mitigate such situations:

    Current configuration

    BNB chain

    Pool
    Market
    MAIN oracle
    PIVOT oracle
    FALLBACK oracle
    Notes

    Ethereum

    Pool
    Market
    MAIN oracle
    PIVOT oracle
    FALLBACK oracle
    Notes

    opBNB mainnet

    Pool
    Market
    MAIN oracle
    PIVOT oracle
    FALLBACK oracle
    Notes

    Arbitrum One

    Pool
    Market
    MAIN oracle
    PIVOT oracle
    FALLBACK oracle
    Notes

    ZKsync Mainnet

    Pool
    Market
    MAIN oracle
    PIVOT oracle
    FALLBACK oracle
    Notes

    Optimism Mainnet

    Pool
    Market
    MAIN oracle
    PIVOT oracle
    FALLBACK oracle
    Notes

    Base Mainnet

    Pool
    Market
    MAIN oracle
    PIVOT oracle
    FALLBACK oracle
    Notes

    Unichain Mainnet

    Pool
    Market
    MAIN oracle
    PIVOT oracle
    FALLBACK oracle
    Notes

    Further Reading

    For more detailed information, refer to the following resources:

    Audit reports

    References

    ). It returns the USD price of the
    token, converting on-chain from eBTC to WBTC using the exchange rate from the
    contract.
  • PendleOracle. It returns the USD price of the PT Pendle token, converting on-chain from the PT token to the underlying token using a Pendle market contract.

  • SFraxOracle. It returns the USD price of the sFRAX token, converting on-chain from sFRAX to FRAX using the exchange rate from the sFRAX contract.

  • SlisBNBOracle. It returns the USD price of the slisBNB token, converting on-chain from slisBNB to BNB using the exchange rate from the stake manager contract.

  • AsBNBOracle. It returns the USD price of the asBNB token, converting on-chain from asBNB to slisBNB using the exchange rate from the asBNB minter contract.

  • StkBNBOracle. It returns the USD price of the stkBNB token, converting on-chain from stkBNB to BNB using the exchange rate from the stake pool contract.

  • WBETHOracle. It returns the USD price of the WBETH token, converting on-chain from WBETH to BNB using the exchange rate from the WBETH contract.

  • WeETHOracle. It returns the USD price of the weETH token, converting on-chain from weETH to eETH using the exchange rate from the liquidity pool contract, and assumming 1 eETH = 1 ETH.

  • WeETHsOracle (instance of WeETHAccountantOracle). It returns the USD price of the weETHs token, converting on-chain from weETHs to WETH using the exchange rate from the Accountant contract.

  • WstETHOracle. It returns the USD price of the wstETH token, converting on-chain from wstETH to stETH using the exchange rate from the stETH contract, and assumming 1 stETH = 1 ETH.

  • We will deploy two on-chain oracles for each LST token:

    • The first oracle will return the price based on the assumption of a 1:1 ratio between the LST token and the underlying asset.

    • The second oracle will return the price based on a secondary market feed (using Chainlink, for instance).

  • By default, the ResilientOracle will be configured to use only the oracle assuming a 1:1 ratio between the LST asset and the underlying, serving as the primary oracle.

  • The second oracle, which derives price from the market price feed without assuming a 1:1 ratio, will not be initially configured in our ResilientOracle.

  • We have implemented an off-chain monitoring system to track the prices returned by both oracles. In the event of a significant deviation over an extended period, the situation will be reviewed. It will be determined whether to switch the primary oracle from the one assuming a 1:1 ratio to the one that does not, or whether to temporarily include the latter as a pivot oracle in the ResilientOracle configuration.

  • -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    asBNB

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    BCH

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    BETH (Paused)

    -

    -

    Core

    BNB

    Upper bound: 1.01. Lower bound: 0.99

    Core

    BTCB

    Upper bound: 1.01. Lower bound: 0.99

    Core

    BUSD (Paused)

    -

    -

    Core

    CAKE

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    DAI

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    DOGE

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    DOT

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    ETH

    Upper bound: 1.01. Lower bound: 0.99

    Core

    FDUSD

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    FIL

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    LINK

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    lisUSD

    -

    -

    Core

    LTC

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    MATIC (Paused)

    -

    -

    Price feed from

    Core

    PT-sUSDE-26JUN2025 (Paused)

    -

    -

    Core

    SOL

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    SolvBTC

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    sUSDe

    Upper bound: 1.01. Lower bound: 0.99

    Core

    SXP(Paused)

    -

    -

    Core

    THE

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    TRX

    -

    Upper bound: 1.01. Lower bound: 0.99

    Core

    TRXOLD(Paused)

    -

    Upper bound: 1.01. Lower bound: 0.99

    Core

    TUSD

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    TUSDOLD (Paused)

    -

    -

    Core

    TWT

    -

    -

    Core

    UNI

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    USDC

    Upper bound: 1.01. Lower bound: 0.99

    Core

    USDe

    Upper bound: 1.06. Lower bound: 0.94

    Core

    USDT

    Upper bound: 1.01. Lower bound: 0.99

    Core

    USD1

    Core

    VAI

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    WBETH

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    XRP

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    xSolvBTC

    -

    -

    Core

    XVS

    -

    Upper bound: 1.05. Lower bound: 0.95

    Stablecoins

    lisUSD

    -

    -

    Stablecoins

    USDD

    -

    -

    Stablecoins

    USDT

    Upper bound: 1.01. Lower bound: 0.99

    Stablecoins

    EURA

    -

    -

    DeFi

    BSW

    -

    -

    DeFi

    ALPACA

    -

    -

    DeFi

    USDT

    Upper bound: 1.01. Lower bound: 0.99

    DeFi

    USDD

    -

    -

    DeFi

    ANKR

    -

    -

    DeFi

    ankrBNB

    -

    -

    DeFi

    TWT

    -

    -

    DeFi

    PLANET

    -

    -

    GameFi

    RACA

    -

    -

    GameFi

    FLOKI

    -

    -

    GameFi

    USDD

    -

    -

    GameFi

    USDT

    Upper bound: 1.01. Lower bound: 0.99

    Liquid Staked BNB

    ankrBNB

    -

    Liquid Staked BNB

    asBNB

    -

    Upper bound: 1.05. Lower bound: 0.95

    Liquid Staked BNB

    BNBx

    -

    -

    Liquid Staked BNB

    PT-clisBNB-24APR2025

    -

    Liquid Staked BNB

    stkBNB

    -

    Liquid Staked BNB

    slisBNB

    -

    -

    Liquid Staked BNB

    WBNB

    -

    -

    Meme

    BabyDoge

    -

    -

    Meme

    USDT

    Upper bound: 1.01. Lower bound: 0.99

    Tron

    BTT

    -

    -

    Tron

    TRX

    -

    -

    Tron

    WIN

    -

    -

    Tron

    USDD

    -

    -

    Tron

    USDT

    Upper bound: 1.01. Lower bound: 0.99

    Liquid Staked ETH

    ETH

    Upper bound: 1.01. Lower bound: 0.99

    Liquid Staked ETH

    weETH

    Upper bound: 1.01. Lower bound: 0.99

    Liquid Staked ETH

    wstETH

    Upper bound: 1.01. Lower bound: 0.99

    BTC

    BTCB

    Upper bound: 1.01. Lower bound: 0.99

    BTC

    PT-SolvBTC.BBN-27MAR2025

    -

    -

    -

    Core

    TUSD

    -

    -

    Core

    USDC

    -

    -

    Core

    USDT

    -

    -

    Core

    WBTC

    -

    -

    Core

    WETH

    -

    -

    Core

    FRAX

    -

    -

    Core

    LBTC

    -

    -

    Core

    EIGEN

    -

    -

    Core

    sFRAX

    -

    -

    Core

    eBTC

    -

    -

    Core

    USDS

    -

    -

    Core

    sUSDS

    -

    -

    Core

    BAL

    -

    -

    Core

    yvUSDC-1

    -

    -

    Core

    yvUSDS-1

    -

    -

    Core

    yvUSDT-1

    -

    -

    Core

    yvWETH-1

    -

    -

    Core

    sUSDe

    -

    -

    Core

    USDe

    Upper bound: 1.01. Lower bound: 0.99

    Core

    tBTC

    -

    -

    Curve

    crvUSD

    -

    -

    Curve

    CRV

    -

    -

    Ethena

    PT-sUSDE-27MAR2025

    -

    -

    Ethena

    PT-USDe-27MAR2025

    -

    -

    Ethena

    sUSDe

    -

    -

    Ethena

    USDC

    -

    -

    Ethena

    USDe

    Upper bound: 1.01. Lower bound: 0.99

    Liquid Staked ETH

    ezETH

    Upper bound: 1.01. Lower bound: 0.99

    Liquid Staked ETH

    PTweETH-26DEC2024

    -

    -

    Liquid Staked ETH

    pufETH

    -

    -

    Liquid Staked ETH

    rsETH

    Upper bound: 1.01. Lower bound: 0.99

    Liquid Staked ETH

    sfrxETH

    -

    -

    Liquid Staked ETH

    WETH

    -

    -

    Liquid Staked ETH

    wstETH

    -

    -

    Assume 1:1 for ETH:stETH

    Liquid Staked ETH

    weETH

    -

    -

    Assume 1:1 for ETH:eETH

    Liquid Staked ETH

    weETHs

    -

    -

    -

    Core

    FDUSD

    -

    -

    Core

    USDT

    -

    -

    Core

    WBNB

    -

    -

    -

    Core

    USDC

    -

    -

    Core

    USDT

    -

    -

    Core

    gmWETH-USDC

    -

    -

    Core

    gmBTC-USDC

    -

    -

    Core

    ARB

    -

    -

    Liquid Staked ETH

    weETH

    -

    -

    Liquid Staked ETH

    wstETH

    -

    -

    Liquid Staked ETH

    WETH

    -

    -

    -

    Core

    USDC

    -

    -

    Core

    USDC_E

    -

    -

    Core

    USDT

    -

    -

    Core

    ZK

    Upper bound: 1.01. Lower bound: 0.99

    Core

    wstETH

    -

    -

    Core

    wUSDM

    -

    -

    Core

    zkETH

    -

    -

    Assume 1:1 for WETH:rzkETH

    -

    Core

    USDC

    -

    -

    Core

    USDT

    -

    -

    Core

    OP

    -

    -

    -

    Core

    USDC

    -

    -

    Core

    wsuperOETHb

    -

    -

    Core

    wstETH

    -

    -

    -

    Core

    USDC

    -

    -

    Core

    USD₮0

    -

    -

    Core

    UNI

    -

    -

    Core

    weETH

    -

    -

    Core

    wstETH

    -

    -

    Core

    AAVE

    Chainlink

    Binance

    -

    Upper bound: 1.05. Lower bound: 0.95

    Core

    ADA

    Chainlink

    Core

    crvUSD

    Chainlink

    -

    -

    Core

    DAI

    Chainlink

    Core

    BTCB

    Binance

    -

    -

    Core

    ETH

    Binance

    Core

    WBTC

    SequencerChainlinkOracle

    -

    -

    Core

    WETH

    SequencerChainlinkOracle

    Core

    WBTC

    ChainlinkOracle

    -

    -

    Core

    WETH

    ChainlinkOracle

    Core

    WBTC

    SequencerChainlinkOracle

    -

    -

    Core

    WETH

    SequencerChainlinkOracle

    Core

    cbBTC

    ChainlinkOracle

    -

    -

    Core

    WETH

    ChainlinkOracle

    Core

    WBTC

    RedStone

    -

    -

    Core

    WETH

    RedStone

    ankrBNB
    BNBx
    stake manager
    Resilient Price Oracle
    Resilient Price Oracle upgrade
    WstETH oracle
    Correlated token oracles
    Repository
    Community post about Venus V4, introducing Resilient Price Feeds
    Venus Stars blog post about Binance Oracle

    -

    -

    -

    -

    -

    -

    -

    eBTC
    Accountant
    Binance
    AsBNBOracle
    Binance
    Chainlink
    Binance
    Chainlink
    RedStone
    Chainlink
    Binance
    RedStone
    Chainlink
    Chainlink
    Chainlink
    Price fixed to $1
    Chainlink
    Binance
    Chainlink
    Binance
    Chainlink
    Binance
    Chainlink
    Binance
    Chainlink
    RedStone
    Binance
    Chainlink
    Binance
    Chainlink
    Binance
    Chainlink
    Binance
    Binance
    Chainlink
    Binance
    Chainlink
    $POL
    PendleOracle-PT-sUSDe-26JUN2025
    Chainlink
    Binance
    RedStone
    Binance
    sUSDeOneJumpRedstoneOracle
    sUSDeOneJumpChainlinkOracle
    sUSDeOneJumpChainlinkOracle
    Chainlink
    RedStone
    Binance
    Chainlink
    RedStone
    Chainlink
    RedStone
    Chainlink
    Binance
    Chainlink
    Binance
    Chainlink
    Binance
    Chainlink
    RedStone
    Binance
    USDTChainlinkOracle
    Chainlink
    Chainlink
    Chainlink
    RedStone
    Binance
    RedStone
    Chainlink
    Chainlink
    Chainlink
    Binance
    WBETHOracle
    Binance
    Chainlink
    Binance
    xSolvBTCOneJumpRedstoneOracle
    Chainlink
    Binance
    Binance
    Binance
    Chainlink
    RedStone
    Binance
    Binance
    Chainlink
    Chainlink
    Chainlink
    RedStone
    Binance
    Binance
    Binance
    AnkrBNBOracle
    Binance
    Binance
    Binance
    Binance
    Binance
    Chainlink
    RedStone
    Binance
    AnkrBNBOracle
    AsBNBOracle
    Binance
    BNBxOracle
    PendleOracle-PT-clisBNB-25APR2025
    StkBNBOracle
    SlisBNBOracle
    Chainlink
    Binance
    Chainlink
    RedStone
    Binance
    Binance
    Chainlink
    Chainlink
    Binance
    Chainlink
    RedStone
    Binance
    Chainlink
    RedStone
    Binance
    weETHOneJumpRedstoneOracle
    weETHOneJumpChainlinkOracle
    weETHOneJumpChainlinkOracle
    wstETHOneJumpChainlinkOracle
    wstETHOneJumpRedstoneOracle
    wstETHOneJumpRedstoneOracle
    RedStone
    Chainlink
    Chainlink
    PendleOracle-PT-SolvBTC.BBN-27MAR2025
    Chainlink
    Chainlink
    Chainlink
    Chainlink
    Chainlink
    Chainlink
    LBTCOneJumpRedStoneOracle
    Chainlink
    SFraxOracle
    eBTCAccountantOracle
    Chainlink
    sUSDS-ERC4646Oracle
    Chainlink
    yvUSDC-1-ERC4646Oracle
    yvUSDS-1-ERC4646Oracle
    yvUSDT-1-ERC4646Oracle
    yvWETH-1-ERC4646Oracle
    sUSDe-ERC4626Oracle
    RedStone
    Chainlink
    Chainlink
    Chainlink
    Chainlink
    Chainlink
    PendleOracle-PT-sUSDe-27MAR2025
    PendleOracle-PT-USDe-27MAR2025
    sUSDe-ERC4626Oracle
    Chainlink
    RedStone
    Chainlink
    Chainlink
    ezETHOneJumpRedstoneOracle
    ezETHOneJumpChainlinkOracle
    ezETHOneJumpChainlinkOracle
    PendleOracle-PT-weETH-26DEC2024
    pufETHOneJumpRedstoneOracle
    rsETHOneJumpRedstoneOracle
    rsETHOneJumpChainlinkOracle
    rsETHOneJumpChainlinkOracle
    SFrxETHOracle
    Chainlink
    WstETHOracle_Equivalence
    WeETHOracle_Equivalence
    WeETHAccountantOracle
    Binance
    Binance
    Binance
    SequencerChainlinkOracle
    SequencerChainlinkOracle
    SequencerChainlinkOracle
    SequencerChainlinkOracle
    SequencerChainlinkOracle
    weETHOneJumpChainlinkOracle
    wstETHOneJumpChainlinkOracle
    SequencerChainlinkOracle
    ChainlinkOracle
    ChainlinkOracle
    ChainlinkOracle
    RedStoneOracle
    ChainlinkOracle
    ChainlinkOracle
    wstETHOneJumpChainlinkOracle
    wUSDM-ERC4626Oracle
    ZkETHOracle
    SequencerChainlinkOracle
    SequencerChainlinkOracle
    SequencerChainlinkOracle
    ChainlinkOracle
    wsuperOETHb-ERC4626Oracle
    wstETHOneJumpChainlinkOracle
    RedStone
    RedStone
    RedStone
    weETHOneJumpOracle
    wstETHOneJumpOracle