Oracles are critical components of blockchain networks, bridging the gap between onchain and off-chain worlds by fetching real-world data for use in smart contracts. When building oracles, security is important, and Oasis Runtime Offchain Logic (ROFL) offers an exciting new way to build them, leveraging confidentiality and powerful off-chain capabilities.
ROFL is commonly used for oracles, but it is also capable of much more. It enables off-chain services to work with blockchains while keeping data safe and handling complex tasks that would be too slow or costly to do onchain. So, beyond oracles, ROFL can handle private data analysis, run big calculations more efficiently, and connect safely to outside systems or APIs.
In this guide, we'll explore how to build a secure oracle using the ROFL framework and Sapphire, the Oasis Network's confidential Ethereum Virtual Machine (EVM). We'll cover what makes ROFL and Sapphire uniquely suited to this task and provide a hands-on walkthrough to set up an oracle using the Oasis SDK and ROFL. By the end, you will have a deep understanding of the steps needed to build secure and efficient oracles for decentralized applications. Let's get started!
Before we jump into the development details, let's take a closer look at what makes ROFL special. Runtime Offchain Logic is a framework designed to extend the capabilities of runtime environments like Sapphire, the confidential EVM-compatible environment from the Oasis Network. ROFL allows for off-chain computations that are verified by the blockchain, providing flexibility and scalability without compromising security.
ROFL essentially provides a secure way for smart contracts to interact with external data sources. The framework works by ensuring that all off-chain data is processed within a Trusted Execution Environment (TEE). This guarantees that no third party can tamper with or alter the data before it reaches the blockchain. It also allows the blockchain to leverage the computational power of off-chain environments, thus making complex operations more feasible without burdening the network itself.
Sapphire is the world's only confidential EVM network, and it offers several features that make it attractive for developers building decentralized applications (dApps):
Runtime Offchain Logic extends the capabilities of Oasis Sapphire by enabling off-chain components to interact with smart contracts securely. This flexibility allows you to build an oracle that can access off-chain data sources such as web APIs and bring that data on-chain.
With TEEs, ROFL ensures that off-chain computations are not only efficient but also trustworthy. These features make ROFL ideal for building secure oracles, decentralized exchanges, gaming platforms, and more.
In this section, we'll walk you through the steps required to set up an oracle using Oasis ROFL. By the end of this guide, you should be able to create an oracle that fetches data from Binance and posts it on-chain. The process involves setting up your development environment, writing both on-chain and off-chain code, and testing everything on a local Sapphire instance.
To begin, ensure you have the following:
You can install Rust by running:
Oasis CLI: This guide uses the Oasis CLI for easy interaction with ParaTimes like Sapphire.
Install the CLI binary for the latest available version https://github.com/oasisprotocol/cli/releases
This will help you deploy smart contracts, interact with nodes, and manage your ROFL applications.
SGX Tools: If you're planning to deploy to a trusted execution environment, install Intel SGX tools to generate TEE-compatible binaries. Refer to the setup guide.
In order to generate binaries suitable for use with Intel SGX, you also need to install the relevant utilities. You can do so as follows:
To start, we'll create a new project using Cargo, the Rust package manager:
This creates a rofl-oracle directory with the boilerplate needed for a Rust project. You will then need to declare your dependencies in the Cargo.toml file.
Since the Runtime SDK relies on a nightly version of the Rust toolchain, you must specify which version to use by creating a rust-toolchain.toml file with the following configuration:
Furthermore, due to upstream dependencies, Cargo must be configured to always build with specific CPU platform features (namely AES-NI and SSE3). To do this, create a .cargo/config.toml file with the following settings:\
For this tutorial, You can install the following dependencies
You can use the debug-mock-sgx
feature to enable the use of a mock SGX environment during non-SGX builds for testing and debugging purposes by adding the following in Cargo.toml
file
With the dependencies declared, it's time to start implementing the core logic of our oracle. This logic will involve setting up both the smart contract component and the off-chain component.
Your oracle will be split into two main components: the smart contract running on Sapphire and the off-chain code running inside the ROFL TEE. The smart contract will serve as the destination for our price data, while the off-chain code will fetch the data from Binance and send it to the contract. You can refer to the example repository for demonstration code.
Create a Solidity smart contract to hold the fetched data. The contract will store price observations submitted by the ROFL app:
The PriceOracle
contract stores observations submitted by the ROFL oracle. Only the ROFL application (identified by the roflApp
address) can call submitObservation
. This ensures that the data is only modified by the trusted ROFL app, maintaining the integrity of the oracle data.
Next, implement the off-chain component of the oracle in Rust. This code will run inside the ROFL environment, which provides a secure enclave for off-chain logic.
In the src/main.rs
file with the following code:
This code connects to Binance to fetch the current price of the ROSE/USDT pair, multiplies it by one million to convert it to an integer (since Ethereum smart contracts don't handle floating-point operations), and submits it to the smart contract.
The async design ensures that the heavy computation does not block the runtime, allowing other parts of the app to continue running smoothly. By making use of the ROFL utilities, the data fetched is kept secure, and no one can tamper with the communication between Binance and the smart contract.
The ROFL App ID can be kept as it is for local testing. When you want to deploy it, then you can generate an App ID by registering your app with the Oasis Network.
After developing the ROFL app, it's time to test it. Spin up a local instance of the Sapphire network and deploy your contract:
consensus_trust_root()
This command runs the Sapphire localnet and automatically launches your ROFL application. Running a local instance helps you simulate real-world scenarios without spending gas fees on a public Testnet or Mainnet.
Test the Oracle: Use the Web3-compatible interface like Remix to interact with the deployed contract. Verify that the observations are being updated as expected. This step will validate whether the data from Binance is being correctly fetched and recorded on-chain.
We can also verify the contract on the sapphire-localnet network. First, set up the PRIVATE_KEY for your deployment account and the identifier for the ROFL app. Then, you can deploy the contract by running the following command:
If all works good then You should see something like this as output: