Skip to main content

Introducing Tellor’s EVMCall

Contract Calldata Across EVM Chains

Discover the power of Tellor’s EVMCall for cross-chain calldata retrieval, and experience enhanced security, efficiency, and transparency when relaying on-chain data across EVM chains.

TLDR: EVMCall enables Tellor users on chain X to receive data from smart contracts on chain Y and have them written to chain X. This is a powerful query type that allows Tellor reporters to become automated cross-chain information relays for token balances, NFT ownership information, or any other contract call data.

EVMCall: Permissionless Contract Calldata Relay For EVM Chains

Tellor’s EVMCall enables users to incentivize a permissionless network of reporters to read the calldata from contracts on one EVM chain and write them to another. Simply specify what contract you want to call, what chain it is on, and the call data you want returned to your chain.

EVMCall Parameters

chainId (uint256)

contractAddress (address)

calldata (bytes)

Bridging the Gap in Cross-Chain Data Retrieval

Currently, many decentralized applications (dApps) and DAOs rely on traditional bridges or multi-sig wallets to transfer data between EVM chains.  Bridges are focused on token transfers, and the security and decentralization of these is still an open research problem.  However, when it comes to decentralized cross-chain relaying of contract calldata there hasn’t been any great options.  Tellor’s EVMCall addresses this product gap by providing a trustless, decentralized solution for one-way data retrieval between EVM chains. Have a contract that needs to know something about what is going on on another chain?  With EVMCall, Tellor users can now create tips to Tellor reporters who will relay that data.

Potential Use-Cases

Cross-Chain Admin Management: Tokenholders vote for a multi-chain protocol’s admin on chain X. The admin controls fee settings and fee distribution. Deployed across multiple chains, the protocol reads the admin address updates from Tellor using EVMCall, avoiding voting on each chain.

Cross-chain DAO voting: Facilitate voting for DAO members operating on multiple chains by using EVMCall to verify the voting weight of each member based on their token holdings on chain Y. 

Cross-chain NFT ownership verification: Verify the ownership of NFTs on chain Y from chain X, allowing users to showcase their NFT collections or verify ownership for decentralized marketplaces operating on multiple chains. 

Cross-chain loan collateral validation: Decentralized lending platforms on chain X can use EVMCall to validate collateral locked on chain Y, expanding their lending services across multiple chains while maintaining security. 

Cross-chain insurance: Access risk and coverage data from insurance protocols on chain X, enabling users on chain Y to purchase coverage and hedge against potential risks.

*Bridging Tokens Across EVM Chains: Users lock tokens on chain X to move them to chain Y. Tellor reporters on chain Y track locked tokens and relay the data. A smart contract on chain Y mints synthetic tokens for the user. When users return tokens to chain X, they burn synthetic tokens on chain Y, and Tellor reporters on chain X observe and relay the information. A smart contract on chain X unlocks the original tokens for the user.

*Additionally, with more considerations and requirements, EVMCall has potential to serve as a general two-way bridge between chains.

Seamless Integration and Trustless Execution

As a Tellor Query Type EVMCall integrates seamlessly with Tellor’s existing infrastructure, allowing for easy adoption. The trustless execution of cross-chain calldata relaying is enabled through incentives and game theory:

  • Users are incentivized to submit correct data for execution.
  • Users are also incentivized to dispute any errors in the submitted data.

In the case of a dispute, the transaction is not executed, and the correct data must be resubmitted. Meanwhile, Tellor token holders review the dispute and reward the correct party using the other party’s bond.

Getting Started with EVMCall

Here is an example for a contract on Polygon that aims  to read a user’s DAI balance on Ethereum mainnet. To allow your contract to read Tellor data, you can install the `usingtellor` library:

Reading Data

To get started, you need to install the usingtellor package:

npm install usingtellor

After installation, you can import the UsingTellor contract into your contract. Pass the Tellor contract address through your constructor to the UsingTellor constructor, which will grant your contract access to the Tellor oracle getter functions.

To read the DAI balance of a specific user, you must generate the corresponding queryId or unique data identifier, according to the EVMCall data specification. You will need three inputs:

  1. Ethereum mainnet chainId: 1
  2. DAI contract address on Ethereum mainnet: 0x6B175474E89094C44Da98b954EedeAC495271d0F
  3. balanceOf function calldata with user address:

bytes memory _calldata = abi.encodeWithSignature("balanceOf(address)", userAddress);

Create your queryData using these inputs, and then compute the keccak256 hash of the queryData to obtain the queryId. You can now use the getDataBefore function from UsingTellor to retrieve your data from Tellor.

Here’s an example of setting up your contract to read data from Tellor:

import "usingtellor/contracts/UsingTellor.sol";

contract EVMCallExample is UsingTellor {
    uint256 public ethChainId = 1;
    address public daiEthMainnet = 0x6B175474E89094C44Da98b954EedeAC495271d0F;

    constructor(address payable _tellor) UsingTellor(_tellor) {}
    function getQueryId(address _user) 
        returns(bytes32 _queryId) 
        bytes memory _calldata = abi.encodeWithSignature("balanceOf(address)", _user);
        bytes memory _queryDataArgs = abi.encode(ethChainId, daiEthMainnet, _calldata);
	    bytes memory _queryData = abi.encode("EVMCall", _queryDataArgs);
        _queryId = keccak256(_queryData);

    function getUserBalance(address _user) public view returns(uint256 _userBalance) {
        bytes32 _queryId = getQueryId(_user);
        (bytes memory _value, uint256 _timestampRetrieved) = getDataBefore(_queryId, block.timestamp - 12 hours);
        require(_timestampRetrieved > 0, "No value retrieved");
        (bytes memory _encodedResponse, uint256 _callTimestamp) = abi.decode(_value, (bytes, uint256));
        require(_callTimestamp > block.timestamp - 24 hours, "Call response too old");
        _userBalance = abi.decode(_encodedResponse, (uint256));
Requesting Data

In order to request data from Tellor, you need two elements:

  1. Communicate what data is being requested (queryData and a queryId)
  2. Provide an incentive for someone to submit your data on-chain (a tip)

Tellor’s Autopay contract allows users to incentivize reporters to submit their data. To request data, you can use the tip function:

function tip(bytes32 _queryId, uint256 _amount, bytes calldata _queryData) external;

These tips can be submitted via off-chain scripts, or through your contract.

A Bright Future for Decentralized Cross-Chain Communication

Tellor’s EVMCall has the potential to revolutionize the way DAOs and dApps utilize data between EVM chains. We encourage you to explore the possibilities that Tellor’s EVMCall has to offer. To learn more or get started, please visit our documentation , reach out to us on our Discord channel, or email us at [email protected]  for support.