FDC by hand
In this guide, we will demonstrate how FDC workflow can be performed almost entirely without the use of any script. The purpose of this guide is to familiarize the reader with the FDC workflow and introduce them to tooling surrounding FDC. This is not how the FDC is intended to be used. Nonetheless, the tools described in this guide may prove useful when debugging the actual code.
Request data
In this guide, we will check whether the string rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe
is a valid XRPL testnet address.
This is an example of the AddressValidity
attestation request.
We chose it for demonstration purposes because it requires a single input parameter, but the same process would work for any of the FDC attestation types.
Preparing the request
The FDC accepts requests as byte strings, encoded in a special way.
These can be produced manually, but an easier way to do it is through a verifier server.
A verifier server checks the validity of input data and returns an abiEncodedRequest
that can be passed on to the FDC.
In this guide, we will use the Flare-hosted verifier server. Its interactive documentation is available at the address.
The interface requires authentication;
the key 00000000-0000-0000-0000-000000000000
can be used.
To authenticate, click Authorize
in the top right corner, and input the above key.






Once authenticated, scroll down to the AddressValidity section, and expand the /verifier/xrp/AddressValidity/prepareRequest
item.
Click on the Try it out
button in the upper right corner of the expanded card,
and a Request body
field will appear.




Replace the addressStr
field value with the above address rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe
, and ensure that the form matches:
{
"attestationType": "0x4164647265737356616c69646974790000000000000000000000000000000000",
"sourceId": "0x7465737458525000000000000000000000000000000000000000000000000000",
"requestBody": {
"addressStr": "r3wvdzNDkNJ3e5ut1RJfWtBxDHT9sddQRQ"
}
}


Then click Execute
.
The abiEncodedRequest
will appear under the Response body
section below, along with the request status which should be VALID
.


{
"status": "VALID",
"abiEncodedRequest": "0x4164647265737356616c696469747900000000000000000000000000000000007465737458525000000000000000000000000000000000000000000000000000cf6de269807c522f39f90e9a84ec13993f58d5473fe918acbe6197efb5a17c2e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002272337776647a4e446b4e4a336535757431524a665774427844485439736464515251000000000000000000000000000000000000000000000000000000000000"
}
There are two additional values within the request body that we have not yet properly explained.
They are the UTF8 hex-encoded strings of AddressValidity
and testXRP
respectively, zero-padded to 32 bytes.
These will be different for each attestation type and source.
The full list of values is available below.
Interactive documentation for all attestation types, and the corresponding
values for the attestationType
and sourceId
fields.
attestationType
and sourceId
fields.Input the appropriate value into the encoder bellow.
To Hex Converter
Encoded string:
Submitting the request
We submit the attestation request to the FDC through the FdcHub
contract.
It is one of the official Flare contracts, and it is deployed on each of the Flare chains.
We will submit the attestation request to the FdcHub
contract on Coston2.
Either Flare Explorer or Flarescan can be used.
First, we must navigate to the Contract
tab on the chosen explorer, and then to Write contract
(Flare Explorer, Flarescan).
We can then open the requestAttestation
function widget.
Here we input the abiEncodedRequest
value that we received from the verifier server, as well as the fee that needs to be paid to the contract.


The request fee can be queried from the FdcRequestFeeConfigurations
contract, through its getRequestFee
function (Flare Explorer, Flarescan).
The input parameter for this function is the abiEncodedRequest
from the verifier server.


To execute the requestAttestation
call, we need to connect the wallet.
We input the abiEncodedRequest
value, and the amount returned by the getRequestFee
function.
After the transaction has been executed successfully, we need to open it up in the explorer. We should remember its block number for later.
Links to FdcHub
and FdcRequestFeeConfigurations
contracts on all Flare chains.
Waiting for the voting round to finalize
Before we can retrieve the proof and data, we must wait for the voting round in which the request was made to be finalized. To check whether the round has been finalized, we need to know the block in which the attestation request transaction was made; or more precisely, we need the timestamp of that block.
We can calculate the voting round ID from the transaction timestamp using the following formula.
Here, the transactionTimestamp
represents the timestamp of the transaction in which we submitted the attestation request.
The other two values are:
The following form calculates the round ID for you.
Voting Round ID Calculator
Round ID:
Once we know the voting round ID, we can go to the Finalizations
tab of the Coston2 Systems Explorer.
When the round has been finalized, its ID will appear on the list.
Preparing the proof request
Once the round has been finalized, we can prepare the proof request using the Flare Data Availability Client interactive documentation.
As in the previous step, we first need to authenticate using the same API key, 00000000-0000-0000-0000-000000000000
.
We can then expand the /api/v1/fdc/proof-by-request-round
widget, and click Try it out
.




We input the voting round ID of our request under the votingRoundId
field, and the abiEncodedRequest
under the requestBytes
field.
Then we click on the Execute
button.
The proof response will appear under the Response body
section.


{
"response": {
"attestationType": "0x4164647265737356616c69646974790000000000000000000000000000000000",
"sourceId": "0x7465737458525000000000000000000000000000000000000000000000000000",
"votingRound": 1028678,
"lowestUsedTimestamp": 18446744073709552000,
"requestBody": {
"addressStr": "r3wvdzNDkNJ3e5ut1RJfWtBxDHT9sddQRQ"
},
"responseBody": {
"isValid": true,
"standardAddress": "r3wvdzNDkNJ3e5ut1RJfWtBxDHT9sddQRQ",
"standardAddressHash": "0x1e2adcb99103f6396903f33db1526fa66aedfbfee4405def0ef69e0fcd949f47"
}
},
"proof": [
"0x5422093333fabcdd137138efa611efcbb932e65184b12415d2f74d511c1f27b9",
"0x28b15d5e07d2249c7acd8b6deae1706e01be84231264bc66d99553970dbf3bde",
"0x486452aac82578f8b2b9a88df400e80a33d9945111d503f2b205d4209279f225",
"0xc7188d9db7d522ba2b9a84d7aec34745e6acde1a5118372b53aa072d1ad61894"
]
}
The Data Availability Client informs us that the address is, indeed, a valid XRPL address.
But the above response is not entirely correct;
the timestamp is off by 385
.
This is a JavaScript rounding error.
To get the right response, we need to use the curl
command in a terminal.
The curl
command is displayed as the first part of the Responses
section.
In this case, it is:
curl -X 'POST' \
'https://ctn2-data-availability.flare.network/api/v1/fdc/proof-by-request-round' \
-H 'accept: application/json' \
-H 'x-api-key: 00000000-0000-0000-0000-000000000000' \
-H 'Content-Type: application/json' \
-H 'X-CSRFTOKEN: rYJ04UxDuekdzYgChGXRIfQI904VD8qK2UtiBwZ1uMLlkAEwPgNrxvCLsNS5PdYX' \
-d '{
"votingRoundId": 1028678,
"requestBytes": "0x4164647265737356616c696469747900000000000000000000000000000000007465737458525000000000000000000000000000000000000000000000000000cf6de269807c522f39f90e9a84ec13993f58d5473fe918acbe6197efb5a17c2e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002272337776647a4e446b4e4a336535757431524a665774427844485439736464515251000000000000000000000000000000000000000000000000000000000000"
}'
The output of the curl
command is then:
{
"response": {
"attestationType": "0x4164647265737356616c69646974790000000000000000000000000000000000",
"sourceId": "0x7465737458525000000000000000000000000000000000000000000000000000",
"votingRound": 1028678,
"lowestUsedTimestamp": 18446744073709551615,
"requestBody": {
"addressStr": "r3wvdzNDkNJ3e5ut1RJfWtBxDHT9sddQRQ"
},
"responseBody": {
"isValid": true,
"standardAddress": "r3wvdzNDkNJ3e5ut1RJfWtBxDHT9sddQRQ",
"standardAddressHash": "0x1e2adcb99103f6396903f33db1526fa66aedfbfee4405def0ef69e0fcd949f47"
}
},
"proof": [
"0x5422093333fabcdd137138efa611efcbb932e65184b12415d2f74d511c1f27b9",
"0x28b15d5e07d2249c7acd8b6deae1706e01be84231264bc66d99553970dbf3bde",
"0x486452aac82578f8b2b9a88df400e80a33d9945111d503f2b205d4209279f225",
"0xc7188d9db7d522ba2b9a84d7aec34745e6acde1a5118372b53aa072d1ad61894"
]
}
Verifying the data
The last thing remaining is to verify the proof returned by the Data Availability Client.
We do so through the FdcVerification
contract (Flare Explorer Flarescan).


We input the above Response body
data as parameters to the verifyAddressValidity
function of the FdcVerification
contract.
When we Read
the function, we get back true
, which means that the proof is valid.
Details
Links to FdcVerification
contract on all Flare chains.
-
Coston - Flare
Explorer
FdcVerification
contract on all Flare chains.- Coston2 - Flare Explorer
- Songbird - Flare Explorer
- Flare - Flare Explorer