Skip to main content
To integrate Chaos Labs’ dynamic risk parameters into your protocol, you’ll need to coordinate with the Chaos labs team to deploy the RiskOracle contract. This smart contract acts as the on-chain source of truth for validated risk parameters such as caps, thresholds, and limits. Each oracle contract is deployed for each client’s specific needs.
 Risk oracle flow

Risk oracle flow

Step 1: Align on parameter requirements

Align with Chaos Labs on the parameters that should be automated. This should include:
  • Name of parameter: A string label such as maxOpenInterestForLongs. This is used for updateType.
  • Values: The expected value and type. Chaos Labs sends this encoded as bytes.
  • Market: The market that is the parameter target, which is also encoded as bytes or an address.
  • Blockchain: The chain where the RiskOracle contract is deployed.
  • Additional data: Any optional metadata like source, confidence score, and strategy used.
These inputs help ensure the oracle updates are processed correctly and contextually in your protocol.

Step 2: Understand the contract interface

Understanding the contract ABI is essential for secure and reliable integration. Each function and data structure defines how your protocol communicates with the RiskOracle, ensuring that updates are posted, tracked, and consumed accurately. For a detailed look at the implementation, the RiskOracle contract is open-sourced and available on GitHub.

Querying Oracle Data

These functions expose the current and historical state of risk parameter updates for external queries and verification.
Function nameParametersDescription
getLatestUpdateByParameterAndMarketupdateType (string), market (address)Returns the most recent update for a given parameter and market.
getUpdateByIdupdateId (uint256)Returns a specific update by its ID.
getAllUpdateTypesNoneReturns all currently allowed update types, such as maxLeverage.
isAuthorizedaddress (address)Checks if a given address is authorized to post updates.

Struct: RiskParameterUpdate

This struct defines the data model for each parameter update, capturing key metadata and context for auditing and integration.
AttributeData typeDescription
timestampuint256The block timestamp when the update was recorded.
newValuebytesThe new value of the risk parameter is stored in a bytes format to support various data typologies and complexity.
previousValuebytesThe parameter value before the current update, enabling historical comparison and possible rollback scenarios.
updateTypestringA categorization of the update, allowing different types of updates such as maxOpenInterestForLongs.
updateIduint256A unique identifier for the specific update.
marketaddressAn identifier for the market in which the parameter update applies.
referenceIdstringAn external or internal reference ID linking to additional documentation, a dashboard, REST API, or data related to the parameter update.
additionalDatabytesAny additional data for the update.

Events: ParameterUpdated

Emitted after every successful update.
ParameterTypeDescription
referenceIdstringTraceable identifier
newValuebytesUpdated value
previousValuebytesOld value
timestampuint256Time of update
updateTypestring (indexed)What was updated
updateIduint256 (indexed)Unique update ID
marketaddress (indexed)Affected market
additionalDatabytesOptional

Step 3: Integrate the Oracle

Once the RiskOracle is deployed and being updated by authorized senders, you’ll want to consume those updates inside your own contracts. This section outlines a secure and flexible consumption pattern using interface-based access.

Objective

Consume parameter updates from RiskOracle and use them to dynamically adjust logic in your own smart contracts, such as update caps, fees, interest rates.

Integration Pattern

This pattern uses two interfaces:
  • IRiskOracle: Use this interface to fetch updates by an ID.
  • IAnotherContract: A mock contract you wish to update using values from the oracle.
The RiskOracleConsumer contract fetches the update, decodes the values, and forwards them into another contract.
The following code is for illustrative purposes only, has not been audited, and should not be used in production without thorough testing.
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

// Oracle interface exposing the `getUpdateById()` function
interface IRiskOracle {
    struct RiskParameterUpdate {
        uint256 timestamp;
        bytes newValue;
        string referenceId;
        bytes previousValue;
        string updateType;
        uint256 updateId;
        address market;
        bytes additionalData;
    }

    function getUpdateById(uint256 updateId) external view returns (RiskParameterUpdate memory);
}

// Mock contract that will be updated
interface IAnotherContract {
    function updateParameter(uint256 newValue, address market) external;
}

contract RiskOracleConsumer {
    IRiskOracle public riskOracle;
    IAnotherContract public anotherContract;

    constructor(address _riskOracleAddress, address _anotherContractAddress) {
        riskOracle = IRiskOracle(_riskOracleAddress);
        anotherContract = IAnotherContract(_anotherContractAddress);
    }

    /**
     * @notice Requests an update by ID and decodes the newValue and market parameters.
     * @param updateId The ID of the update to request.
     * @return Decoded newValue as uint256 and market as address
     */
    function requestAndDecodeUpdate(uint256 updateId) public view returns (uint256, address) {
        IRiskOracle.RiskParameterUpdate memory update = riskOracle.getUpdateById(updateId);
        uint256 decodedValue = _decodeNewValue(update.newValue);
        address decodedMarket = _decodeMarket(update.market);
        return (decodedValue, decodedMarket);
    }

    /**
     * @notice Uses values decoded from Risk Oracle to interact with another contract.
     * @param updateId The ID of the update to request and use.
     */
    function updateAnotherContract(uint256 updateId) external {
        (uint256 newValue, address market) = requestAndDecodeUpdate(updateId);
        anotherContract.updateParameter(newValue, market);
    }

    /**
     * @dev Decodes a bytes value to uint256 using abi.decode.
     * @param data The bytes value to decode.
     * @return The decoded uint256 value.
     */
    function _decodeNewValue(bytes memory data) internal pure returns (uint256) {
        return abi.decode(data, (uint256));
    }

    /**
     * @dev Decodes a bytes value to address using abi.decode.
     * @param data The bytes value to decode.
     * @return The decoded address value.
     */
    function _decodeMarket(bytes memory data) internal pure returns (address) {
        return abi.decode(data, (address));
    }
}

Breakdown Function

These helper functions handle decoding and forwarding of update data, enabling seamless integration with other contracts.
FunctionRoles or description
requestAndDecodeUpdate()Pulls the update by ID and decodes newValue and market.
updateAnotherContract()Uses the decoded values to interact with another contract.
_decodeNewValue()Converts bytesuint256. Assumes newValue is a uint256.
_decodeMarket()Converts bytesaddress. Assumes market is encoded that way.
This consumption pattern lets you:
  • Safely integrate dynamic risk parameters.
  • Offload value validation and signing to Chaos Labs.
  • Keep your contracts modular and upgrade-friendly.

Step 4: Go-live checklist

Before deploying your integration in production, follow these implementation and deployment steps to ensure secure and reliable operation of your RiskOracle setup.

Part A: Implementation Steps

  1. Get your RiskOracle contract address
    • Obtain the specific RiskOracle contract address from the Chaos Labs team
    • This contract will be customized for your protocol’s needs
    • Verify the contract is deployed on your target network
  2. Coordinate message format
    • Work with Chaos Labs to define the exact format of the parameter updates
    • For example, if implementing a supply cap:
    Solidity
    // Example parameter format for a supply cap
    struct SupplyCapUpdate {
        uint256 maxSupply;
        address asset;
        uint256 timestamp;
    }
    
  3. Setup your consumer contract
    • Implement the IRiskOracle interface in your contract
    • Define the parameter struct matching the agreed format
    Solidity
    contract YourContract {
        IRiskOracle public riskOracle;
        
        constructor(address _riskOracleAddress) {
            riskOracle = IRiskOracle(_riskOracleAddress);
        }
        
        function getLatestSupplyCap(address market) public view returns (uint256) {
            RiskParameterUpdate memory update = riskOracle.getLatestUpdateByParameterAndMarket("supplyCap", market);
            return abi.decode(update.newValue, (uint256));
        }
    }
    
  4. Implement update retrieval
    • Add functions to fetch and decode the latest parameter values
    • Include proper error handling for cases when updates aren’t available
    • Test the integration with sample data from Chaos Labs

Part B: Deployment and Monitoring

  1. Set up event monitoring
    • Implement monitoring for the ParameterUpdated event
    • This allows your protocol or off-chain services like (Gelato) to react to new risk parameter updates in real time
    • Example monitoring setup:
    Javascript
    riskOracle.on("ParameterUpdated", (referenceId, newValue, previousValue, timestamp, updateType, updateId, market) => {
        if (updateType === "supplyCap") {
            // Handle supply cap update
            updateProtocolLimits(market, newValue);
        }
    });
    
  2. Verify integration
    • Test the complete flow with actual parameter updates
    • Verify parameter values are correctly decoded and applied
    • Monitor the first few updates in production closely
  3. Document integration details
    • Record all parameter types and their encoding formats
    • Document the update frequency and monitoring setup
    • Maintain contact information for the Chaos Labs team
Remember to implement proper access controls and validation checks in your consumer contract to ensure only authorized updates are processed.
I