๐Ÿ”งBuilding a Consumer Contract

We'll now guide you through how to build a SEDA consumer contract using the PriceFeed example, which demonstrates 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 Prover Contract

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

constructor(address _sedaProverContract) {
    sedaProverContract = SedaProver(_sedaProverContract);
}

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.DataRequestInputs memory drInputs = SedaDataTypes
    .DataRequestInputs(
        oracleProgramId,                // Oracle Program ID
        "eth-usdc",                     // Input parameters for the data request
        oracleProgramId,                // Tally binary ID
        hex"00",                        // Tally inputs
        1,                              // Replication factor
        hex"00",                        // Consensus filter
        1,                              // Gas price in SEDA
        5000000000,                     // Gas limit in SEDA
        abi.encodePacked(block.number)  // Additional information (e.g., block number)
    );

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: While not used in this example, these manage transaction 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 postDataRequest function from the SedaProver contract, which handles the interaction between your consumer contract and the SEDA network. This function submits the request and returns a unique data request ID (dataRequestId), which will be used later to fetch the results.

Hereโ€™s an example of how to post the data request using the SedaProver contract:

dataRequestId = sedaProverContract.postDataRequest(inputs);

This step is essential as it officially submits your data request for execution on the network. The dataRequestId 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.DataRequestInputs memory inputs = SedaDataTypes
        .DataRequestInputs(
            oracleProgramId,                // Oracle Program ID
            "eth-usdc",                     // Inputs for the data request
            oracleProgramId,                // Tally binary ID
            hex"00",                        // Tally inputs
            1,                              // Replication factor
            hex"00",                        // Consensus filter
            1,                              // Gas price
            5000000000,                     // Gas limit
            abi.encodePacked(block.number)  // Additional info (block number)
        );

    dataRequestId = sedaProverContract.postDataRequest(inputs);
    return dataRequestId;
}

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 getDataResult function from the SedaProver 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.DataResult memory result = sedaProverContract.getDataResult(dataRequestId);

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

function latestAnswer() public view returns (uint128) {
    // Ensure a data request has been transmitted.
    require(dataRequestId != bytes32(0), "No data request transmitted");

    // Fetch the data result from the SedaProver contract using the stored data request ID.
    SedaDataTypes.DataResult memory dataResult = sedaProverContract
        .getDataResult(dataRequestId);

    // Check if the data result reached consensus (โ‰ฅ 66% agreement among nodes).
    if (dataResult.consensus) {
        return uint128(bytes16(dataResult.result));
    }

    // Return 0 if no valid result or no consensus.
    return 0;
}

Breaking it down:

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

  • Fetch the Result: The key line here is the call to sedaProverContract.getDataResult(dataRequestId), which retrieves the results from the SedaProver 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