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:
- Fetch and decode reports (API) using the Go or Rust SDK
- Stream and decode reports (WebSocket) using the Go or Rust SDK
Requirements
- This guide requires testnet ETH and LINK on Arbitrum Sepolia. Both are available at faucets.chain.link.
- Learn how to Fund your contract with LINK.
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.
-
Open the ClientReportsVerifier.sol contract in Remix.
-
Select the
ClientReportsVerifier.solcontract in the Solidity Compiler tab. -
Compile the contract.
-
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.
-
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.
-
In the Contract section, select the
ClientReportsVerifiercontract and fill in the Arbitrum Sepolia verifier proxy address:0x2ff010DEbC1297f19579B4246cad07bd24F2488A. You can find the verifier proxy addresses on the Verifier Proxy Addresses page. -
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.
-
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
FeeManagerdeployed: 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
-
In Remix, on the Deploy & Run Transactions tab, expand your verifier contract under the Deployed Contracts section.
-
Fill in the
verifyReportfunction 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 -
Click the
verifyReportbutton to call the function. MetaMask prompts you to accept the transaction. -
Click the
lastDecodedPricegetter function to view the decoded price from the verified report. The answer on the EUR/USD stream uses 18 decimal places, so an answer of1137900000000000100indicates 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_feeManagerfunction to estimate the verification fees. - The
verifyfunction 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
unverifiedReportto 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.
- The function decodes the
-
Fee calculation and handling:
- The function first checks if a
FeeManagercontract exists by queryings_feeManager()on the verifier proxy. - If a
FeeManagerexists (non-zero address):- It calculates the fees required for verification using the
getFeeAndRewardfunction. - It approves the
RewardManagercontract to spend the calculated amount of LINK tokens from the contract's balance. - It encodes the fee token address into the
parameterPayloadfor the verification call. FeeManagercontracts are currently deployed on: Arbitrum, Avalanche, Base, Blast, Bob, Ink, Linea, OP, Scroll, Soneium, and ZKSync.
- It calculates the fees required for verification using the
- If no
FeeManagerexists (zero address):- The function skips the fee calculation and approval steps entirely.
- It passes an empty
parameterPayloadto the verification call.
- This automatic detection makes the contract compatible with any network, regardless of whether fee management is deployed.
- The function first checks if a
-
Report verification:
- The
verifyfunction of the verifier proxy is called to perform the actual verification. - It passes the
unverifiedReportand theparameterPayload(which contains either the encoded fee token address or empty bytes) as parameters.
- The
-
Data decoding:
- Depending on the report version, the function decodes the verified report data into the appropriate struct (
ReportV3orReportV4). - It emits a
DecodedPriceevent with the price extracted from the verified report. - The
lastDecodedPricestate variable is updated with the new price.
- Depending on the report version, the function decodes the verified report data into the appropriate struct (
Additional functionality
The contract also includes:
- Owner-only token withdrawal: The
withdrawTokenfunction 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
FeeManagerdetection makes the same contract code work on any supported network, whether fees are required or not.