/sampleUsingTellor

An example repo for the usingTellor package

Primary LanguageJavaScript

tellor.io

Twitter WeAreTellor

Sample project UsingTellor

The Tellor oracle is a decentralized oracle. It provides an option for contracts to interact securely with and obtain data from off-chain.

This repository aims to provide an updated version of sample code that uses Tellor by using Ethers.js, Waffle,and Hardhat.

For more in-depth information about Tellor, check out our documentation.

Quick references are included below:

Implement Tellor into your project

This repo already includes the usingTellor package.

How to use

1. Clone project and install dependencies

git clone git@github.com:tellor-io/sampleUsingTellor.git

foundry:

cd foundry
forge install

hardhat:

cd hardhat
npm i

2. How to Use

Just inherit the UsingTellor contract, passing the Tellor address as a constructor argument:

Here's an example:

contract PriceContract is UsingTellor {

  uint256 public btcPrice;

  //This Contract now has access to all functions in UsingTellor

  constructor(address payable _tellorAddress) UsingTellor(_tellorAddress) {}

  function setBtcPrice() public {

    bytes memory _b = abi.encode("SpotPrice",abi.encode("btc","usd"));
    bytes32 _queryId = keccak256(_b);

    uint256 _timestamp;
    bytes memory _value;

    (_value, _timestamp) = _getDataBefore(_queryId, block.timestamp - 15 minutes);

    require(_timestamp > 0, "No data exists");
    require(block.timestamp - _timestamp < 24 hours, "Data is too old");

    btcPrice = abi.decode(_value,(uint256));
  }
}

3. The sample contract SampleUsingTellor has access to the following Tellor functions:

/**
 * @dev Retrieves the next value for the queryId after the specified timestamp
 * @param _queryId is the queryId to look up the value for
 * @param _timestamp after which to search for next value
 * @return _value the value retrieved
 * @return _timestampRetrieved the value's timestamp
 */
function _getDataAfter(bytes32 _queryId, uint256 _timestamp)
    internal
    view
    returns (bytes memory _value, uint256 _timestampRetrieved);

/**
 * @dev Retrieves the latest value for the queryId before the specified timestamp
 * @param _queryId is the queryId to look up the value for
 * @param _timestamp before which to search for latest value
 * @return _value the value retrieved
 * @return _timestampRetrieved the value's timestamp
 */
function _getDataBefore(bytes32 _queryId, uint256 _timestamp)
    internal
    view
    returns (bytes memory _value, uint256 _timestampRetrieved);

/**
 * @dev Retrieves next array index of data after the specified timestamp for the queryId
 * @param _queryId is the queryId to look up the index for
 * @param _timestamp is the timestamp after which to search for the next index
 * @return _found whether the index was found
 * @return _index the next index found after the specified timestamp
 */
function _getIndexForDataAfter(bytes32 _queryId, uint256 _timestamp)
    internal
    view
    returns (bool _found, uint256 _index);

/**
 * @dev Retrieves latest array index of data before the specified timestamp for the queryId
 * @param _queryId is the queryId to look up the index for
 * @param _timestamp is the timestamp before which to search for the latest index
 * @return _found whether the index was found
 * @return _index the latest index found before the specified timestamp
 */
function _getIndexForDataBefore(bytes32 _queryId, uint256 _timestamp)
    internal
    view
    returns (bool _found, uint256 _index);

/**
 * @dev Retrieves multiple uint256 values before the specified timestamp
 * @param _queryId the unique id of the data query
 * @param _timestamp the timestamp before which to search for values
 * @param _maxAge the maximum number of seconds before the _timestamp to search for values
 * @param _maxCount the maximum number of values to return
 * @return _values the values retrieved, ordered from oldest to newest
 * @return _timestamps the timestamps of the values retrieved
 */
function _getMultipleValuesBefore(
  bytes32 _queryId,
  uint256 _timestamp,
  uint256 _maxAge,
  uint256 _maxCount
)
  internal
  view
  returns (bytes[] memory _values, uint256[] memory _timestamps);

/**
 * @dev Counts the number of values that have been submitted for the queryId
 * @param _queryId the id to look up
 * @return uint256 count of the number of values received for the queryId
 */
function _getNewValueCountbyQueryId(bytes32 _queryId)
  internal
  view
  returns (uint256);

/**
 * @dev Returns the address of the reporter who submitted a value for a data ID at a specific time
 * @param _queryId is ID of the specific data feed
 * @param _timestamp is the timestamp to find a corresponding reporter for
 * @return address of the reporter who reported the value for the data ID at the given timestamp
 */
function _getReporterByTimestamp(bytes32 _queryId, uint256 _timestamp)
  internal
  view
  returns (address);

/**
 * @dev Gets the timestamp for the value based on their index
 * @param _queryId is the id to look up
 * @param _index is the value index to look up
 * @return uint256 timestamp
 */
function _getTimestampbyQueryIdandIndex(bytes32 _queryId, uint256 _index)
  internal
  view
  returns (uint256);

/**
 * @dev Determines whether a value with a given queryId and timestamp has been disputed
 * @param _queryId is the value id to look up
 * @param _timestamp is the timestamp of the value to look up
 * @return bool true if queryId/timestamp is under dispute
 */
function _isInDispute(bytes32 _queryId, uint256 _timestamp)
  internal
  view
  returns (bool);

/**
 * @dev Retrieve value from oracle based on queryId/timestamp
 * @param _queryId being requested
 * @param _timestamp to retrieve data/value from
 * @return bytes value for query/timestamp submitted
 */
function _retrieveData(bytes32 _queryId, uint256 _timestamp)
  internal
  view
  returns (bytes memory);

Tellor Playground:

For ease of use, the UsingTellor repo comes with a version of the Tellor Playground contract for easier integration. The most useful Playground functions for testing are as follows:

/**
 * @dev A mock function to submit a value to be read without staking needed
 * @param _queryId The tellorId to associate the value to
 * @param _value the value for the queryId
 * @param _nonce the current value count for the query id (just use 0)
 * @param _queryData the data used by reporters to fulfill the data query
 */
function submitValue(bytes32 _queryId, bytes calldata _value, uint256 _nonce, bytes memory _queryData) external;

/**
 * @dev A mock function to create a dispute
 * @param _queryId The tellorId to be disputed
 * @param _timestamp the timestamp of the value to be disputed
 */
function beginDispute(bytes32 _queryId, uint256 _timestamp) external;

5. To run tests:

Hardhat:

npx hardhat test

Foundry

forge test

6. Deployment:

Hardhat:

First create a .env file corresponding to the .env.example file

Next update your hardhat.config with the correct network/gas settings.

Then, in ignition/modules/SampleUsingTellor.js, change the tellor address to correspond to the correct address corresponding to your deployment network https://docs.tellor.io/tellor/the-basics/contracts-reference

Next run:

npx hardhat ignition deploy ignition/modules/SampleUsingTellor.js --network <my_network>

Foundry:

Find a node URL, fund a wallet, and get a tellor address to corresponding to your deployment network https://docs.tellor.io/tellor/the-basics/contracts-reference. Then run:

forge create --rpc-url <your_rpc_url> \
    --constructor-args "0x123_myTellorAddress" \
    --private-key <your_private_key> \
    src/SampleUsingTellor.sol:SampleUSingTellor

Maintainers

@themandalore
@brendaloya

How to Contribute

Join our Discord:

Check out our issues log here on Github or contribute to our future plans to build a better miner and more examples of data secured by Tellor.

Contributors

This repository is maintained by the Tellor team - www.tellor.io

Copyright

Tellor Inc. 2024