Documentation

Signed report verification

A DataLink report is signed by the DataLink oracle network. You can check those signatures on-chain through the VerifierProxy contract before trusting the values — either from your own smart contract or manually.

This guide covers:

  1. fetching the signed report with your Marketplace API key;
  2. preparing the payload;
  3. calling verify(bytes payload, bytes parameterPayload);
  4. reading the result: the return value, the transaction receipt and the ReportVerified event.

Contracts

XDC Mainnet (chain ID 50)
VerifierProxy — call this one0xCf49c434f2206Df1D507dE9f5DA70cA8c3dA61d2 (VerifierProxy 2.0.0)
Verifier — checks the signatures0x181175142a98c8922310e304d9b591d5cbca37b4 (Verifier 1.2.0)

Always call the VerifierProxy. It reads the report's configuration digest and forwards the report to the Verifier configured for it, so your integration keeps working if the Verifier is ever replaced. The Verifier Proxy address for your feed is also shown on its Feed Access & Integration page in the Consumer portal.

1. Fetch the signed report

Call the Marketplace API with an API key for an active subscription to the feed (create keys in the Consumer portal). Keep the key on your server — never in browser or mobile code.

Bash

curl "$MARKETPLACE_URL/api/v1/reports/latest?feedID=0x00018cd7a1e01e764604c0e299f74a0ff4179d81e92111389e6585ba6318cbd1" \
  -H "Authorization: Bearer YOUR_API_KEY"

JSON

{
  "createdAt": 1794516848,
  "feedId": "00018cd7a1e01e764604c0e299f74a0ff4179d81e92111389e6585ba6318cbd1",
  "payload": "00065652d1d0bb609d5723654d7388b9b6823c85e269367d4ae558cc4073624e…"
}
  • payload is the complete signed report, hex-encoded (736 bytes for the current report format).
  • feedId and payload are returned without a 0x prefix.
  • createdAt is API metadata (when the report was stored). It is not part of the signed data — see Report schema.

2. Prepare the payload: add 0x

Solidity bytes arguments are passed as 0x-prefixed hex. Add the prefix before sending the payload anywhere on-chain:

JavaScript

const res = await fetch(`${process.env.MARKETPLACE_URL}/api/v1/reports/latest?feedID=${feedId}`, {
  headers: { Authorization: `Bearer ${process.env.DATALINK_API_KEY}` },
});
if (!res.ok) throw new Error(`DataLink request failed: ${res.status}`);
const report = await res.json();
const payload = report.payload.startsWith("0x") ? report.payload : `0x${report.payload}`;

Pass the payload exactly as received. Changing, trimming or re-encoding any byte makes verification fail.

3. Call verify

Solidity

interface IVerifierProxy {
    function verify(bytes calldata payload, bytes calldata parameterPayload)
        external
        payable
        returns (bytes memory verifierResponse);
}
ArgumentValue
payloadThe signed report from step 2 (0x…)
parameterPayload0x (empty) — see below

On success, verify returns the report's report data: the nine encoded fields described in Report schema. If the signatures don't match the report, the call reverts and nothing is returned — see Troubleshooting.

When parameterPayload can be 0x

parameterPayload carries fee information for a FeeManager. On XDC Mainnet the VerifierProxy has no FeeManager configured, so verification is free and parameterPayload is ignored: pass 0x (or "" in Solidity).

Access control

The VerifierProxy can restrict who may call verify through an access controller. On XDC Mainnet no access controller is configured: any wallet or contract can verify reports. A restricted caller would get AccessForbidden.

Check a report without a transaction

verify isn't a view function, but your backend can simulate it with an eth_call — free, and nothing is sent:

JavaScript

import { createPublicClient, http, parseAbi } from "viem";

const client = createPublicClient({ transport: http(process.env.XDC_RPC_URL) });
const { result: reportData } = await client.simulateContract({
  address: "0xCf49c434f2206Df1D507dE9f5DA70cA8c3dA61d2",
  abi: parseAbi(["function verify(bytes payload, bytes parameterPayload) payable returns (bytes)"]),
  functionName: "verify",
  args: [payload, "0x"],
});
// reportData: the verified report data (288 bytes) — decode it as shown in Report schema.

A simulation proves the report is validly signed right now; only an on-chain transaction (or your own contract) leaves a record of the verification.

4. Verify manually

With Remix

  1. Open Remix and create IVerifierProxy.sol with the interface above (plus // SPDX-License-Identifier: MIT and pragma solidity ^0.8.24;).
  2. Compile it.
  3. In Deploy & run transactions, set Environment to Injected Provider and connect a wallet on XDC Mainnet (chain ID 50) with a little XDC for gas.
  4. Select IVerifierProxy, paste 0xCf49c434f2206Df1D507dE9f5DA70cA8c3dA61d2 into At Address, and click it.
  5. Expand verify, enter the 0x-prefixed payload and 0x for parameterPayload, then transact and confirm in your wallet.

With a block explorer

If the VerifierProxy's source code is verified on the explorer, its Write Contract tab offers the same verify call. If it isn't, use Remix (it only needs the interface above).

5. Read the receipt

A successful verification transaction:

  • has status success;
  • contains a ReportVerified event, emitted by the Verifier (not the proxy):

Solidity

event ReportVerified(bytes32 indexed feedId, address requester);
FieldMeaning
feedId (indexed — the event's second topic)The feed the verified report belongs to
requesterThe address that called the VerifierProxy: your wallet, or your contract when called from a contract

Example: a verified transaction

Transaction 0xfb203d3d636309a4ae255fba3e95dac440bc4ee527b521c05dd5c9a7aa4339e7 on XDC Mainnet:

Block109,335,393
ToVerifierProxy 0xCf49c434f2206Df1D507dE9f5DA70cA8c3dA61d2
Functionverify(bytes,bytes) — 736-byte payload, parameterPayload = 0x
StatusSuccess, 88,258 gas used
EventReportVerified from the Verifier 0x1811…37b4, feedId = 0x00018cd7…cbd1

Signed or decoded?

The Marketplace also offers GET /api/v1/reports/decoded with the same report's values as JSON. It's convenient for dashboards and backends, but decoded JSON is not cryptographically verifiable on its own. Use the signed report wherever the values must be trusted.