Verify Report Data Onchain (EVM)

In this guide, you'll learn how to verify onchain the integrity of reports by confirming their authenticity as signed by the Decentralized Oracle Network (DON). You'll use a verifier contract to verify the data onchain and pay the verification fee in LINK tokens.

Before you begin

Make sure you understand how to fetch reports via the REST API or WebSocket connection. Refer to the following guides for more information:

Requirements

Tutorial

Deploy the verifier contract

Deploy a ClientReportsVerifier contract on Arbitrum Sepolia. This contract is enabled to verify reports and pay the verification fee in LINK tokens.

  1. Open the ClientReportsVerifier.sol contract in Remix.

  2. Select the ClientReportsVerifier.sol contract in the Solidity Compiler tab.

  3. Compile the contract.

  4. Open MetaMask and set the network to Arbitrum Sepolia. If you need to add Arbitrum Sepolia to your wallet, you can find the chain ID and the LINK token contract address on the LINK Token Contracts page.

  5. On the Deploy & Run Transactions tab in Remix, select Injected Provider - MetaMask in the Environment list. Remix will use the MetaMask wallet to communicate with Arbitrum Sepolia.

  6. In the Contract section, select the ClientReportsVerifier contract and fill in the Arbitrum Sepolia verifier proxy address: 0x2ff010DEbC1297f19579B4246cad07bd24F2488A. You can find the verifier proxy addresses on the Verifier Proxy Addresses page.

  7. Click the Deploy button to deploy the contract. MetaMask prompts you to confirm the transaction. Check the transaction details to ensure you deploy the contract to Arbitrum Sepolia.

  8. After you confirm the transaction, the contract address appears under the Deployed Contracts list in Remix. Save this contract address for the next step.

Fund the verifier contract

In this example, the client contract pays for onchain verification of reports in LINK tokens when fees are required. The contract automatically detects whether the target network requires fees:

  • Networks with FeeManager deployed: Verification requires token payments. These networks include: Arbitrum, Avalanche, Base, Blast, Bob, Ink, Linea, OP, Scroll, Soneium, and ZKSync.

  • Networks without FeeManager: No funding is needed since you can verify reports without fees. The contract skips the fee calculation and approval steps.

For this tutorial on Arbitrum Sepolia, fees are required, so you need to fund the contract with LINK tokens. Open MetaMask and send 1 testnet LINK on Arbitrum Sepolia to the verifier contract address you saved earlier.

Verify a report onchain

  1. In Remix, on the Deploy & Run Transactions tab, expand your verifier contract under the Deployed Contracts section.

  2. Fill in the verifyReport function input parameter with the report payload you want to verify. You can use the following full report payload obtained in the Fetch and decode report via a REST API guide (EUR/USD feed) as an example:

    0x00090d9e8d96765a0c49e03a6ae05c82e8f8de70cf179baa632f18313e54bd69000000000000000000000000000000000000000000000000000000000041438a000000000000000000000000000000000000000000000000000000030000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000004b9905d8337c34e00f8dbe31619428bac5c3937e73e6af75c71780f1770ce00000000000000000000000000000000000000000000000000000000683f13dd00000000000000000000000000000000000000000000000000000000683f13dd00000000000000000000000000000000000000000000000000006e0e3915bcc3000000000000000000000000000000000000000000000000004edc1454fb6ef0000000000000000000000000000000000000000000000000000000006866a0dd0000000000000000000000000000000000000000000000000fcaa20569eac064000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000027b160a6824ccce49dc0bd19f636c40de2f3033410c7d1a7400b9a3cb0073d19dde0f87cfd6d9ce03156464a49cacb07136d2e7d717efcf42bc2795fd5c513e4a00000000000000000000000000000000000000000000000000000000000000025e075a9d8a6223ce2b9e524a7b5a563c2924a67b544e6676a751f5374b2a42ee37684b560eb72546f87b7287cefc668705461b7f4ebe4dabd7babe397cc98b89
    
  3. Click the verifyReport button to call the function. MetaMask prompts you to accept the transaction.

  4. Click the lastDecodedPrice getter function to view the decoded price from the verified report. The answer on the EUR/USD stream uses 18 decimal places, so an answer of 1137900000000000100 indicates an EUR/USD price of 1.1379000000000001. Note: Each feed may use a different number of decimal places for answers.

Examine the code

The example code you deployed has all the interfaces and functions required to verify DataLink reports onchain.

undefined

Initializing the contract

When deploying the contract, you define the verifier proxy address for the feed you want to read from. You can find this address on the Verifier Proxy Addresses page. The verifier proxy address provides functions that are required for this example:

  • The s_feeManager function to estimate the verification fees.
  • The verify function to verify the report onchain.

Verifying a report

The verifyReport function is the core function that handles onchain report verification. Here's how it works:

  • Report data extraction:

    • The function decodes the unverifiedReport to extract the report data.
    • It then extracts the report version by reading the first two bytes of the report data, which correspond to the schema version encoded in the feed ID.
    • If the report version is unsupported, the function reverts with an InvalidReportVersion error.
  • Fee calculation and handling:

    • The function first checks if a FeeManager contract exists by querying s_feeManager() on the verifier proxy.
    • If a FeeManager exists (non-zero address):
      • It calculates the fees required for verification using the getFeeAndReward function.
      • It approves the RewardManager contract to spend the calculated amount of LINK tokens from the contract's balance.
      • It encodes the fee token address into the parameterPayload for the verification call.
      • FeeManager contracts are currently deployed on: Arbitrum, Avalanche, Base, Blast, Bob, Ink, Linea, OP, Scroll, Soneium, and ZKSync.
    • If no FeeManager exists (zero address):
      • The function skips the fee calculation and approval steps entirely.
      • It passes an empty parameterPayload to the verification call.
    • This automatic detection makes the contract compatible with any network, regardless of whether fee management is deployed.
  • Report verification:

    • The verify function of the verifier proxy is called to perform the actual verification.
    • It passes the unverifiedReport and the parameterPayload (which contains either the encoded fee token address or empty bytes) as parameters.
  • Data decoding:

    • Depending on the report version, the function decodes the verified report data into the appropriate struct (ReportV3 or ReportV4).
    • It emits a DecodedPrice event with the price extracted from the verified report.
    • The lastDecodedPrice state variable is updated with the new price.

Additional functionality

The contract also includes:

  • Owner-only token withdrawal: The withdrawToken function allows the contract owner to withdraw any ERC-20 tokens (including LINK) from the contract.
  • Enhanced error handling: The contract includes specific error types (InvalidReportVersion, NotOwner, NothingToWithdraw) for better debugging and user experience.
  • Cross-chain compatibility: The automatic FeeManager detection makes the same contract code work on any supported network, whether fees are required or not.

Get the latest Chainlink content straight to your inbox.