feat: add hub funded spoke pool testnet VIP - #762
Conversation
- Foundation draft only. The spoke comptroller, markets, adapter and yield source are unbuilt, so their addresses are zero placeholders and the proposal cannot be simulated until they land. - Command order is load-bearing in four places: acceptOwnership before any owner-gated setter, setPriceOracle before addPool, the bounded oracle before the pool serves a borrow or redeem, and addMarket before the supply allowlist is armed. - Grants only the six ACM roles this chain does not already cover. The rest are held by the timelock or the registry as wildcards, checked on chain - Risk parameters the PRD does not specify are left as TODO, as are the bStock liquidation calls, which have no testnet target yet.
…ase 1 - Refined comments and descriptions in config.ts for clarity and accuracy regarding pool mechanics and risk factors. - Adjusted liquidation incentive and collateral factor definitions to align with updated PRD references. - Enhanced the permissions.ts file to include necessary role strings for the new Spoke pool, ensuring proper access control. - Added comments to clarify the implications of wildcard grants and the necessity of specific role grants for the new registry. - Introduced new roles for governance and registry-driven actions, ensuring smooth operation of the Spoke pool.
Greptile SummaryThis PR introduces the BNB Chain testnet Phase 1 VIP for a Hub-Funded Spoke pool.
Confidence Score: 4/5The PR is not safe to use or merge as an executable VIP until proposal-consumed zero addresses are replaced; the unresolved risk configuration and missing simulation should also be addressed. The proposal deterministically attempts to configure zero-address spoke contracts and upgrade ProtocolShareReserve to a zero implementation, so governance execution cannot complete in its current form. The remaining findings concern risk sign-off, unused IRM configuration, and absent regression coverage. Files Needing Attention: vips/vip-671/addresses/bsctestnet.ts, vips/vip-671/bsctestnet.ts, vips/vip-671/config.ts
|
| Filename | Overview |
|---|---|
| vips/vip-671/addresses/bsctestnet.ts | Adds the testnet address book, but proposal-critical spoke and implementation addresses remain zero placeholders. |
| vips/vip-671/bsctestnet.ts | Builds the ordered governance payload, but lacks fork simulation and does not apply or verify configured market IRMs. |
| vips/vip-671/config.ts | Defines four markets and reserve distribution constants, with several materially consequential risk values still awaiting approval. |
| vips/vip-671/permissions.ts | Defines registry and governance ACM roles using a command-builder pattern consistent with existing VIPs. |
Reviews (1): Last reviewed commit: "feat(: update Hub-Funded Spoke pool para..." | Re-trigger Greptile
| export const PROTOCOL_SHARE_RESERVE_IMPL = "0x0000000000000000000000000000000000000000"; | ||
|
|
||
| /// TODO(deploy): isolated-pools `deploy/024-deploy-spoke-pool-registry.ts` -> `SpokePoolRegistry`. | ||
| /// A SECOND `PoolRegistry` instance, behind the chain's existing DefaultProxyAdmin. The spoke pool is | ||
| /// deliberately kept out of the isolated-pools directory that the indexer, the frontend pool list and | ||
| /// the risk tooling all iterate. | ||
| /// `Ownable2Step`: the deploy script only NOMINATES the Normal Timelock, so this VIP must call | ||
| /// `acceptOwnership()` before `addPool`. | ||
| export const SPOKE_POOL_REGISTRY = "0x0000000000000000000000000000000000000000"; |
There was a problem hiding this comment.
Proposal targets zero addresses
The executable proposal still uses zero-address placeholders for the spoke registry, comptroller, markets, and new reserve implementation. If vip671 is submitted in this state, its calls cannot configure the spoke contracts, and the ProxyAdmin upgrade to the zero implementation will revert, preventing proposal execution. Replace every address consumed by the proposal before merging the executable VIP.
| collateralFactor: parseUnits("0.75", 18), // PRD §6 | ||
| liquidationThreshold: parseUnits("0.8", 18), // PRD §6 | ||
| supplyCap: parseUnits("236", 18), // TODO(risk): copied from VIP-633's Core listing. | ||
| }; | ||
|
|
||
| export const MARKET_NVDAB: SpokeMarket = { | ||
| ...collateralDefaults, | ||
| symbol: "vNVDAB_HubSpoke", | ||
| vToken: VNVDAB_SPOKE, | ||
| underlying: NVDAB, | ||
| collateralFactor: parseUnits("0.75", 18), // PRD §6 | ||
| liquidationThreshold: parseUnits("0.8", 18), // PRD §6 | ||
| supplyCap: parseUnits("450", 18), // TODO(risk): copied from VIP-633's Core listing. | ||
| }; | ||
|
|
||
| export const MARKET_SPCXB: SpokeMarket = { | ||
| ...collateralDefaults, | ||
| symbol: "vSPCXB_HubSpoke", | ||
| vToken: VSPCXB_SPOKE, | ||
| underlying: SPCXB, | ||
| collateralFactor: parseUnits("0.7", 18), // PRD §6 | ||
| liquidationThreshold: parseUnits("0.75", 18), // PRD §6 |
There was a problem hiding this comment.
These collateral factors and liquidation thresholds are explicitly unresolved risk placeholders, but proposal tooling does not prevent them from entering the governance payload. Compared with VIP-633 for the same assets, these factors allow 25% more borrowing for TSLAB and NVDAB and 40% more for SPCXB. Obtain risk approval and replace or explicitly validate these values before making the proposal executable.
What this VIP does
Phase 1 of the Hub-Funded Spoke pool on BNB Chain testnet. Covers the spoke pool side only (isolated-pools#559). Hub integration and bStock liquidation are Phase 2.
62 commands. Addresses are placeholders until deployment, so this cannot be simulated yet.
Permissions
Everything else is already covered by wildcard grants on this chain, verified on chain rather than assumed. The registry grants are the easy miss: the identical wildcards exist but name the isolated-pools registry as the account, so the spoke registry inherits none and addPool reverts without them.
Notes
Known follow-up, not blocking
RiskFundConverter still resolves through a single registry. It stops being a PSR destination after step 5, so it does not affect this launch, but it needs the same multi-registry treatment before any spoke pool reaches mainnet. Noted on protocol-reserve#168.