# IPayment

> Relay a transaction in native currency.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

Source: https://dev.flare.network/fdc/reference/IPayment

An interface to relay and verify payment transactions in native currencies across multiple external blockchains.

Sourced from `IPayment.sol` on [GitHub](https://github.com/flare-foundation/flare-smart-contracts-v2/blob/main/contracts/userInterfaces/fdc/IPayment.sol).

## Overview[​](#overview "Direct link to Overview")

The IPayment interface enables smart contracts on Flare networks to access and verify native currency payment transactions from external blockchains. It provides a standardized way to prove that payments have occurred between entities, similar to traditional banking transfers, with support for payment references. This attestation type handles the different transaction models across various blockchains, offering a unified interface for payment verification.

## Supported Chains[​](#supported-chains "Direct link to Supported Chains")

Network Type

Supported Chains

**Mainnet**

`BTC` (Bitcoin), `DOGE` (Dogecoin), `XRP` (XRP Ledger)

**Testnet**

`testBTC` (Bitcoin Testnet 4), `testDOGE`, `testXRP`

## Chain-Specific Implementation Details[​](#chain-specific-implementation-details "Direct link to Chain-Specific Implementation Details")

### UTXO Chains (Bitcoin and Dogecoin)[​](#utxo-chains-bitcoin-and-dogecoin "Direct link to UTXO Chains (Bitcoin and Dogecoin)")

-   **Transaction Model**: Uses inputs and outputs, where multiple addresses can contribute inputs and receive outputs
-   **inUtxo**: Index of the transaction input with the source address
-   **utxo**: Index of the transaction output with the receiving address
-   **blockTimestamp**: Derived from the mediantime of the block

### Account-based Chains (XRPL)[​](#account-based-chains-xrpl "Direct link to Account-based Chains (XRPL)")

-   **Transaction Model**: Direct transfers between accounts
-   **inUtxo** and **utxo**: Always set to 0 (not used)
-   **blockTimestamp**: Derived from the close\_time of the ledger converted to UNIX time

## Interface Definition[​](#interface-definition "Direct link to Interface Definition")

```
// SPDX-License-Identifier: MITpragma solidity >=0.7.6 <0.9;/** * @custom:name IPayment * @custom:id 0x01 * @custom:supported BTC, DOGE, XRP * @author Flare * @notice A relay of a transaction on an external chain that is considered a payment in a native currency. * Various blockchains support different types of native payments. For each blockchain, it is specified how a payment * transaction should be formed to be provable by this attestation type. * The provable payments emulate traditional banking payments from entity A to entity B in native currency with an * optional payment reference. * @custom:verification The transaction with `transactionId` is fetched from the API of the blockchain node or * relevant indexer. * If the transaction cannot be fetched or the transaction is in a block that does not have a sufficient * [number of confirmations](/specs/attestations/configs.md#finalityconfirmation), the attestation request is rejected. * * Once the transaction is received, the payment summary is computed according to the rules for the source chain. * If the summary is successfully calculated, the response is assembled from the summary. * `blockNumber` and `blockTimestamp` are retrieved from the block if they are not included in the transaction data. * For Bitcoin and Dogecoin, `blockTimestamp` is mediantime of the block. * For XRPL, `blockTimestamp` is close time of the ledger converted to UNIX time. * * If the summary is not successfully calculated, the attestation request is rejected. * @custom:lut `blockTimestamp` * @custom:lutlimit `0x127500`, `0x127500`, `0x127500` */interface IPayment {    /**     * @notice Toplevel request     * @param attestationType ID of the attestation type.     * @param sourceId ID of the data source.     * @param messageIntegrityCode `MessageIntegrityCode` that is derived from the expected response.     * @param requestBody Data defining the request. Type (struct) and interpretation is determined     * by the `attestationType`.     */    struct Request {        bytes32 attestationType;        bytes32 sourceId;        bytes32 messageIntegrityCode;        RequestBody requestBody;    }    /**     * @notice Toplevel response     * @param attestationType Extracted from the request.     * @param sourceId Extracted from the request.     * @param votingRound The ID of the FDC round in which the request was considered.     * @param lowestUsedTimestamp The lowest timestamp used to generate the response.     * @param requestBody Extracted from the request.     * @param responseBody Data defining the response. The verification rules for the construction     * of the response body and the type are defined per specific `attestationType`.     */    struct Response {        bytes32 attestationType;        bytes32 sourceId;        uint64 votingRound;        uint64 lowestUsedTimestamp;        RequestBody requestBody;        ResponseBody responseBody;    }    /**     * @notice Toplevel proof     * @param merkleProof Merkle proof corresponding to the attestation response.     * @param data Attestation response.     */    struct Proof {        bytes32[] merkleProof;        Response data;    }    /**     * @notice Request body for Payment attestation type     * @param transactionId ID of the payment transaction.     * @param inUtxo For UTXO chains, this is the index of the transaction input with source address.     * Always 0 for the non-utxo chains.     * @param utxo For UTXO chains, this is the index of the transaction output with receiving address.     * Always 0 for the non-utxo chains.     */    struct RequestBody {        bytes32 transactionId;        uint256 inUtxo;        uint256 utxo;    }    /**     * @notice Response body for Payment attestation type     * @param blockNumber Number of the block in which the transaction is included.     * @param blockTimestamp The timestamp of the block in which the transaction is included.     * @param sourceAddressHash Standard address hash of the source address.     * @param sourceAddressesRoot The root of the Merkle tree of the source addresses.     * @param receivingAddressHash Standard address hash of the receiving address.     * The zero 32-byte string if there is no receivingAddress (if `status` is not success).     * @param intendedReceivingAddressHash Standard address hash of the intended receiving address.     * Relevant if the transaction is unsuccessful.     * @param spentAmount Amount in minimal units spent by the source address.     * @param intendedSpentAmount Amount in minimal units to be spent by the source address.     * Relevant if the transaction status is unsuccessful.     * @param receivedAmount Amount in minimal units received by the receiving address.     * @param intendedReceivedAmount Amount in minimal units intended to be received by the receiving address.     * Relevant if the transaction is unsuccessful.     * @param standardPaymentReference Standard payment reference of the transaction.     * @param oneToOne Indicator whether only one source and one receiver are involved in the transaction.     * @param status Success status of the transaction: 0 - success, 1 - failed by sender's fault,     * 2 - failed by receiver's fault.     */    struct ResponseBody {        uint64 blockNumber;        uint64 blockTimestamp;        bytes32 sourceAddressHash;        bytes32 sourceAddressesRoot;        bytes32 receivingAddressHash;        bytes32 intendedReceivingAddressHash;        int256 spentAmount;        int256 intendedSpentAmount;        int256 receivedAmount;        int256 intendedReceivedAmount;        bytes32 standardPaymentReference;        bool oneToOne;        uint8 status;    }}
```

## Structs[​](#structs "Direct link to Structs")

### Request[​](#request "Direct link to Request")

Toplevel request structure.

#### Parameters[​](#parameters "Direct link to Parameters")

-   `attestationType`: ID of the attestation type (0x01 for Payment)
-   `sourceId`: ID of the data source (e.g., BTC, DOGE, XRP)
-   `messageIntegrityCode`: MessageIntegrityCode derived from the expected response
-   `requestBody`: Data defining the request

### Response[​](#response "Direct link to Response")

Toplevel response structure.

#### Parameters[​](#parameters-1 "Direct link to Parameters")

-   `attestationType`: Extracted from the request
-   `sourceId`: Extracted from the request
-   `votingRound`: The ID of the FDC round in which the request was considered
-   `lowestUsedTimestamp`: The lowest timestamp used to generate the response
-   `requestBody`: Extracted from the request
-   `responseBody`: Data defining the response

### Proof[​](#proof "Direct link to Proof")

Toplevel proof structure for verification.

#### Parameters[​](#parameters-2 "Direct link to Parameters")

-   `merkleProof`: Merkle proof corresponding to the attestation response
-   `data`: Attestation response

### RequestBody[​](#requestbody "Direct link to RequestBody")

Request body specific to payment verification.

#### Parameters[​](#parameters-3 "Direct link to Parameters")

-   `transactionId`: The unique identifier of the transaction to verify
-   `inUtxo`: Index of the transaction input with source address (UTXO chains only)
-   `utxo`: Index of the transaction output with receiving address (UTXO chains only)

### ResponseBody[​](#responsebody "Direct link to ResponseBody")

Response body containing payment transaction details.

#### Parameters[​](#parameters-4 "Direct link to Parameters")

-   `blockNumber`: Block number containing the transaction
-   `blockTimestamp`: Timestamp of the block containing the transaction
-   `sourceAddressHash`: Standard hash of the source address
-   `sourceAddressesRoot`: Root of the Merkle tree of all source addresses
-   `receivingAddressHash`: Standard hash of the receiving address (zero if transaction failed)
-   `intendedReceivingAddressHash`: Standard hash of the intended receiving address (for failed transactions)
-   `spentAmount`: Amount spent by the source address in minimal units
-   `intendedSpentAmount`: Amount intended to be spent (for failed transactions)
-   `receivedAmount`: Amount received by the receiving address
-   `intendedReceivedAmount`: Amount intended to be received (for failed transactions)
-   `standardPaymentReference`: Standard payment reference included in the transaction
-   `oneToOne`: True if the transaction involves only one source and one receiver
-   `status`: Transaction status (0=success, 1=sender failure, 2=receiver failure)

## Transaction Status Codes[​](#transaction-status-codes "Direct link to Transaction Status Codes")

Status Code

Description

Explanation

0

SUCCESS

Transaction completed successfully

1

SENDER\_FAILURE

Transaction failed due to issues on the sender's side

2

RECEIVER\_FAILURE

Transaction failed due to issues on the receiver's side

## Implementation Notes[​](#implementation-notes "Direct link to Implementation Notes")

-   Attestation ID: `0x01`
-   The `lowestUsedTimestamp` parameter uses the value of `blockTimestamp`
-   The `lutlimit` (Lowest Used Timestamp limit) is `0x127500` (1,209,600 seconds = 14 days) for all supported chains
-   Standard payment references can be included for cross-chain payment identification
-   For account-based chains like XRPL, `inUtxo` and `utxo` parameters should be set to 0
-   The `sourceAddressesRoot` is a Merkle tree root of all transaction input addresses, useful for multi-input transactions
-   The `oneToOne` flag helps identify simple peer-to-peer transfers versus more complex multi-party transactions

## Standard Payment Reference[​](#standard-payment-reference "Direct link to Standard Payment Reference")

A standardized payment reference follows a specific format to ensure consistency across different blockchains:

-   For UTXO chains (BTC, DOGE): Derived from OP\_RETURN outputs or specific patterns in transaction data
-   For XRPL: Derived from the MemoData field in the transaction

Payment references allow for correlation of payments across chains and facilitate payment reconciliation in cross-chain applications.

## Usage Example[​](#usage-example "Direct link to Usage Example")

PaymentVerifier.sol

```
// SPDX-License-Identifier: MITpragma solidity ^0.8.25;import {ContractRegistry} from "@flarenetwork/flare-periphery-contracts/coston2/ContractRegistry.sol";import {IFdcVerification} from "@flarenetwork/flare-periphery-contracts/coston2/IFdcVerification.sol";import {IPayment} from "@flarenetwork/flare-periphery-contracts/coston2/IPayment.sol";contract PaymentVerifier {    // A struct to store the details of a successfully verified payment.    struct VerifiedPayment {        bytes32 transactionId;        bytes32 sourceAddressHash;        bytes32 receivingAddressHash;        int256 receivedAmount;        bytes32 standardPaymentReference;    }    // A public array to keep a log of all payments verified by this contract.    VerifiedPayment[] public verifiedPayments;    // A mapping to prevent the same transaction proof from being processed more than once.    mapping(bytes32 => bool) public processedTransactions;    event PaymentVerified(        bytes32 indexed transactionId,        bytes32 indexed sourceAddressHash,        bytes32 indexed receivingAddressHash,        int256 receivedAmount,        bytes32 standardPaymentReference    );    function processPaymentProof(IPayment.Proof calldata _proof) external {        // 1. FDC Logic: Verify the proof's authenticity with the Flare network.        require(isProofValid(_proof), "Invalid payment proof");        // 2. Business Logic: Execute actions based on the verified proof data.        bytes32 transactionId = _proof.data.requestBody.transactionId;        IPayment.ResponseBody memory response = _proof.data.responseBody;        // Ensure the payment was successful (status 0) and hasn't been processed before.        require(response.status == 0, "Payment status not successful");        require(            !processedTransactions[transactionId],            "Payment already processed"        );        // Take action: update state, store the payment details, and emit an event.        processedTransactions[transactionId] = true;        verifiedPayments.push(            VerifiedPayment({                transactionId: transactionId,                sourceAddressHash: response.sourceAddressHash,                receivingAddressHash: response.receivingAddressHash,                receivedAmount: response.receivedAmount,                standardPaymentReference: response.standardPaymentReference            })        );        emit PaymentVerified(            transactionId,            response.sourceAddressHash,            response.receivingAddressHash,            response.receivedAmount,            response.standardPaymentReference        );    }    function isProofValid(        IPayment.Proof memory _proof    ) public view returns (bool) {        IFdcVerification fdcVerification = ContractRegistry            .getFdcVerification();        return fdcVerification.verifyPayment(_proof);    }}
```

[Open example in Remix](https://remix.ethereum.org/#url=https://github.com/flare-foundation/developer-hub/blob/main/examples/developer-hub-solidity/PaymentVerifier.sol&version=builtin&evmVersion=cancun&optimize=true&runs=200)
