Links

Oracles

Learn how to use oracle smart contracts to access and use external data sources.
There is a critical need to feed accurate token prices to smart contracts when building DeFi apps on FVM. As an example, consider an options market where trades are triggered upon a smart contract receiving information about the price of a given token crossing a certain threshold.
One Oracle solution that allows a developer to pull token prices into a smart contract on Filecoin is the ChainLink Price Feeds. This Cookbook pulls code from the ChainLink Blog by Harry Papacharissiou.
Ingredients
Instructions
  1. 1.
    Assuming you are on an FVM testnet, obtain testnet tFIL from a faucet.
  2. 2.
    Import the relevant ChainLink functionality.
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
AggregatorV3Interface internal priceFeed;
  1. 3.
    Instantiate a variable for the price feed contract you want to pull prices from.
priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
  1. 4.
    Write a function that pulls the price from the priceFeed address using latestRoundData().
function getLatestPrice() public view returns (int) {
(
uint80 roundID,
int price,
uint startedAt,
uint timeStamp,
uint80 answeredInRound
) = priceFeed.latestRoundData();
return price;
}
  1. 5.
    Deploy the contract and write tests that determine whether or not your function is pulling the prices correctly from Oracle.

Tellor's Oracle Contract

Tellor is an optimistic oracle. Builders should not accept instant price quotes and should wait a few minutes before locking in details.
Tellor supports a price feed oracle and a data oracle for the Filecoin network. The data oracle can provide Filecoin-specific data, such as the reputation of storage providers, which helps lending protocols determine interest rates for SPs.
Ingredients
Instructions
Below is a sample code showing how Tellor can be used to pull data into a smart contract. This is an insurance contract, where "users can deposit tokens to request coverage for the chance that a Filecoin deal becomes inactive, sending the IPFS pin offline. If the Filecoin deal becomes inactive, users can reclaim their tokens as a claim."
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "hardhat/console.sol";
import "usingtellor/contracts/UsingTellor.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract FilecoinInsurance is UsingTellor, ERC20 {
string queryType;
mapping(bytes32 => mapping(address => uint256)) public claims;
constructor(address payable _tellorAddress) UsingTellor(_tellorAddress) ERC20("FilecoinInsurance", "FCI") {
queryType = "FilecoinDealStatus";
}
function requestClaim(string memory _proposalCID) external {
bytes memory queryData = abi.encode(queryType, abi.encode(_proposalCID));
bytes32 queryId = keccak256(queryData);
(bool success, bytes memory rawStatus, uint256 timestamp) = getDataBefore(queryId, block.timestamp - 3 hours);
require(success, "request to Tellor unsuccessful");
bool status = abi.decode(rawStatus, (bool));
uint256 claimAmount = claims[keccak256(abi.encode(_proposalCID))][msg.sender];
if (status == false) {
claims[keccak256(abi.encode(_proposalCID))][msg.sender] = 0;
}
transferFrom(address(this), msg.sender, claimAmount);
}
function requestCoverage(string memory _proposalCID, uint256 _amount) external {
bytes memory queryData = abi.encode(queryType, abi.encode(_proposalCID));
bytes32 queryId = keccak256(queryData);
(bool success, bytes memory rawStatus, uint256 timestamp) = getDataBefore(queryId, block.timestamp - 3 hours);
require(success, "request to Tellor unsuccessful");
bool status = abi.decode(rawStatus, (bool));
require(status, "Filecoin deal is non-active!");
//set claim
claims[keccak256(abi.encode(_proposalCID))][msg.sender] = _amount;
//approve
approve(msg.sender, _amount);
//transfer from
transferFrom(msg.sender, address(this), _amount);
}
}