diff --git a/docs/building-on-lisk/use-oracle-data.md b/docs/building-on-lisk/using-oracle-data/redstone-pull.md similarity index 90% rename from docs/building-on-lisk/use-oracle-data.md rename to docs/building-on-lisk/using-oracle-data/redstone-pull.md index f682e1e88..e7bc1b63f 100644 --- a/docs/building-on-lisk/use-oracle-data.md +++ b/docs/building-on-lisk/using-oracle-data/redstone-pull.md @@ -1,6 +1,6 @@ --- -title: Accessing real-world data with Oracles -slug: /building-on-lisk/use-oracle-data +title: ...with Redstone (Pull) +slug: /building-on-lisk/use-oracle-data/redstone-pull description: A guide on using Redstone Data Feeds to access real-world data such as asset prices, directly from your smart contracts on the Lisk testnet. keywords: [ Oracle @@ -22,7 +22,7 @@ keywords: [ # Accessing real-world data using the Redstone Oracle -This page will explain how you can access real world / off-chain data using Oracles such as Redstone. +This page will explain how you can access oracle data using Redstone. RedStone is a data ecosystem that delivers frequently updated, reliable, and diverse data for your dApp and smart contracts deployed on Lisk. @@ -32,7 +32,7 @@ To create a smart contract that directly fetches the latest data from the Redsto This guide uses the [Redstone Pull model](https://docs.redstone.finance/docs/get-started/models/redstone-pull) to fetch the data. -For an overview of the different modules that Redstone offers to receive oracle data, go to [Oracles > Redstone](../lisk-tools/oracles#redstone). +For an overview of the different modules that Redstone offers to receive oracle data, go to [Oracles > Redstone](../../lisk-tools/oracles#redstone). [Hardhat](https://hardhat.org/) is used in this guide to create the smart contract. In case you want to use Foundry, check out the [Redstone docs](https://docs.redstone.finance/docs/get-started/models/redstone-pull#foundry) for instructions. @@ -158,5 +158,5 @@ Latest ETH price: To deploy the smart contract on Lisk Sepolia or Lisk Mainnet, follow the guides -- [Deploying a smart contract with Hardhat](deploying-smart-contract/with-Hardhat.md), or -- [Deploying a smart contract with Foundry](deploying-smart-contract/with-Foundry.md) \ No newline at end of file +- [Deploying a smart contract with Hardhat](../deploying-smart-contract/with-Hardhat.md), or +- [Deploying a smart contract with Foundry](../deploying-smart-contract/with-Foundry.md) \ No newline at end of file diff --git a/docs/building-on-lisk/using-oracle-data/tellor.md b/docs/building-on-lisk/using-oracle-data/tellor.md new file mode 100644 index 000000000..2fd8ff4dd --- /dev/null +++ b/docs/building-on-lisk/using-oracle-data/tellor.md @@ -0,0 +1,205 @@ +--- +title: ...with Tellor +slug: /building-on-lisk/use-oracle-data/tellor +description: A guide on using Redstone Data Feeds to access real-world data such as asset prices, directly from your smart contracts on the Lisk testnet. +keywords: [ + Oracle + Oracles, + Redstone, + price feeds, + data feeds, + smart contract, + Lisk blockchain, + Lisk network, + Lisk testnet, + Lisk test network, + app development, + dapp development, + build a dapp on Lisk, + build on Lisk, + ] +--- + +# Using oracle data with Tellor +[Tellor](https://tellor.io/) is an immutable decentralized oracle protocol where parties can request the value of an offchain data point (e.g. ETH/USD, LSK/USD) and reporters compete to add this value to an onchain databank. +The inputs to this data-bank are secured by a network of staked reporters. + +Tellor utilizes crypto-economic incentive mechanisms, rewarding honest data submissions by reporters and punishing bad actors through the issuance of Tellor’s token, Tributes (TRB) and a dispute mechanism. + +This incentivizes an open, permissionless network of data reporting and data validation, ensuring that data can be provided by anyone and checked by everyone. + +## Installation +The first thing you'll want to do is install the basic tools necessary for using Tellor as your oracle. + +To install [usingtellor](https://github.com/tellor-io/usingtellor), run one the following commands: + +- Hardhat: `npm install usingtellor` +- Foundry: `forge install tellor-io/usingtellor` + +Once installed, this will allow your contracts to inherit the functions from the 'UsingTellor' contract. + +Great! Now that you've got the tools ready, let's go through a simple exercise where we retrieve the `eth/usd` and `lsk/usd` prices from Tellor. + +## Import + +```solidity +pragma solidity >=0.8.0; + +import "usingtellor/contracts/UsingTellor.sol"; +/** + * Network: Lisk Mainnet + * Address: 0x896419Ed2E0dC848a1f7d2814F4e5Df4b9B9bFcc +*/ +contract MyContract is UsingTellor { + + constructor(address payable _tellorOracle) UsingTellor(_tellorOracle) { + + } + + // ... + +} +``` + +To import the UsingTellor contract into your Solidity file, pass the desired Tellor Oracle address as a parameter. +For the Lisk Mainnet, the Tellor Oracle address is: [0x896419Ed2E0dC848a1f7d2814F4e5Df4b9B9bFcc](https://blockscout.lisk.com/address/0x896419Ed2E0dC848a1f7d2814F4e5Df4b9B9bFcc) + +## Reading data + +In the example below, we add two functions: + +- `getETHSpotPrice()` that reads the ETH/USD price feed and another function +- `getLSKSpotPrice()` that reads the LSK/USD price feed from the Oracle + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import { UsingTellor } from "usingtellor/contracts/UsingTellor.sol"; + +contract MyContract is UsingTellor { + + uint256 public ethLastStoredTimestamp; + uint256 public ethLastStoredPrice; + uint256 public lskLastStoredTimestamp; + uint256 public lskLastStoredPrice; + bytes32 public immutable ethQueryId; + bytes32 public immutable lskQueryId; + uint256 public constant DISPUTE_BUFFER = 20 minutes; + uint256 public constant STALENESS_AGE = 12 hours; + + error StalePrice(uint256 price, uint256 timestamp); + error NoValueRetrieved(uint256 timestamp); + + /** + * @dev the constructor sets the Tellor address and the ETH and LSK queryIds + * @param _tellorOracle is the address of the Tellor oracle + */ + constructor (address payable _tellorOracle) UsingTellor(_tellorOracle) { + // set the ETH queryId + bytes memory _ethQueryData = abi.encode("SpotPrice", abi.encode("eth", "usd")); + ethQueryId = keccak256(_ethQueryData); + // set the LSK queryId + bytes memory _lskQueryData = abi.encode("SpotPrice", abi.encode("lsk", "usd")); + lskQueryId = keccak256(_lskQueryData); + } + + /** + * @dev Allows a user contract to read the ETH price from Tellor and perform some + * best practice checks on the retrieved data + * @return _value the ETH spot price from Tellor, with 18 decimal places + * @return timestamp the value's timestamp + */ + function getETHSpotPrice() + public + returns ( + uint256 _value, + uint256 timestamp + ) + { + // retrieve the most recent 20+ minute old ETH price. + // the buffer allows time for a bad value to be disputed + (bytes memory _data, uint256 _timestamp) = getDataBefore(ethQueryId, block.timestamp - DISPUTE_BUFFER); + + // check whether any value was retrieved + if (_timestamp == 0 || _data.length == 0) revert NoValueRetrieved(_timestamp); + + // decode the value from bytes to uint256 + _value = abi.decode(_data, (uint256)); + + // prevent a back-in-time dispute attack by caching the most recent value and timestamp. + // this stops an attacker from disputing tellor values to manupulate which price is used + // by your protocol + if (_timestamp > ethLastStoredTimestamp) { + // if the new value is newer than the last stored value, update the cache + ethLastStoredTimestamp = _timestamp; + ethLastStoredPrice = _value; + } else { + // if the new value is older than the last stored value, use the cached value + _value = ethLastStoredPrice; + _timestamp = ethLastStoredTimestamp; + } + + // check whether value is too old + if (block.timestamp - _timestamp > STALENESS_AGE) revert StalePrice(_value, _timestamp); + + // return the value and timestamp + return (_value, _timestamp); + } + + /** + * @dev Allows a user contract to read the LSK price from Tellor and perform some + * best practice checks on the retrieved data + * @return _value the LSK spot price from Tellor, with 18 decimal places + * @return timestamp the value's timestamp + */ + function getLSKSpotPrice() + public + returns ( + uint256 _value, + uint256 timestamp + ) + { + (bytes memory _data, uint256 _timestamp) = getDataBefore(lskQueryId, block.timestamp - DISPUTE_BUFFER); + + if (_timestamp == 0 || _data.length == 0) revert NoValueRetrieved(_timestamp); + + _value = abi.decode(_data, (uint256)); + + if (_timestamp > lskLastStoredTimestamp) { + lskLastStoredTimestamp = _timestamp; + lskLastStoredPrice = _value; + } else { + _value = lskLastStoredPrice; + _timestamp = lskLastStoredTimestamp; + } + + if (block.timestamp - _timestamp > STALENESS_AGE) revert StalePrice(_value, _timestamp); + + return (_value, _timestamp); + } +} +``` + +You can adapt this contract to your needs. +The example utilizes some best practices[^1] for using Tellor by implementing a dispute time buffer and a data staleness check. +In addition, it also seeks to mitigate back-in-time dispute attacks by caching the most recent value and timestamp. + +[^1]: Based on examples in [Tellor's best practices repository](https://github.com/tellor-io/best-practices-user/tree/main) + +:::tip +For a general overview of best practices using Tellor, go to the [User checklists](https://docs.tellor.io/tellor/getting-data/user-checklists) in the Tellor docs. +::: + +## Deploying on Lisk + +To deploy the smart contract on Lisk Sepolia or Lisk Mainnet, follow the guides + +- [Deploying a smart contract with Hardhat](../deploying-smart-contract/with-Hardhat.md), or +- [Deploying a smart contract with Foundry](../deploying-smart-contract/with-Foundry.md) + +## Further resources + +- For a more robust implementation of the Tellor oracle, check out the full list of available functions [here](https://github.com/tellor-io/usingtellor/blob/master/README.md). +- Have a specific Data Feed Request? [Fill out this form](https://github.com/tellor-io/dataSpecs/issues/new?assignees=&labels=&template=new_query_type.yaml&title=%5BNew+Data+Request+Form%5D%3A+). +- Still have question? Reach out to the Tellor team on Discord [here](https://discord.gg/tellor). \ No newline at end of file diff --git a/docs/lisk-tools/oracles.md b/docs/lisk-tools/oracles.md index 8b90c0de7..a0739e9c0 100644 --- a/docs/lisk-tools/oracles.md +++ b/docs/lisk-tools/oracles.md @@ -11,6 +11,7 @@ keywords: Lisk Testnet, Lisk network, Redstone, + Tellor, price feeds, data feeds, ] @@ -39,4 +40,27 @@ Interested in integration? [Get in contact](https://discord.com/invite/PVxBZKFr4 #### Supported Networks - Lisk -- Lisk Sepolia \ No newline at end of file +- Lisk Sepolia + +### Guides + +- [Accessing oracle data with Redstone (Pull)](../building-on-lisk/using-oracle-data/redstone-pull.md) + +## Tellor + +Tellor is an immutable decentralized oracle protocol where parties can request the value of an off-chain data point (e.g. ETH/USD) and reporters compete to add this value to an on-chain data-bank. +The inputs to this data-bank are secured by a network of staked reporters. + +Tellor utilizes crypto-economic incentive mechanisms, rewarding honest data submissions by reporters and punishing bad actors through the issuance of Tellor’s token, Tributes (TRB) and a dispute mechanism. + +This incentivizes an open, permissionless network of data reporting and data validation, ensuring that data can be provided by anyone and checked by everyone. + +[A list of all the Tellor contracts deployed on Lisk is available on their documentation](https://docs.tellor.io/tellor/the-basics/contracts-reference#lisk) + +#### Supported Networks + +- Lisk +- Lisk Sepolia + +### Guides +- [Accessing oracle data with Tellor](../building-on-lisk/using-oracle-data/tellor.md) \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index b24fbe1ed..4398106c5 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -101,11 +101,10 @@ const config = { items: [ /*{ TODO: Uncomment when all localozed pages are translated - */ - { + /* { type: 'localeDropdown', position: 'right', - }, + }, */ { type: 'doc', position: 'left', diff --git a/sidebars.js b/sidebars.js index d0c56742d..c8084612f 100644 --- a/sidebars.js +++ b/sidebars.js @@ -108,7 +108,16 @@ const sidebars = { keywords: ['guides','smart contracts','token development','token standards','erc-20','erc-721','erc-1155'], }, }, - 'building-on-lisk/use-oracle-data', + { + type: 'category', + label: 'Using oracle data', + collapsible: true, + collapsed: true, + items: [ + 'building-on-lisk/using-oracle-data/redstone-pull', + 'building-on-lisk/using-oracle-data/tellor', + ], + } ], link: { type: 'generated-index',