Integrating your Feed On-Chain

This guide provides a comprehensive walkthrough of integrating Switchboard feeds into your Solidity smart contracts on EVM-compatible chains.

1. Understanding Switchboard's Diamond Pattern

Switchboard contracts use the Diamond Pattern. To simplify modular contract design it presents a single unchanging contract address. Traditional explorers cannot easily locate the verified contract, so this solution has been developed to make this process easier.

  • To help with this issue, we recommend the using louper.dev. This can be used for for seamless contract analysis and function calls. This is a custom diamond explorer, specifically designed to interact with Switchboard diamond contracts.

2. Installation

Before you begin, install these items:

  1. Switchboard On-Demand Solidity SDK:

    npm add @switchboard-xyz/on-demand-solidity
  2. Forge (Optional):

    • If you are working with Forge, include this in your remappings.txt file:

    @switchboard-xyz/on-demand-solidity/=node_modules/@switchboard-xyz/on-demand-solidity

3. Minimal Integration

To minimise dependencies, you can integrate Switchboard feeds by defining only function signatures and structures.

struct Update {
    bytes32 oracleId; // The publisher of the update
    int128 result; // The value of the recorded update
    uint256 timestamp; // The timestamp of the update
}

interface ISwitchboard {
    function latestUpdate(
        bytes32 aggregatorId
    ) external view returns (Update memory);
    function updateFeeds(bytes[] calldata updates) external payable;
    function getFee(bytes[] calldata updates) external view returns (uint256);
}

4. Solidity Walkthrough

Let’s walk through how to use Switchboard feeds in your Solidity code:

  1. Import Statements:

    • ISwitchboard: Defining the core implementation of the Switchboard contract interface.

    • Structs: Contract containing the data formats used within the Switchboard structure.

  2. Contract Definition:

    Within the Example contract:

    • switchboard is the reference to the diamond contract, it can be found in Technical Resources

    • aggregatorId that we're interested in reading. If you don't have an aggregatorId yet, create a feed by following: Designing a Feed (EVM).

  3. Function Boilerplate:

    1. Here we're adding the function to get feed data. The idea is that we'll pass in an encoded Switchboard update (or set of updates) that will be used to update the aggregatorId of our choice. We can then read our recently-written update safely.

  4. Adding a Fee:

    Here we're doing a few things relating to update fees.

    We're adding a new error,

    that will be used if the submitted transaction value isn't enough to cover the update.

    We're calling

    to get the cost of submitting a Switchboard update programmatically from the Switchboard program.

    We're enforcing that users pay for fees before submitting any updates.

  5. Submitting Updates:

    This line updates feed values in the Switchboard contract, and sends the required fee. Internally, each update is parsed and encoded signatures are verified and checked against the list of valid oracles on a given chain.

    This bytes[] calldata parameter keeps things simple by making common Switchboard updates into one data-type. Everything is handled behind the scenes.

    The { value: fee } in the call sends fee wei over to the Switchboard contract as payment for updates. The intent here is to pay for the updates.

  6. Checking Validated Data:

    Here we're pulling the result out of the latest update. Switchboard updates are encoded as int128's. Another important fact is that values are decimals scaled up by 10^18.

    For example, the value

    would represent

    Next, we check that the value is positive and revert with an

    if it isn't. Finally, if the update was successful, we emit a FeedData event.

  7. Putting It All Together: (Full Example.Sol)

Review

This contract:

  1. Sets the Switchboard contract address and feed ID in the constructor

  2. Defines a function getFeedData

  3. Checks if the transaction fee is paid, using switchboard.getFee(bytes[] calldata updates).

  4. Submits the updates to the Switchboard contract using switchboard.updateFeeds(bytes[] calldata updates).

  5. Reads the latest value from the feed using switchboard.getLatestValue(bytes32 aggregatorId).

  6. Emits the latest result from the feed.

Follow the next section to understand how to use data feeds with Typescript

Last updated