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...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
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.
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.
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.
Transactions on the Venus V4 protocol require BNB Chain fees, which depend on network congestion and the complexity of the transaction.
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.
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.
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.
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.
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.
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.
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.
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.
Users can perform the following actions on any market in a pool:
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.
Borrow: Users can borrow assets, in exchange for locked collateral.
Redeem: Users can redeem vTokens for the underlying asset based on the exchange rate.
Repay Borrow: Users can repay the borrowed asset and accrued interest.
To be released
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.
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.
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.
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.
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:
Risk management
Decentralization
User experience
In doing so, Venus continues to push the boundaries of what's possible within the realm of decentralized finance.
The Token Converter works on four key principles:
Distributed and Autonomous: No centralized management or human interactions needed, ensuring a secure and seamless conversion process.
Efficient: The system is designed to maximize the amount of specific tokens we receive while protecting against potential risks like sandwich attacks.
Streaming: The conversions occur continually, without waiting for scheduled intervals.
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.
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.
The dashed lines represent transactions initiated by external agents (VIP’s, scripts, arbitrage bots, etc.), and the solid lines represent transfers of funds.
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).
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.
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.
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).
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.
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.
If the oracle price of the paired stablecoin is above $1, the conversion rate is 1 stablecoin = oracle price.
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.
If the oracle price of the paired stablecoin is above $1, the conversion rate is 1 stablecoin = $1.
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.
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.
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).
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 (60%): 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.
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 (80%)
XVS Vault Rewards (20%)
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.
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.
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 .
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 and treasury reserves.
These rewards will be transferred every six months from the to the , where they will be emitted at a rate of 308.7 XVS per day.
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.
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.
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.
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
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.
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.
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.
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.
The Whitepaper Rate Model is simpler, where the borrow rate depends linearly on the utilization:
For Borrow rate:
For Supply rate:
Where,
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.
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.
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.
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.
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.
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.
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.
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.
Access our detailed audit reports here:
Explore our monitoring dashboard for real-time insights: .
Join our alert channel to stay updated: .
Several security measures have been implemented to mitigate the security risks associated with the frontend app deployed at .
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.
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.
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.
This is the implementation contract for the VAIUnitroller proxy
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
mintVAIAmount
uint256
The amount of the VAI to be minted.
Return Values
[0]
uint256
0 on success, otherwise an error code
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
amount
uint256
The amount of VAI to be repaid.
Return Values
[0]
uint256
Error code (0=success, otherwise a failure, see ErrorReporter.sol)
[1]
uint256
Actual repayment amount
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
borrower
address
The account to repay the debt for.
amount
uint256
The amount of VAI to be repaid.
Return Values
[0]
uint256
Error code (0=success, otherwise a failure, see ErrorReporter.sol)
[1]
uint256
Actual repayment amount
The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.
Parameters
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
Return Values
[0]
uint256
Error code (0=success, otherwise a failure, see ErrorReporter.sol)
[1]
uint256
Actual repayment amount
Sets a new comptroller
Return Values
[0]
uint256
uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)
Set the prime token contract address
Parameters
prime_
address
The new address of the prime token contract
Set the VAI token contract address
Parameters
vai_
address
The new address of the VAI token contract
Toggle mint only for prime holder
Return Values
[0]
uint256
uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)
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
minter
address
The account to check mintable VAI
Return Values
[0]
uint256
Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)
[1]
uint256
Mintable amount (with 18 decimals)
Update treasury data
Parameters
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
Gets yearly VAI interest rate based on the VAI price
Return Values
[0]
uint256
uint256 Yearly VAI interest rate
Get interest rate per block
Return Values
[0]
uint256
uint256 Interest rate per bock
Get the last updated interest index for a VAI Minter
Parameters
minter
address
Address of VAI minter
Return Values
[0]
uint256
uint256 Returns the interest rate index for a minter
Get the current total VAI a user needs to repay
Parameters
account
address
The address of the VAI borrower
Return Values
[0]
uint256
(uint256) The total amount of VAI the user needs to repay
Calculate how much VAI the user needs to repay
Parameters
borrower
address
The address of the VAI borrower
repayAmount
uint256
The amount of VAI being returned
Return Values
[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
Accrue interest on outstanding minted VAI
Sets the address of the access control of this contract
Parameters
newAccessControlAddress
address
New address for the access control
Set VAI borrow base rate
Parameters
newBaseRateMantissa
uint256
the base rate multiplied by 10**18
Set VAI borrow float rate
Parameters
newFloatRateMantissa
uint256
the VAI float rate multiplied by 10**18
Set VAI stability fee receiver address
Parameters
newReceiver
address
the address of the VAI fee receiver
Set VAI mint cap
Parameters
_mintCap
uint256
the amount of VAI that can be minted
Return the address of the VAI token
Return Values
[0]
address
The address of VAI
This is the proxy contract for the VAIComptroller
Admin Functions **
Accepts new implementation of comptroller. msg.sender must be pendingImplementation
Return Values
[0]
uint256
uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
Begins transfer of admin rights. The newPendingAdmin must call _acceptAdmin
to finalize the transfer.
Parameters
newPendingAdmin
address
New pending admin.
Return Values
[0]
uint256
uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
Accepts transfer of admin rights. msg.sender must be pendingAdmin
Return Values
[0]
uint256
uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
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
Navigate to the Venus app (app.venus.io) and connect your BNB Chain Wallet or other supported wallet apps.
On the left side of the screen, click on the 'Vault' tab.
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
Follow the same steps as above to access the 'Vault' tab in the Venus app.
This time, select the 'VAI' vault.
Upon clicking on the 'VAI' vault, you'll see the option to 'Stake'.
Enter the amount of VAI you'd like to stake and confirm the staking action.
Just like with the XVS vault, you'll need to confirm the transaction in your wallet.
After staking, the interface will show the staked amount, potential rewards, and other relevant statistics related to the VAI vault.
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.
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.
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.
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.
Your borrowing limit on Venus Protocol is a function of the assets you have supplied. The following steps guide you to manage it:
Navigate to the "Account" section.
Here, you'll find your Borrow Limit on each pool, represented as a percentage of the total value of your supplied assets.
To adjust this limit, you can either supply more assets or repay some of your outstanding loans.
After supplying assets, you can borrow other assets within your borrowing limit:
From the "Dashboard" menu, select the asset you want to borrow.
Input the amount you wish to borrow and confirm the transaction.
In addition to earning interest on supplied assets, you can also farm $XVS tokens:
In the "Vaults" section, you can stake your XVS or VAI tokens to earn XVS tokens.
Click on 'Stake'. You will be prompted to confirm the transaction in your wallet.
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.
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.
An easy way to get WETH from ETH is by using Uniswap. For example, on the Ethereum mainnet, the process would be:
Connect your wallet.
Type the amount of ETH you want to wrap.
Click on Wrap
.
Review and accept the transaction in your Web3 wallet.
Remember to add the WETH token to your Web3 wallet to see your WETH balance.
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'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:
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.
If a user decides to withdraw XVS and their balance falls below 1000, their Prime Token will be automatically revoked.
Irrevocable "OG" Prime Token (Phase 2):
To be defined
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.
Reward Formula: Cobb-Douglas function
Where:
= Rewards for user in market
= Protocol Reserve Revenue for market
= Proportion to be distributed as rewards
= Protocol stake and supply & borrow amplification weight
= XVS staked amount for user
= Sum of qualified supply and borrow balance for user
= Sum for all users in markets
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.
Model Parameters
= 0.5
= 744,164
= 8 BTC
= 0.2
BTC Supply Multiplier = 2
XVS Price = $4.0
User Parameters
Staked XVS
1,200
$4,800
BTC Supply
0.097
$2,500
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.
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.
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.
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":
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.
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.
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.
Proposals can also be created manually by clicking on "Create manually".
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.
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.
The third screen is where you can specify descriptions for the voting options (for, against, abstain).
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.
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.
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.
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.\
Step 1: Visit the Venus Governance Portal
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.
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.
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.
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.
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.
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.
Venus Protocol uses two calculations to determine account liquidity: Collateral Factor (CF) and Liquidation Threshold (LT).
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.
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.
By combining the information obtained from these functions, one can accurately identify under-collateralized accounts that are suitable for liquidation.
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).
The first step to performing a liquidation is to identify under-collateralized accounts. Here's a suggested approach to finding under-collateralized accounts:
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.
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.
Consider using a subgraph to index these events.
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.
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.
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.
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.
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.
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.
Collateral < minLiquidatableCollateral && account is solvent --> liquidateAccount()
: this function liquidates all borrows of the borrower.
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)
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.
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.
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.
Given:
vUSDT
collateral factor: 80%
1 USDT = 1 BUSD = 1 USDC = $1 (for simplicity)
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).
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.
Check that VAI liquidations are not paused in Comptroller.
The forceVAILiquidate flag is set to true.
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.
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.
The seized collateral is distributed between the Liquidator and the ProtocolShareReserve
contract:
Liquidator's Share:
The Liquidator receives a designated portion of the collateral as an incentive.
ProtocolShareReserve
contract's Share:
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.
The Liquidator contract attempts to redeem the protocol's portion of the liquidation incentive in underlying tokens for the VTokens:
Successful Redemption:
If the redemption is successful, the underlying tokens are sent to the ProtocolShareReserve
contract.
Failed Redemption:
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.
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.
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.
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.
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.
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.
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.
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:
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.
Connect your Web3 wallet on MetaMask or other supported wallet app to the Venus app ().
ETH is the native token for the Ethereum blockchain, used to pay gas fees, for example. WETH is an token representing ETH. Most Web3 apps (including Venus) are compatible with ERC-20 tokens, so it's necessary to convert ETH to WETH.
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 )).
Go to the .
To unwrap WETH tokens (getting ETH), you can also use , switching the input and output currencies.
The limit to the number of revocable Prime tokens is 500 on BNB chain. . It can be changed with a VIP.
Navigate to the Venus Governance Portal using your preferred web browser. You can access the portal at .
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.
Access the Venus governance portal via your browser. The URL is .
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 .
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 .
For a visualization of the current interest rate model applied to each market, refer to the market pages at the .
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.
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.
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:
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.
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.
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.
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:
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.
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.
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.
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
This guide provides step-by-step instructions on how to bridge XVS tokens from the BNB Chain to the Ethereum network.
Click on the "Connect wallet" button in the top right corner of the Venus Bridge interface to connect your wallet.
From: Ensure "BNB mainnet" is selected in the "From" dropdown menu.
To: Select "Ethereum" in the "To" dropdown menu to set the destination network.
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.
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.
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.
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.
Once the transaction is complete, the XVS tokens will be available in your Ethereum wallet.
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.
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.
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
incentiveBps
- Incentive to auction participants. Initial value set to 1000 bps or 10%
Make sure you are connected to the ZKsync network. If you are not, switch your wallet’s network to ZKsync.
In this example, we will approve the use of the ZK market as collateral.
Navigate to the ZK market on Venus.
Click on "Collateral" to enable the use of this market as collateral.
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.
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.
Once signed, Zyfi processes the transaction, and it is sent to the ZKsync blockchain with gas paid through their vault.
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.
The Venus Protocol generates income from two main sources:
Spread between the borrowing rate and the supply rate
Part of the liquidation incentives
The initial distribution excludes VAI funds, which are kept in the VTreasury.
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.
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.
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.
Distribution of income generated by the interest rate spread in Isolated Pools is socialized and distributed periodically just like in the Core Pool
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.
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
FunctionThe 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
FunctionThe 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:
Transfer the tokens to the destination addresses.
Invoke the updateAssetsState
function in the receiver contract.
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.
Venus Protocol contracts are divided in these repositories:
There are 2 categories of isolated pools contracts:
Pool
Risk Management
Pool contracts can be divided into 4 categories:
Configuration
Logic
Miscellaneous
Configuration contracts are used to deploy, configure, and manage pools.
Isolated Pools use additional contracts such as lenses, rewards, ect.
Venus Protocol contracts can be grouped as follows:
Lending
Tokens
Vault
Lens
XVS Vault
VAI Vault
ComptrollerLens
SnapshotLens
VenusLens
There are three main Governance contracts:
GovernorBravoDelegate
AccessControlManager
Timelock
GovernorBravoDelegate
AccessControlManager
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.
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.
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.
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.
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:
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.
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.
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.
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.
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.
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.
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.
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.
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 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.
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.
BaseOmnichainControllerSrc
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.
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.
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.
Pausable: Implements a pausing mechanism, inherited from the OpenZeppelin Pausable
contract. This functionality allows the contract owner to temporarily halt omnichain communication if necessary.
Inheritance: Extends the functionalities of the Ownable
and Pausable
contracts from OpenZeppelin, inheriting ownership management and pausing capabilities.
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.
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.
SetMaxDailyLimit (event)
: Emitted when the daily command limit for a chain is modified.
NewAccessControlManager (event)
: Triggered when the address of the AccessControlManager
is updated.
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
.
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
.
OmnichainProposalSender
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.
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.
Security Measures: Enforces access control using the AccessControlManager
for critical functions.
Inheritance: Inherits functionalities from both the ReentrancyGuard
and BaseOmnichainControllerSrc
contracts, providing reentrancy protection and foundational omnichain communication capabilities.
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.
trustedRemoteLookup (mapping)
: Maps remote chain IDs to trusted remote contract addresses for message transmission.
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.
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.
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.
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.
BaseOmnichainControllerDest
This contract serves as the base for the Omnichain controller destination contract. It provides functionality related to daily command limits and pausing.
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.
SetMaxDailyReceiveLimit (event)
: Emitted when the maximum daily limit for receiving commands from BNB Chain is modified.
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.
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.
OmnichainGovernanceExecutor
This contract executes proposal transactions sent from the main chain. It controls LayerZero configuration and implements a non-blocking behavior.
GUARDIAN (address)
: A privileged role that can cancel any proposal.
srcChainId (uint16)
: Stores the layerzero endpoint ID.
lastProposalReceived (uint256)
: Last proposal count received.
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.
ProposalReceived (event)
: Emitted when a proposal is received.
ProposalQueued (event)
: Emitted when a proposal is queued.
ProposalExecuted (event)
: Emitted when a proposal is executed.
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.
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.
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.
OmnichainExecutorOwner
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.
OMNICHAIN_GOVERNANCE_EXECUTOR (immutable)
:
This variable holds the address of the OmnichainGovernanceExecutor
contract and is immutable once initialized.
functionRegistry (mapping)
:
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.
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).
constructor(address omnichainGovernanceExecutor_)
:
Initializes the contract with the address of the OmnichainGovernanceExecutor
contract.
This constructor ensures that the provided address is not zero.
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.
TimelockV8
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.
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.
Transaction Cancellation: Allows cancellation of queued transactions before execution, providing flexibility and control.
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.
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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Comptroller storage contains the facet addresses, mapping of the function selectors to the facet address, and mapping of all selectors to the facet address.
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.
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
.
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:
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:
This contract contains functions related to facets
Call _acceptImplementation to accept the diamond proxy as new implementaion
Parameters
To add function selectors to the facet's mapping
Parameters
Get all function selectors mapped to the facet address
Parameters
Return Values
Get facet position in the _facetFunctionSelectors through facet address
Parameters
Return Values
Get all facet addresses
Return Values
Get facet address and position through function selector
Parameters
Return Values
Get all facets address and their function selector
Return Values
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.
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.
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.
Lens for querying information relating to liquidations
Computes the number of collateral tokens to be seized in a liquidation event
Parameters
Return Values
Computes the number of VAI tokens to be seized in a liquidation event
Parameters
Return Values
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
Return Values
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 α:
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.
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:
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
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:
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.
The steps to perform this calculation are:
Fetch the income per block from PrimeLiquidityProvider
Calculate the user yearly income by multiplying (1) with blocks per year
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.
Calculate the capped supply and borrow of the user for the market
Calculate the ratio of allocation of the rewards based on capped supply and borrow of the user
Now borrow and supply APR of user can be calculated based on ratio of capped borrow and supply of the user.
Example:
Income per block 0.00003 USDT
Income per year is 10512000 blocks/year * 0.00003 = 315.36 USDT
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)
Assuming the user has the following positions:
borrow: 30 USDT. Let's say it's capped at 15 USDT, so we'll consider 15 USDT
supply: 10 USDT. Let's say it's also capped at 15 USDT, so we'll consider 10 USDT
Allocating the rewards (94.608 USDT), considering these capped versions, we would have:
borrow: 94.608 * 15/25 = 56.76 USDT
supply: 94.608 * 10/25 = 37.84 USDT
Calculating the APR with these allocations, we would have:
borrow: 56.76/30 = 1.89 = 189%
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.
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 last time those tokens were released
The PrimeLiquidityProvider
provides a function to transfer the available funds to the Prime
contract.
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.
This facet contract contains all the configurational setter functions
Sets a new price oracle for the comptroller
Return Values
Sets the closeFactor used when liquidating borrows
Parameters
Return Values
Sets the address of the access control of this contract
Parameters
Return Values
Sets the collateralFactor for a market
Parameters
Return Values
Sets liquidationIncentive
Parameters
Return Values
Update the address of the liquidator contract
Parameters
Admin function to change the Pause Guardian
Parameters
Return Values
Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert
Parameters
Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert
Parameters
Set whole protocol pause/unpause state
Parameters
Return Values
Pause/unpause certain actions
Parameters
Sets a new VAI controller
Return Values
Set the VAI mint rate
Parameters
Return Values
Set the minted VAI amount of the owner
Parameters
Return Values
Set the treasury data.
Parameters
Return Values
Set the amount of XVS distributed per block to VAI Vault
Parameters
Set the VAI Vault infos
Parameters
Sets the prime token contract for the comptroller
Return Values
Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity
Parameters
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
This facet contract contains functions regarding markets
Indicator that this is a Comptroller contract (for inspection)
Returns the assets an account has entered
Parameters
Return Values
Return all of the markets
Return Values
Calculate number of tokens of collateral asset to seize given an underlying amount
Parameters
Return Values
Calculate number of tokens of collateral asset to seize given an underlying amount
Parameters
Return Values
Returns whether the given account is entered in the given asset
Parameters
Return Values
Add assets to be included in account liquidity calculation
Parameters
Return Values
Removes asset from sender's account liquidity calculation
Parameters
Return Values
Add the market to the markets mapping and set it as listed
Parameters
Return Values
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
This facet contract contains all the external pre-hook functions related to vToken
Checks if the account should be allowed to mint tokens in the given market
Parameters
Return Values
Validates mint and reverts on rejection. May emit logs.
Parameters
Checks if the account should be allowed to redeem tokens in the given market
Parameters
Return Values
Validates redeem and reverts on rejection. May emit log
Parameters
Checks if the account should be allowed to borrow the underlying asset of the given market
Parameters
Return Values
Validates borrow and reverts on rejection. May emit log
Parameters
Checks if the account should be allowed to repay a borrow in the given market
Parameters
Return Values
Validates repayBorrow and reverts on rejection. May emit log
Parameters
Checks if the liquidation should be allowed to occur
Parameters
Validates liquidateBorrow and reverts on rejection. May emit logs.
Parameters
Checks if the seizing of assets should be allowed to occur
Parameters
Validates seize and reverts on rejection. May emit log
Parameters
Checks if the account should be allowed to transfer tokens in the given market
Parameters
Return Values
Validates transfer and reverts on rejection. May emit log
Parameters
Determine the current account liquidity wrt collateral requirements
Return Values
Determine what the account liquidity would be if the given amounts were redeemed/borrowed
Parameters
Return Values
Set XVS speed for a single market
Parameters
This facet contract provides the external functions related to all claims and rewards of the protocol
Claim all the xvs accrued by holder in all markets and VAI
Parameters
Claim all the xvs accrued by holder in the specified markets
Parameters
Claim all xvs accrued by the holders
Parameters
Claim all the xvs accrued by holder in all markets, a shorthand for claimVenus
with collateral set to true
Parameters
Transfer XVS to the recipient
Parameters
Return the address of the XVS vToken
Return Values
Claim all xvs accrued by the holders
Parameters
PrimeLiquidityProvider is used to fund Prime
The default max token distribution speed
Address of the Prime contract
The rate at which token is distributed (per block)
The max token distribution speed for token
The rate at which token is distributed to the Prime contract
The token accrued but not yet transferred to prime contract
PrimeLiquidityProvider initializer
Parameters
❌ Errors
Throw InvalidArguments on different length of tokens and speeds array
Initialize the distribution of the token
Parameters
⛔️ Access Requirements
Only Governance
Pause fund transfer of tokens to Prime contract
⛔️ Access Requirements
Controlled by ACM
Resume fund transfer of tokens to Prime contract
⛔️ Access Requirements
Controlled by ACM
Set distribution speed (amount of token distribute per block)
Parameters
⛔️ Access Requirements
Controlled by ACM
❌ Errors
Throw InvalidArguments on different length of tokens and speeds array
Set max distribution speed for token (amount of maximum token distribute per block)
Parameters
⛔️ Access Requirements
Controlled by ACM
❌ Errors
Throw InvalidArguments on different length of tokens and speeds array
Set the prime token contract address
Parameters
📅 Events
Emits PrimeTokenUpdated event
⛔️ Access Requirements
Only owner
Set the limit for the loops can iterate to avoid the DOS
Parameters
📅 Events
Emits MaxLoopsLimitUpdated event on success
⛔️ Access Requirements
Controlled by ACM
Claim all the token accrued till last block
Parameters
📅 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
A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to user
Parameters
📅 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
Get rewards per block for token
Parameters
Return Values
Accrue token by updating the distribution state
Parameters
📅 Events
Emits TokensAccrued event
Get the latest block number
Return Values
Storage for Prime Token
Mapping to get prime token's metadata
Tracks total irrevocable tokens minted
Tracks total revocable tokens minted
Indicates maximum revocable tokens that can be minted
Indicates maximum irrevocable tokens that can be minted
Tracks when prime token eligible users started staking for claiming prime token
vToken to market configuration
vToken to user to user index
numerator of alpha. Ex: if alpha is 0.5 then this will be 1
denominator of alpha. Ex: if alpha is 0.5 then this will be 2
address of XVS vault
address of XVS vault reward token
address of XVS vault pool id
mapping to check if a account's score was updated in the round
unique id for next round
total number of accounts whose score needs to be updated
total number of accounts whose score is yet to be updated
mapping used to find if an asset is part of prime markets
address of core pool comptroller contract
unreleased income from PLP that's already distributed to prime holders
The address of PLP contract
The address of ResilientOracle contract
XVS Store responsible for distributing XVS rewards
Safely transfer rewards. Only active reward tokens can be sent using this function. Only callable by owner
Parameters
Allows the admin to propose a new admin Only callable admin
Parameters
Allows an account that is pending as admin to accept the role nly calllable by the pending admin
Set the contract owner
Parameters
Set or disable a reward token
Parameters
Security function to allow the owner of the contract to withdraw from the contract
Parameters
This contract stores XVS
received from XVSVaultConverter and funds XVSVault
The xvs token address
The xvsvault address
This function transfers funds to the XVS vault
Parameters
📅 Events
FundsTransferredToXVSStore emits on success
⛔️ Access Requirements
Restricted by ACM
❌ Errors
InsufficientBalance is thrown when amount entered is greater than balance
This function sweep tokens from the contract
Parameters
📅 Events
SweepToken emits on success
⛔️ Access Requirements
Restricted by ACM
We have a strict policy on how we should commit our work. Following these guidelines will help us to:
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.
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.
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 :)
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.
Prefer short and descriptive names for branches (good: polynomial-interest-curve
, bad: fix-rate
).
Use lowercase words separated by dashes (good: xvs-vault
, bad: XVSVault
).
You may include work type into the branch name (ok: feature/polynomial-interest-curve
).
Make sure no-one else works in your feature branch.
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
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.
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
.
Your feature branch should have linear history. No merge commits are allowed.
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.
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.
Every feature branch should have one active maintainer. No-one else is allowed to directly commit to your feature branch.
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.
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 :)
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 sure your commit history follows the guidelines written above. Rebase once again if necessary.
If your PR is work in progress, explicitly mark it as WIP.
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.
Avoid fixing up a fixup :)
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.
Do not add any new changes to the code after the review (except for squashing and reordering the commits).
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.
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.
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.
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%
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()
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].startBlock
state variable.
Placing a bid triggers BidPlaced
event which can be monitored.
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.
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.
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).
Placing a bid triggers BidPlaced
event which can be monitored.
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.
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)
Place Bids and Close Auction: Now just like previous steps a user can place bids and close the auction.
The XVS Vault allows XVS holders to lock their XVS to recieve voting rights in Venus governance and are rewarded with XVS.
Pauses vault
Resume vault
Returns the number of pools with the specified reward token
Parameters
Return Values
Add a new token pool
Parameters
Update the given pool's reward allocation point
Parameters
Update the given reward token's amount per block
Parameters
Update the lock period after which a requested withdrawal can be executed
Parameters
Deposit XVSVault for XVS allocation
Parameters
Claim rewards for pool
Parameters
Execute withdrawal to XVSVault for XVS allocation
Parameters
Request withdrawal to XVSVault for XVS allocation
Parameters
Get unlocked withdrawal amount
Parameters
Return Values
Get requested amount
Parameters
Return Values
Returns the array of withdrawal requests that have not been executed yet
Parameters
Return Values
View function to see pending XVSs on frontend
Parameters
Return Values
Update reward variables of the given pool to be up-to-date
Parameters
Get user info with reward token address and pid
Parameters
Return Values
Gets the total pending withdrawal amount of a user before upgrade
Parameters
Return Values
Delegate votes from msg.sender
to delegatee
Parameters
Delegates votes from signatory to delegatee
Parameters
Gets the current votes balance for account
Parameters
Return Values
Determine the xvs stake balance for an account
Parameters
Return Values
Admin Functions **
Sets the address of the access control of this contract
Parameters
XVS Vault Proxy contract
Admin Functions **
Accepts new implementation of XVS Vault. msg.sender must be pendingImplementation
Return Values
Begins transfer of admin rights. The newPendingAdmin must call _acceptAdmin
to finalize the transfer.
Parameters
Return Values
Accepts transfer of admin rights. msg.sender must be pendingAdmin
Return Values
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.
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:
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).
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
.
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).
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)
ONLY_FOR_USERS
: Conversion is enabled only for users
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
)
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.
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
: 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
.
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:
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
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).
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
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
: 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.
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)
amountConvertedMantissa
: $100 * 10^{18}$ (USDC), different from the amountOutMantissa
param because there is not enough liquidity
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
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 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.
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.
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.
One instance of XVSVaultTreasury
is configured as the destination address in the XVSVaultConverter
. This treasury is used to fund the XVSVault
.
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.
Abstract base for vTokens
Transfer amount
tokens from msg.sender
to dst
Parameters
Return Values
Transfer amount
tokens from src
to dst
Parameters
Return Values
Approve spender
to transfer up to amount
from src
Parameters
Return Values
Get the underlying balance of the owner
Parameters
Return Values
Returns the current total borrows plus accrued interest
Return Values
Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex
Parameters
Return Values
Transfers collateral tokens (this market) to the liquidator.
Parameters
Return Values
Begins transfer of admin rights. The newPendingAdmin must call _acceptAdmin
to finalize the transfer.
Parameters
Return Values
Accepts transfer of admin rights. msg.sender must be pendingAdmin
Return Values
accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh
Return Values
Sets the address of the access control manager of this contract
Parameters
Return Values
Accrues interest and reduces reserves by transferring to protocol share reserve
Parameters
Return Values
Get the current allowance from owner
for spender
Parameters
Return Values
Get the token balance of the owner
Parameters
Return Values
Get a snapshot of the account's balances, and the cached exchange rate
Parameters
Return Values
Returns the current per-block supply interest rate for this vToken
Return Values
Returns the current per-block borrow interest rate for this vToken
Return Values
Get cash balance of this vToken in the underlying asset
Return Values
Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve
Parameters
Sets protocol share reserve contract address
Parameters
Initialize the money market
Parameters
Accrue interest then return the up-to-date exchange rate
Return Values
Applies accrued interest to total borrows and reserves
Sets a new comptroller for the market
Return Values
Accrues interest and updates the interest rate model using _setInterestRateModelFresh
Parameters
Return Values
Calculates the exchange rate from the underlying to the VToken
Return Values
Return the borrow balance of account based on stored data
Parameters
Return Values
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
total blocks per year
address of WBNB contract
address of VBNB contract
minimum amount of XVS user needs to stake to become a prime member
maximum XVS taken in account when calculating user score
number of days user need to stake to claim prime token
Prime initializer
Parameters
❌ Errors
Throw InvalidAddress if any of the address is invalid
Returns boosted pending interest accrued for a user for all markets
Parameters
Return Values
Update total score of multiple users and market
Parameters
📅 Events
Emits UserScoreUpdated event
❌ Errors
Throw NoScoreUpdatesRequired if no score updates are required
Throw UserHasNoPrimeToken if user has no prime token
Update value of alpha
Parameters
📅 Events
Emits AlphaUpdated event
⛔️ Access Requirements
Controlled by ACM
Update multipliers for a market
Parameters
📅 Events
Emits MultiplierUpdated event
⛔️ Access Requirements
Controlled by ACM
❌ Errors
Throw MarketNotSupported if market is not supported
Update staked at timestamp for multiple users
Parameters
📅 Events
Emits StakedAtUpdated event for each user
⛔️ Access Requirements
Controlled by ACM
❌ Errors
Throw InvalidLength if users and timestamps length are not equal
Add a market to prime program
Parameters
📅 Events
Emits MarketAdded event
⛔️ Access Requirements
Controlled by ACM
❌ Errors
Throw MarketAlreadyExists if market already exists
Throw InvalidVToken if market is not valid
Set limits for total tokens that can be minted
Parameters
📅 Events
Emits MintLimitsUpdated event
⛔️ Access Requirements
Controlled by ACM
❌ Errors
Throw InvalidLimit if any of the limit is less than total tokens minted
Set the limit for the loops can iterate to avoid the DOS
Parameters
📅 Events
Emits MaxLoopsLimitUpdated event on success
⛔️ Access Requirements
Controlled by ACM
Directly issue prime tokens to users
Parameters
⛔️ Access Requirements
Controlled by ACM
Executed by XVSVault whenever user's XVSVault balance changes
Parameters
accrues interes and updates score for an user for a specific market
Parameters
For claiming prime token when staking period is completed
For burning any prime token
Parameters
⛔️ Access Requirements
Controlled by ACM
To pause or unpause claiming of interest
⛔️ Access Requirements
Controlled by ACM
For user to claim boosted yield
Parameters
Return Values
For user to claim boosted yield
Parameters
Return Values
Retrieves an array of all available markets
Return Values
fetch the numbers of seconds remaining for staking period to complete
Parameters
Return Values
Returns supply and borrow APR for user for a given market
Parameters
Return Values
Returns supply and borrow APR for estimated supply, borrow and XVS staked
Parameters
Return Values
Distributes income from market since last distribution
Parameters
❌ Errors
Throw MarketNotSupported if market is not supported
Returns boosted interest accrued for a user
Parameters
Return Values
Navigate to the Venus Protocol and select the "Bridge" option from the sidebar menu.
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 of the project. The risk fund also covers bad debt in case of bankruptcy without a liquidator.
The funds generated in the Core pool, that should be allocated to the risk fund, are temporarily sent to the contract. With the relase of the feature, this income will be sent to the ProtocolShareReserve
contract, where there will be distributed following the of the project.
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.
Open the and connect your wallet.
You can verify the transaction on the . The transaction will display Zyfi as the Paymaster, covering the gas fees.
goes into more detail about the distribution schema and desired outcomes.
: Contains core contracts for isolated lending, including logic for supplying, borrowing, liquidations, pool and market deployments, and interest rate models.
: 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.
Creating and managing pools is done by the . It can add markets to pools, update pool metadata, and return pool information.
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.
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.
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.
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.
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.
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 .
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
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 staked in the earn XVS. Staking rewards are accumulated daily.
The contains methods for fetching the liquidity of an account and the amount of tokens that can be seized for a repayable amount
The contains methods for getting the details of account for a specific market or all markets where an account is active.
Protocol level data is made available through the . It contains getters related to XVS distribution, governance, and markets.
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.
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.
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 .
chainID
: Identifies the destination network for the remote execution (endpointId
according to ).
As features continued to be introduced to the Core Pool Comptroller contract, it grew to exceed the . 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 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.
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.
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.
: 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.
: This contract contains functions related to access and checks.
This technical article explains implementation details of the Venus Prime program. The overview of the Venus Prime program can be checked .
()
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 is calculated considering the caps:
Every market in Venus (including Isolated Lending markets) contributes to the rewards that the Prime contract will distribute, following the protocol . The following diagram shows the current implementation for the flow of funds.
Interest reserves (part of the protocol income) from Isolated Pools and the Core Pool markets are sent to the PSR () 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 24 hours, but this can be changed by the community via ).
The PSR has a function releaseFunds
that needs to be invoked to release the funds to the destination contracts. We have contracts which receive income from the PSR and convert them to Prime supported reward tokens.
More information about income collection and distribution can be found .
The goal is to offer a view function that allows the to show an estimation of the APR associated with the Prime token and the borrow/supply position of a user.
By default, git merges the upstream changes into your local branch on pull. This silently 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
.
Commit messages will need to follow a standard format in order to be able to correctly bumpt the next version and format the release. is a nice standard to use for formatting the commit messages. There are different tools available to enforce these messages
- Precommit hook with husky ( currently implement in the api repo)
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.
RiskFund
already includes the integration with the Shortfall
contract. The USDT received in the conversions will be .
PrimeLiquidityProvider
accumulates and distributes them according to the speeds configured via VIP.
See the second invocation example in the section
unitroller
contract Unitroller
Address of the unitroller
diamondCut_
struct IDiamondCut.FacetCut[]
IDiamondCut contains facets address, action and function selectors
facet
address
Address of the facet
[0]
bytes4[]
selectors Array of function selectors
facet
address
Address of the facet
[0]
uint256
Position of the facet
[0]
address[]
facetAddresses Array of facet addresses
functionSelector
bytes4
function selector
[0]
struct ComptrollerV13Storage.FacetAddressAndPosition
FacetAddressAndPosition facet address and position
[0]
struct Diamond.Facet[]
facets_ Array of Facet
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
[0]
uint256
A tuple of error code, and tokens to seize
[1]
uint256
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
[0]
uint256
A tuple of error code, and tokens to seize
[1]
uint256
comptroller
address
Address of comptroller
account
address
Address of the borrowed vToken
vTokenModify
contract VToken
Address of collateral for vToken
redeemTokens
uint256
Number of vTokens being redeemed
borrowAmount
uint256
Amount borrowed
[0]
uint256
Returns a tuple of error code, liquidity, and shortfall
[1]
uint256
[2]
uint256
USDT
40%
USDC
30%
ETH
25%
BTC
5%
[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
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
[0]
uint256
uint256 0=success, otherwise a failure. (See ErrorReporter for details)
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 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 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 ComptrollerV9Storage.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
[0]
uint256
uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
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 address of the account to pull assets for
[0]
contract VToken[]
A dynamic list with the assets 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
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
vTokens
address[]
The list of addresses of the vToken markets to be enabled
[0]
uint256[]
Success indicator for whether each corresponding market was entered
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)
delegate
address
The address to update the rights for
allowBorrows
bool
Whether to grant (true) or revoke (false) the rights
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
[0]
uint256
0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
vToken
address
Asset being minted
minter
address
The address minting the tokens
actualMintAmount
uint256
The amount of the underlying asset being minted
mintTokens
uint256
The number of tokens being minted
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
[0]
uint256
0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
vToken
address
Asset being redeemed
redeemer
address
The address redeeming the tokens
redeemAmount
uint256
The amount of the underlying asset being redeemed
redeemTokens
uint256
The number of tokens being redeemed
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
[0]
uint256
0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
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
payer
address
The account which would repay the asset
borrower
address
The account which borrowed the asset
repayAmount
uint256
The amount of the underlying asset the account would repay
[0]
uint256
0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
vToken
address
Asset being repaid
payer
address
The address repaying the borrow
borrower
address
The address of the borrower
actualRepayAmount
uint256
The amount of underlying being repaid
borrowerIndex
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
The address of the borrower
repayAmount
uint256
The amount of underlying being repaid
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
The address of the borrower
actualRepayAmount
uint256
The amount of underlying being repaid
seizeTokens
uint256
The amount of collateral token that will be seized
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
The address of the borrower
seizeTokens
uint256
The number of collateral tokens to seize
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
The address of the borrower
seizeTokens
uint256
The number of collateral tokens to seize
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
The number of vTokens to transfer
[0]
uint256
0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)
vToken
address
Asset being transferred
src
address
The account which sources the tokens
dst
address
The account which receives the tokens
transferTokens
uint256
The number of vTokens to transfer
[0]
uint256
(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)
[1]
uint256
[2]
uint256
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
The amount of underlying to hypothetically borrow
[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
vTokens
contract VToken[]
The market whose XVS speed to update
supplySpeeds
uint256[]
New XVS speed for supply
borrowSpeeds
uint256[]
New XVS speed for borrow
holder
address
The address to claim XVS for
holder
address
The address to claim XVS for
vTokens
contract VToken[]
The list of markets to claim XVS in
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
Whether or not to claim XVS earned by supplying
holder
address
The address to claim XVS for
recipient
address
The address of the recipient to transfer XVS to
amount
uint256
The amount of XVS to (possibly) transfer
[0]
address
The address of XVS vToken
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
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
accessControlManager_
address
AccessControlManager contract address
tokens_
address[]
Array of addresses of the tokens
distributionSpeeds_
uint256[]
New distribution speeds for tokens
maxDistributionSpeeds_
uint256[]
loopsLimit_
uint256
Maximum number of loops allowed in a single transaction
tokens_
address[]
Array of addresses of the tokens to be intialized
tokens_
address[]
Array of addresses of the tokens
distributionSpeeds_
uint256[]
New distribution speeds for tokens
tokens_
address[]
Array of addresses of the tokens
maxDistributionSpeeds_
uint256[]
New distribution speeds for tokens
prime_
address
The new address of the prime token contract
loopsLimit
uint256
Limit for the max loops can execute at a time
token_
address
The token to release to the Prime contract
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
token_
address
Address of the token
[0]
uint256
speed returns the per block reward
token_
address
Address of the token
[0]
uint256
blockNumber returns the block number
token
address
Reward token to transfer
_to
address
Destination address of the reward
_amount
uint256
Amount to transfer
_admin
address
Propose an account as admin of the XVS store
_owner
address
The address of the owner to set Only callable admin
_tokenAddress
address
The address of a token to set as active or inactive
status
bool
Set whether a reward token is active or not
_tokenAddress
address
Reward token address to withdraw
_amount
uint256
Amount of token to withdraw
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
breaking change
major
true
feat
minor
true
build
false
false
ci
false
false
fix
patch
true
refactor
patch
false
test
false
false
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
Initial reward per block, in terms of _rewardToken
_lockPeriod
uint256
A period between withdrawal request and a moment when it's executable
_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
The recovery byte of the signature
r
bytes32
Half of the ECDSA signature pair
s
bytes32
Half of the ECDSA signature pair
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
[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)
RiskFundConverter
USDT
0%
0%
XVSVaultConverter
XVS
20%
20%
USDTPrimeConverter
USDT
10%
0%
USDCPrimeConverter
USDC
6%
0%
BTCBPrimeConverter
BTCB
1%
0%
ETHPrimeConverter
ETH
3%
0%
RiskFundConverter
USDT
0%
0%
XVSVaultConverter
XVS
20%
20%
USDTPrimeConverter
USDT
1.4%
0%
USDCPrimeConverter
USDC
1.4%
0%
WBTCPrimeConverter
WBTC
1.4%
0%
WETHPrimeConverter
WETH
15.8%
0%
XVSVaultConverter
XVS
20%
20%
USDTPrimeConverter
USDT
5%
0%
USDCPrimeConverter
USDC
5%
0%
WBTCPrimeConverter
WBTC
3%
0%
WETHPrimeConverter
WETH
7%
0%
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 (-1 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 (-1 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 InterestRateModel
The address of the interest rate model
initialExchangeRateMantissa_
uint256
The initial exchange rate, scaled by 1e18
name_
string
EIP-20 name of this token
symbol_
string
EIP-20 symbol of this token
decimals_
uint8
EIP-20 decimal precision of this token
[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 InterestRateModel
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
xvsVault_
address
Address of XVSVault
xvsVaultRewardToken_
address
Address of XVSVault reward token
xvsVaultPoolId_
uint256
Pool id of XVSVault
alphaNumerator_
uint128
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
user
address
the account for which to get the accrued interests
pendingRewards
struct PrimeStorageV1.PendingReward[]
the number of underlying tokens accrued by the user for all markets
users
address[]
accounts for which we need to update score
_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
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
users
address[]
accounts for which we need to update staked at timestamp
timestamps
uint256[]
new staked at timestamp for the users
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
_irrevocableLimit
uint256
total number of irrevocable tokens that can be minted
_revocableLimit
uint256
total number of revocable tokens that can be minted
loopsLimit
uint256
Number of loops limit
isIrrevocable
bool
are the tokens being issued
users
address[]
list of address to issue tokens to
user
address
the account address whose balance was updated
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
user
address
the account address for which the prime token will be burned
vToken
address
the market for which claim the accrued interest
[0]
uint256
amount the amount of tokens transferred to the msg.sender
vToken
address
the market for which claim the accrued interest
user
address
the user for which to claim the accrued interest
[0]
uint256
amount the amount of tokens transferred to the user
[0]
address[]
an array of addresses representing all available markets
user
address
the account address for which we are checking the remaining time
[0]
uint256
timeRemaining the number of seconds the user needs to wait to claim prime token
market
address
the market for which to fetch the APR
user
address
the account for which to get the APR
supplyAPR
uint256
supply APR of the user in BPS
borrowAPR
uint256
borrow APR of the user in BPS
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
hypothetical supply amount
xvsStaked
uint256
hypothetical staked XVS amount
supplyAPR
uint256
supply APR of the user in BPS
borrowAPR
uint256
borrow APR of the user in BPS
vToken
address
the market for which to distribute the income
vToken
address
the market for which to fetch the accrued interest
user
address
the account for which to get the accrued interest
[0]
uint256
interestAccrued the number of underlying tokens accrued by the user since the last accrual
The VAI Vault is configured for users to stake VAI And receive XVS as a reward.
Pause vault
Resume vault
Deposit VAI to VAIVault for XVS allocation
Parameters
_amount
uint256
The amount to deposit to vault
Withdraw VAI from VAIVault
Parameters
_amount
uint256
The amount to withdraw from vault
Claim XVS from VAIVault
Claim XVS from VAIVault
Parameters
account
address
The account for which to claim XVS
View function to see pending XVS on frontend
Parameters
_user
address
The user to see pending XVS
Return Values
[0]
uint256
Amount of XVS the user can claim
Function that updates pending rewards
Admin Functions **
Sets the address of the access control of this contract
Parameters
newAccessControlAddress
address
New address for the access control
Lens for querying interest rate model simulations
Simulate interest rate curve fo a specific interest rate model given a reference borrow amount and reserve factor
Parameters
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
[0]
struct InterestRateModelLens.SimulationResponse
Proxy contract for the VAI Vault
Admin Functions **
Accepts new implementation of VAI Vault. msg.sender must be pendingImplementation
Return Values
[0]
uint256
uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
Begins transfer of admin rights. The newPendingAdmin must call _acceptAdmin
to finalize the transfer.
Parameters
newPendingAdmin
address
New pending admin.
Return Values
[0]
uint256
uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
Accepts transfer of admin rights. msg.sender must be pendingAdmin
Return Values
[0]
uint256
uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
The parameterized model described in section 2.4 of the original Venus Protocol whitepaper
Construct an interest rate model
Parameters
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)
Calculates the utilization rate of the market: borrows / (cash + borrows - reserves)
Parameters
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)
Return Values
[0]
uint256
The utilization rate as a mantissa between [0, 1e18]
Calculates the current borrow rate per block, with the error code expected by the market
Parameters
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
[0]
uint256
The borrow rate percentage per block as a mantissa (scaled by 1e18)
Calculates the current supply rate per block
Parameters
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
[0]
uint256
The supply rate percentage per block as a mantissa (scaled by 1e18)
Address of vBNB contract.
Address of Venus Unitroller contract.
Address of VAIUnitroller contract.
Address of wBNB contract
Constructor for the implementation contract. Sets immutable variables.
Parameters
comptroller_
address
The address of the Comptroller contract
vBnb_
address payable
The address of the VBNB
wBNB_
address
The address of wBNB
Initializer for the implementation contract.
Parameters
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
An admin function to restrict liquidations to allowed addresses only.
Parameters
borrower
address
The address of the borrower
An admin function to remove restrictions for liquidations.
Parameters
borrower
address
The address of the borrower
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
borrower
address
The address of the borrower
liquidator
address
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
borrower
address
The address of the borrower
liquidator
address
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
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
Sets the new percent of the seized amount that goes to treasury. Should be less than or equal to comptroller.liquidationIncentiveMantissa().sub(1e18).
Parameters
newTreasuryPercentMantissa
uint256
New treasury percent (scaled by 10^18).
Sets protocol share reserve contract address
Parameters
protocolShareReserve_
address payable
The address of the protocol share reserve contract
Reduce the reserves of the pending accumulated reserves
Sets the threshold for minimum amount of vaiLiquidate
Parameters
minLiquidatableVAI_
uint256
New address for the access control
Length of the pendingRedeem array to be consider while redeeming in Liquidation transaction
Parameters
newLength_
uint256
Length of the chunk
Pause Force Liquidation of VAI
Resume Force Liquidation of VAI
An interest rate model with two different slope increase or decrease each after a certain utilization threshold called kink is reached.
The multiplier of utilization rate per block that gives the slope 1 of the interest rate scaled by EXP_SCALE
The base interest rate per block which is the y-intercept when utilization rate is 0 scaled by EXP_SCALE
The utilization point at which the multiplier2 is applied
The multiplier of utilization rate per block that gives the slope 2 of the interest rate scaled by EXP_SCALE
The base interest rate per block which is the y-intercept when utilization rate hits KINK_1 scaled by EXP_SCALE
The maximum kink interest rate scaled by EXP_SCALE
The utilization point at which the jump multiplier is applied
The multiplier of utilization rate per block that gives the slope 3 of interest rate scaled by EXP_SCALE
The maximum kink interest rate scaled by EXP_SCALE
Construct an interest rate model
Parameters
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)
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
Calculates the current borrow rate per slot (block)
Parameters
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
[0]
uint256
The borrow rate percentage per slot (block) as a mantissa (scaled by EXP_SCALE)
Calculates the current supply rate per slot (block)
Parameters
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
[0]
uint256
The supply rate percentage per slot (block) as a mantissa (scaled by EXP_SCALE)
Calculates the utilization rate of the market: borrows / (cash + borrows - reserves)
Parameters
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
[0]
uint256
The utilization rate as a mantissa between [0, EXP_SCALE]
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.
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.
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.
Storage layout for the Comptroller
contract.
Oracle which gives the price of any given asset
Multiplier used to calculate the maximum repayAmount when liquidating a borrow
Multiplier representing the discount on collateral that a liquidator receives
Per-account mapping of "assets you are in"
Official mapping of vTokens -> Market metadata
A list of all markets
Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.
Minimal collateral required for regular (non-batch) liquidations
Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed
Flag indicating whether forced liquidation enabled for a market
Prime token address
Whether the delegate is allowed to borrow or redeem on behalf of the user
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).
address of vBNB
address of WBNB contract
Used to initialize non-immutable variables
PSR setter.
Parameters
📅 Events
Emits ProtocolShareReserveUpdated event.
⛔️ Access Requirements
Only owner (Governance)
Reduce reserves of vBNB, wrap them and send them to the PSR contract
Parameters
📅 Events
Emits ReservesReduced event.
Sets the interest rate model of the vBNB contract
Parameters
⛔️ Access Requirements
Controlled by ACM
Invoked when BNB is sent to this contract
⛔️ Access Requirements
Only vBNB is considered a valid sender
Invoked when called function does not exist in the contract. The function will be executed in the vBNB contract.
⛔️ Access Requirements
Only owner (Governance)
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
Query the metadata of a vToken by its address
Parameters
Return Values
Get VTokenMetadata for an array of vToken addresses
Parameters
Return Values
Get amount of XVS distributed daily to an account
Parameters
Return Values
Get the current vToken balance (outstanding borrows) for an account
Parameters
Return Values
Get the current vToken balances (outstanding borrows) for all vTokens on an account
Parameters
Return Values
Get the price for the underlying asset of a vToken
Parameters
Return Values
Query the underlyingPrice of an array of vTokens
Parameters
Return Values
Query the account liquidity and shortfall of an account
Parameters
Return Values
Query the voting information of an account for a list of governance proposals
Parameters
Return Values
Query the details of a list of governance proposals
Parameters
Return Values
Query the XVSBalance info of an account
Parameters
Return Values
Query the XVSBalance extended info of an account
Parameters
Return Values
Query the voting power for an account at a specific list of block numbers
Parameters
Return Values
Calculate the total XVS tokens pending or accrued by a user account
Parameters
Return Values
Each asset that is supported by a pool is integrated through an instance of the VToken
contract. As outlined in the protocol overview, each isolated pool creates its own vToken
corresponding to an asset. Within a given pool, each included vToken
is referred to as a market of the pool. The main actions a user regularly interacts with in a market are:
mint/redeem of vTokens;
transfer of vTokens;
borrow/repay a loan on an underlying asset;
liquidate a borrow or liquidate/heal an account.
A user supplies the underlying asset to a pool by minting vTokens
, where the corresponding vToken
amount is determined by the exchangeRate
. The exchangeRate
will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted vToken
in a pool, they can borrow any asset in the isolated pool by using their vToken
as collateral. In order to borrow an asset or use a vToken
as collateral, the user must be entered into each corresponding market (else, the vToken
will not be considered collateral for a borrow). Note that a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also pay off interest accrued on the borrow.
The Venus Protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the Comptroller
and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a total collateral amount that is no larger than a universal minLiquidatableCollateral
value, which is used for all markets within a Comptroller
. Both functions settle all of an account’s borrows, but healAccount()
may add badDebt
to a vToken. For more detail, see the description of healAccount()
and liquidateAccount()
in the Comptroller
summary section below.
Construct a new money market
Parameters
❌ Errors
ZeroAddressNotAllowed is thrown when admin address is zero
ZeroAddressNotAllowed is thrown when shortfall contract address is zero
ZeroAddressNotAllowed is thrown when protocol share reserve address is zero
Transfer amount
tokens from msg.sender
to dst
Parameters
Return Values
📅 Events
Emits Transfer event on success
⛔️ Access Requirements
Not restricted
❌ Errors
TransferNotAllowed is thrown if trying to transfer to self
Transfer amount
tokens from src
to dst
Parameters
Return Values
📅 Events
Emits Transfer event on success
⛔️ Access Requirements
Not restricted
❌ Errors
TransferNotAllowed is thrown if trying to transfer to self
Approve spender
to transfer up to amount
from src
Parameters
Return Values
📅 Events
Emits Approval event
⛔️ Access Requirements
Not restricted
❌ Errors
ZeroAddressNotAllowed is thrown when spender address is zero
Increase approval for spender
Parameters
Return Values
📅 Events
Emits Approval event
⛔️ Access Requirements
Not restricted
❌ Errors
ZeroAddressNotAllowed is thrown when spender address is zero
Decreases approval for spender
Parameters
Return Values
📅 Events
Emits Approval event
⛔️ Access Requirements
Not restricted
❌ Errors
ZeroAddressNotAllowed is thrown when spender address is zero
Get the underlying balance of the owner
Parameters
Return Values
Returns the current total borrows plus accrued interest
Return Values
Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex
Parameters
Return Values
Sender supplies assets into the market and receives vTokens in exchange
Parameters
Return Values
📅 Events
Emits Mint and Transfer events; may emit AccrueInterest
⛔️ Access Requirements
Not restricted
Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange
Parameters
Return Values
📅 Events
Emits Mint and Transfer events; may emit AccrueInterest
⛔️ Access Requirements
Not restricted
❌ Errors
ZeroAddressNotAllowed is thrown when minter address is zero
Sender redeems vTokens in exchange for the underlying asset
Parameters
Return Values
📅 Events
Emits Redeem and Transfer events; may emit AccrueInterest
⛔️ Access Requirements
Not restricted
❌ Errors
RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash
Sender redeems vTokens in exchange for a specified amount of underlying asset
Parameters
Return Values
Sender borrows assets from the protocol to their own address
Parameters
Return Values
📅 Events
Emits Borrow event; may emit AccrueInterest
⛔️ Access Requirements
Not restricted
❌ Errors
BorrowCashNotAvailable is thrown when the protocol has insufficient cash
Sender repays their own borrow
Parameters
Return Values
📅 Events
Emits RepayBorrow event; may emit AccrueInterest
⛔️ Access Requirements
Not restricted
Sender repays a borrow belonging to borrower
Parameters
Return Values
📅 Events
Emits RepayBorrow event; may emit AccrueInterest
⛔️ Access Requirements
Not restricted
The sender liquidates the borrowers collateral. The collateral seized is transferred to the liquidator.
Parameters
Return Values
📅 Events
Emits LiquidateBorrow event; may emit AccrueInterest
⛔️ Access Requirements
Not restricted
❌ Errors
LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken
LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken
LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self
LiquidateCloseAmountIsZero is thrown when repayment amount is zero
LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX
sets protocol share accumulated from liquidations
Parameters
📅 Events
Emits NewProtocolSeizeShare event on success
⛔️ Access Requirements
Controlled by AccessControlManager
❌ Errors
Unauthorized error is thrown when the call is not authorized by AccessControlManager
ProtocolSeizeShareTooBig is thrown when the new seize share is too high
accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh
Parameters
📅 Events
Emits NewReserveFactor event; may emit AccrueInterest
⛔️ Access Requirements
Controlled by AccessControlManager
❌ Errors
Unauthorized error is thrown when the call is not authorized by AccessControlManager
SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high
Accrues interest and reduces reserves by transferring to the protocol reserve contract
Parameters
📅 Events
Emits ReservesReduced event; may emit AccrueInterest
⛔️ Access Requirements
Not restricted
❌ Errors
ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash
ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have
The sender adds to reserves.
Parameters
📅 Events
Emits ReservesAdded event; may emit AccrueInterest
⛔️ Access Requirements
Not restricted
accrues interest and updates the interest rate model using _setInterestRateModelFresh
Parameters
📅 Events
Emits NewMarketInterestRateModel event; may emit AccrueInterest
⛔️ Access Requirements
Controlled by AccessControlManager
❌ Errors
Unauthorized error is thrown when the call is not authorized by AccessControlManager
Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially "forgiving" the borrower. Healing is a situation that should rarely happen. However, some pools may list risky assets or be configured improperly – we want to still handle such cases gracefully. We assume that Comptroller does the seizing, so this function is only available to Comptroller.
Parameters
📅 Events
Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest
⛔️ Access Requirements
Only Comptroller
❌ Errors
HealBorrowUnauthorized is thrown when the request does not come from Comptroller
The extended version of liquidations, callable only by Comptroller. May skip the close factor check. The collateral seized is transferred to the liquidator.
Parameters
📅 Events
Emits LiquidateBorrow event; may emit AccrueInterest
⛔️ Access Requirements
Only Comptroller
❌ Errors
ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller
LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken
LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken
LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self
LiquidateCloseAmountIsZero is thrown when repayment amount is zero
LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX
Transfers collateral tokens (this market) to the liquidator.
Parameters
📅 Events
Emits Transfer, ReservesAdded events
⛔️ Access Requirements
Not restricted
❌ Errors
LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self
Updates bad debt
Parameters
📅 Events
Emits BadDebtRecovered event
⛔️ Access Requirements
Only Shortfall contract
Sets protocol share reserve contract address
Parameters
⛔️ Access Requirements
Only Governance
❌ Errors
ZeroAddressNotAllowed is thrown when protocol share reserve address is zero
Sets shortfall contract address
Parameters
⛔️ Access Requirements
Only Governance
❌ Errors
ZeroAddressNotAllowed is thrown when shortfall contract address is zero
A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)
Parameters
⛔️ Access Requirements
Only Governance
A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve
Parameters
⛔️ Access Requirements
Only Governance
Get the current allowance from owner
for spender
Parameters
Return Values
Get the token balance of the owner
Parameters
Return Values
Get a snapshot of the account's balances, and the cached exchange rate
Parameters
Return Values
Get cash balance of this vToken in the underlying asset
Return Values
Returns the current per-block borrow interest rate for this vToken
Return Values
Returns the current per-block supply interest rate for this v
Return Values
Return the borrow balance of account based on stored data
Parameters
Return Values
Calculates the exchange rate from the underlying to the VToken
Return Values
Accrue interest then return the up-to-date exchange rate
Return Values
Applies accrued interest to total borrows and reserves
Return Values
📅 Events
Emits AccrueInterest event on success
⛔️ Access Requirements
Not restricted
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.
60% to Treasury
20% to XVS Vault rewards
20% to Venus Prime
Schema (ADDITIONAL_REVENUE): Valid for liquidation and other product developments.
80% to Treasury
20% to XVS Vault rewards
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.
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.
The dashed lines represent transactions initiated by external agents (VIP’s, scripts, arbitrage bots, etc.), and the solid lines represent transfers of funds.
Interface implemented by PoolRegistry
.
Get all pools in PoolRegistry
Get a pool by comptroller address
Get the address of the VToken contract in the Pool where the underlying token is the provided asset
Get the addresss of the Pools supported that include a market for the provided asset
Get the metadata of a Pool by comptroller address
NativeTokenGateway contract facilitates interactions with a vToken market for native tokens (Native or wNativeToken)
Address of wrapped native token contract
Address of wrapped native token market
Constructor for NativeTokenGateway
Parameters
To receive Native when msg.data is empty
To receive Native when msg.data is not empty
Wrap Native, get wNativeToken, mint vWNativeToken, and supply to the market.
Parameters
📅 Events
TokensWrappedAndSupplied is emitted when assets are supplied to the market
❌ Errors
ZeroAddressNotAllowed is thrown if address of minter is zero address
ZeroValueNotAllowed is thrown if mintAmount is zero
Redeem vWNativeToken, unwrap to Native Token, and send to the user
Parameters
📅 Events
TokensRedeemedAndUnwrapped is emitted when assets are redeemed from a market and unwrapped
❌ Errors
ZeroValueNotAllowed is thrown if redeemAmount is zero
Redeem vWNativeToken, unwrap to Native Token, and send to the user
Parameters
📅 Events
TokensRedeemedAndUnwrapped is emitted when assets are redeemed from a market and unwrapped
❌ Errors
ZeroValueNotAllowed is thrown if redeemTokens is zero
Wrap Native, repay borrow in the market, and send remaining Native to the user
📅 Events
TokensWrappedAndRepaid is emitted when assets are repaid to a market and unwrapped
❌ Errors
ZeroValueNotAllowed is thrown if repayAmount is zero
Sweeps native assets (Native) from the contract and sends them to the owner
📅 Events
SweepNative is emitted when assets are swept from the contract
⛔️ Access Requirements
Controlled by Governance
Sweeps the input token address tokens from the contract and sends them to the owner
Parameters
📅 Events
SweepToken emits on success
⛔️ Access Requirements
Controlled by Governance
The Isolated Pools architecture centers around the PoolRegistry
contract. The PoolRegistry
maintains a directory of isolated lending pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required metadata, and providing the getter methods to get information on the pools.
Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools. It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of any existing pool like getVTokenForAsset
and getPoolsSupportedByAsset
. It also contains methods for updating pool metadata (updatePoolMetadata
) and setting pool name (setPoolName
).
The directory of pools is managed through two mappings: _poolByComptroller
which is a hashmap with the comptroller address as the key and VenusPool
as the value and _poolsByID
which is an array of comptroller addresses. Individual pools can be accessed by calling getPoolByComptroller
with the pool's comptroller address. _poolsByID
is used to iterate through all of the pools.
PoolRegistry also contains a map of asset addresses called _supportedPools
that maps to an array of assets suppored by each pool. This array of pools by asset is retrieved by calling getPoolsSupportedByAsset
.
PoolRegistry registers new isolated pools in the directory with the createRegistryPool
method. Isolated pools are composed of independent markets with specific assets and custom risk management configurations according to their markets.
Maps pool's comptroller address to metadata.
Initializes the deployer to owner
Parameters
Adds a new Venus pool to the directory
Parameters
Return Values
❌ Errors
ZeroAddressNotAllowed is thrown when Comptroller address is zero
ZeroAddressNotAllowed is thrown when price oracle address is zero
Add a market to an existing pool and then mint to provide initial supply
Parameters
❌ Errors
ZeroAddressNotAllowed is thrown when vToken address is zero
ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero
Modify existing Venus pool name
Parameters
Update metadata of an existing pool
Parameters
Returns arrays of all Venus pools' data
Return Values
Get the address of the VToken contract in the Pool where the underlying token is the provided asset
Get the addresss of the Pools supported that include a market for the provided asset
Calculates the current borrow interest rate per block
Parameters
Return Values
Calculates the current supply interest rate per block
Parameters
Return Values
Indicator that this is an InterestRateModel contract (for inspection)
Return Values
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.
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.
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.
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.
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:
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.
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:
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.
For more detailed information, refer to the following resources:
The PoolLens
contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function getAllPools()
. Additionally, the following records can be looked up for specific pools and markets:
the vToken balance of a given user;
the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;
the vToken address in a pool for a given asset;
a list of all pools that support an asset;
the underlying asset price of a vToken;
the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.
Queries the user's supply/borrow balances in vTokens
Parameters
Return Values
Queries all pools with addtional details for each of them
Parameters
Return Values
Queries the details of a pool identified by Comptroller address
Parameters
Return Values
Returns vToken holding the specified underlying asset in the specified pool
Parameters
Return Values
Returns all pools that support the specified underlying asset
Parameters
Return Values
Returns the price data for the underlying assets of the specified vTokens
Parameters
Return Values
Returns the pending rewards for a user for a given pool.
Parameters
Return Values
Returns a summary of a pool's bad debt broken down by market
Parameters
Return Values
Queries the user's supply/borrow balances in the specified vToken
Parameters
Return Values
Queries additional information for the pool
Parameters
Return Values
Returns the metadata of VToken
Parameters
Return Values
Returns the metadata of all VTokens
Parameters
Return Values
Returns the price data for the underlying asset of the specified vToken
Parameters
Return Values
Storage layout used by the VToken
contract
Underlying asset for this VToken
EIP-20 token name for this token
EIP-20 token symbol for this token
EIP-20 token decimals for this token
Protocol share Reserve contract address
Contract which oversees inter-vToken operations
Model which tells what the current interest rate should be
Fraction of interest currently set aside for reserves
Block number that interest was last accrued at
Accumulator of the total earned interest rate since the opening of the market
Total amount of outstanding borrows of the underlying in this market
Total amount of reserves of the underlying held in this market
Total number of tokens in circulation
Total bad debt of the market
Share of seized collateral that is added to reserves
Storage of Shortfall contract address
delta block after which reserves will be reduced
last block number at which reserves were reduced
Indicator that this is a VToken contract (for inspection)
Return Values
Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol. Users can receive additional rewards through a RewardsDistributor
. Each RewardsDistributor
proxy is initialized with a specific reward token and Comptroller
, which can then distribute the reward token to users that supply or borrow in the associated pool. Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward token to be released each block for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.
The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed automatically and must be claimed by a user calling claimRewardToken()
. Users should be aware that it is up to the owner and other centralized entities to ensure that the RewardsDistributor
holds enough tokens to distribute the accumulated rewards of users and contributors.
The initial REWARD TOKEN index for a market
The REWARD TOKEN market supply state for each market
The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN
The REWARD TOKEN accrued but not yet transferred to each user
The rate at which rewardToken is distributed to the corresponding borrow market (per block)
The rate at which rewardToken is distributed to the corresponding supply market (per block)
The REWARD TOKEN market borrow state for each market
The portion of REWARD TOKEN that each contributor receives per block
Last block at which a contributor's REWARD TOKEN rewards have been allocated
The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN
RewardsDistributor initializer
Parameters
Calculate reward token accrued by a borrower and possibly transfer it to them Borrowers will begin to accrue after the first interaction with the protocol.
Parameters
Transfer REWARD TOKEN to the recipient
Parameters
Set REWARD TOKEN borrow and supply speeds for the specified markets
Parameters
Set REWARD TOKEN last rewarding block for the specified markets
Parameters
Set REWARD TOKEN speed for a single contributor
Parameters
Claim all the rewardToken accrued by holder in all markets
Parameters
Set the limit for the loops can iterate to avoid the DOS
Parameters
Calculate additional accrued REWARD TOKEN for a contributor since last accrual
Parameters
Claim all the rewardToken accrued by holder in the specified markets
Parameters
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 .
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
). It returns the USD price of the token, converting on-chain from eBTC to WBTC using the exchange rate from the contract.
SFraxOracle
. It returns the USD price of the token, converting on-chain from sFRAX to FRAX using the exchange rate from the sFRAX contract.
SlisBNBOracle
. It returns the USD price of the token, converting on-chain from slisBNB to BNB using the exchange rate from the contract.
AsBNBOracle
. It returns the USD price of the token, converting on-chain from asBNB to slisBNB using the exchange rate from the contract.
StkBNBOracle
. It returns the USD price of the token, converting on-chain from stkBNB to BNB using the exchange rate from the contract.
WBETHOracle
. It returns the USD price of the token, converting on-chain from WBETH to BNB using the exchange rate from the WBETH contract.
WeETHOracle
. It returns the USD price of the token, converting on-chain from weETH to eETH using the exchange rate from the contract, and assumming 1 eETH = 1 ETH.
WeETHsOracle
(instance of WeETHAccountantOracle
). It returns the USD price of the token, converting on-chain from weETHs to WETH using the exchange rate from the contract.
WstETHOracle
. It returns the USD price of the token, converting on-chain from wstETH to stETH using the exchange rate from the contract, and assumming 1 stETH = 1 ETH.
protocolShareReserve_
contract IProtocolShareReserve
Address of the PSR contract
reduceAmount
uint256
amount of reserves to reduce
newInterestRateModel
address
Address of the new interest rate model
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
governor
contract GovernorAlpha
Governor address
voter
address
Voter address
proposalIds
uint256[]
Array of proposal ids
[0]
struct VenusLens.GovReceipt[]
Array of governor receipts
governor
contract GovernorAlpha
Address of governor contract
proposalIds
uint256[]
Array of proposal Ids
[0]
struct VenusLens.GovProposal[]
GovProposal structs for provided proposal Ids
xvs
contract XVS
XVS contract address
account
address
Account address
[0]
struct VenusLens.XVSBalanceMetadata
Struct with XVS balance and voter details
xvs
contract XVS
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 XVS
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]
uint256
Total number of accrued XVS that can be claimed
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
underlying_
address
The address of the underlying asset
comptroller_
contract ComptrollerInterface
The address of the Comptroller
interestRateModel_
contract InterestRateModel
The address of the interest rate model
initialExchangeRateMantissa_
uint256
The initial exchange rate, scaled by 1e18
name_
string
ERC-20 name of this token
symbol_
string
ERC-20 symbol of this token
decimals_
uint8
ERC-20 decimal precision of this token
admin_
address
Address of the administrator of this token
accessControlManager_
address
AccessControlManager contract address
riskManagement
struct VTokenInterface.RiskManagementInit
Addresses of risk & income related contracts
reserveFactorMantissa_
uint256
Percentage of borrow interest that goes to reserves (from 0 to 1e18)
dst
address
The address of the destination account
amount
uint256
The number of tokens to transfer
[0]
bool
success True if the transfer succeeded, reverts otherwise
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
success True if the transfer succeeded, reverts otherwise
spender
address
The address of the account which may transfer tokens
amount
uint256
The number of tokens that are approved (uint256.max means infinite)
[0]
bool
success Whether or not the approval succeeded
spender
address
The address of the account which may transfer tokens
addedValue
uint256
The number of additional tokens spender can transfer
[0]
bool
success Whether or not the approval succeeded
spender
address
The address of the account which may transfer tokens
subtractedValue
uint256
The number of tokens to remove from total approval
[0]
bool
success Whether or not the approval succeeded
owner
address
The address of the account to query
[0]
uint256
amount The amount of underlying owned by owner
[0]
uint256
totalBorrows The total borrows with interest
account
address
The address whose balance should be calculated after updating borrowIndex
[0]
uint256
borrowBalance The calculated balance
mintAmount
uint256
The amount of the underlying asset to supply
[0]
uint256
error Always NO_ERROR for compatibility with Venus core tooling
minter
address
User whom the supply will be attributed to
mintAmount
uint256
The amount of the underlying asset to supply
[0]
uint256
error Always NO_ERROR for compatibility with Venus core tooling
redeemTokens
uint256
The number of vTokens to redeem into underlying
[0]
uint256
error Always NO_ERROR for compatibility with Venus core tooling
redeemAmount
uint256
The amount of underlying to receive from redeeming vTokens
[0]
uint256
error Always NO_ERROR for compatibility with Venus core tooling
borrowAmount
uint256
The amount of the underlying asset to borrow
[0]
uint256
error Always NO_ERROR for compatibility with Venus core tooling
repayAmount
uint256
The amount to repay, or type(uint256).max for the full outstanding amount
[0]
uint256
error Always NO_ERROR for compatibility with Venus core tooling
borrower
address
the account with the debt being payed off
repayAmount
uint256
The amount to repay, or type(uint256).max for the full outstanding amount
[0]
uint256
error Always NO_ERROR for compatibility with Venus core tooling
borrower
address
The borrower of this vToken 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 Always NO_ERROR for compatibility with Venus core tooling
newProtocolSeizeShareMantissa_
uint256
new protocol share mantissa
newReserveFactorMantissa
uint256
New reserve factor (from 0 to 1e18)
reduceAmount
uint256
Amount of reduction to reserves
addAmount
uint256
The amount of underlying token to add as reserves
newInterestRateModel
contract InterestRateModel
the new interest rate model to use
payer
address
account who repays the debt
borrower
address
account to heal
repayAmount
uint256
amount to repay
liquidator
address
The address repaying the borrow and seizing collateral
borrower
address
The borrower of this vToken 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
skipLiquidityCheck
bool
If set to true, allows to liquidate up to 100% of the borrow regardless of the account liquidity
liquidator
address
The account receiving seized collateral
borrower
address
The account having collateral seized
seizeTokens
uint256
The number of vTokens to seize
recoveredAmount_
uint256
The amount of bad debt recovered
protocolShareReserve_
address payable
The address of the protocol share reserve contract
shortfall_
address
The address of the shortfall contract
token
contract IERC20Upgradeable
The address of the ERC-20 token to sweep
_newReduceReservesBlockDelta
uint256
block difference value
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
amount The number of tokens allowed to be spent (type(uint256).max means infinite)
owner
address
The address of the account to query
[0]
uint256
amount The number of tokens owned by owner
account
address
Address of the account to snapshot
error
uint256
Always NO_ERROR for compatibility with Venus core tooling
vTokenBalance
uint256
User's balance of vTokens
borrowBalance
uint256
Amount owed in terms of underlying
exchangeRate
uint256
Stored exchange rate
[0]
uint256
cash The quantity of underlying asset owned by this contract
[0]
uint256
rate The borrow interest rate per block, scaled by 1e18
[0]
uint256
rate The supply interest rate per block, scaled by 1e18
account
address
The address whose balance should be calculated
[0]
uint256
borrowBalance The calculated balance
[0]
uint256
exchangeRate Calculated exchange rate scaled by 1e18
[0]
uint256
exchangeRate Calculated exchange rate scaled by 1e18
[0]
uint256
Always NO_ERROR
vWrappedNativeToken
contract IVToken
Address of wrapped native token market
minter
address
The address on behalf of whom the supply is performed.
redeemAmount
uint256
The amount of underlying tokens to redeem
redeemTokens
uint256
The amount of vWNative tokens to redeem
token
contract IERC20
Address of the token
accessControlManager_
address
AccessControlManager contract address
name
string
The name of the pool
comptroller
contract Comptroller
Pool's Comptroller contract
closeFactor
uint256
The pool's close factor (scaled by 1e18)
liquidationIncentive
uint256
The pool's liquidation incentive (scaled by 1e18)
minLiquidatableCollateral
uint256
Minimal collateral for regular (non-batch) liquidations flow
index
uint256
The index of the registered Venus pool
input
struct PoolRegistry.AddMarketInput
The structure describing the parameters for adding a market to a pool
comptroller
address
Pool's Comptroller
name
string
New pool name
comptroller
address
Pool's Comptroller
metadata_
struct PoolRegistryInterface.VenusPoolMetaData
New pool metadata
[0]
struct PoolRegistryInterface.VenusPool[]
A list of all pools within PoolRegistry, with details for each pool
cash
uint256
The total amount of cash the market has
borrows
uint256
The total amount of borrows the market has outstanding
reserves
uint256
The total amount of reserves the market has
badDebt
uint256
The amount of badDebt in the market
[0]
uint256
The borrow rate per block (as a percentage, and scaled by 1e18)
cash
uint256
The total amount of cash the market has
borrows
uint256
The total amount of borrows the market has outstanding
reserves
uint256
The total amount of reserves the market has
reserveFactorMantissa
uint256
The current reserve factor the market has
badDebt
uint256
The amount of badDebt in the market
[0]
uint256
The supply rate per block (as a percentage, and scaled by 1e18)
[0]
bool
Always true
vTokens
contract VToken[]
The list of vToken addresses
account
address
The user Account
[0]
struct PoolLens.VTokenBalances[]
A list of structs containing balances data
poolRegistryAddress
address
The address of the PoolRegistry contract
[0]
struct PoolLens.PoolData[]
Arrays of all Venus pools' data
poolRegistryAddress
address
The address of the PoolRegistry contract
comptroller
address
The Comptroller implementation address
[0]
struct PoolLens.PoolData
PoolData structure containing the details of the pool
poolRegistryAddress
address
The address of the PoolRegistry contract
comptroller
address
The pool comptroller
asset
address
The underlyingAsset of VToken
[0]
address
Address of the vToken
poolRegistryAddress
address
The address of the PoolRegistry contract
asset
address
The underlying asset of vToken
[0]
address[]
A list of Comptroller contracts
vTokens
contract VToken[]
The list of vToken addresses
[0]
struct PoolLens.VTokenUnderlyingPrice[]
An array containing the price data for each asset
account
address
The user account.
comptrollerAddress
address
address
[0]
struct PoolLens.RewardSummary[]
Pending rewards array
comptrollerAddress
address
Address of the comptroller
[0]
struct PoolLens.BadDebtSummary
badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market
vToken
contract VToken
vToken address
account
address
The user Account
[0]
struct PoolLens.VTokenBalances
A struct containing the balances data
poolRegistryAddress
address
Address of the PoolRegistry
venusPool
struct PoolRegistryInterface.VenusPool
The VenusPool Object from PoolRegistry
[0]
struct PoolLens.PoolData
Enriched PoolData
vToken
contract VToken
The address of vToken
[0]
struct PoolLens.VTokenMetadata
VTokenMetadata struct
vTokens
contract VToken[]
The list of vToken addresses
[0]
struct PoolLens.VTokenMetadata[]
An array of VTokenMetadata structs
vToken
contract VToken
vToken address
[0]
struct PoolLens.VTokenUnderlyingPrice
The price data for each asset
[0]
bool
Always true
comptroller_
contract Comptroller
Comptroller to attach the reward distributor to
rewardToken_
contract IERC20Upgradeable
Reward token to distribute
loopsLimit_
uint256
Maximum number of iterations for the loops in this contract
accessControlManager_
address
AccessControlManager contract address
vToken
address
The market in which the borrower is interacting
borrower
address
The address of the borrower to distribute REWARD TOKEN to
marketBorrowIndex
struct ExponentialNoError.Exp
The current global borrow index of vToken
recipient
address
The address of the recipient to transfer REWARD TOKEN to
amount
uint256
The amount of REWARD TOKEN to (possibly) transfer
vTokens
contract VToken[]
The markets whose REWARD TOKEN speed to update
supplySpeeds
uint256[]
New supply-side REWARD TOKEN speed for the corresponding market
borrowSpeeds
uint256[]
New borrow-side REWARD TOKEN speed for the corresponding market
vTokens
contract VToken[]
The markets whose REWARD TOKEN last rewarding block to update
supplyLastRewardingBlocks
uint32[]
New supply-side REWARD TOKEN last rewarding block for the corresponding market
borrowLastRewardingBlocks
uint32[]
New borrow-side REWARD TOKEN last rewarding block for the corresponding market
contributor
address
The contributor whose REWARD TOKEN speed to update
rewardTokenSpeed
uint256
New REWARD TOKEN speed for contributor
holder
address
The address to claim REWARD TOKEN for
limit
uint256
Limit for the max loops can execute at a time
contributor
address
The address to calculate contributor rewards for
holder
address
The address to claim REWARD TOKEN for
vTokens
contract VToken[]
The list of markets to claim REWARD TOKEN in
Core
AAVE
-
-
Core
ADA
-
-
Core
BCH
-
-
Core
BETH
-
-
Core
BNB
Upper bound: 1.01. Lower bound: 0.99
Core
BTCB
Upper bound: 1.01. Lower bound: 0.99
Core
BUSD
-
-
Core
CAKE
-
-
Core
DAI
-
-
Core
DOGE
-
-
Core
DOT
-
-
Core
ETH
-
-
Core
FDUSD
-
-
Core
FIL
-
-
Core
LINK
-
-
Core
lisUSD
-
-
Core
LTC
-
-
Core
LUNA
-
-
Core
MATIC
-
-
Core
PT-sUSDE-26JUN2025
-
-
Core
SOL
-
-
Core
SolvBTC
-
-
Core
sUSDe
Upper bound: 1.01. Lower bound: 0.99
Core
SXP
-
-
Core
THE
-
-
-
Core
TRX
-
Upper bound: 1.01. Lower bound: 0.99
Core
TRXOLD
-
Upper bound: 1.01. Lower bound: 0.99
Core
TUSD
-
-
Core
TUSDOLD
-
-
Core
TWT
-
-
Core
UNI
-
-
Core
USDC
-
-
Core
USDe
Upper bound: 1.01. Lower bound: 0.99
Core
USDT
-
-
Core
UST
-
-
Core
VAI
-
-
Core
WBETH
-
-
Core
XRP
-
-
Core
XVS
-
-
Stablecoins
lisUSD
-
-
Stablecoins
USDD
-
-
Stablecoins
USDT
-
-
Stablecoins
EURA
-
-
DeFi
BSW
-
-
DeFi
ALPACA
-
-
DeFi
USDT
-
-
DeFi
USDD
-
-
DeFi
ANKR
-
-
DeFi
ankrBNB
-
-
DeFi
TWT
-
-
DeFi
PLANET
-
-
GameFi
RACA
-
-
GameFi
FLOKI
-
-
GameFi
USDD
-
-
GameFi
USDT
-
-
Liquid Staked BNB
ankrBNB
-
Liquid Staked BNB
asBNB
-
-
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
-
-
Tron
BTT
-
-
Tron
TRX
-
-
Tron
WIN
-
-
Tron
USDD
-
-
Tron
USDT
-
-
Liquid Staked ETH
ETH
-
-
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
crvUSD
-
-
Core
DAI
-
-
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
-
-
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
BTCB
-
-
Core
ETH
-
-
Core
FDUSD
-
-
Core
USDT
-
-
Core
WBNB
-
-
Core
WBTC
-
-
Core
WETH
-
-
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
WBTC
-
-
Core
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
WBTC
-
-
Core
WETH
-
-
Core
USDC
-
-
Core
USDT
-
-
Core
OP
-
-
Core
cbBTC
-
-
Core
WETH
-
-
Core
USDC
-
-
Core
wsuperOETHb
-
-
Core
wstETH
-
-
Core
WETH
-
-
Core
USDC
-
-
Core
UNI
-
-
Let's take a quick look at the Venus interface and the features available in each menu of the navigation bar.
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.
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.
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.
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.
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.
The Swap interface enables you to swap one cryptocurrency for another within the Venus Protocol. You can exchange your assets conveniently and quickly.
In the History interface, you can review transaction history and track your previous activities on the Protocol.
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.
The XVS interface displays the current daily reward distribution rate for each of the protocol markets.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
The bridge supports transfers between all network pairs, providing users with enhanced flexibility and interoperability across blockchain ecosystems.
To start using the XVS Cross-Chain Bridge, follow these steps:
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:
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.
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:
_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).
The actual token transfer is performed using the sendFrom
function of the Bridge
contract. Follow these steps:
Call the sendFrom
function of the Bridge
contract with the following parameters::
_from
: Your address on the BNB chain
_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)
adapterParams
: 0x000100000000000000000000000000000000000000000000000000000000000493E0
(ethers.utils.solidityPack(['uint16','uint256'],[1, gasValue]) the gas value should be greater then minDestGas which is set to 300k).
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.
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).
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.
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.
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.
Configurable delay after XVS transfers to the target network by specifying a minimum number of blocks in the LayerZero endpoint configuration.
Cap on the amount of tokens that can be minted in the destination target network. This feature can be integrated in Token Controller.
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.
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:
In the event that a Bridge
contract needs replacement, such as due to a security risk, the following steps will be taken:
Pause the Bridge:
Temporarily pause the Bridge
contract to prevent further transactions.
Token Evaluation:
Evaluate whether pausing the XVS token is necessary during the replacement process.
Migrate MinterToMintedAmount:
Move the minterToMintedAmount
value to a different Bridge
contract address using the migrateMintedTokens
function.
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.
Here, we provide more details about the key contracts used in the XVS Cross-chain Bridge:
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.
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.
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.
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.
In addition to the core functionality, the XVS Cross-chain Bridge includes additional features to enhance its capabilities:
The contract incorporates an oracle integration through the ResilientOracleInterface
. It allows the contract to fetch price data for the token using the getPrice
function.
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.
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
-
$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
$20,000
$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
-
Daily Send Limit (source network in the first column, destination network in the first row)
BNB
-
$50,000
$100,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
-
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.
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.
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.
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.
Identify the Failed Transaction:
Examine the MessageFailed Log:
Extract Function Parameters:
From the MessageFailed
log, extract the following essential function parameters:
_srcChainId
_srcAddress
_nonce
_payload
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.
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:
The system consists of multiple contracts, including , , , and token contracts.
The functionality of the bridge relies on 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.
_dstChainId
: Destination chain ID, (e.g., Ethereum virtual chain ID (101))
_dstChainId
: Destination chain ID (e.g., Ethereum virtual chain ID (101))
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 to monitor your cross-chain transactions.
contract within the XVS token deployed on the target network to blacklist addresses, preventing them from transferring or receiving XVS. Integrated with the ACM.
Currently, the Bridge
relies on a single relayer, the 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.
is the admin contract for the bridge, ensuring proper setup.
extends the contract and includes custom logic for token transfers.
is similar to XVSProxySrc
but with specific differences.
The 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 ownable contract, which contains all controlling mechanisms of the XVS.
integration is used for setting minting caps and blacklisting, and these settings can be configured via VIPs or Guardian.
In the event of a failed transaction, follow the below step-by-step process using block explorers and the function to retry transactions on the respective blockchain. Here's a detailed guide:
Use to identify the failed transaction within the target network by providing the transaction hash from the source network where the transaction was initiated.
Access the emitted events of the failed transaction and specifically examine the log. This log contains essential function parameters needed for the retry.
Construct an interest rate model
Parameters
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
Calculates the utilization rate of the market: borrows / (cash + borrows - reserves)
Parameters
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)
Return Values
[0]
uint256
The utilization rate as a mantissa between [0, 1e18]
Calculates the current borrow rate per block, with the error code expected by the market
Parameters
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
[0]
uint256
The borrow rate percentage per block as a mantissa (scaled by 1e18)
Calculates the current supply rate per block
Parameters
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
[0]
uint256
The supply rate percentage per block as a mantissa (scaled by 1e18)
Contract for swapping stable token for VAI token and vice versa to maintain the peg stability between them.
The divisor used to convert fees to basis points.
The mantissa value representing 1 (used for calculations).
The value representing one dollar in the stable token.
VAI token contract.
The address of the stable token contract.
The address of ResilientOracle contract wrapped in its interface.
The address of the Venus Treasury contract.
The incoming stableCoin fee. (Fee for swapStableForVAI).
The outgoing stableCoin fee. (Fee for swapVAIForStable).
The maximum amount of VAI that can be minted through this contract.
The total amount of VAI minted through this contract.
A flag indicating whether the contract is currently paused or not.
Initializes the contract via Proxy Contract with the required parameters.
Parameters
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
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.
Swaps VAI for a stable token.
Parameters
receiver
address
The address where the stablecoin will be sent.
stableTknAmount
uint256
The amount of stable tokens to receive.
Return Values
[0]
uint256
The amount of VAI received and burnt from the sender.
Swaps stable tokens for VAI with fees.
Parameters
receiver
address
The address that will receive the VAI tokens.
stableTknAmount
uint256
The amount of stable tokens to be swapped.
Return Values
[0]
uint256
Amount of VAI minted to the sender.
Pause the PSM contract.
Resume the PSM contract.
Set the fee percentage for incoming swaps.
Parameters
feeIn_
uint256
The new fee percentage for incoming swaps.
Set the fee percentage for outgoing swaps.
Parameters
feeOut_
uint256
The new fee percentage for outgoing swaps.
Set the address of the Venus Treasury contract.
Parameters
venusTreasury_
address
The new address of the Venus Treasury contract.
Set the address of the ResilientOracle contract.
Parameters
oracleAddress_
address
The new address of the ResilientOracle contract.
Calculates the amount of VAI that would be burnt from the user.
Parameters
stableTknAmount
uint256
The amount of stable tokens to be received after the swap.
Return Values
[0]
uint256
The amount of VAI that would be taken from the user.
Calculates the amount of VAI that would be sent to the receiver.
Parameters
stableTknAmount
uint256
The amount of stable tokens provided for the swap.
Return Values
[0]
uint256
The amount of VAI that would be sent to the receiver.
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.
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.
Add assets to be included in account liquidity calculation; enabling them to be used as collateral
Parameters
vTokens
address[]
The list of addresses of the vToken markets to be enabled
Return Values
[0]
uint256[]
errors An array of NO_ERROR for compatibility with Venus core tooling
📅 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
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
delegate
address
The address to update the rights for
allowBorrows
bool
Whether to grant (true) or revoke (false) the rights
📅 Events
DelegateUpdated emits on success
⛔️ Access Requirements
Not restricted
❌ Errors
ZeroAddressNotAllowed is thrown when delegate address is zero
Removes asset from sender's account liquidity calculation; disabling them as collateral
Parameters
vTokenAddress
address
The address of the asset to be removed
Return Values
[0]
uint256
error Always NO_ERROR for compatibility with Venus core tooling
📅 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
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
Checks if the account should be allowed to mint tokens in the given market
Parameters
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
⛔️ 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
Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.
Parameters
vToken
address
Asset being minted
minter
address
The address minting the tokens
actualMintAmount
uint256
The amount of the underlying asset being minted
mintTokens
uint256
The number of tokens being minted
Checks if the account should be allowed to redeem tokens in the given market
Parameters
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
⛔️ 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
PriceError is thrown if the oracle returns an incorrect price for some asset
Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.
Parameters
vToken
address
Asset being redeemed
redeemer
address
The address redeeming the tokens
redeemAmount
uint256
The amount of the underlying asset being redeemed
redeemTokens
uint256
The number of tokens being redeemed
Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.
Parameters
vToken
address
Asset being repaid
payer
address
The address repaying the borrow
borrower
address
The address of the borrower
actualRepayAmount
uint256
The amount of underlying being repaid
borrowerIndex
uint256
Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.
Parameters
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
The address of the borrower
actualRepayAmount
uint256
The amount of underlying being repaid
seizeTokens
uint256
The amount of collateral token that will be seized
Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.
Parameters
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
The address of the borrower
seizeTokens
uint256
The number of collateral tokens to seize
Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.
Parameters
vToken
address
Asset being transferred
src
address
The account which sources the tokens
dst
address
The account which receives the tokens
transferTokens
uint256
The number of vTokens to transfer
disable-eslint
Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.
Parameters
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
Checks if the account should be allowed to repay a borrow in the given market
Parameters
vToken
address
The market to verify the repay against
borrower
address
The account which would borrowed the asset
⛔️ 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
Checks if the liquidation should be allowed to occur
Parameters
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
The amount of underlying being repaid
skipLiquidityCheck
bool
Allows the borrow to be liquidated regardless of the account liquidity
❌ 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
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
Checks if the seizing of assets should be allowed to occur
Parameters
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
The address of the borrower
⛔️ 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
Checks if the account should be allowed to transfer tokens in the given market
Parameters
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
The number of vTokens to transfer
⛔️ 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
PriceError is thrown if the oracle returns an incorrect price for some asset
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
user
address
account to heal
⛔️ 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
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
borrower
address
the borrower address
orders
struct ComptrollerStorage.LiquidationOrder[]
an array of liquidation orders
⛔️ 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
Sets the closeFactor to use when liquidating borrows
Parameters
newCloseFactorMantissa
uint256
New close factor, scaled by 1e18
📅 Events
Emits NewCloseFactor on success
⛔️ Access Requirements
Controlled by AccessControlManager
Sets the collateralFactor for a market
Parameters
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
📅 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
Sets liquidationIncentive
Parameters
newLiquidationIncentiveMantissa
uint256
New liquidationIncentive scaled by 1e18
📅 Events
Emits NewLiquidationIncentive on success
⛔️ Access Requirements
Controlled by AccessControlManager
Add the market to the markets mapping and set it as listed
Parameters
vToken
contract VToken
The address of the market (token) to list
⛔️ Access Requirements
Only PoolRegistry
❌ Errors
MarketAlreadyListed is thrown if the market is already listed in this pool
Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.
Parameters
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.
⛔️ Access Requirements
Controlled by AccessControlManager
Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.
Parameters
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.
⛔️ Access Requirements
Controlled by AccessControlManager
Pause/unpause specified actions
Parameters
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)
⛔️ Access Requirements
Controlled by AccessControlManager
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
newMinLiquidatableCollateral
uint256
The new min liquidatable collateral (in USD).
⛔️ Access Requirements
Controlled by AccessControlManager
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
_rewardsDistributor
contract RewardsDistributor
Address of the RewardDistributor contract to add
📅 Events
Emits NewRewardsDistributor with distributor address
⛔️ Access Requirements
Only Governance
Sets a new price oracle for the Comptroller
Parameters
newOracle
contract ResilientOracleInterface
Address of the new price oracle to set
📅 Events
Emits NewPriceOracle on success
❌ Errors
ZeroAddressNotAllowed is thrown when the new oracle address is zero
Set the for loop iteration limit to avoid DOS
Parameters
limit
uint256
Limit for the max loops can execute at a time
Sets the prime token contract for the comptroller
Parameters
_prime
contract IPrime
Address of the Prime contract
Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity
Parameters
vTokenBorrowed
address
Borrowed vToken
enable
bool
Whether to enable forced liquidations
Determine the current account liquidity with respect to liquidation threshold requirements
Parameters
account
address
The account get liquidity for
Return Values
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
Determine the current account liquidity with respect to collateral requirements
Parameters
account
address
The account get liquidity for
Return Values
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
Determine what the account liquidity would be if the given amounts were redeemed/borrowed
Parameters
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
The amount of underlying to hypothetically borrow
Return Values
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
Return all of the markets
Return Values
[0]
contract VToken[]
markets The list of market addresses
Check if a market is marked as listed (active)
Parameters
vToken
contract VToken
vToken Address for the market to check
Return Values
[0]
bool
listed True if listed otherwise false
Returns the assets an account has entered
Parameters
account
address
The address of the account to pull assets for
Return Values
[0]
contract VToken[]
A list with the assets the account has entered
Returns whether the given account is entered in a given market
Parameters
account
address
The address of the account to check
vToken
contract VToken
The vToken to check
Return Values
[0]
bool
True if the account is in the market specified, otherwise false.
Calculate number of tokens of collateral asset to seize given an underlying amount
Parameters
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
Return Values
error
uint256
Always NO_ERROR for compatibility with Venus core tooling
tokensToSeize
uint256
Number of vTokenCollateral tokens to be seized in a liquidation
❌ Errors
PriceError if the oracle returns an invalid price
Returns reward speed given a vToken
Parameters
vToken
address
The vToken to get the reward speeds for
Return Values
rewardSpeeds
struct ComptrollerStorage.RewardSpeeds[]
Array of total supply and borrow speeds and reward token for all reward distributors
Return all reward distributors for this pool
Return Values
[0]
contract RewardsDistributor[]
Array of RewardDistributor addresses
A marker method that returns true for a valid Comptroller contract
Return Values
[0]
bool
Always true
Update the prices of all the tokens associated with the provided account
Parameters
account
address
Address of the account to get associated tokens with
Checks if a certain action is paused on a market
Parameters
market
address
vToken address
action
enum ComptrollerStorage.Action
Action to check
Return Values
[0]
bool
paused True if the action is paused otherwise false