# Oracle Smart Contract Research
*References: [Source 1](https://kennyran.substack.com/p/introduction-to-oracles), Source 2(chat gpt), [Chainlink](https://blog.chain.link/what-is-the-blockchain-oracle-problem/), [101 Blockchains]([https:/](https://101blockchains.com/blockchain-oracle-problem/)/), [Open Zeppelin](https://blog.openzeppelin.com/secure-smart-contract-guidelines-the-dangers-of-price-oracles/), [Phala Oracle Workshop](https://github.com/Phala-Network/phat-offchain-rollup/tree/sub0-workshop/phat)*
---
Cryptocurrency oracles are third-party services that provide blockchain networks with external data.
In a blockchain network, smart contracts and oracles work together to enable decentralized applications (dApps) to access external data and execute based on that data.
### How do Oracles Work
*(chat gpt)*
Smart contract oracles work by using an Application Programming Interface (API) to retrieve data from external sources, then translating that data into a format that the smart contract can understand. The oracle then sends the data to the smart contract, which can execute based on that information.
1. A smart contract is deployed on the blockchain network. The smart contract contains code that defines the terms of an agreement or transaction between two or more parties.
2. The smart contract requires external data to execute. For example, a smart contract that pays out insurance claims based on weather data requires access to weather information.
3. An oracle is used to retrieve the required external data. The oracle retrieves data from external sources, such as APIs, websites, or IoT devices.
4. The oracle validates and verifies the external data to ensure its accuracy and reliability. This step is crucial to ensure that the smart contract executes based on valid and trustworthy data.
5. The oracle sends the validated external data to the smart contract. The smart contract then executes based on the data and automatically enforces the terms of the agreement or transaction.
---
### What are the functions of an Oracle?
**Listen** – monitor the blockchain network to check for any incoming user or smart contract requests for off-chain data.
**Extract** – fetch data from one or multiple external systems such as off-chain APIs hosted on third-party web servers.
**Format** – format data retrieved from external APIs into a blockchain readable format (input) and/or making blockchain data compatible with an external API (output).
**Validate** – generate a cryptographic proof attesting to the performance of an oracle service using any combination of data signing, blockchain transaction signing, TLS signatures, Trusted Execution Environment (TEE) attestations, or zero-knowledge proofs.
**Compute** – perform some type of secure off-chain computation for the smart contract, such as calculating a median from multiple oracle submissions or generating a verifiable random number for a gaming application.
**Broadcast** – sign and broadcast a transaction on the blockchain in order to send data and any corresponding proof on-chain for consumption by the smart contract.
**Output (optional)** – send data to an external system upon the execution of a smart contract, such as relaying payment instructions to a traditional payment network or triggering actions from a cyber-physical system.
### How Oracles Might Be Programmed
*(chat gpt)*
1. **Identify the data source:** The first step in programming an oracle is to identify the data source that the oracle will retrieve data from. This could be an API, a website, an IoT device, or any other source of data.
2. **Define the API:** If the oracle will be retrieving data from an API, the next step is to define the API endpoints and request parameters. This will typically involve creating API requests using HTTP or HTTPS and specifying the required parameters for the data retrieval.
3. **Create the smart contract:** Once the API has been defined, the next step is to create the smart contract that will use the oracle to retrieve data. This will typically involve defining the smart contract logic and integrating the oracle code into the contract.
4. **Retrieve the data:** With the smart contract and API in place, the oracle can now retrieve data from the data source. This will typically involve sending API requests and parsing the returned data.
5. **Validate and verify the data:** Before sending the data to the smart contract, the oracle must validate and verify that the data is accurate and trustworthy. This might involve checking the data against multiple sources, applying data analysis techniques, or using other validation methods.
6. **Send the data to the smart contract:** Once the data has been validated and verified, the oracle can send the data to the smart contract. The smart contract can then use the data to execute its logic and automatically enforce the terms of the agreement or transaction.
**Example of a Solidity SC for retreiving data from a Notion doc? Not sure if accurate; generated by chatgpt**
```
// Importing the necessary libraries and contracts
pragma solidity ^0.8.0;
import "https://github.com/ethereum-diamond/ethereum-diamond/blob/main/contracts/ImmutableOwnable.sol";
import "https://github.com/notion-dao/notion-contracts/blob/main/contracts/NotionData.sol";
// Defining the smart contract and inheriting from the ImmutableOwnable contract
contract NotionOracle is ImmutableOwnable {
// Defining the NotionData contract and initializing the contract owner
NotionData notionData;
constructor(address _owner, address _notionData) ImmutableOwnable(_owner) {
notionData = NotionData(_notionData);
}
// Retrieving data from a Notion document using the Notion API
function getDataFromNotion() public view returns (string memory) {
// Specify the Notion database ID and query parameters
string memory databaseId = "NOTION_DATABASE_ID";
string[] memory properties = new string[](1);
properties[0] = "title";
uint pageSize = 1;
// Call the NotionData contract to retrieve data from the Notion API
(string memory response, uint256 timestamp) = notionData.getDatabaseEntries(databaseId, properties, pageSize);
// Parse the response and return the data
// In this example, we assume that the data is a string and return it directly
return response;
}
}
```
Extra info:
In this example, the contract imports the ImmutableOwnable contract from the Ethereum Diamond library and the NotionData contract from the Notion DAO library. The NotionData contract provides a wrapper around the Notion API, which allows us to retrieve data from a Notion document.
The NotionOracle contract inherits from the ImmutableOwnable contract, which defines the contract owner and restricts certain functions to be callable only by the owner.
The NotionOracle contract is initialized with the address of the NotionData contract, which is used to retrieve data from the Notion document.
The getDataFromNotion() function retrieves data from the Notion document using the getDatabaseEntries() function from the NotionData contract. In this example, we assume that the data is a string and return it directly, but you can modify this function to parse the data and return it in a format that's appropriate for your use case.
**Simple Chat GPT Generated Oracle Smart Contract for AAVE Snapshot details**
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ISnapshot {
function getVotes(address account, uint256 blockNumber) external view returns (uint256);
}
contract AaveOracle {
ISnapshot public snapshot;
address public aaveAddress = 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9; // Aave token address
uint256 public blockNumber;
constructor(address snapshotAddress) {
snapshot = ISnapshot(snapshotAddress);
}
function update() external {
blockNumber = block.number;
}
function getPrice() external view returns (uint256) {
uint256 votes = snapshot.getVotes(aaveAddress, blockNumber);
return votes / 1000; // assuming 1 AAVE = 1000 votes
}
}
```
**Simple Chat GPT Generated Oracle Smart Contract for AAVE Notion Page Text**
```
pragma solidity ^0.8.0;
import "https://github.com/ethereum/solidity/blob/v0.8.0/libs/multiaddr/contracts/Multiaddr.sol";
contract AaveGrantsOracle {
using Multiaddr for Multiaddr.Address;
string public websiteUrl;
string public extractedText;
constructor(string memory _websiteUrl) {
websiteUrl = _websiteUrl;
}
function requestData() public {
bytes memory html = websiteUrl.toMultiaddr().getContent();
// Parse the HTML content to extract the desired text
// Store the extracted text in the extractedText variable
}
}
```
Notes:
1. The contract would first define the Aave Grants website as its data source.
2. The contract would use an HTTP request to retrieve the HTML content of the website.
3. The contract would then use an HTML parser to extract the desired text content from the website.
4. The extracted text content could be stored in a variable within the smart contract or used to trigger other actions within the contract.
**ChatGPT Generated Example of an INK! SC with deployment details**
```
#![cfg_attr(not(feature = "std"), no_std)]
use ink_core::{
storage,
env::{
self,
DefaultSrmlTypes,
},
memory::format,
};
use ink_lang::contract;
use ink_prelude::string::String;
#[cfg(feature = "ink-as-dependency")]
#[macro_use]
extern crate ink_lang as ink;
contract! {
#![env = ink_env::DefaultSrmlTypes]
/// A simple oracle smart contract that retrieves data from the Aave Snapshot proposal.
struct AaveOracle {
/// The URL of the Aave Snapshot proposal.
url: storage::Value<String>,
}
impl AaveOracle {
/// Creates a new AaveOracle contract with the specified URL.
pub fn new(url: String) -> Self {
Self {
url: storage::Value::new(url),
}
}
/// Retrieves data from the Aave Snapshot proposal and returns it as a string.
pub fn get_data(&self) -> String {
let url = self.url.get();
let response = env::http_get(&url)
.expect("could not retrieve data from Aave Snapshot proposal");
// Parse the JSON response and return the relevant data as a string.
let json: serde_json::Value = serde_json::from_str(&response)
.expect("could not parse JSON response from Aave Snapshot proposal");
let result = json["proposal"]["metadata"]["body"]
.as_str()
.expect("could not retrieve relevant data from JSON response from Aave Snapshot proposal");
format!("{:?}", result)
}
}
}
```
This contract has a single url storage value, which represents the URL of the Aave Snapshot proposal. The new constructor initializes this value with the specified URL.
The get_data function retrieves data from the Aave Snapshot proposal using the env::http_get function. It then parses the JSON response and returns the relevant data as a string.
Note that this contract assumes that the Aave Snapshot proposal returns a JSON response in the following format:
```
{
"proposal": {
"metadata": {
"body": "<relevant data>"
}
}
}
```
You will need to modify the get_data function if the Aave Snapshot proposal returns a different JSON format.
To deploy and interact with this contract, you can use the Ink! CLI tool. First, compile the contract using the following command:
`cargo +nightly contract deploy --no-default-features --features=std <account-id> --value=1000000000000000000`
Then, deploy the contract to your local development chain using the following command:
```
cargo +nightly contract deploy --no-default-features --features=std <account-id> --value=1000000000000000000
```
Replace <account-id> with the account ID that you want to deploy the contract from. The --value option specifies the amount of value to transfer to the contract upon deployment.
You can then call the get_data function on the deployed contract using the following command:
`cargo +nightly contract call <contract-address> get_data
`
Replace <contract-address> with the address of the deployed contract. The get_data function will retrieve data from the Aave Snapshot proposal and return it as a string.
**CHAT GPT Generated FAT Smart contract using aavegrants.com as a data source**
```
use ink_lang::contract;
#[derive(Default, Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(
feature = "std",
derive(
serde::Serialize,
serde::Deserialize,
ink_storage::traits::SpreadLayout,
ink_storage::traits::PackedLayout
)
)]
pub struct AaveGrantsData {
pub total_grants: u64,
pub total_value: u64,
pub funded_grants: Vec<(String, u64)>,
}
#[contract]
mod aave_grants_contract {
use super::*;
use ink_storage::collections::HashMap;
#[ink(storage)]
pub struct AaveGrantsContract {
data: HashMap<String, AaveGrantsData>,
}
impl AaveGrantsContract {
#[ink(constructor)]
pub fn new() -> Self {
Self {
data: HashMap::new(),
}
}
#[ink(message)]
pub async fn get_total_grants(&self) -> u64 {
let data = self.get_data().await;
data.total_grants
}
#[ink(message)]
pub async fn get_total_value(&self) -> u64 {
let data = self.get_data().await;
data.total_value
}
#[ink(message)]
pub async fn get_funded_grants(&self) -> Vec<(String, u64)> {
let data = self.get_data().await;
data.funded_grants.clone()
}
async fn get_data(&self) -> AaveGrantsData {
let mut data = self
.data
.get(&String::from("aave_grants"))
.cloned()
.unwrap_or_default();
let url = "https://aavegrants.org/api/grants";
let resp = reqwest::get(url).await.unwrap();
let json = resp.json::<serde_json::Value>().await.unwrap();
data.total_grants = json["total_grants"].as_u64().unwrap_or(0);
data.total_value = json["total_value"].as_u64().unwrap_or(0);
data.funded_grants = json["funded_grants"]
.as_array()
.unwrap_or(&vec![])
.iter()
.map(|x| {
let name = x["name"].as_str().unwrap_or("").to_string();
let value = x["value"].as_u64().unwrap_or(0);
(name, value)
})
.collect();
self.data.insert(String::from("aave_grants"), data.clone());
data
}
}
}
```
In this contract, the AaveGrantsData struct represents the data that will be retrieved from the Aave Grants website. The AaveGrantsContract struct is the main contract that uses a HashMap to store the retrieved data.
The contract provides three public functions to retrieve data from the contract. The get_total_grants function returns the total number of grants, get_total_value returns the total value of grants, and get_funded_grants returns a list of tuples representing the name and value of funded grants.
The get_data function is a private function that retrieves the data from the Aave Grants website using the reqwest crate, updates the AaveGrantsData struct, and inserts it into the contract's HashMap.
### Oracle Types
* Software oracles retrieve data from web APIs and other software sources.
* Hardware oracles retrieve data from physical devices like sensors and IoT devices.
* Centralized oracles are managed by a single entity, while decentralized oracles use a network of nodes to verify data.
* Hybrid oracles combine elements of both centralized and decentralized oracles.
---
### Drawbacks and potential exploit areas
**Data source manipulation:** One of the most significant security threats to smart contract oracles is data source manipulation. Malicious actors may attempt to manipulate the data source to provide false or misleading data, which can lead to unintended outcomes in the smart contract.
**Denial-of-service attacks:** Smart contract oracles are vulnerable to denial-of-service attacks, in which an attacker floods the oracle with requests, making it impossible for legitimate requests to be processed. This can lead to delays in smart contract execution or even prevent the contract from executing altogether.
---
### Available Oracles
**Chainlink:** Chainlink is one of the most popular and widely used Web3 oracles. It provides a decentralized oracle network that aggregates data from multiple sources, including APIs, websites, and IoT devices, to provide high-quality data for smart contracts. Chainlink is also highly customizable, allowing developers to specify the data sources and security parameters for their smart contracts.
**Band Protocol:** Band Protocol is another decentralized oracle network that provides real-time data to smart contracts. It uses a delegated proof-of-stake (DPoS) consensus mechanism to ensure the accuracy of its data, and supports a wide range of data types, including cryptocurrency prices, weather data, and sports scores.
**Tellor:** Tellor is a decentralized oracle network that uses a unique Proof-of-Work (PoW) consensus mechanism to provide high-quality data to smart contracts. It is designed to be highly scalable, and can support a wide range of data types and sources.
**Augur:** Augur is a decentralized prediction market platform that uses a decentralized oracle system to resolve bets. Its oracles are designed to be highly resistant to manipulation, and use a unique consensus mechanism to ensure the accuracy of their predictions.
**Oraclize:** Oraclize is a centralized oracle service that provides real-time data to smart contracts. It supports a wide range of data types, including cryptocurrency prices, weather data, and stock prices. Oraclize is also highly customizable, allowing developers to specify the data sources and security parameters for their smart contracts.
---
### Why Phat Smart Contracts
*From [Phala Workshop](https://github.com/Phala-Network/phat-offchain-rollup/tree/sub0-workshop/phat)*
Existing oracles don't scale. For instance, ChainLink is the most commonly used oracle. It supports only 12 EVM blockchains, and they struggle to add long-tail support. On the other hand, existing oracles often serve very limited data sources and functions (price feed and VRF). Though there are rich data available on the internet, none of the oracle is flexible enough to process this data and make it useful to blockchain apps.
The key to scale oracle is the ability to make its logic programmable. Thinking about building a customized oracle as easy as writing smart contracts, it would be easy to support all the long-tail blockchain and use cases.
Is it possible to build a scalable oracle efficiently at all? It turns out possible, but we need an off-chain execution environment with:
- Internet access: it enables access to all the data available around the world
- Easy integration: can easily integrate to long-tail blockchains
- Off-chain security: running off-chain, but still as secure as on-chain apps
Phat Contract is designed to meet all these requirements! As the decentralized offchain computation network for Web3, Phala allows you to deploy the customized program to access the internet and report data to any blockchain reliably.
One of the key features of Phala Network is the Trusted Compute Framework (TCF), which enables secure off-chain computation while preserving data privacy. The TCF makes use of Intel SGX (Software Guard Extensions), which provides a secure enclave for executing computations off-chain.
In the context of the oracle problem, Phala Network's TCF can be used to provide secure and trustless data feeds to smart contracts. By using SGX to run the oracle, data can be securely retrieved and transmitted to the smart contract without the risk of tampering or malicious activity from the oracle. The SGX ensures the confidentiality and integrity of the data, which is critical for ensuring the accuracy of smart contracts that rely on external data sources.