> For the complete documentation index, see [llms.txt](https://docs-v4.venus.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-v4.venus.io/technical-reference/reference-core-pool/prime/prime.md).

# Prime token

## PrimeV2

PrimeV2 is the Prime token contract with leaderboard-based distribution. Prime status is decided by the `PrimeLeaderboard` contract based on time-weighted XVS staking, and boosted rewards are distributed to Prime holders across supported markets.

{% hint style="warning" %}
BNB Chain only. At block `118,364,540`, proxy `0x059EabA8676b03e4e8f009eFb7F587C28450F50f` used implementation `0x18cb7198cbb6d6e94001458cf3cf47c106d83a1b` and was unpaused. Other mainnets currently use Prime V1; see [Prime Contract Versions](/technical-reference/reference-core-pool/prime.md).
{% endhint %}

## Solidity API

#### WRAPPED\_NATIVE\_TOKEN

Address of wrapped native token

```solidity
address WRAPPED_NATIVE_TOKEN
```

***

#### NATIVE\_MARKET

Address of native market vToken

```solidity
address NATIVE_MARKET
```

***

#### xvsVault

Address of XVSVault contract

```solidity
address xvsVault
```

***

#### xvsVaultRewardToken

Reward token address in XVSVault

```solidity
address xvsVaultRewardToken
```

***

#### xvsVaultPoolId

Pool ID in XVSVault

```solidity
uint256 xvsVaultPoolId
```

***

#### constructor

PrimeV2 constructor. Sets the immutable references above and disables further initialization of the implementation contract.

```solidity
constructor(address wrappedNativeToken_, address nativeMarket_, address xvsVault_, address xvsVaultRewardToken_, uint256 xvsVaultPoolId_, bool timeBased_, uint256 blocksPerYear_) public
```

**Parameters**

| Name                  | Type    | Description                                                         |
| --------------------- | ------- | ------------------------------------------------------------------- |
| wrappedNativeToken\_  | address | Address of wrapped native token                                     |
| nativeMarket\_        | address | Address of native market                                            |
| xvsVault\_            | address | Address of XVSVault contract                                        |
| xvsVaultRewardToken\_ | address | Reward token address in XVSVault                                    |
| xvsVaultPoolId\_      | uint256 | Pool ID in XVSVault                                                 |
| timeBased\_           | bool    | A boolean indicating whether the contract is based on time or block |
| blocksPerYear\_       | uint256 | Total blocks per year                                               |

**❌ Errors**

* Throw InvalidAddress if xvsVault\_ or xvsVaultRewardToken\_ is the zero address

***

#### initialize

PrimeV2 initializer

```solidity
function initialize(uint128 alphaNumerator_, uint128 alphaDenominator_, address accessControlManager_, address primeLiquidityProvider_, address corePoolComptroller_, address oracle_, uint256 loopsLimit_) external
```

**Parameters**

| Name                     | Type    | Description                                                 |
| ------------------------ | ------- | ----------------------------------------------------------- |
| alphaNumerator\_         | uint128 | numerator of alpha. If alpha is 0.5 then numerator is 1     |
| alphaDenominator\_       | uint128 | denominator of alpha. If alpha is 0.5 then denominator is 2 |
| accessControlManager\_   | address | Address of AccessControlManager                             |
| primeLiquidityProvider\_ | address | Address of PrimeLiquidityProvider                           |
| corePoolComptroller\_    | address | Address of core pool comptroller                            |
| oracle\_                 | address | Address of Oracle                                           |
| loopsLimit\_             | uint256 | Maximum number of loops allowed in a single transaction     |

**❌ Errors**

* Throw InvalidAddress if any of the address is zero
* Throw InvalidAlphaArguments if alpha arguments are invalid

***

#### claimPrime

Mint a Prime token for a user in a permissionless way. Checks the user's Prime Score (their effective stake, read via `PrimeLeaderboard.getEffectiveStake`) against `mintThreshold`. Anyone can call this on behalf of an eligible user; no ACM required. Reverts while the contract is paused.

```solidity
function claimPrime(address user) external
```

**Parameters**

| Name | Type    | Description              |
| ---- | ------- | ------------------------ |
| user | address | User address to mint for |

**📅 Events**

* Emits Mint event on new token issuance

**❌ Errors**

* Throw InvalidAddress if user is the zero address
* Throw ScoreUpdateInProgress if a score update round is active
* Throw UserAlreadyHasPrimeToken if user already has a token
* Throw LeaderboardNotSet if primeLeaderboard address is not configured
* Throw MintThresholdNotSet if mintThreshold is zero
* Throw EligibilityBelowThreshold if user's Prime Score < mintThreshold
* Throw InvalidLimit if mint limit would be exceeded
* Throw MintWindowClosed if the minting deadline has passed

***

#### claimPrimeBatch

Mint Prime tokens for multiple users in a permissionless way. Non-holders below `mintThreshold` are skipped with a `SkippedIneligibleUser` event (not reverted). Existing Prime holders are silently skipped. Anyone can call this; no ACM required. Reverts while the contract is paused.

```solidity
function claimPrimeBatch(address[] users) external
```

**Parameters**

| Name  | Type       | Description                         |
| ----- | ---------- | ----------------------------------- |
| users | address\[] | Array of user addresses to mint for |

**📅 Events**

* Emits Mint event for each new token issuance
* Emits SkippedIneligibleUser for each non-holder below threshold

**❌ Errors**

* Throw ScoreUpdateInProgress if a score update round is active
* Throw LeaderboardNotSet if primeLeaderboard address is not configured
* Throw MintThresholdNotSet if mintThreshold is zero
* Throw MintWindowClosed if the minting deadline has passed
* Throw InvalidLimit if mint limit would be exceeded
* Throw MaxLoopsLimitExceeded if the batch is larger than loopsLimit

***

#### issue

Issue a Prime token to a single user (admin function)

```solidity
function issue(address user) external
```

**Parameters**

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| user | address | User address |

**📅 Events**

* Emits Mint event on new token issuance

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw InvalidAddress if user is zero address
* Throw InvalidLimit if mint limit would be exceeded
* Throw UserAlreadyHasPrimeToken if user already has a token
* Throw ScoreUpdateInProgress if a score update round is active

***

#### issueBatch

Issue Prime tokens to multiple users (admin function)

```solidity
function issueBatch(address[] users) external
```

**Parameters**

| Name  | Type       | Description             |
| ----- | ---------- | ----------------------- |
| users | address\[] | Array of user addresses |

**📅 Events**

* Emits Mint event on new token issuance

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw InvalidAddress if any user in the batch is zero address
* Throw InvalidLimit if mint limit would be exceeded
* Throw ScoreUpdateInProgress if a score update round is active
* Throw MaxLoopsLimitExceeded if the batch is larger than loopsLimit

***

#### burn

Burn a user's Prime token (admin function)

```solidity
function burn(address user) external
```

**Parameters**

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| user | address | User address |

**📅 Events**

* Emits Burn event

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw UserHasNoPrimeToken if user has no prime token
* Throw ScoreUpdateInProgress if a score update round is active

***

#### burnBatch

Burn Prime tokens for multiple users (admin function)

```solidity
function burnBatch(address[] users) external
```

**Parameters**

| Name  | Type       | Description             |
| ----- | ---------- | ----------------------- |
| users | address\[] | Array of user addresses |

**📅 Events**

* Emits Burn event for each user

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw ScoreUpdateInProgress if a score update round is active
* Throw MaxLoopsLimitExceeded if the batch is larger than loopsLimit

***

#### isUserPrimeHolder

Check if a user has a Prime token

```solidity
function isUserPrimeHolder(address user) external view returns (bool)
```

**Parameters**

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| user | address | User address |

**Return Values**

| Name | Type | Description                        |
| ---- | ---- | ---------------------------------- |
| \[0] | bool | whether the user has a Prime token |

***

#### claimInterest

Claim accrued interest for a market (to msg.sender). If the PrimeV2 balance is insufficient, funds are pulled from the PrimeLiquidityProvider in the same transaction; any remaining shortfall stays recorded as accrued and claimable later (partial claim, no revert). Residual accrued interest remains claimable even after a market is removed. Reverts while the contract is paused.

```solidity
function claimInterest(address vToken) external returns (uint256)
```

**Parameters**

| Name   | Type    | Description    |
| ------ | ------- | -------------- |
| vToken | address | Market address |

**Return Values**

| Name | Type    | Description    |
| ---- | ------- | -------------- |
| \[0] | uint256 | amount claimed |

**📅 Events**

* Emits InterestClaimed event

**❌ Errors**

* Throw MarketNotSupported if market is not supported (only when the vToken is not a current Prime market — never added, or since removed — and the user has no residual accrued balance)

***

#### claimInterest

Claim accrued interest for a market to a specific address. Permissionless: anyone can trigger a claim on behalf of a user. Tokens are always sent to the user address, never to msg.sender. Same shortfall behavior as the single-argument overload: partial claim with the remainder kept as accrued, no revert. Reverts while the contract is paused.

```solidity
function claimInterest(address vToken, address user) external returns (uint256)
```

**Parameters**

| Name   | Type    | Description       |
| ------ | ------- | ----------------- |
| vToken | address | Market address    |
| user   | address | Recipient address |

**Return Values**

| Name | Type    | Description    |
| ---- | ------- | -------------- |
| \[0] | uint256 | amount claimed |

**📅 Events**

* Emits InterestClaimed event

**❌ Errors**

* Throw MarketNotSupported if market is not supported (only when the vToken is not a current Prime market — never added, or since removed — and the user has no residual accrued balance)

***

#### accrueInterest

Accrue interest for a market. Intentionally not gated by the pause to ensure fair reward distribution during pauses.

```solidity
function accrueInterest(address vToken) public
```

**Parameters**

| Name   | Type    | Description    |
| ------ | ------- | -------------- |
| vToken | address | Market address |

**❌ Errors**

* Throw MarketNotSupported if market is not supported

***

#### accrueInterestAndUpdateScore

Accrue interest and update score for a user in a specific market. Called by the Comptroller hooks.

```solidity
function accrueInterestAndUpdateScore(address user, address market) external
```

**Parameters**

| Name   | Type    | Description    |
| ------ | ------- | -------------- |
| user   | address | User address   |
| market | address | Market address |

***

#### accrueInterestAndUpdateScore

Accrue interest and update score for a user across all markets. Called by `PrimeLeaderboard` when a user's XVS stake changes, so rewards are accrued at the old score before the score is recalculated.

```solidity
function accrueInterestAndUpdateScore(address user) external
```

**Parameters**

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| user | address | User address |

**❌ Errors**

* Throw OnlyPrimeLeaderboard if caller is not the PrimeLeaderboard contract

***

#### getPendingRewards

Get pending rewards for a user (accrues first)

```solidity
function getPendingRewards(address user) external returns (struct PrimeV2StorageV1.PendingReward[] pendingRewards)
```

**Parameters**

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| user | address | User address |

**Return Values**

| Name           | Type                                     | Description                         |
| -------------- | ---------------------------------------- | ----------------------------------- |
| pendingRewards | struct PrimeV2StorageV1.PendingReward\[] | Array of pending rewards per market |

***

#### getPendingRewardsStatic

Get pending rewards for a user (view-only, does not accrue). Returns rewards based on the last accrued state without triggering new accrual.

```solidity
function getPendingRewardsStatic(address user) external view returns (struct PrimeV2StorageV1.PendingReward[] pendingRewards)
```

**Parameters**

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| user | address | User address |

**Return Values**

| Name           | Type                                     | Description                         |
| -------------- | ---------------------------------------- | ----------------------------------- |
| pendingRewards | struct PrimeV2StorageV1.PendingReward\[] | Array of pending rewards per market |

***

#### getLifetimeAccruedByMarket

Lifetime accrued rewards for many users in a single market. Pure view over the `lifetimeAccrued` field; intended for the off-chain cycle pipeline to snapshot per-(market, user) earnings without indexing events.

```solidity
function getLifetimeAccruedByMarket(address market, address[] users) external view returns (uint256[] amounts)
```

**Parameters**

| Name   | Type       | Description             |
| ------ | ---------- | ----------------------- |
| market | address    | vToken address          |
| users  | address\[] | Array of user addresses |

**Return Values**

| Name    | Type       | Description                                           |
| ------- | ---------- | ----------------------------------------------------- |
| amounts | uint256\[] | Lifetime accrued amounts, indexed parallel to `users` |

***

#### getLifetimeAccruedByUser

Lifetime accrued rewards for one user across many markets.

```solidity
function getLifetimeAccruedByUser(address user, address[] markets_) external view returns (uint256[] amounts)
```

**Parameters**

| Name      | Type       | Description               |
| --------- | ---------- | ------------------------- |
| user      | address    | User address              |
| markets\_ | address\[] | Array of vToken addresses |

**Return Values**

| Name    | Type       | Description                                              |
| ------- | ---------- | -------------------------------------------------------- |
| amounts | uint256\[] | Lifetime accrued amounts, indexed parallel to `markets_` |

***

#### updateScores

Update scores for a batch of users. Intentionally not gated by the pause — the keeper must complete rounds even during pauses.

```solidity
function updateScores(address[] users) external
```

**Parameters**

| Name  | Type       | Description             |
| ----- | ---------- | ----------------------- |
| users | address\[] | Array of user addresses |

**📅 Events**

* Emits UserScoreUpdated event

**❌ Errors**

* Throw NoScoreUpdatesRequired if no score updates are required
* Throw MaxLoopsLimitExceeded if the batch is larger than loopsLimit

***

#### getAllMarkets

Get all Prime markets

```solidity
function getAllMarkets() external view returns (address[])
```

**Return Values**

| Name | Type       | Description               |
| ---- | ---------- | ------------------------- |
| \[0] | address\[] | Array of market addresses |

***

#### xvsBalanceOfUser

Get a user's XVS balance from the vault (net of pending withdrawals)

```solidity
function xvsBalanceOfUser(address user) external view returns (uint256)
```

**Parameters**

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| user | address | User address |

**Return Values**

| Name | Type    | Description        |
| ---- | ------- | ------------------ |
| \[0] | uint256 | User's XVS balance |

***

#### addMarket

Add a market to Prime. Opens a new score-update round: all Prime holders' scores must be recomputed via `updateScores` before issuing, burning and claiming Prime tokens are unblocked.

```solidity
function addMarket(address market, uint256 supplyMultiplier, uint256 borrowMultiplier) external
```

**Parameters**

| Name             | Type    | Description                       |
| ---------------- | ------- | --------------------------------- |
| market           | address | Market address                    |
| supplyMultiplier | uint256 | Supply multiplier, scaled by 1e18 |
| borrowMultiplier | uint256 | Borrow multiplier, scaled by 1e18 |

**📅 Events**

* Emits MarketAdded event
* Emits IncompleteRoundDiscarded if a previous score-update round was still in progress

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw MarketAlreadyExists if market already exists
* Throw InvalidMultipliers if both multipliers are zero
* Throw InvalidVToken if market is not listed
* Throw AssetAlreadyExists if asset already has a market
* Throw MaxLoopsLimitExceeded if listing this market would exceed loopsLimit
* Throw UnsupportedUnderlyingDecimals if underlying token has decimals > 18

***

#### removeMarket

Remove a market from the Prime program

```solidity
function removeMarket(address market) external
```

**Parameters**

| Name   | Type    | Description                     |
| ------ | ------- | ------------------------------- |
| market | address | Market vToken address to remove |

**📅 Events**

* Emits MarketRemoved event

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw MarketNotSupported if market doesn't exist
* Throw MarketHasActiveMembers if market still has members with scores

***

#### setLimit

Update mint limit (maximum Prime tokens)

```solidity
function setLimit(uint256 tokenLimit_) external
```

**Parameters**

| Name         | Type    | Description     |
| ------------ | ------- | --------------- |
| tokenLimit\_ | uint256 | New token limit |

**📅 Events**

* Emits MintLimitUpdated event

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw InvalidLimit if limit is less than current count

***

#### updateAlpha

Update alpha parameter. Opens a new score-update round: all Prime holders' scores must be recomputed via `updateScores` before issuing, burning and claiming Prime tokens are unblocked.

```solidity
function updateAlpha(uint128 alphaNumerator_, uint128 alphaDenominator_) external
```

**Parameters**

| Name               | Type    | Description           |
| ------------------ | ------- | --------------------- |
| alphaNumerator\_   | uint128 | New alpha numerator   |
| alphaDenominator\_ | uint128 | New alpha denominator |

**📅 Events**

* Emits AlphaUpdated event
* Emits IncompleteRoundDiscarded if a previous score-update round was still in progress

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw InvalidAlphaArguments if alpha arguments are invalid

***

#### updateMultipliers

Update market multipliers. Opens a new score-update round: all Prime holders' scores must be recomputed via `updateScores` before issuing, burning and claiming Prime tokens are unblocked.

```solidity
function updateMultipliers(address market, uint256 supplyMultiplier, uint256 borrowMultiplier) external
```

**Parameters**

| Name             | Type    | Description           |
| ---------------- | ------- | --------------------- |
| market           | address | Market address        |
| supplyMultiplier | uint256 | New supply multiplier |
| borrowMultiplier | uint256 | New borrow multiplier |

**📅 Events**

* Emits MultiplierUpdated event
* Emits IncompleteRoundDiscarded if a previous score-update round was still in progress

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw MarketNotSupported if market is not supported
* Throw InvalidMultipliers if both multipliers are zero

***

#### pause

Pause the contract

```solidity
function pause() external
```

**📅 Events**

* Emits Paused event

**⛔️ Access Requirements**

* Controlled by ACM

***

#### unpause

Unpause the contract

```solidity
function unpause() external
```

**📅 Events**

* Emits Unpaused event

**⛔️ Access Requirements**

* Controlled by ACM

***

#### setMaxLoopsLimit

Set the max loops limit

```solidity
function setMaxLoopsLimit(uint256 loopsLimit) external
```

**Parameters**

| Name       | Type    | Description     |
| ---------- | ------- | --------------- |
| loopsLimit | uint256 | New loops limit |

**📅 Events**

* Emits MaxLoopsLimitUpdated event

**⛔️ Access Requirements**

* Controlled by ACM

***

#### setPrimeLeaderboard

Set the `PrimeLeaderboard` contract address used for permissionless mint eligibility

```solidity
function setPrimeLeaderboard(address primeLeaderboard_) external
```

**Parameters**

| Name               | Type    | Description                          |
| ------------------ | ------- | ------------------------------------ |
| primeLeaderboard\_ | address | Address of PrimeLeaderboard contract |

**📅 Events**

* Emits PrimeLeaderboardSet event

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw InvalidAddress if address is zero

***

#### setMintThreshold

Set the minimum Prime Score threshold and minting deadline for permissionless Prime minting. Each epoch is one calendar month; governance typically calls this at end-of-epoch with the #500 user's Prime Score as the threshold. Pass `mintThreshold_ = 0` to disable the permissionless minting window immediately. Pass `mintDeadline_ = 0` for no expiry; otherwise the window auto-closes once `block.timestamp` exceeds it.

```solidity
function setMintThreshold(uint256 mintThreshold_, uint256 mintDeadline_) external
```

**Parameters**

| Name            | Type    | Description                                                    |
| --------------- | ------- | -------------------------------------------------------------- |
| mintThreshold\_ | uint256 | New mint threshold (set to 0 to close the window)              |
| mintDeadline\_  | uint256 | Unix timestamp after which minting is closed (0 = no deadline) |

**📅 Events**

* Emits MintThresholdUpdated event

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw InvalidDeadline if mintDeadline\_ is non-zero and not strictly in the future

***

#### recordCycleSnapshot

Emit a cycle-start anchor event so the off-chain reward pipeline can recover cycle boundaries by indexing the event log. Operational hook, not a policy lever. Not idempotent on-chain: duplicate `cycleId`s emit duplicate events and must be de-duplicated by the indexer.

```solidity
function recordCycleSnapshot(uint256 cycleId) external
```

**Parameters**

| Name    | Type    | Description                                           |
| ------- | ------- | ----------------------------------------------------- |
| cycleId | uint256 | Identifier of the cycle whose start is being recorded |

**📅 Events**

* Emits CycleSnapshotRecorded(cycleId, block.number, block.timestamp)

**⛔️ Access Requirements**

* Controlled by ACM. Check the live grantees and current operations runbook; this reference does not prescribe an EOA, bot, or Timelock as the caller.

***

#### sweepUndistributed

Reclaim PLP income that accrued for a market while no scored members existed in it. Flushes any pending PLP delta via `accrueInterest` first, then transfers the recorded slice to the recipient.

```solidity
function sweepUndistributed(address vToken, address to) external
```

**Parameters**

| Name   | Type    | Description                                           |
| ------ | ------- | ----------------------------------------------------- |
| vToken | address | Market address whose underlying slice should be swept |
| to     | address | Recipient of the swept tokens                         |

**📅 Events**

* Emits UndistributedSwept on a non-zero transfer

**⛔️ Access Requirements**

* Controlled by ACM

**❌ Errors**

* Throw InvalidAddress if to is the zero address

Note: for a removed Prime market the call does not revert; it returns without transferring once the market's `undistributedReward` slice is zero. Passing an address that is not a vToken at all reverts when resolving its underlying token.

***


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs-v4.venus.io/technical-reference/reference-core-pool/prime/prime.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
