Skip to content

[VPD-1314] Configure PrimeV2 on BSC#712

Open
Debugger022 wants to merge 20 commits into
mainfrom
feat/VPD-1314
Open

[VPD-1314] Configure PrimeV2 on BSC#712
Debugger022 wants to merge 20 commits into
mainfrom
feat/VPD-1314

Conversation

@Debugger022

@Debugger022 Debugger022 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Brings the new PrimeV2 and PrimeLeaderboard contracts live and decommissions the legacy Prime, on BSC testnet and mainnet. The contracts are implemented in venus-protocol PR #670 (development) and deployed via venus-protocol PR #677 (deployments). These VIPs perform the on-chain governance setup the deploy scripts intentionally leave to governance.

Why two VIPs on mainnet?

  • Legacy Prime and PrimeV2 share one rewards vault (the PrimeLiquidityProvider, "PLP"). That vault can be pointed at only one Prime at a time.
  • The migration VIP points the PLP at PrimeV2. From that moment the legacy Prime can no longer pay out the rewards its users already earned — those claimInterest calls would start failing.
  • So we split the rollout: a first critical VIP freezes the system (pauses staking, stops new reward accrual), then an off-chain script pays every legacy user their pending rewards against that frozen balance.
  • Only after everyone is paid does the second migration VIP flip the PLP, vault, and Comptroller over to PrimeV2.

This ordering guarantees no user is left holding unclaimable legacy rewards. (Mechanically, repointing the shared PLP strands the legacy Prime's accounting and its next claim reverts — proven in the simulations below — which is exactly why the off-chain sweep must run first.)

Mainnet rollout sequence

  1. Critical VIP — freeze (vips/vip-675/bscmainnet-critical.ts)

    • XVSVault.pause() — freeze staking for the migration window (Critical Timelock already holds the perm).
    • PLP.setTokensDistributionSpeed = 0 for every legacy Prime underlying (ETH, BTCB, USDC, USDT, U, WBNB) — stop new interest accrual so the sweep captures a stable balance. Legacy claimInterest keeps working while the vault is paused.
  2. BE sweep (off-chain) — call claimInterest(vToken, user) for every legacy Prime holder across all markets, then verify V1 is clean (every holder's claimable == 0) as a hard gate before the next VIP.

  3. Migration VIP — regular (vips/vip-675/bscmainnet.ts) — ten command groups, in order:

    1. Accept ownershipPrimeV2.acceptOwnership() and PrimeLeaderboard.acceptOwnership(). The deploy script (PR [VPD-687]: VIP to Update Core Pool vslisBNB Market Risk Parameters #677) initiated the 2-step transfer to NormalTimelock; this completes it.
    2. Grant ACM permissions — full matrix in the ACM permission matrix section below.
    3. Wire PrimeV2 ↔ PrimeLeaderboardPrimeV2.setPrimeLeaderboard(PrimeLeaderboard) and PrimeLeaderboard.setPrimeV2(PrimeV2).
    4. Repoint the PLPPLP.setPrimeToken(PrimeV2). The shared PrimeLiquidityProvider now serves PrimeV2; legacy Prime is no longer its authorized prime (this is the step that strands legacy unreleasedPLPIncome, hence the pre-VIP sweep).
    5. Switch the XVSVault prime hookXVSVault.setPrimeToken(PrimeLeaderboard, XVS, 0). Vault deposits/withdrawals now update PrimeLeaderboard (which calls PrimeV2); reward token and pool id unchanged.
    6. Point the Core pool Comptroller at PrimeV2Comptroller.setPrimeToken(PrimeV2), so market supply/borrow hooks call the new contract.
    7. Repoint the VAIController at PrimeV2VAIController.setPrimeToken(PrimeV2). VAI minting is gated on Prime-holder status (mintEnabledOnlyForPrimeHolder = true, reads IPrime(prime).isUserPrimeHolder), so this keeps the gate tracking live PrimeV2 membership instead of the decommissioned legacy Prime.
    8. Add Core pool marketsPrimeV2.addMarket for vUSDT and vWBNB (2x supply multiplier, 0x borrow multiplier). PrimeV2 intentionally does not carry the other legacy markets.
    9. Restore PLP emissionssetTokensDistributionSpeed for the two carried underlyings back to their prior live speeds (USDT 2170138888888888, WBNB 3472222222222); the other four underlyings stay at 0.
    10. Decommission legacy PrimeLegacyPrime.togglePause() to pause it permanently.

    Not re-set by this VIP (configured in the contracts' initializers): the PrimeLeaderboard multiplier tiers (30/60/90 days → 1.3x/1.6x/2.0x) and the PrimeV2 token limit (500). The permissionless mint window is also left uninitialized on purpose (mintThreshold = 0, mintDeadline = 0) — governance or the Guardian opens it later via setMintThreshold.

  4. BE seeding (off-chain) — snapshot staker list, seed existing stakers into PrimeLeaderboard via initializeStakers/finalizeInitialization, mint initial Prime users via the Keeper issue path (the permissionless mint window is left uninitialized: mintThreshold = 0, mintDeadline = 0).

  5. Resume — Guardian calls XVSVault.resume() (Guardian already holds the perm).

The XVS Vault stays paused from step 1 through step 5; users continue to supply/borrow on the Core pool markets throughout — only XVS staking is frozen.

ACM permission matrix

Granted by the migration VIP (vips/vip-675/bscmainnet.ts, step 2). NT = NormalTimelock, FTT = FastTrackTimelock, CT = CriticalTimelock, GUARDIAN = Venus Guardian (0x1C2CAc6ec528c20800B2fe734820D87b581eAA6B), KEEPER = 0xe0237587acA20f9304d30FACC9Afcd5DD9a94899, MULTISIG_PAUSER = Venus team multisig (0xCCa5a587eBDBe80f23c8610F2e53B03158e62948).

ACM permission matrix — who can call each gated function, grouped by intent (click to expand)

Read it as: keeper-driven cycle ops go to NT + KEEPER + GUARDIAN; one-off policy levers stay NT-only; pause is split between the timelocks (full control) and the team multisig (one-way circuit breaker).

Contract Function Granted to Rationale
PrimeV2 issue / issueBatch / burn / burnBatch NT + KEEPER + GUARDIAN Per-cycle minting/burning; keeper EOA drives, NT/Guardian as governance/multisig paths
PrimeV2 recordCycleSnapshot NT + KEEPER + GUARDIAN Per-cycle snapshot; keeper-driven
PrimeV2 setMintThreshold NT + GUARDIAN (not KEEPER) Opens/closes the permissionless mint window — sensitive, governance/multisig only
PrimeV2 setPrimeLeaderboard, addMarket, removeMarket, setLimit, updateAlpha, updateMultipliers, setMaxLoopsLimit, sweepUndistributed NT only Policy levers
PrimeV2 pause / unpause NT + FTT + CT Standard timelock pause control
PrimeV2 pause MULTISIG_PAUSER One-way circuit breaker
PrimeLeaderboard initializeStakers / finalizeInitialization KEEPER + GUARDIAN (not NT) One-time off-chain bootstrap; keeper-driven, NT never calls it
PrimeLeaderboard setMultiplierTiers, setPrimeV2, setMaxLoopsLimit NT only Policy levers
XVSVault pause MULTISIG_PAUSER One-way circuit breaker (vault resume() already held by Guardian + NT)

Command card — every on-chain command (both mainnet VIPs)

Complete, execution-ordered list of every command in the two mainnet proposals. ACM grant rows use ACM.giveCallPermission(target, signature, account); each expands to one tx per grantee (see Txns). Addresses: PrimeV2 0x4f5f…1628, PrimeLeaderboard 0x55e2…2c0b, PLP 0x23c4…33F2, LegacyPrime 0xBbCD…71FC, VAIController 0x0040…FAFE, Comptroller = Unitroller, KEEPER 0xe023…4899, MULTISIG_PAUSER 0xCCa5…2948, GUARDIAN 0x1C2C…aA6B.

Critical VIP — 2 txns (freeze staking + stop emissions)
# Target Signature Params Txns
1 XVSVault pause() 1
2 PLP setTokensDistributionSpeed(address[],uint256[]) [ETH,BTCB,USDC,USDT,U,WBNB], [0,0,0,0,0,0] 1
Migration VIP · Ownership — 2 txns (complete the 2-step transfer)
# Target Signature Params Txns
1 PrimeV2 acceptOwnership() 1
2 PrimeLeaderboard acceptOwnership() 1
Migration VIP · ACM grants — 40 txns (one giveCallPermission per grantee)

Each row grants target.signature to every listed account; Txns = number of grantees (the literal command count). Target of each command is the ACM.

# Grant target Signature granted Grantees Txns
3 PrimeV2 issue(address) NT, KEEPER, GUARDIAN 3
4 PrimeV2 issueBatch(address[]) NT, KEEPER, GUARDIAN 3
5 PrimeV2 burn(address) NT, KEEPER, GUARDIAN 3
6 PrimeV2 burnBatch(address[]) NT, KEEPER, GUARDIAN 3
7 PrimeV2 setMintThreshold(uint256,uint256) NT, GUARDIAN 2
8 PrimeV2 recordCycleSnapshot(uint256) NT, KEEPER, GUARDIAN 3
9 PrimeV2 setPrimeLeaderboard(address) NT 1
10 PrimeV2 addMarket(address,uint256,uint256) NT 1
11 PrimeV2 removeMarket(address) NT 1
12 PrimeV2 setLimit(uint256) NT 1
13 PrimeV2 updateAlpha(uint128,uint128) NT 1
14 PrimeV2 updateMultipliers(address,uint256,uint256) NT 1
15 PrimeV2 setMaxLoopsLimit(uint256) NT 1
16 PrimeV2 sweepUndistributed(address,address) NT 1
17 PrimeV2 pause() NT, FTT, CT 3
18 PrimeV2 unpause() NT, FTT, CT 3
19 PrimeV2 pause() MULTISIG_PAUSER 1
20 PrimeLeaderboard initializeStakers(address[],uint256[],uint64[]) KEEPER, GUARDIAN 2
21 PrimeLeaderboard finalizeInitialization() KEEPER, GUARDIAN 2
22 PrimeLeaderboard setMultiplierTiers(uint256[],uint256[]) NT 1
23 PrimeLeaderboard setPrimeV2(address) NT 1
24 PrimeLeaderboard setMaxLoopsLimit(uint256) NT 1
25 XVSVault pause() MULTISIG_PAUSER 1
Migration VIP · Wiring, repoint, markets, emissions, decommission — 10 txns
# Target Signature Params Txns
26 PrimeV2 setPrimeLeaderboard(address) PrimeLeaderboard 1
27 PrimeLeaderboard setPrimeV2(address) PrimeV2 1
28 PLP setPrimeToken(address) PrimeV2 1
29 XVSVault setPrimeToken(address,address,uint256) PrimeLeaderboard, XVS, 0 1
30 Comptroller setPrimeToken(address) PrimeV2 1
31 VAIController setPrimeToken(address) PrimeV2 1
32 PrimeV2 addMarket(address,uint256,uint256) vUSDT, 2e18, 0 1
33 PrimeV2 addMarket(address,uint256,uint256) vWBNB, 2e18, 0 1
34 PLP setTokensDistributionSpeed(address[],uint256[]) [USDT,WBNB], [2170138888888888, 3472222222222] 1
35 LegacyPrime togglePause() 1

Totals: Critical = 2 txns · Migration = 52 txns (2 ownership + 40 ACM grants + 10 wiring/config) · combined = 54 on-chain txns.

Testnet

vips/vip-675/bsctestnet.ts plus addenda iterated the rollout on testnet:

  • bsctestnet — initial PrimeV2 + PrimeLeaderboard setup (markets vUSDT, vUSDC, vBTC, vETH).
  • addendum — extend Guardian permissions and compress leaderboard tiers.
  • addendum 2 — upgrade PrimeV2 implementation.
  • addendum 3 — re-wire to the redeployed PrimeV2/PrimeLeaderboard pair.
  • addendum 4 — add the vWBNB market.
  • addendum-testnet-reset — reset testnet state for a clean re-run.

Simulations

  • simulations/vip-675/bscmainnet-critical.ts — asserts the pre/post state of the freeze (XVS Vault paused, every Prime underlying distribution speed zeroed, legacy Prime still active). Also proves the off-chain sweep is viable: for four real legacy Prime whale holders, an arbitrary EOA (not the holder) calls claimInterest(vUSDT, whale) after the freeze and the whale's USDT balance increases — confirming claimInterest is permissionless and pays the holder directly.
  • simulations/vip-675/bscmainnet.ts — runs the critical VIP first (pretendExecutingVip via Critical Timelock), then asserts the full migration lifecycle and post-state: ownership, wiring, PLP/Comptroller/vault hook repoint, restored emissions, ACM roles, markets, and legacy Prime decommission. Includes two tests proving the legacy claim path is dead post-migration — one reverting cleanly under pause, one proving the underlying Panic(0x11) underflow when unpaused after the PLP drain.
  • simulations/vip-675/bsctestnet*.ts — testnet lifecycle + addenda post-state.

Test case index — simulations/vip-675/bscmainnet.ts

Every test case in the mainnet migration simulation, with one line on what each proves (click to expand)

Setup: the suite forks at block 105868057 and first runs the critical VIP (pretendExecutingVip via Critical Timelock) so the migration executes against the real frozen state (XVS Vault paused, PLP speeds zeroed). The core-pool integration block repoints stale feeds to Chainlink-only — test scaffolding, not part of the VIP — so reads survive the testVip ~3-day time-jump that would otherwise stale the live oracles.

Pre-VIP behavior — pins the deployed-but-unwired starting state so post-VIP deltas are real:

  • PrimeV2 ownership pending on NormalTimelock (not accepted) — 2-step transfer initiated by the deploy script, not yet accepted.
  • PrimeLeaderboard ownership pending on NormalTimelock (not accepted) — same for the leaderboard.
  • PLP prime token is still the legacy Prime — rewards vault still serves the old Prime.
  • PrimeV2 <-> PrimeLeaderboard are not yet wired — both cross-references are the zero address.
  • PrimeV2 mint window is uninitializedmintThreshold/mintDeadline both 0.
  • legacy Prime is active (unpaused) — old Prime still live before migration.
  • XVSVault prime hook still points at legacy Prime — stake updates still flow to old Prime.
  • XVSVault is already paused (by the preceding critical VIP) — confirms the freeze landed.
  • Comptroller prime still points at legacy Prime — market hooks still call old Prime.
  • VAIController prime still points at legacy Prime, with the holder mint gate enabled — VAI gate reads old Prime.
  • PLP distribution speeds are zeroed (by the preceding critical VIP) — emissions stopped for every Prime underlying.

VIP execution (testVip callback) — asserts the proposal's emitted effects:

  • emits PrimeLeaderboardSet(0 -> PrimeLeaderboard) and one MarketAdded per configured market (vUSDT, vWBNB).
  • emits exactly 40 RoleGranted events — the full ACM matrix (32 PrimeV2 + 7 PrimeLeaderboard + 1 XVSVault).

Post-VIP behavior — every wiring delta the proposal promises:

  • PrimeV2 owner is the NormalTimelock / PrimeLeaderboard owner is the NormalTimelock — ownership transfers accepted.
  • PLP points at PrimeV2 — rewards vault repointed.
  • PrimeV2 <-> PrimeLeaderboard are wired — both cross-references set.
  • PrimeV2 token limit is the initializer default (500) — VIP never calls setLimit, cap stays at init value.
  • PrimeV2 mint window is left uninitialized — window stays closed until a later Guardian/governance action.
  • XVSVault prime hook points at PrimeLeaderboard — stake updates now flow to the leaderboard.
  • XVSVault stays paused (awaiting off-chain staker seeding) — vault frozen so live stake can't shift during seeding.
  • Comptroller prime points at PrimeV2 — market hooks now call PrimeV2.
  • VAIController prime points at PrimeV2 (gate now tracks PrimeV2 membership) — VAI gate repointed.
  • PLP distribution speeds restored for USDT and WBNB — emissions back to prior live speeds for the two carried markets.
  • legacy Prime is decommissioned (paused) — old Prime frozen permanently.
  • account <X> holds the cycle permissions on PrimeV2 (NT, Keeper, Guardian) — steady-state issue/burn/snapshot automation surface.
  • account <X> holds the seeding permissions on PrimeLeaderboard (Keeper, Guardian) — one-time staker bootstrap.
  • NormalTimelock does NOT hold the one-time seeding permissions on PrimeLeaderboard — seeding is keeper/Guardian-only.
  • setMintThreshold is held by the NormalTimelock and the Guardian multisig only — sensitive mint-window lever.
  • Keeper does NOT hold setMintThreshold on PrimeV2 — keeper kept off the mint-window lever.
  • Keeper does NOT hold the admin-only permissions on PrimeV2 / ...on PrimeLeaderboard — policy levers stay NT-only.
  • Guardian holds the XVSVault resume() permission — Guardian unfreezes the vault after seeding.
  • Venus team multisig holds the circuit-breaker pause() permissions — one-way pause on PrimeV2 + XVSVault.
  • market <vToken> is configured on PrimeV2 (vUSDT, vWBNB) — multipliers match the proposal (2x supply, 0x borrow).

Core pool integration after migration (no breakage) — proves the repoint didn't break the live money market:

  • checkCorePoolComptroller (reusable) — supply/borrow/claim/repay/redeem on vETH + vUSDT for a non-Prime user; the Comptroller→PrimeV2 hook must no-op, not revert.
  • End-user full lifecycle on every core-pool market (vUSDT + vWBNB, non-Prime user — each step fires the hook, which must no-op):
    • supplies underlying and receives vTokens
    • enters the market as collateral
    • reports healthy account liquidity (no shortfall)
    • shows sufficient hypothetical liquidity for the intended borrow
    • borrows against the supplied collateral
    • accrues borrow interest over time
    • claims XVS rewards without reverting
    • repays the full borrow
    • redeems all supplied collateral
    • exits the market once the position is closed
  • PrimeV2 score hook executes the live path for a Prime holder (whale staked 20k XVS, then issued):
    • issuing a token to a supplier initializes a non-zero market score — live score path runs on issue.
    • a holder's further supply updates the market score via the live hook — extra supply lifts the score (stake cap kept above supplied capital).
  • Liquidation path stays wired through PrimeV2:
    • liquidateCalculateSeizeTokens returns a positive seize amount — seize math reachable and prices correctly.
    • seize amount scales with the repaid amount — math is monotonic in repaid amount.
  • PrimeV2 market accrual is wired to the PLP:
    • accrueInterest succeeds for configured market (vUSDT, vWBNB) — accrual works for added markets.
    • accrueInterest reverts for a market not configured on PrimeV2 (vETH) — explicit accrual requires the market to exist (distinct from the no-op Comptroller hook).
  • PrimeV2 membership admin (issue/burn) flows through ACM:
    • Keeper can issue a PrimeV2 token, flipping the holder flag on
    • Keeper can burn the PrimeV2 token, flipping the holder flag off
  • VAI mint gate now tracks PrimeV2 membership:
    • a non-PrimeV2 holder is blocked from minting VAI — gate returns 0 mintable for a non-holder.
  • VAI mint/repay lifecycle once the user holds a PrimeV2 token:
    • checkVAIController (reusable) — full VAI mint/repay works once the user is issued, proving the gate repoint is correct.

Test plan

  • npx hardhat test simulations/vip-675/bscmainnet.ts --fork bscmainnet
  • npx hardhat test simulations/vip-675/bscmainnet-critical.ts --fork bscmainnet
  • npx hardhat test simulations/vip-675/bsctestnet.ts --fork bsctestnet
  • yarn tsc --noEmit, yarn lint → clean

References

Bring PrimeV2 + PrimeLeaderboard live on bsctestnet: accept ownership,
grant ACM perms (epoch ops to NormalTimelock + Guardian), wire the pair,
repoint PrimeLiquidityProvider, add Core pool markets, open the mint
window, and pause the legacy Prime. Includes fork simulation.
@Debugger022 Debugger022 self-assigned this May 29, 2026
Comment thread vips/vip-675/bsctestnet.ts
Comment thread simulations/vip-675/bsctestnet.ts Outdated
Comment thread simulations/vip-675/bsctestnet.ts
@GitGuru7

GitGuru7 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

missing command for XVSVault.setPrimeToken(PRIME_LEADERBOARD) ?

@GitGuru7

GitGuru7 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

also update the Prime address in the Comptroller ?
here : https://github.com/VenusProtocol/venus-protocol/blob/b531da6fd7c4cc28e2b1abca668474638b5aeded/contracts/Comptroller/ComptrollerStorage.sol#L269

Add missing XVSVault.setPrimeToken (-> PrimeLeaderboard) and
Comptroller.setPrimeToken (-> PrimeV2); extend sim assertions and
fix grant helper comment.
Add pre-VIP assertions for wiring=0 and mint window=0; tighten PLP
prime equality check; mention vault/comptroller switches in header.
@Debugger022

Copy link
Copy Markdown
Contributor Author

Extend Guardian ACM permissions to every remaining ACM-gated function on
PrimeV2 / PrimeLeaderboard, and compress the leaderboard multiplier tiers
from days (30/60/90d) to hours (1/2/3h) so testnet integration can
exercise the tier progression without long waits.
@Debugger022

Copy link
Copy Markdown
Contributor Author

Upgrades the bsctestnet PrimeV2 proxy to the new implementation deployed
via venus-protocol PR #677 and grants ACM permission for the new
recordCycleSnapshot(uint256) function to NormalTimelock and Guardian,
matching the keeper grant pattern from the original VIP-675.
Redeployed PrimeV2/PrimeLeaderboard (fresh proxies + impls), so the old
addenda's wiring is stale. Accept ownership, re-grant the full ACM set
against the new addresses (plus testnet-only resetCycle), wire the pair,
and repoint the shared PLP/XVS Vault/Comptroller hooks old→new. No legacy
togglePause — already paused by VIP-675.
@Debugger022

Copy link
Copy Markdown
Contributor Author

Wire deployed PrimeV2 / PrimeLeaderboard: accept ownership, grant cycle
ACM perms to NT + Keeper + Guardian (admin NT-only), repoint PLP / XVS
Vault / Comptroller from legacy Prime, add 6 markets, pause vault until
seeding, decommission legacy.
Add the vWBNB market to PrimeV2 on bsctestnet so FE/BE integration can
exercise the new market flow. Initializes WBNB on PrimeLiquidityProvider
and sets the distribution speed to mirror mainnet (3.47e12 wei/block)
for production-like accrual during testing. Supply/borrow multipliers
match the legacy mainnet Prime (2e18 / 0).
@Debugger022

Copy link
Copy Markdown
Contributor Author

Testnet addedum to add WBNB market: https://venus-testnet.vercel.app/#/governance/proposal/691?chainId=97

Add ACM grants so the team multisig (0xCCa5...2948) can fire pause() on
both PrimeV2 and the XVS Vault as an emergency circuit breaker, matching
the cross-chain MULTISIG_PAUSER pattern from vip-616.
Remove setMintThreshold from the Keeper's permission set on PrimeV2 —
opening/closing the permissionless mint window is sensitive and reserved
for governance and the Venus Guardian multisig. Update simulation
assertions (RoleGranted 43 -> 42) and add tests verifying NormalTimelock
and Guardian hold the role while the Keeper does not.
…issions

Pauses the XVS Vault and zeroes the PLP distribution speed for every
legacy Prime underlying, so an off-chain claimInterest sweep runs against
frozen balances before PrimeV2 goes live. Executes via CriticalTimelock,
which already holds both permissions (no ACM grants).
Launch PrimeV2 with only the vUSDT and vWBNB markets instead of all six
legacy Prime markets, and re-set the PLP distribution speed for USDT and
WBNB (zeroed by the preceding critical VIP) back to their prior live
values. Sim now runs that critical VIP via CriticalTimelock in before()
so the regular VIP executes against real frozen state.

@fred-venus fred-venus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also consider reallocating the xvs buyback part to prime reward buyback contract ?

…st-freeze

Add a post-VIP block to the critical sim proving an arbitrary EOA can sweep
vUSDT interest on behalf of four real legacy Prime whale holders after the
freeze, confirming the off-chain claimInterest sweep pays holders directly.
@Debugger022

Copy link
Copy Markdown
Contributor Author

Should we also consider reallocating the xvs buyback part to prime reward buyback contract ?

As discussed, we will handle this through a separate VIP, where the reserve protocol configurations will be updated and the income from the XVS buyback contract will be allocated to Prime reward distribution.

…mounts

Strengthen the permissionless-claim test: assert the sweeping EOA is not a
legacy Prime holder while each whale is, and console the prime status plus the
before/after USDT balances so the sweep payout is visible in the run output.
initializeStakers and finalizeInitialization are a one-time off-chain
bootstrap, so the NormalTimelock does not need them. Grant only the Keeper
and the Guardian multisig; drops the RoleGranted count from 42 to 40.
Exercise the full end-user lifecycle (mint/borrow/accrue/claim/repay/redeem/exit)
across PrimeV2 and non-Prime markets, the PrimeV2 score hook for a real holder,
liquidation seize math, and the VAI mint gate after the legacy Prime -> PrimeV2
repoint. Repoint stale feeds to Chainlink-only to survive the testVip time-jump.
Document each scenario and ACM permission assertion inline.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants