> For the complete documentation index, see [llms.txt](https://docs.humanity.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.humanity.org/build-with-humanity/build-on-chain/canonical-contracts/ifeeescrow.md).

# IFeeEscrow

## Contract address

| Tesnet  | `0x1a247b7d7076e4c4D97D87c62947Ab5495C13423` |
| ------- | -------------------------------------------- |
| Mainnet | `0xe433f01131eAbD8060a1E34149eF0e79b2b86fEc` |

## Overview

`IFeeEscrow` enables DApps to deposit native tokens to pre-fund verification requests. The Oracle reserves funds per request before processing, settles actual fees upon completion, and supports controlled withdrawals of unused balances.

### Core Concepts

| Concept                       | Description                                                                                                                   |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **Prepaid Model**             | DApps top up a balance in FeeEscrow. Funds are reserved per verification request before the Oracle processes it.              |
| **Per-Request Reservation**   | Each verification request (identified by `requestUID`) has an associated reserved amount, preventing double-spending of fees. |
| **Settlement & Distribution** | Upon successful verification, the Oracle finalizes the request and transfers the consumed fee to the designated receiver.     |

***

## Lifecycle Flow

### **1. DEPOSIT**

DApp calls `deposit()`. Funds are added to the DApp's escrow balance.

### **2. CHECK BALANCE**

Before verification, ensure `getAvailable(dapp) >= verificationFee`.

### **3. RESERVATION**

Oracle calls `reserveForRequest(dapp, requestUID, amount)`. Funds are locked for the specific verification request.

### **4a. SETTLEMENT (on success)**

Oracle calls `settleRequest(requestUID, consumedAmount)`. Fee is deducted and transferred to the recipient.

### **4b. RELEASE (on failure/cancellation)**

Oracle calls `releaseReservationForRequest(requestUID)`. Reserved funds are unlocked back to available balance.

### **5. WITHDRAWAL**

DApp calls `requestWithdrawal(recipient, amount)`. Admin approves, then funds are transferred to the recipient.

***

## Interface

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;

interface IFeeEscrow is IFeeEscrowErrors {
    // Core Functions
    function deposit(address dapp) external payable;
    function reserveForRequest(address dapp, bytes32 requestUID, uint256 amount) external;
    function settleRequest(bytes32 requestUID, uint256 consumedAmount) external;
    function releaseReservationForRequest(bytes32 requestUID) external;

    // Balance Queries
    function checkBalance(address dapp, uint256 requiredAmount) external view returns (bool);
    function getBalance(address dapp) external view returns (uint256);
    function getReserved(address dapp) external view returns (uint256);
    function getAvailable(address dapp) external view returns (uint256);
    function hasMinimumBalance(address dapp) external view returns (bool);
    function getBalanceInfo(address dapp) external view returns (uint256 total, uint256 reservedAmount, uint256 availableAmount);
    function canAffordFee(address dapp, uint256 fee) external view returns (bool canAfford, uint256 availableBalance);

    // Withdrawals
    function withdraw(uint256 amount) external;
    function requestWithdrawal(address recipient, uint256 amount) external returns (uint256 requestId);
    function cancelWithdrawalRequest(uint256 requestId) external;

    // Admin Functions
    function updateMinimumBalance(uint256 _newMinimumBalance) external;
    function updateMaxWithdrawalLimit(uint256 _newLimit) external;
    function updateVerificationOracle(address _newOracle) external;
    function pause() external;
    function unpause() external;
    function emergencyWithdraw(address dapp) external;

    // Contract Statistics
    function getContractStats() external view returns (uint256 _totalDeposited, uint256 _totalSettled, uint256 _currentHoldings);
    function getRequestReservation(bytes32 requestUID) external view returns (address dapp, uint256 amount);

    // State Variables
    function verificationOracle() external view returns (address);
    function minimumBalance() external view returns (uint256);
    function maxWithdrawalLimit() external view returns (uint256);
    function balances(address dapp) external view returns (uint256);
    function reserved(address dapp) external view returns (uint256);
    function totalDeposited() external view returns (uint256);
    function totalFeesSettled() external view returns (uint256);
}
```

***

## Functions

### Funding

#### `deposit()`

DApp deposits native tokens to pre-fund `dapp`.

```solidity
function deposit(address dapp) external payable;
```

**Usage:**

```solidity
// DApp deposits 10 HP to their escrow balance
feeEscrow.deposit{value: 10 ether}(address(yourDApp));
```

**Emits:** `Deposited(address indexed dapp, uint256 amount, uint256 newBalance)`

***

> Note: These functions are restricted to the Verification Oracle via onlyOracle modifier.

#### `reserveForRequest(address dapp, bytes32 requestUID, uint256 amount)`

Lock funds for a specific verification request before processing.

```solidity
function reserveForRequest(address dapp, bytes32 requestUID, uint256 amount) external;
```

| Parameter    | Type      | Description                                    |
| ------------ | --------- | ---------------------------------------------- |
| `dapp`       | `address` | Address of the DApp                            |
| `requestUID` | `bytes32` | Unique identifier for the verification request |
| `amount`     | `uint256` | Amount to reserve                              |

**Reverts:**

* `InsufficientAvailableBalance` if DApp’s available balance is insufficient

**Emits:** `ReservationCreated(bytes32 indexed requestUID, address indexed dapp, uint256 amount)`

***

#### `settleRequest(bytes32 requestUID, uint256 consumedAmount)`

Deduct actual consumed fee and transfer to the designated recipient.

```solidity
function settleRequest(bytes32 requestUID, uint256 consumedAmount) external;
```

| Parameter        | Type      | Description                                    |
| ---------------- | --------- | ---------------------------------------------- |
| `requestUID`     | `bytes32` | Unique identifier for the verification request |
| `consumedAmount` | `uint256` | Actual fee amount consumed                     |

**Emits:** `ReservationSettled(bytes32 indexed requestUID, address indexed dapp, uint256 consumedAmount, uint256 reservedAmount)`

***

#### `releaseReservationForRequest(bytes32 requestUID)`

Release reserved funds if the request is cancelled or fails.

```solidity
function releaseReservationForRequest(bytes32 requestUID) external;
```

| Parameter    | Type      | Description                                    |
| ------------ | --------- | ---------------------------------------------- |
| `requestUID` | `bytes32` | Unique identifier for the verification request |

**Emits:** `ReservationReleasedForRequest(bytes32 indexed requestUID, address indexed dapp, uint256 amount)`

***

### Balance Queries

#### `getBalance(address dapp)`

Get current total balance of a DApp (reserved + available).

```solidity
function getBalance(address dapp) external view returns (uint256);
```

***

#### `getReserved(address dapp)`

Get amount currently reserved for pending verification requests.

```solidity
function getReserved(address dapp) external view returns (uint256);
```

***

#### `getAvailable(address dapp)`

Get available balance (total - reserved) that can be used for new requests or withdrawals.

```solidity
function getAvailable(address dapp) external view returns (uint256);
```

***

#### `getBalanceInfo(address dapp)`

Get comprehensive balance information in a single call.

```solidity
function getBalanceInfo(address dapp) external view returns (
    uint256 total,
    uint256 reservedAmount,
    uint256 availableAmount
);
```

***

#### `checkBalance(address dapp, uint256 requiredAmount)`

Check if DApp has sufficient available balance.

```solidity
function checkBalance(address dapp, uint256 requiredAmount) external view returns (bool);
```

***

#### `canAffordFee(address dapp, uint256 fee)`

Check if a DApp can afford a specific verification fee.

```solidity
function canAffordFee(address dapp, uint256 fee) external view returns (
    bool canAfford,
    uint256 availableBalance
);
```

***

### Withdrawals

#### `requestWithdrawal(address recipient, uint256 amount)`

DApp initiates withdrawal from available funds (not reserved).

```solidity
function requestWithdrawal(address recipient, uint256 amount) external returns (uint256 requestId);
```

| Parameter   | Type      | Description                                   |
| ----------- | --------- | --------------------------------------------- |
| `recipient` | `address` | Wallet address to receive the withdrawn funds |
| `amount`    | `uint256` | Amount to withdraw                            |

**Returns:** `requestId` - The ID of the created withdrawal request

**Reverts:**

* `NoBalanceToWithdraw` if no available funds
* `WithdrawalLimitExceeded` if amount exceeds configured cap
* `PendingWithdrawalExists` if a withdrawal is already pending

**Emits:** `WithdrawalRequested(uint256 indexed requestId, address indexed dapp, address indexed recipient, uint256 amount, uint256 timestamp)`

***

#### `cancelWithdrawalRequest(uint256 requestId)`

Cancel a pending withdrawal request.

```solidity
function cancelWithdrawalRequest(uint256 requestId) external;
```

**Reverts:**

* `WithdrawalRequestNotFound` if request doesn’t exist
* `UnauthorizedWithdrawalCancellation` if caller is not authorized

**Emits:** `WithdrawalCancelled(uint256 indexed requestId, address indexed dapp, uint256 amount)`

***

### Admin Functions

#### `updateMinimumBalance(uint256 _newMinimumBalance)`

Update minimum balance requirement for DApps.

```solidity
function updateMinimumBalance(uint256 _newMinimumBalance) external;
```

**Emits:** `MinimumBalanceUpdated(uint256 oldValue, uint256 newValue)`

***

#### `updateMaxWithdrawalLimit(uint256 _newLimit)`

Update maximum withdrawal limit per request.

```solidity
function updateMaxWithdrawalLimit(uint256 _newLimit) external;
```

**Emits:** `MaxWithdrawalLimitUpdated(uint256 oldValue, uint256 newValue)`

***

#### `updateVerificationOracle(address _newOracle)`

Update the authorized Verification Oracle address.

```solidity
function updateVerificationOracle(address _newOracle) external;
```

**Emits:** `VerificationOracleUpdated(address oldOracle, address newOracle)`

***

#### `pause()` / `unpause()`

Pause or unpause contract operations.

```solidity
function pause() external;
function unpause() external;
```

***

#### `emergencyWithdraw(address dapp)`

Emergency withdrawal function for DApps (only available when contract is paused).

```solidity
function emergencyWithdraw(address dapp) external;
```

**Emits:** `EmergencyWithdrawal(address indexed dapp, uint256 amount)`

***

## Integration Example

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;

import "./interfaces/feeEscrow/IFeeEscrow.sol";

contract MyDApp {
    IFeeEscrow public feeEscrow;

    constructor(address _feeEscrow) {
        feeEscrow = IFeeEscrow(_feeEscrow);
    }

    // Fund the escrow for verification fees
    function fundEscrow() external payable {
        feeEscrow.deposit{value: msg.value}();
    }

    // Check balance before requesting verification
    function canRequestVerification(uint256 verificationFee) external view returns (bool) {
        return feeEscrow.getAvailable(address(this)) >= verificationFee;
    }

    // Get detailed balance info
    function getEscrowBalance() external view returns (
        uint256 total,
        uint256 reserved,
        uint256 available
    ) {
        return feeEscrow.getBalanceInfo(address(this));
    }

    // Withdraw unused funds
    function withdrawFunds(address recipient, uint256 amount) external returns (uint256) {
        return feeEscrow.requestWithdrawal(recipient, amount);
    }
}
```

***

## Integration Tips

1. **Configure Oracle Address**: Ensure the escrow’s `verificationOracle` is set to the actual Oracle contract address. Otherwise, `reserveForRequest` and `settleRequest` will revert with `UnauthorizedCaller`.
2. **Pre-fund Before Requests**: Always check `getAvailable(dapp) >= verificationFee` before initiating verification requests to avoid `InsufficientAvailableBalance` errors.
3. **Monitor Available Balance**: The `available` balance (not `total`) determines what can be used for new requests or withdrawals. Reserved funds are locked until settlement or release.
4. **Handle Withdrawal Limits**: Be aware of `maxWithdrawalLimit` when requesting withdrawals. Large withdrawals may need to be split into multiple requests.
5. **Upgrades (UUPS)**: Do not increase `__gap` size on upgrade. Only append new state variables and decrement `__gap` accordingly.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.humanity.org/build-with-humanity/build-on-chain/canonical-contracts/ifeeescrow.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
