🔧Using SEDA in a Contract

We'll now guide you through how to build a contract that uses SEDA, using the PriceFeed example as a demonstration, which shows how to post data requests to the SEDA network and read the results.

Quickstart: SEDA Hardhat Starter Kit

To get started quickly, use the SEDA Hardhat Starter Kit. This kit provides the necessary tools for deploying and interacting with the SEDA network.

  1. Clone the repository and install dependencies:

    git clone git@github.com:sedaprotocol/seda-hardhat-starter-kit.git
    cd seda-hardhat-starter-kit
    npm install
  2. Compile and test the contracts:

    npx hardhat compile
    npx hardhat test

Step 1: Use an existing Core Contract

To interact with the SEDA network, import and initialize the ISedaCore in your contract. You'll need to pass the address of an already deployed core contract to the constructor, allowing your contract to connect with SEDA.

constructor(address _sedaCoreAddress, bytes32 _oracleProgramId) {
    sedaCore = ISedaCore(_sedaCoreAddress);
    oracleProgramId = _oracleProgramId;
}

Refer to the Deployments section for available addresses, or contact us for new instances.

Step 2: Create a Data Request

Data requests are defined by setting the appropriate inputs, which describe the parameters required for execution and tally phases. The SedaDataTypes library is used to structure these inputs, ensuring that the request is properly formatted for the SEDA network.

In the PriceFeed example, we specify several key parameters such as the oracleProgramId, the asset pair to query, and other configurations like replication factor and consensus filter.

Below is an example of how this data request is defined using SedaDataTypes:

SedaDataTypes.RequestInputs memory inputs = SedaDataTypes.RequestInputs(
        oracleProgramId,   // execProgramId (Execution WASM binary ID)
        bytes("eth-usdc"), // execInputs (Inputs for Execution WASM)
        20000000000000,    // execGasLimit
        oracleProgramId,   // tallyProgramId (same as execProgramId in this example)
        hex"00",           // tallyInputs
        10000000000000,    // tallyGasLimit
        1,                 // replicationFactor (number of required DR executors)
        hex"00",           // consensusFilter (set to `None`)
        2000,              // gasPrice (SEDA tokens per gas unit)
        abi.encodePacked(block.number) // memo (Additional public info)
    );

Some of the key parameters include:

  • Oracle Program ID: Specifies which Oracle Program on the SEDA network will handle the request.

  • Execution Input Parameters: Defines inputs passed during the execution phase, such as asset pairs like "eth-usdc."

  • Tally Input Parameters: Parameters for the tally phase, which aggregates the execution results.

  • Replication Factor: Indicates how many Overlay Nodes execute the request.

  • Consensus Filter: Defines the method for achieving consensus. Here we use None, but other filters like mode or standard deviation are available.

  • Gas Parameters: data request transaction and computation costs.

Note: In this example, the same Oracle Program handles both execution and tally phases, but you can use different programs for each phase.

Step 3: Post a Data Request

Once your data request is defined, it needs to be sent to the SEDA network for processing. This is done using the postRequest function from the Core Contract, which handles the interaction between your contract and the SEDA network. This function submits the request and returns a unique data request ID (requestId), which will be used later to fetch the results.

Here’s an example of how to post the data request using the ISedaCore interface:

requestId = sedaCore.postRequest(inputs);

This step is essential as it officially submits your data request for execution on the network. The requestId returned by this function is stored, allowing you to track the request and retrieve the result after the execution and tally phases have completed.

In the PriceFeed example, steps 2 (defining the data request) and 3 (posting the data request) are combined into a single function called transmit(). This method simplifies the process by defining the request inputs and immediately submitting the request to the network:

function transmit() public returns (bytes32) {
    SedaDataTypes.RequestInputs memory inputs = SedaDataTypes.RequestInputs(
            oracleProgramId, // execProgramId (Execution WASM binary ID)
            bytes("eth-usdc"), // execInputs (Inputs for Execution WASM)
            20000000000000, // execGasLimit
            oracleProgramId, // tallyProgramId (same as execProgramId in this example)
            hex"00", // tallyInputs
            10000000000000, // tallyGasLimit
            1, // replicationFactor (number of required DR executors)
            hex"00", // consensusFilter (set to `None`)
            2000, // gasPrice (SEDA tokens per gas unit)
            abi.encodePacked(block.number) // memo (Additional public info)
        );

    requestId = sedaCore.postRequest(inputs);
    return requestId;
}

By combining these steps into the transmit() function, the process of creating and posting a data request becomes streamlined and easy to manage within your contract.

Step 4: Read a Data Result

Once the SEDA network has processed your data request, the results can be retrieved using the getResult function from the Core Contract. This function allows you to fetch the outcome of the data request, including whether a consensus was reached, and use the data in your application.

SedaDataTypes.Result memory result = sedaCore.getResult(requestId);

In the PriceFeed contract, the latestAnswer() function encapsulates the logic to retrieve the result. It uses the requestId generated during the posting phase to access the result, verify consensus, and return the final value.

function latestAnswer() public view returns (uint128) {
    if (requestId == bytes32(0)) revert RequestNotTransmitted();

    SedaDataTypes.Result memory result = sedaCore.getResult(requestId);

    if (result.consensus) {
        return uint128(bytes16(result.result));
    }

    return 0;
}

Breaking it down:

  • Data Request Check: Before fetching results, the function ensures that requestId is set, confirming a data request was previously posted.

  • Fetch the Result: The key line here is the call to sedaCore.getResult(requestId), which retrieves the results from the Core Contract.

  • Consensus Verification: The function checks if the result has achieved consensus (≥ 66% agreement among nodes), ensuring data integrity.

  • Return the Result: If consensus is reached, the final result is returned. Otherwise, the function returns 0.

This step is crucial in ensuring that the data retrieved from the SEDA network is accurate, verified, and secure, allowing your smart contracts to operate with trusted off-chain data.

Last updated