Skip to content

feat: VIP-675/677/678 list the bStock mainstream spoke pool on BNB Chain - #787

Merged
fred-venus merged 37 commits into
mainfrom
feat/bluechips-spoke-pool
Nov 3, 2026
Merged

fred-venus merged 37 commits into
mainfrom
feat/bluechips-spoke-pool

Conversation

@Debugger022

@Debugger022 Debugger022 commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Lists the bStock mainstream Hub-Funded Spoke pool on BNB Chain, in the same SpokePoolRegistry as the bStock index pool.

  • Collateral: 20 single-stock bStocks. BNCB and AMATB are left out.
  • Liquidity: USDT, USDC and U, funded by the existing Spoke sources.

Listing doc: bStock mainstream spoke pool listing

Proposals

VIP File Scope execute() gas
VIP-675 vips/vip-675/bscmainnet.ts Pool, descriptions of both Spoke pools, Spoke comptroller roles as wildcards, USDT/USDC/U markets with Hub wiring, tier 1 (7 bStocks) 13.68M (82%)
VIP-677 vips/vip-675/bscmainnet-part-2.ts Tier 2 and 3 (8 bStocks) 10.78M (64%)
VIP-678 vips/vip-675/bscmainnet-part-3.ts Tier 4 (5 bStocks) 6.90M (41%)

VIP-677 and VIP-678 need VIP-675 executed first. They do not depend on each other.

Each collateral market gets its own CF, LT, liquidation incentive and supply cap from the listing doc. Where the doc sets a protocol seize share other than the 5% default, the aggregator batch sets it after the market's incentive, since setProtocolSeizeShare is bounded by that incentive.

Permissions

VIP-675 grants all 20 Spoke comptroller roles as wildcards, so later Spoke pools need no ACM grants. It then revokes the scoped grants those wildcards replace: the 20 on the bStock index pool's comptroller and CollateralGateway's enterMarketForAccount on Core.

Deployments

isolated-pools#575: Comptroller_bStockMainstream and its 23 markets (vX_bStockMainstream). Every market has the Normal Timelock as owner and shortfall.

Before proposing

  • The risk owner signs off the risk values and supply caps.

  • Seed the aggregator batches:

    npx hardhat seedAggregatorBatches vip-675/bscmainnet.ts --network bscmainnet
    npx hardhat seedAggregatorBatches vip-675/bscmainnet-part-2.ts --network bscmainnet
    npx hardhat seedAggregatorBatches vip-675/bscmainnet-part-3.ts --network bscmainnet
    
  • Pin the printed indices as seededIndices on PART_1, PART_2 and PART_3.

  • Move FORK_BLOCK past the seeding and re-run the simulation.

Status: All three VIPs are seeded and pinned: VIP-675 at indices 5 and 6, VIP-677 at index 7 (seeding transaction), and VIP-678 at index 8 (seeding transaction). Both new batches were read back and matched byte-for-byte against the proposal builders.

Simulation

npx hardhat test simulations/vip-675/bscmainnet.ts --fork bscmainnet: 168 passing at block 131,366,432. All three proposals use their seeded on-chain batches: 5 and 6 for VIP-675, 7 for VIP-677, and 8 for VIP-678. The simulation uses a separate proposer and sufficient supporters because VIP-675 is active at this fork block.

It runs all three VIPs, then an end-to-end flow:

  • every bStock supplied through CollateralGateway
  • a borrow and liquidation, with the protocol share reaching the PSR
  • interest accrual and the reserve sweep
  • full repayment
  • Hub withdrawals drawn from the bStock mainstream market first

At this block the VTreasury holds every seed, all 16 new Atlas feeds authorize AtlasOracle and VIP-673 has executed, so the simulation does not stand in for any of them. It pins direct prices to survive the governance warp, so it checks the feed authorization with isAuthorizedCaller rather than through a live read.

Note

  • Why 3 VIPs: execute() runs in one transaction under the 16.7M gas cap, and the aggregator does not reduce execute() gas. The part that creates the pool fits at most 8 bStocks, and the other 12 revert in one part (measured), so two VIPs do not fit. The split is by tier.
  • Why one PR and folder: the three share one command builder, address book and simulation, and are reviewed against one spec. Happy to split them into separate PRs if the team prefers.

Lists a second Hub-Funded Spoke pool of single-stock bStocks on BNB Chain.
Its execute() does not fit one or two proposals under the per-tx gas cap,
so the listing is split by tier into three proposals built from one shared
command builder.

- VIP-674: the pool, the USDT, USDC and U markets with their Hub wiring,
  and the tier 1 bStocks
- VIP-675: tier 2 and 3 bStocks
- VIP-676: tier 4 bStocks
- one fork simulation covering all three, end to end
@Debugger022 Debugger022 self-assigned this Oct 27, 2026
Drop AMATB and set per-market risk values and protocol seize shares.

- Drop AMATB, leaving 20 collateral markets.
- Set each market's CF, LT, liquidation incentive and supply cap.
- Set the protocol seize share where it differs from the 5% default, in the
  aggregator batch after the market's incentive.
- Raise the e2e loan to 45% of the collateral value. At 40%, NVDAB's 80% LT
  left the loan exactly at the threshold after the price halved.
- Check each part's incentive and seize share in its own test, and expect
  ActionPaused on a collateral borrow.
- Trim comments that went stale or restated the code.
The pool's markets were redeployed under the bStock mainstream name.

- Use the 23 redeployed markets, and name the pool, symbols and code after
  bStock mainstream.
- Move the simulation fork past the deployments. VIP-673 is queued there, so
  the simulation applies its commands without cancelling it.
- Measure feed age at the fork block, not at the latest block.
@Debugger022 Debugger022 changed the title feat: list Bluechips spoke pool on BNB Chain feat: list the bStock mainstream spoke pool on BNB Chain Oct 28, 2026
Debugger022 and others added 2 commits October 29, 2026 11:38
VIP-674 is already on chain for another proposal, so the three parts
move up by one and the folders move to vip-675.
A third pool in the Spoke pool registry: BPNC, the BPN Credit Token, priced
at a fixed $1 and suppliable only by allowlisted accounts, as collateral, and
USDT, USDC and U as Hub-funded liquidity at a flat 6% borrow APY.

Draft: BPNC, the comptroller, the four markets, the flat rate model and
BPN's supply address are pending, and vip678() throws until they are set.
The simulation deploys stand-ins for them on a bscmainnet fork.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
vancegpt-bot and others added 2 commits October 29, 2026 08:02
BPNC is a CustodyReceiptToken, the vceBTC contract, deployed with the Normal
Timelock nominated as owner. VIP-678 accepts ownership and mints the first
3,333,334 BPNC to the Operator and the 10 BPNC seed. The Normal Timelock holds
mint only for those two mints. The Operator gets mint and pause; the Normal
Timelock and the Critical Guardian get burn and unpause.

With the token steps the proposal needed 99.3% of the per-tx gas cap to be
proposed through the Safe. The grants, risk setters, allowlists and Hub
wiring now run as two adjacent AuxiliaryCommandsAggregator batches.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
VIP-678 now turns on the pool's liquidation allowlist with only the Liquidity
Hub Operator on it, per the updated listing doc. Every seizure checks the
allowlist, so no one else can liquidate BPNC through liquidateBorrow,
liquidateAccount or healAccount. The two calls run in the second batch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@fred-venus

Copy link
Copy Markdown
Contributor
  1. need to add updatePoolMetadata
CleanShot 2026-10-29 at 16 48 46@2x
  1. also add for this index pool as last time we forgot
CleanShot 2026-10-29 at 16 49 37@2x

Comment thread vips/vip-675/addresses/bscmainnet.ts Outdated
underlying: CRCLB,
supplyCap: cap(12340),
initialSupply: parseUnits("0.13", 18),
atlasFeed: PENDING,

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.

for those pending one, can check out the google doc provided by atlas

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fix: use the authorized Atlas feeds for the bStock mainstream assets
Updated CRCLB, SNDKB, MSFTB and MUB to Atlas's sheet feeds, all authorized for AtlasOracle.

Comment thread vips/vip-675/permissions-bscmainnet.ts Outdated
Comment on lines +35 to +48
export const REGISTRY_GRANTS_MAINSTREAM: Grant[] = REGISTRY_GRANTS.map(role => ({
role,
account: SPOKE_POOL_REGISTRY,
}));

/// The other 14: the Normal Timelock's six, the Critical Guardian's five, the Pause Guardian's two and
/// CollateralGateway's `enterMarketForAccount`. Nothing in VIP-675 needs them first, so they run in the aggregator
/// batch.
export const OTHER_GRANTS_MAINSTREAM: Grant[] = [
...NORMAL_TIMELOCK_GRANTS.map(role => ({ role, account: NORMAL_TIMELOCK })),
...CRITICAL_GUARDIAN_GRANTS.map(role => ({ role, account: CRITICAL_GUARDIAN })),
...PAUSE_GUARDIAN_GRANTS.map(role => ({ role, account: PAUSE_GUARDIAN })),
...ROUTER_ROLES.map(role => ({ role, account: COLLATERAL_GATEWAY })),
];

@fred-venus fred-venus Oct 29, 2026 •

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.

lets apply this following rule for the acm grants, for each caller + exact function signature:

  • if an on-chain wildcard already covers that caller/function, omit the redundant contract-scoped grant.
  • otherwise, where the permission should apply across pools, grant the wildcard once and revoke scoped permissions on existing pools if the wildcard also covers the case
  • only keep scoped permissions where access is intentionally limited to specific contracts

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.

this way in the future when adding more spoke pool we no gonna need acm setting

@Debugger022 Debugger022 Oct 29, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@fred-venus Should Critical Guardian's setCloseFactor, setLiquidationIncentive, setMinLiquidatableCollateral and setForcedLiquidation be wildcards? As wildcards they also reach FRV LiquidationAdapter, where it has no access today.

Granting CollateralGateway enterMarketForAccount as a wildcard, and revoking its scoped grants on the bStock index pool and Core.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done: feat: grant the spoke comptroller roles as wildcards
LMK if any changes in permissions are required

Comment thread vips/vip-675/addresses/bscmainnet.ts Outdated
underlying: GOOGLB,
supplyCap: cap(3060),
initialSupply: parseUnits("0.032", 18),
atlasFeed: "0x2FcEafD81a4dBDa2409B6fe5ce2afFe3cD46eDbC",

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.

Image

can probabaly confirm why its different

@fred-venus fred-venus Oct 29, 2026 •

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.

seems not limited to google, others are different as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The Notion doc listed Atlas feeds that are not authorized for AtlasOracle, so all 16 new assets were affected, not only GOOGLB. They now use the authorized feeds from Atlas's sheet, and the sim checks isAuthorizedCaller
fix: use the authorized Atlas feeds for the bStock mainstream assets

@Debugger022

Debugger022 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor Author
  1. need to add updatePoolMetadata
CleanShot 2026-10-29 at 16 48 46@2x 2. also add for this index pool as last time we forgot CleanShot 2026-10-29 at 16 49 37@2x

@fred-venus While reviewing, I found this point too but dropped it for the reason below. We're adding it now, so sharing the reason FYI:

  • No VIP or multisig proposal has ever called updatePoolMetadata.
  • BSC isolated PoolRegistry: all 8 pools return ("", "", ""). They're sunset, so it doesn't matter.
  • Ethereum PoolRegistry: Core, Curve, Liquid Staked ETH and Ethena return ("", "", "") too.

add it for both pools: feat: set the bStock mainstream and bStock index pool descriptions

Debugger022 and others added 3 commits October 29, 2026 16:18
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Final BPNC roles: mint and pause to the Operator, the Normal Timelock and the
Critical Guardian; burn and unpause to the Normal Timelock and the Critical
Guardian. The Normal Timelock keeps the mint it is granted for the two mints,
so the revoke is gone and the batch skips that one grant.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Debugger022 and others added 11 commits October 29, 2026 18:06
The listed Atlas feeds for the 16 new assets never authorized the Atlas
oracle, so execution would revert when the deviation-bounded oracle reads
the price.

- Switch every new asset to the feed from Atlas's feed list
- Drop the candidate feeds and the simulation's stand-in for them
- Check isAuthorizedCaller on every Atlas feed in the simulation
- Fork at 130,450,000 and propose from an account with no live proposal
Drop the comptroller grants the bStock mainstream pool's address(0) wildcards cover,
keeping the Critical Guardian's setCloseFactor scoped. The sim now applies that VIP's
part 1 with pretendExecutingVip at a recent block.
Only BPN's supplier is still pending. The sim drops its stand-ins and runs against the live deployments.
Every command now sits in makeProposal in execution order, run by the Normal Timelock,
since without the wildcard-covered grants it proposes at 75% of the gas cap. BPN's
supplier is a placeholder, and the sim impersonates it.
Add updatePoolMetadata after addPool, as the bStock mainstream pool does. The addresses
folder becomes config.ts, with network addresses from NETWORK_ADDRESSES and the rest
written out instead of re-exported through earlier VIPs.
…revoke the gateway's Core grant

- Grant all 20 spoke comptroller roles against address(0), including the Critical Guardian's
  setCloseFactor, so a later spoke pool needs no ACM grant. As a wildcard it also reaches FRV's
  LiquidationAdapter, the only Critical Guardian role FRV checks.
- Revoke CollateralGateway's scoped enterMarketForAccount grant on Core, which its wildcard covers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The VTreasury now holds every seed and VIP-673 has executed, so the
simulation no longer has to fake either.

- Move FORK_BLOCK to 130640000
- Remove the VIP-673 apply, the treasury top-up and the explicit proposer
- Assert that the VTreasury holds every seed
- Remove comments that are stale or point to docs outside the repo
Pin part 1's aggregator batches at their seeded indices 5 and 6, fork the
simulation after the seeding, and drop the inline backticks the governance UI
hides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fred-venus fred-venus changed the title feat: list the bStock mainstream spoke pool on BNB Chain feat: VIP-675/677/678 list the bStock mainstream spoke pool on BNB Chain Nov 2, 2026
fred-venus and others added 4 commits November 2, 2026 16:21
The Operator keeps pause, so it can still stop BPNC transfers, but no longer gets
mint. Minting, burning and unpausing BPNC are left to the Normal Timelock and the
Critical Guardian. The simulation mints its test BPNC from the Normal Timelock and
checks that the Operator cannot mint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each Spoke yield group now withdraws from bStock mainstream, then bStock index,
and only then from its BPN Loan market, so the Hub pulls liquidity from the loan
last. The deposit queues are unchanged, with the BPN Loan market last.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Debugger022

Copy link
Copy Markdown
Contributor Author

@multica-review please review this VIP before we take it forward.

Main things to check:

  • Addresses in vips/vip-675/addresses/bscmainnet.ts match the deployment files
  • ACM permission strings in permissions-bscmainnet.ts match what the target contracts check
  • Command order across the three parts: bscmainnet.ts, bscmainnet-part-2.ts, bscmainnet-part-3.ts
  • Whether simulations/vip-675/bscmainnet.ts covers every command

fred-venus and others added 5 commits November 3, 2026 10:55
…IP-676

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d LT

For each of the 20 collateral markets, after VIP-678:

- borrowing power equals CF x collateral value, and account liquidity LT x value
- a loan of the full borrowing power succeeds, and 1 wei more reverts InsufficientLiquidity
- 0.01% above the price where LT covers the loan, liquidation reverts InsufficientShortfall;
  0.01% below, it succeeds
- the loan is then repaid in full

Runs after the end-to-end flow, whose exact seed vToken count its liquidations would shift.
Values collateral at the market's exchange rate, as the comptroller does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat: VIP-676 [BNB Chain] list the BPN Loan Hub-Funded Spoke pool
@fred-venus
fred-venus merged commit ff33425 into main Nov 3, 2026
3 checks passed
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.

4 participants