diff --git a/.gitbook/assets/riskSteward.png b/.gitbook/assets/riskSteward.png new file mode 100644 index 0000000..b810cea Binary files /dev/null and b/.gitbook/assets/riskSteward.png differ diff --git a/deployed-contracts/governance.md b/deployed-contracts/governance.md index d7d3072..b137998 100644 --- a/deployed-contracts/governance.md +++ b/deployed-contracts/governance.md @@ -12,6 +12,8 @@ * Guardian 2: [`0x1C2CAc6ec528c20800B2fe734820D87b581eAA6B`](https://bscscan.com/address/0x1C2CAc6ec528c20800B2fe734820D87b581eAA6B) - pause and resume features * Guardian 3: [`0x3a3284dC0FaFfb0b5F0d074c4C704D14326C98cF`](https://bscscan.com/address/0x3a3284dC0FaFfb0b5F0d074c4C704D14326C98cF) - oracles * Omnichain Proposal Sender: [`0x36a69dE601381be7b0DcAc5D5dD058825505F8f6`](https://bscscan.com/address/0x36a69dE601381be7b0DcAc5D5dD058825505F8f6) +* RiskStewardReceiver: [`0xBa2a43279a228cf9cD94d072777d8d98e7e0a229`](https://bscscan.com/address/0xBa2a43279a228cf9cD94d072777d8d98e7e0a229) +* MarketCapsRiskSteward: [`0xE7252dccd79F2A555E314B9cdd440745b697D562`](https://bscscan.com/address/0xE7252dccd79F2A555E314B9cdd440745b697D562) ## BNB Chain Testnet @@ -21,6 +23,8 @@ * FastTrack Timelock: [`0x3CFf21b7AF8390fE68799D58727d3b4C25a83cb6`](https://testnet.bscscan.com/address/0x3CFf21b7AF8390fE68799D58727d3b4C25a83cb6) * Critical Timelock: [`0x23B893a7C45a5Eb8c8C062b9F32d0D2e43eD286D`](https://testnet.bscscan.com/address/0x23B893a7C45a5Eb8c8C062b9F32d0D2e43eD286D) * Omnichain Proposal Sender: [`0xCfD34AEB46b1CB4779c945854d405E91D27A1899`](https://testnet.bscscan.com/address/0xCfD34AEB46b1CB4779c945854d405E91D27A1899) +* RiskStewardReceiver: [`0x31DEb4D1326838522697f7a012992f0824d80f2b`](https://testnet.bscscan.com/address/0x31DEb4D1326838522697f7a012992f0824d80f2b) +* MarketCapsRiskSteward: [`0x9b40390771cAeEa69DE55EEd176aeDC72d70cA3E`](https://testnet.bscscan.com/address/0x9b40390771cAeEa69DE55EEd176aeDC72d70cA3E) ## Ethereum mainnet @@ -31,6 +35,8 @@ * Critical Timelock: [`0xeB9b85342c34F65af734C7bd4a149c86c472bC00`](https://etherscan.io/address/0xeB9b85342c34F65af734C7bd4a149c86c472bC00) * Omnichain Governance Executor: [`0xd70ffB56E4763078b8B814C0B48938F35D83bE0C`](https://etherscan.io/address/0xd70ffB56E4763078b8B814C0B48938F35D83bE0C) * Omnichain Executor Owner Proxy: [`0x87Ed3Fd3a25d157637b955991fb1B41B566916Ba`](https://etherscan.io/address/0x87Ed3Fd3a25d157637b955991fb1B41B566916Ba) +* RiskStewardReceiver: [`0x5086Dc718D1288E4cc4F6a75991E4a0bD0611bF1`](https://etherscan.io/address/0x5086Dc718D1288E4cc4F6a75991E4a0bD0611bF1) +* MarketCapsRiskSteward: [`0x7191b4602Fe9d36E1A4b2cb84D0c80C543F13f9A`](https://etherscan.io/address/0x7191b4602Fe9d36E1A4b2cb84D0c80C543F13f9A) ## Sepolia (Ethereum testnet) @@ -41,6 +47,8 @@ * Critical Timelock: [`0xA24A7A65b8968a749841988Bd7d05F6a94329fDe`](https://sepolia.etherscan.io/address/0xA24A7A65b8968a749841988Bd7d05F6a94329fDe) * Omnichain Governance Executor: [`0xD9B18a43Ee9964061c1A1925Aa907462F0249109`](https://sepolia.etherscan.io/address/0xD9B18a43Ee9964061c1A1925Aa907462F0249109) * Omnichain Executor Owner Proxy: [`0xf964158C67439D01e5f17F0A3F39DfF46823F27A`](https://sepolia.etherscan.io/address/0xf964158C67439D01e5f17F0A3F39DfF46823F27A) +* RiskStewardReceiver: [`0xDF1807d323Dd2E2871e8b394c8F7595E097e1C73`](https://sepolia.etherscan.io/address/0xDF1807d323Dd2E2871e8b394c8F7595E097e1C73) +* MarketCapsRiskSteward: [`0xEa687c54321Db5b20CA544f38f08E429a4bfCBc8`](https://sepolia.etherscan.io/address/0xEa687c54321Db5b20CA544f38f08E429a4bfCBc8) ## opBNB mainnet @@ -81,6 +89,8 @@ * Critical Timelock: [`0x0b32Be083f7041608E023007e7802430396a2123`](https://sepolia.arbiscan.io/address/0x0b32Be083f7041608E023007e7802430396a2123) * Omnichain Governance Executor: [`0xcf3e6972a8e9c53D33b642a2592938944956f138`](https://sepolia.arbiscan.io/address/0xcf3e6972a8e9c53D33b642a2592938944956f138) * Omnichain Executor Owner Proxy: [`0xfCA70dd553b7dF6eB8F813CFEA6a9DD039448878`](https://sepolia.arbiscan.io/address/0xfCA70dd553b7dF6eB8F813CFEA6a9DD039448878) +* RiskStewardReceiver: [`0xE6b7B1846106605fdfaB3a9F407dd64bed6917a6`](https://sepolia.arbiscan.io/address/0xE6b7B1846106605fdfaB3a9F407dd64bed6917a6) +* MarketCapsRiskSteward: [`0xe739ff9CFa2CFA24fb7816133e1CBe7046A37Ecc`](https://sepolia.arbiscan.io/address/0xe739ff9CFa2CFA24fb7816133e1CBe7046A37Ecc) ## ZKsync Mainnet @@ -101,6 +111,8 @@ * Critical Timelock: [`0x0E6138bE0FA1915efC73670a20A10EFd720a6Cc8`](https://sepolia.explorer.zksync.io/address/0x0E6138bE0FA1915efC73670a20A10EFd720a6Cc8) * Omnichain Governance Executor: [`0x83F79CfbaEee738173c0dfd866796743F4E25C9e`](https://sepolia.explorer.zksync.io/address/0x83F79CfbaEee738173c0dfd866796743F4E25C9e) * Omnichain Executor Owner Proxy: [`0xa34607D58146FA02aF5f920f29C3D916acAb0bC5`](https://sepolia.explorer.zksync.io/address/0xa34607D58146FA02aF5f920f29C3D916acAb0bC5) +* RiskStewardReceiver: [`0x25483111881c431492D010a9071Ce6C84C3b90A6`](https://sepolia.explorer.zksync.io/address/0x25483111881c431492D010a9071Ce6C84C3b90A6) +* MarketCapsRiskSteward: [`0xe88C01daAd0b931af68C9fD70bfa9bde8142FF64`](https://sepolia.explorer.zksync.io/address/0xe88C01daAd0b931af68C9fD70bfa9bde8142FF64) ## Optimism Mainnet @@ -142,6 +154,8 @@ * Critical Timelock: [`0xbeDb7F2d0617292364bA4D73cf016c0f6BB5542E`](https://sepolia.basescan.org/address/0xbeDb7F2d0617292364bA4D73cf016c0f6BB5542E) * Omnichain Governance Executor: [`0xDD59be81B3B5BFa391bDA3a84c9f5233BfEF52a4`](https://sepolia.basescan.org/address/0xDD59be81B3B5BFa391bDA3a84c9f5233BfEF52a4) * Omnichain Executor Owner Proxy: [`0xe3fb08B8817a0c88d39A4DA4eFFD586D3326b73b`](https://sepolia.basescan.org/address/0xe3fb08B8817a0c88d39A4DA4eFFD586D3326b73b) +* RiskStewardReceiver: [`0xf69fd7757c8A59DFA5c35622d9D44B31dB21B0a2`](https://sepolia.basescan.org/address/0xf69fd7757c8A59DFA5c35622d9D44B31dB21B0a2) +* MarketCapsRiskSteward: [`0xE03E243AC1f3239ed6a0793C25E79C951339a915`](https://sepolia.basescan.org/address/0xE03E243AC1f3239ed6a0793C25E79C951339a915) ## Unichain Mainnet @@ -162,3 +176,5 @@ * Critical Timelock: [`0x86C093266e824FA4345484a7B9109e9567923DA6`](https://sepolia.uniscan.xyz/address/0x86C093266e824FA4345484a7B9109e9567923DA6) * Omnichain Governance Executor: [`0x4FD69A0821e35104Fc86B8B7fF09026956B45947`](https://sepolia.uniscan.xyz/address/0x4FD69A0821e35104Fc86B8B7fF09026956B45947) * Omnichain Executor Owner Proxy: [`0xD755873C16Eaeb26993D283292d3F6C605D9BC26`](https://sepolia.uniscan.xyz/address/0xD755873C16Eaeb26993D283292d3F6C605D9BC26) +* RiskStewardReceiver: [`0x4fCbfE445396f31005b3Fd2F6DE2A986d6E2dCB5`](https://sepolia.uniscan.xyz/address/0x4fCbfE445396f31005b3Fd2F6DE2A986d6E2dCB5) +* MarketCapsRiskSteward: [`0x6edbFE9a95dB5f0CdDcE446A0Fe75D7832Cf8DDB`](https://sepolia.uniscan.xyz/address/0x6edbFE9a95dB5f0CdDcE446A0Fe75D7832Cf8DDB) diff --git a/risk/risk-oracle-and-risk-stewards.md b/risk/risk-oracle-and-risk-stewards.md new file mode 100644 index 0000000..0151799 --- /dev/null +++ b/risk/risk-oracle-and-risk-stewards.md @@ -0,0 +1,66 @@ +# Risk Stewards & Risk Oracles + +## Overview + +Venus Protocol incorporates Risk Oracles and Risk Stewards to ensure risk parameters remain up-to-date, resilient, and aligned with real-time market conditions—all while preserving decentralized governance. Previously, Venus relied on manually created VIPs to apply risk updates based on Chaos Labs recommendations. With the introduction of the Risk Steward and its on-chain receiver, this process is now automated through a secure and permissioned mechanism. In the initial phase, only market cap-related parameters—specifically supply caps and borrow caps—will be updated automatically, improving responsiveness and operational efficiency. + +--- + +## Chaos Labs Risk Oracle + +The **Chaos Labs Risk Oracle** is a system designed to continuously analyze market conditions—such as price volatility, liquidity, asset utilization, and liquidation events—and generate risk parameter recommendations tailored to the Venus Protocol. + +### Key Benefits: + +- **Real-time updates** to key parameters like supply and borrow caps +- **Automated adjustments** to ensure optimal lending and borrowing rates +- **More responsive risk management** with lower latency +- **Reduced operational overhead** for the Venus community + +The Risk Oracle makes Venus more adaptable while ensuring parameters remain within safe and governance-approved limits. + +--- + +## Risk Steward + +A **Risk Steward** is an on-chain smart contract that executes risk parameter updates on behalf of the protocol, based on recommendations from the Risk Oracle. Venus has introduced this role to bridge off-chain risk intelligence with on-chain execution in a controlled, transparent way. + +### Role of the Risk Steward: + +- Reads values from the Risk Oracle during execution +- Updates only pre-approved risk parameters (e.g., supply caps, borrow caps) +- Operates within limits set by Venus governance +- Cannot modify critical protocol settings such as interest rate models, market listings, or governance controls + +This structure ensures **faster, automated adjustments** without compromising community control. + +--- + +## How It Works + +1. **Data Source**: Chaos Labs publishes updated recommendations via the Risk Oracle. +2. **Keeper Role**: A Keeper bot observes changes and initiates transactions to update Venus Protocol’s parameters. +3. **Validation**: During execution, Venus contracts read and apply new values **only if they are within predefined safety bounds**. +4. **Challenge Window**: Critical updates, which will be introduced in an upcoming phase, will go through governance and can be **challenged or vetoed** during a defined challenge window before they take effect. + +## Governance & Control + +Importantly, this system does **not bypass protocol governance**. All automated updates happen within constraints defined and approved by the Venus community. + +Any change made through the Risk Oracle follows an **optimistic governance model**: + +This process **preserves decentralization** while enabling faster, safer protocol maintenance. + +--- + +## What’s Next + +Initially, the integration focuses on automating supply and borrow cap updates. Over time, additional parameters may be supported as part of a gradual rollout, always subject to DAO approval and governance-defined constraints. + +--- + +## Learn More + +- [Chaos Labs: Risk Oracles — Real-Time Risk Management for DeFi](https://chaoslabs.xyz/posts/risk-oracles-real-time-risk-management-for-defi) +- [Venus Community Proposal: Integrate Chaos Labs Risk Oracle](https://community.venus.io/t/integrate-chaos-labs-risk-oracle-to-venus-protocol/4569) + diff --git a/technical-reference/reference-governance/MarketCapsRiskSteward.md b/technical-reference/reference-governance/MarketCapsRiskSteward.md new file mode 100644 index 0000000..df6c7f6 --- /dev/null +++ b/technical-reference/reference-governance/MarketCapsRiskSteward.md @@ -0,0 +1,112 @@ +# MarketCapsRiskSteward +Contract that can update supply and borrow caps received from RiskStewardReceiver. Requires that the update is within the max delta. +Expects the new value to be an encoded uint256 value of un padded bytes. + +# Solidity API + +### maxDeltaBps + +The max delta bps for the update relative to the current value + +```solidity +uint256 maxDeltaBps +``` + +- - - + +### CORE_POOL_COMPTROLLER + +Address of the CorePoolComptroller used for selecting the correct comptroller abi + +```solidity +contract ICorePoolComptroller CORE_POOL_COMPTROLLER +``` + +- - - + +### RISK_STEWARD_RECEIVER + +Address of the RiskStewardReceiver used to validate incoming updates + +```solidity +contract IRiskStewardReceiver RISK_STEWARD_RECEIVER +``` + +- - - + +### SUPPLY_CAP + +The update type for supply caps + +```solidity +string SUPPLY_CAP +``` + +- - - + +### BORROW_CAP + +The update type for borrow caps + +```solidity +string BORROW_CAP +``` + +- - - + +### setMaxDeltaBps + +Sets the max delta bps + +```solidity +function setMaxDeltaBps(uint256 maxDeltaBps_) external +``` + +#### Parameters +| Name | Type | Description | +| ---- | ---- | ----------- | +| maxDeltaBps_ | uint256 | The new max delta bps | + +#### 📅 Events +* Emits MaxDeltaBpsUpdated with the old and new max delta bps + +#### ⛔️ Access Requirements +* Controlled by AccessControlManager + +#### ❌ Errors +* InvalidMaxDeltaBps if the max delta bps is 0 or greater than MAX_BPS + +- - - + +### processUpdate + +Processes a market cap update from the RiskStewardReceiver. +Validates that the update is within range and then directly update the market supply or borrow cap on the market's comptroller. +RiskParameterUpdate shape is as follows: + * newValue - encoded uint256 value of un padded bytes + * previousValue - encoded uint256 value of un padded bytes + * updateType - supplyCap | borrowCap + * additionalData - encoded bytes of (address underlying, uint16 destChainId) + +```solidity +function processUpdate(struct RiskParameterUpdate update) external +``` + +#### Parameters +| Name | Type | Description | +| ---- | ---- | ----------- | +| update | struct RiskParameterUpdate | RiskParameterUpdate update to process. | + +#### 📅 Events +* Emits SupplyCapUpdated or BorrowCapUpdated depending on the update with the market and new cap + +#### ⛔️ Access Requirements +* Only callable by the RiskStewardReceiver + +#### ❌ Errors +* OnlyRiskStewardReceiver Thrown if the sender is not the RiskStewardReceiver +* UnsupportedUpdateType Thrown if the update type is not supported +* UpdateNotInRange Thrown if the update is not within the allowed range + +- - - + diff --git a/technical-reference/reference-governance/RiskStewardReceiver.md b/technical-reference/reference-governance/RiskStewardReceiver.md new file mode 100644 index 0000000..30e1117 --- /dev/null +++ b/technical-reference/reference-governance/RiskStewardReceiver.md @@ -0,0 +1,201 @@ +# RiskStewardReceiver +Contract that can read updates from the Chaos Labs Risk Oracle, validate them, and push them to the correct RiskSteward. + +# Solidity API + +### riskParameterConfigs + +Mapping of supported risk configurations and their validation parameters + +```solidity +mapping(string => struct RiskParamConfig) riskParameterConfigs +``` + +- - - + +### RISK_ORACLE + +Whitelisted oracle address to receive updates from + +```solidity +contract IRiskOracle RISK_ORACLE +``` + +- - - + +### lastProcessedTime + +Mapping of market and update type to last update timestamp. Used for debouncing updates. + +```solidity +mapping(bytes => uint256) lastProcessedTime +``` + +- - - + +### processedUpdates + +Mapping of processed updates. Used to prevent re-execution + +```solidity +mapping(uint256 => bool) processedUpdates +``` + +- - - + +### UPDATE_EXPIRATION_TIME + +Time before a submitted update is considered stale + +```solidity +uint256 UPDATE_EXPIRATION_TIME +``` + +- - - + +### initialize + +Initializes the contract as ownable, pausable, and access controlled + +```solidity +function initialize(address accessControlManager_) external +``` + +#### Parameters +| Name | Type | Description | +| ---- | ---- | ----------- | +| accessControlManager_ | address | The address of the access control manager | + +- - - + +### pause + +Pauses processing of updates + +```solidity +function pause() external +``` + +#### ⛔️ Access Requirements +* Controlled by AccessControlManager + +- - - + +### unpause + +Unpauses processing of updates + +```solidity +function unpause() external +``` + +#### ⛔️ Access Requirements +* Controlled by AccessControlManager + +- - - + +### setRiskParameterConfig + +Sets the risk parameter config for a given update type + +```solidity +function setRiskParameterConfig(string updateType, address riskSteward, uint256 debounce) external +``` + +#### Parameters +| Name | Type | Description | +| ---- | ---- | ----------- | +| updateType | string | The type of update to configure | +| riskSteward | address | The address for the risk steward contract responsible for processing the update | +| debounce | uint256 | The debounce period for the update | + +#### 📅 Events +* Emits RiskParameterConfigSet with the update type, previous risk steward, new risk steward, previous debounce, +* new debounce, previous active status, and new active status + +#### ⛔️ Access Requirements +* Controlled by AccessControlManager + +#### ❌ Errors +* Throws UnsupportedUpdateType if the update type is an empty string +* Throws InvalidDebounce if the debounce is 0 +* Throws ZeroAddressNotAllowed if the risk steward address is zero + +- - - + +### toggleConfigActive + +Toggles the active status of a risk parameter config + +```solidity +function toggleConfigActive(string updateType) external +``` + +#### Parameters +| Name | Type | Description | +| ---- | ---- | ----------- | +| updateType | string | The type of update to toggle on or off | + +#### 📅 Events +* Emits ToggleConfigActive with the update type and the new active status + +#### ⛔️ Access Requirements +* Controlled by AccessControlManager + +#### ❌ Errors +* Throws UnsupportedUpdateType if the update type is not supported + +- - - + +### processUpdateById + +Processes an update by its ID. Will validate that the update configuration is active, is not expired, unprocessed, and that the debounce period has passed. +Validated updates will be processed by the associated risk steward contract which will perform update specific validations and apply validated updates. + +```solidity +function processUpdateById(uint256 updateId) external +``` + +#### Parameters +| Name | Type | Description | +| ---- | ---- | ----------- | +| updateId | uint256 | The ID of the update to process | + +#### 📅 Events +* Emits RiskParameterUpdated with the update ID + +#### ❌ Errors +* Throws ConfigNotActive if the config is not active +* Throws UpdateIsExpired if the update is expired +* Throws ConfigAlreadyProcessed if the update has already been processed +* Throws UpdateTooFrequent if the update is too frequent + +- - - + +### processUpdateByParameterAndMarket + +Processes the latest update for a given parameter and market. Will validate that the update configuration is active, is not expired, +unprocessed, and that the debounce period has passed. +Validated updates will be processed by the associated risk steward contract which will perform update specific validations and apply validated updates. + +```solidity +function processUpdateByParameterAndMarket(string updateType, address market) external +``` + +#### Parameters +| Name | Type | Description | +| ---- | ---- | ----------- | +| updateType | string | The type of update to process | +| market | address | The market to process the update for | + +#### 📅 Events +* Emits RiskParameterUpdated with the update ID + +#### ❌ Errors +* Throws ConfigNotActive if the config is not active +* Throws UpdateIsExpired if the update is expired +* Throws ConfigAlreadyProcessed if the update has already been processed +* Throws UpdateTooFrequent if the update is too frequent + +- - - + diff --git a/technical-reference/reference-technical-articles/Risk Steward.md b/technical-reference/reference-technical-articles/Risk Steward.md new file mode 100644 index 0000000..031b0e8 --- /dev/null +++ b/technical-reference/reference-technical-articles/Risk Steward.md @@ -0,0 +1,240 @@ +# Risk Steward + +## Overview + +The Risk Stewards system introduces a secure and modular mechanism for automatically updating borrow and supply caps in the Venus Protocol. In the earlier model, these risk parameters were modified manually via governance proposals (VIPs). This new architecture eliminates manual intervention by enabling fully on-chain, automated updates. + +In this updated model, **Chaos Labs provides risk parameter updates through their on-chain Risk Oracle**. These updates are delivered directly to dedicated steward contracts, such as `MarketCapsRiskSteward`, which are responsible for applying the changes to the protocol. + +All updates are executed through a central router contract, `RiskStewardReceiver`, which ensures: + +- Only pre-approved steward contracts are allowed to execute logic +- Updates adhere to protocol-defined rules such as: + - Debounce periods between consecutive updates + - Maximum allowable percentage change in parameters + - Access control enforced through Venus’s `AccessControlManager` + +This architecture enables faster response to market dynamics while maintaining the safety and integrity of the protocol’s core risk parameters. + +--- + +## Contracts and Responsibilities + +### 1. `RiskStewardReceiver.sol` + +### Purpose + +The `RiskStewardReceiver` contract acts as the **central entry point for processing on-chain risk parameter updates** in the Venus Protocol. It integrates directly with the **Chaos Labs Risk Oracle**, pulling risk recommendations (like borrow/supply caps) and forwarding them to the appropriate **RiskSteward** contract (e.g., `MarketCapsRiskSteward`) for enforcement. + +Its key role is to: +- **Validate**, **deduplicate**, and **throttle** risk updates, +- And **delegate the actual update execution** to the appropriate steward contract responsible for enforcing specific risk parameter types. + +This contract enables a **modular and secure pipeline** for processing real-time risk recommendations on-chain. + +--- + +### Key Responsibilities + +- **Oracle Integration**: + Directly reads data from the `IRiskOracle`, which provides structured `RiskParameterUpdate` records. + +- **Per-Type Configuration**: + Maintains a `riskParameterConfigs` mapping to register: + - Which `updateType` is supported, + - Which steward contract should handle it, + - What debounce period (minimum time between updates) is enforced. + +- **Validation Checks Before Processing**: + Before an update is executed, the contract validates that: + - The update type is **active** (`ConfigNotActive`) + - The update is **not expired** (`UpdateIsExpired`) + - The update has **not already been processed** (`ConfigAlreadyProcessed`) + - The **debounce period** since the last update has passed (`UpdateTooFrequent`) + +- **Processing Updates**: + Provides two ways to trigger an update: + 1. `processUpdateById(updateId)` + 2. `processUpdateByParameterAndMarket(updateType, market)` + + Both functions: + - Fetch the update from the risk oracle + - Validate its status + - Delegate the update execution to the configured `IRiskSteward` contract + +- **State Tracking**: + - `lastProcessedTime`: Tracks last update per `(market + updateType)` to enforce debounce period + - `processedUpdates`: Marks updates that have already been processed, preventing replay + +- **Governance and Controls**: + - Uses `AccessControlledV8` to restrict who can: + - Set or modify risk configs + - Pause or unpause the contract + - Can be paused to halt all update processing using OpenZeppelin’s `PausableUpgradeable` + +--- + +### 2. `MarketCapsRiskSteward.sol` + +The `MarketCapsRiskSteward` contract is responsible for **processing supply cap and borrow cap updates** for Venus markets. These updates originate from the `RiskStewardReceiver`, which itself receives on-chain recommendations from the Chaos Labs Risk Oracle. + +This contract **does not fetch or validate updates directly**. Instead, it: +- **Receives validated updates** delegated by the `RiskStewardReceiver` +- **Performs delta checks** to ensure caps are within allowed bounds +- **Writes new cap values** into the correct pool comptroller (either Core or Isolated) +- Emits events for transparency and downstream indexing + +--- + +### Key Responsibilities + +- **Parameter Enforcement** + Applies updates only for: + - `supplyCap` + - `borrowCap` + +- **Source Validation** + Ensures updates can only be executed by the trusted `RiskStewardReceiver`. + → Any direct call from an external or malicious contract is rejected (`OnlyRiskStewardReceiver`). + +- **Delta Bounding** + Before updating any cap, the new value is validated against the previous cap. The change is only allowed if it’s within the `maxDeltaBps` (basis points) threshold. + → Ensures the system remains stable and avoids drastic risk shifts (`UpdateNotInRange`). + +- **Governance Access** + `AccessControlledV8` is used to restrict who can: + - Set the `maxDeltaBps` + - Initialize the contract + +--- + +## End-to-End Flow: Market Cap Update via Risk Stewards + +This example walks through a complete end-to-end flow where **Chaos Labs** updates a **borrow cap** for a market using the on-chain risk oracle, and the change is processed securely through the steward contracts. + +### Roles + +| Role | Description | +|------|-------------| +| Chaos Labs | Publishes risk parameter updates on-chain via a Risk Oracle | +| Keeper Bot | External off-chain agent responsible for calling the RiskStewardReceiver to apply updates | +| RiskStewardReceiver | Central processor that validates updates and routes them to the correct steward | +| MarketCapsRiskSteward | Applies validated supply/borrow cap updates to the appropriate pool comptroller | + +--- + +### Example Scenario + +Chaos Labs recommends updating the **borrow cap** for the USDC market (`vUSDC`) from **5,000,000** to **6,000,000** tokens. + +--- + +### Step-by-Step Execution + +#### 1. **Chaos Labs Publishes an Update On-Chain** + +Chaos Labs publishes the following to the on-chain **Risk Oracle** contract: + +```json +{ + "updateId": 101, + "market": "0x...vUSDC", + "updateType": "borrowCap", + "newValue": 6000000, + "timestamp": 1721036000, + "additionalData": "" +} +``` + +This update is stored in the oracle contract and made available via `getUpdateById(updateId)`. + +--- + +#### 2. **Keeper Bot Detects the Update and Calls `processUpdateById`** + +A **Keeper Bot** regularly polls the Risk Oracle and calls: + +```solidity +riskStewardReceiver.processUpdateById(101); +``` + +--- + +#### 3. **RiskStewardReceiver Validates the Update** + +Upon receiving the call, `RiskStewardReceiver` performs **strict validations**: + +- ✅ Checks that the update is the **latest** from the oracle for the given market and type +- ✅ Validates the update is **active** in config (`ConfigNotActive`) +- ✅ Verifies it is **not expired** (timestamp + 1 day > now) (`UpdateIsExpired`) +- ✅ Ensures it is **not already processed** (`ConfigAlreadyProcessed`) +- ✅ Ensures **debounce interval** has passed for the `(market + updateType)` pair (`UpdateTooFrequent`) + +If any check fails, the transaction reverts with the corresponding error. + +--- + +#### 4. **Update is Routed to MarketCapsRiskSteward** + +Once the update passes all validations, the RiskStewardReceiver uses the updateType to determine which RiskSteward contract should handle it, and delegates the update to MarketCapsRiskSteward: + +```solidity + IRiskSteward(riskParameterConfigs[update.updateType].riskSteward).processUpdate(update); +``` + +Here, the steward performs: + +- ✅ Validates that the `msg.sender` is `RiskStewardReceiver` (`OnlyRiskStewardReceiver`) +- ✅ Confirms that `updateType` is either `supplyCap` or `borrowCap` (`UnsupportedUpdateType`) +- ✅ Retrieves the current cap from the comptroller and validates that the new cap change is within the allowed delta range defined by `maxDeltaBps`: +- ✅ Writes the new cap into the pool comptroller: +- ✅ Emits `BorrowCapUpdated(market, newCap)` for downstream indexing +- ✅ Applies the update to the pool’s comptroller, by directly making a call to the appropriate setter function: +`comptroller.setMarketSupplyCaps(newSupplyCapMarkets, newSupplyCaps)` + +--- + +#### 5. **Update State is Committed** + +Once the steward call completes: + +- The update ID is marked as **processed** +- The `(market + updateType)` debounce timer is updated with the current block time +- `RiskParameterUpdated(updateId)` is emitted + +--- + +### Failure Scenarios + +| Scenario | Failure Trigger | Result | +|----------|-----------------|--------| +| Keeper calls too late (e.g. after 24h) | `UpdateIsExpired` | Revert | +| Keeper tries again for same ID | `ConfigAlreadyProcessed` | Revert | +| Another update was already applied for the same market+type | `UpdateIsExpired` | Revert | +| Debounce timer has not passed | `UpdateTooFrequent` | Revert | +| Chaos Labs sets too large a delta | `UpdateNotInRange` | Revert | +| Cap type is misspelled | `UnsupportedUpdateType` | Revert | +| Non-receiver tries to call steward | `OnlyRiskStewardReceiver` | Revert | + +--- + +
riskSteward
riskSteward
+ +## Limitations + +While the Risk Steward system enables secure and automated updates to certain risk parameters, there are important limitations to keep in mind: + +### 1. Bypasses On-Chain Governance + +This architecture allows updates (e.g., supply and borrow caps) to be applied automatically, without going through the formal governance process. + +- Critical parameters such as collateral factors, liquidation thresholds, and reserve factors are intentionally excluded. +- These parameters are considered sensitive and must be proposed and approved through governance (via Venus Improvement Proposals or VIPs) to ensure proper transparency and community review. + +### 2. No Cross-Chain Initiation Support + +The current design supports only same-chain update processing. + +- Updates on a specific chain can only be processed if a Risk Oracle is deployed and supported on that chain.. +- For operational efficiency and monitoring, it would be beneficial to register or reflect these updates on BNB Chain, where monitoring systems and automation (such as keeper bots) are primarily active. +