# IBalanceDecreasingTransaction

> Detect a transaction that decreases an address balance.

> 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/IBalanceDecreasingTransaction

An interface to detect transactions that decrease the balance of a specific address or are signed by that address on external blockchains.

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

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

The IBalanceDecreasingTransaction interface allows smart contracts to identify and verify transactions on external blockchains that either:

1.  Decrease the balance of a specific address, or
2.  Are signed by the address in question (even if the balance increases)

This attestation type is particularly useful for detecting when a party has violated an agreement by moving funds that were promised to be locked, providing grounds for liquidating collateral locked in a smart contract on Flare.

## 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)")

-   **sourceAddressIndicator**: Index of the transaction input in hex padded to a 0x-prefixed 32-byte string
-   **sourceAddress**: Address of the indicated transaction input
-   **spentAmount**: Sum of values of all inputs with sourceAddress minus sum of all outputs with sourceAddress (can be negative)
-   **blockTimestamp**: Mediantime of the block

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

-   **sourceAddressIndicator**: Standard address hash of the address to monitor
-   **sourceAddress**: Address whose standard hash matches the sourceAddressIndicator
-   **spentAmount**: Difference between the balance after and before the transaction (can be negative)
-   **blockTimestamp**: 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 IBalanceDecreasingTransaction * @custom:id 0x02 * @custom:supported BTC, DOGE, XRP * @author Flare * @notice A detection of a transaction that either decreases the balance for some address or is * signed by the source address. * Such an attestation could prove a violation of an agreement and therefore provides grounds to liquidate * some funds locked by a smart contract on Flare. * * A transaction is considered "balance decreasing" for the address, if the balance after the * transaction is lower than before or the address is among the signers of the transaction * (even if its balance is greater than before the transaction). * @custom:verification The transaction with `transactionId` is fetched from the API of the * source 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, the attestation request is rejected. * * Once the transaction is received, the response fields are extracted if the transaction is balance * decreasing for the indicated address. * Some of the request and response fields are chain specific as described below. * The fields can be computed with the help of a balance decreasing summary. * * ### UTXO (Bitcoin and Dogecoin) * * - `sourceAddressIndicator` is the the index of the transaction input in hex padded to a 0x prefixed 32-byte string. * If the indicated input does not exist or the indicated input does not have the address, * the attestation request is rejected. * The `sourceAddress` is the address of the indicated transaction input. * - `spentAmount` is the sum of values of all inputs with sourceAddress minus the sum of * all outputs with `sourceAddress`. * Can be negative. * - `blockTimestamp` is the mediantime of a block. * * ### XRPL * * - `sourceAddressIndicator` is the standard address hash of the address whose balance has been decreased. * If the address indicated by `sourceAddressIndicator` is not among the signers of the transaction and the balance * of the address was not lowered in the transaction, the attestation request is rejected. * * - `spentAmount` is the difference between the balance of the indicated address after and before the transaction. * Can be negative. * - `blockTimestamp` is the close_time of a ledger converted to unix time. * * @custom:lut `blockTimestamp` * @custom:lutlimit `0x127500`, `0x127500`, `0x127500` */interface IBalanceDecreasingTransaction {    /**     * @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 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.     * This is a security measure to prevent a collision of attestation hashes.     * @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 IBalanceDecreasingTransaction attestation type     * @param transactionId ID of the payment transaction.     * @param sourceAddressIndicator The indicator of the address whose balance has been decreased.     */    struct RequestBody {        bytes32 transactionId;        bytes32 sourceAddressIndicator;    }    /**     * @notice Response body for IBalanceDecreasingTransaction attestation type.     * @param blockNumber The 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 address indicated by the `sourceAddressIndicator`.     * @param spentAmount Amount spent by the source address in minimal units.     * @param standardPaymentReference Standard payment reference of the transaction.     */    struct ResponseBody {        uint64 blockNumber;        uint64 blockTimestamp;        bytes32 sourceAddressHash;        int256 spentAmount;        bytes32 standardPaymentReference;    }}
```

## 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 (0x02 for BalanceDecreasingTransaction)
-   `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 balance decreasing transactions.

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

-   `transactionId`: Unique identifier of the transaction to check
-   `sourceAddressIndicator`: Indicator of the address to monitor (interpretation varies by chain)

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

Response body containing details about the balance decreasing transaction.

#### 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 address indicated by sourceAddressIndicator
-   `spentAmount`: Amount spent by the source address (can be negative)
-   `standardPaymentReference`: Standard payment reference of the transaction

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

-   Attestation ID: `0x02`
-   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
-   A negative `spentAmount` value indicates the address received more funds than it sent
-   The transaction is still considered "balance decreasing" if the address signed the transaction, even if the balance increased

## Practical Applications[​](#practical-applications "Direct link to Practical Applications")

-   **Cross-chain Collateral Monitoring**: Detect when funds that should be locked on one chain are moved, triggering liquidation of collateral on Flare
-   **Agreement Enforcement**: Verify if parties adhere to contractual agreements involving locking funds
-   **Fraud Detection**: Monitor specific addresses for suspicious outgoing transactions
-   **Conditional Smart Contracts**: Trigger contract actions based on external chain activity

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

LockMonitor.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 {IBalanceDecreasingTransaction} from "@flarenetwork/flare-periphery-contracts/coston2/IBalanceDecreasingTransaction.sol";contract LockMonitor {    // Business logic: stores which addresses are being monitored    mapping(bytes32 => bool) public lockedAddresses;    // Business logic: prevents re-processing the same violation proof    mapping(bytes32 => bool) public confirmedViolations;    event ViolationConfirmed(        bytes32 indexed transactionId,        bytes32 indexed sourceAddressHash    );    function registerLockedAddress(bytes32 sourceAddressHash) external {        lockedAddresses[sourceAddressHash] = true;    }    function processViolationProof(        IBalanceDecreasingTransaction.Proof calldata _proof    ) external {        // 1. FDC Logic: Verify the proof's authenticity with the Flare network.        require(isProofValid(_proof), "Invalid transaction proof");        // 2. Business Logic: Execute actions based on the verified proof data.        bytes32 sourceAddressHash = _proof.data.responseBody.sourceAddressHash;        int256 spentAmount = _proof.data.responseBody.spentAmount;        bytes32 transactionId = _proof.data.requestBody.transactionId;        // Check if a monitored address spent funds (a violation).        if (lockedAddresses[sourceAddressHash] && spentAmount > 0) {            require(                !confirmedViolations[transactionId],                "Violation already confirmed"            );            // Take action: log the violation and update state.            confirmedViolations[transactionId] = true;            lockedAddresses[sourceAddressHash] = false; // Example: remove from monitoring after violation.            emit ViolationConfirmed(transactionId, sourceAddressHash);        }    }    function isProofValid(        IBalanceDecreasingTransaction.Proof memory _proof    ) public view returns (bool) {        IFdcVerification fdcVerification = ContractRegistry            .getFdcVerification();        return fdcVerification.verifyBalanceDecreasingTransaction(_proof);    }}
```

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