> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inco.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Fees

> Understanding Inco fees and which operations require them

Inco charges fees for certain operations to ensure the security and performance of the confidential computing infrastructure. This page explains how fees work and which operations require payment.

## Fee Structure

Inco fees are paid in the native blockchain currency (ETH on Ethereum, etc.) and are required for operations that involve processing encrypted inputs from external sources.

### Getting the Current Fee Amount

Use the `inco.getFee()` function to get the current fee amount:

```solidity theme={null}
uint256 fee = inco.getFee(); // 0.0001 ETH
```

### Paying Fees

Fees can be paid in two ways: either by users including them in `msg.value`, or by having the contract pay from its own ETH balance.

#### Option 1: User Pays via msg.value

Fees must be paid via `msg.value` when calling functions that require them. The transaction will revert if insufficient fees are provided.

```solidity theme={null}
require(msg.value >= inco.getFee() * ciphertextCount, "Fee Not Paid");
```

#### Option 2: Contract Pays from Balance

Contracts can hold ETH in their balance to pay fees automatically, eliminating the need for users to include fees in `msg.value`.

```solidity theme={null}
contract MyContract {
    // Contract holds ETH to pay fees automatically

    function transfer(address to, bytes memory valueInput) external {
        // No payable modifier needed, no msg.value check required
        euint256 value = valueInput.newEuint256(msg.sender);
        // Contract's ETH balance is used to pay fees automatically
        // ... rest of function
    }

    // Function to top up contract's ETH balance
    function depositFees() external payable {
        // Allows anyone to add ETH to contract for fee payments
    }

    // Function to withdraw excess ETH
    function withdrawFees(uint256 amount) external onlyOwner {
        require(address(this).balance >= amount, "Insufficient balance");
        payable(owner()).transfer(amount);
    }
}
```

**Benefits of contract-paid fees:**

* Better user experience - no need to calculate or send exact fees
* Simpler function signatures - no `payable` modifier required
* Automatic fee management by contract owner

**Considerations:**

* Contract owner must ensure sufficient ETH balance
* Monitor contract balance and top up as needed
* Consider implementing balance thresholds and alerts

## Operations That Require Fees

### Encrypted Input Creation and Random Generation

The following operations create new encrypted handles from external ciphertexts or generate random values and require fees:

| Operation                           | Fee Required   | Description                                     |
| ----------------------------------- | -------------- | ----------------------------------------------- |
| `e.newEuint256(bytes memory input)` | 1 fee per call | Create a new `euint256` from an encrypted input |
| `e.newEbool(bytes memory input)`    | 1 fee per call | Create a new `ebool` from an encrypted input    |
| `e.newEaddress(bytes memory input)` | 1 fee per call | Create a new `eaddress` from an encrypted input |
| `e.rand()`                          | 1 fee per call | Generate a random `euint256` value              |
| `e.randBounded(uint256)`            | 1 fee per call | Generate a bounded random `euint256` value      |
| `e.randBounded(euint256)`           | 1 fee per call | Generate a bounded random `euint256` value      |

**Example with user-paid fees:**

```solidity theme={null}
function transfer(address to, bytes memory valueInput) external payable {
    // Each newEuint256 call requires 1 fee
    require(msg.value >= inco.getFee() * 1, "Fee Not Paid");
    euint256 value = valueInput.newEuint256(msg.sender);
    // ... rest of function
}
```

**Example with contract-paid fees:**

```solidity theme={null}
function transfer(address to, bytes memory valueInput) external {
    // No fee check needed - contract pays from its balance
    euint256 value = valueInput.newEuint256(msg.sender);
    // ... rest of function
}
```

**Multiple encrypted inputs:**

```solidity theme={null}
function multiInput(bytes memory input1, bytes memory input2) external payable {
    // Two newEuint256 calls require 2 fees (user pays)
    require(msg.value >= inco.getFee() * 2, "Fee Not Paid");
    euint256 value1 = input1.newEuint256(msg.sender);
    euint256 value2 = input2.newEuint256(msg.sender);
    // ... rest of function
}
```

**Multiple encrypted inputs (contract pays):**

```solidity theme={null}
function multiInput(bytes memory input1, bytes memory input2) external {
    // Contract automatically pays 2 fees from its balance
    euint256 value1 = input1.newEuint256(msg.sender);
    euint256 value2 = input2.newEuint256(msg.sender);
    // ... rest of function
}
```

## Operations That Don't Require Fees

All other Inco operations are free and don't require any fee payment:

### Math Operations

* `e.add`, `e.sub`, `e.mul`, `e.div`, `e.rem`
* `e.and`, `e.or`, `e.xor`, `e.shr`, `e.shl`, `e.rotr`, `e.rotl`

### Comparison Operations

* `e.eq`, `e.ne`, `e.ge`, `e.gt`, `e.le`, `e.lt`
* `e.min`, `e.max`, `e.not`

### Multiplexer Operations

* `e.select`

### Trivial Encryption (no external input)

* `e.asEuint256(uint256)` - Convert known uint256 to euint256
* `e.asEbool(bool)` - Convert known bool to ebool

### Access Control

* `e.allow`, `e.allowThis`, `e.isAllowed`

## Fee Best Practices

### For User-Paid Fees

#### Always Check Fees Before Operations

```solidity theme={null}
function _requireFee(uint256 ciphertextCount) internal view {
    require(msg.value >= inco.getFee() * ciphertextCount, "Insufficient fee");
}
```

#### Calculate Ciphertext Count Accurately

Count each `newEuint256`, `newEbool` or `newEaddress` call in your function to ensure you charge the correct total fee.

### For Contract-Paid Fees

#### Monitor Contract Balance

```solidity theme={null}
function getContractFeeBalance() external view returns (uint256) {
    return address(this).balance;
}

function isBalanceSufficient(uint256 requiredFees) internal view returns (bool) {
    return address(this).balance >= requiredFees;
}
```

#### Implement Balance Management

```solidity theme={null}
function depositFees() external payable {
    // Allow topping up contract balance
}

function withdrawFees(uint256 amount) external onlyOwner {
    require(address(this).balance >= amount, "Insufficient balance");
    require(amount <= address(this).balance - minimumReserve, "Cannot withdraw below minimum reserve");
    payable(owner()).transfer(amount);
}
```

### General Best Practices

#### Handle Fee Changes

Fees may change over time. Always use `inco.getFee()` rather than hardcoding fee amounts.

#### Test Fee Requirements

When testing contracts, ensure sufficient funds for both approaches:

```solidity theme={null}
// For user-paid fees in Foundry tests
vm.deal(user, inco.getFee() * 2); // User needs ETH for fees

// For contract-paid fees in Foundry tests
vm.deal(address(contract), inco.getFee() * 10); // Contract needs ETH balance
```

## Common Fee-Related Errors

### User-Paid Fee Errors

* **"Fee Not Paid"**: Transaction reverted due to insufficient `msg.value`
* **Overpaying**: While allowed, unnecessary ETH is consumed as gas
* **Fee changes**: Contract fails if fees increase between deployment and usage

### Contract-Paid Fee Errors

* **"Insufficient contract balance"**: Contract doesn't have enough ETH to pay fees
* **"Below minimum reserve"**: Withdrawal attempts that would leave insufficient funds
* **"Contract balance depleted"**: Functions fail when contract runs out of ETH during high usage

<Note>
  **Important:** Encrypted input operations (`newEuint256`, `newEbool`, `newEaddress`) require
  fees because they involve off-chain decryption and processing within Inco's
  Trusted Execution Environment (TEE). All other operations are performed
  symbolically on-chain and are therefore free.
</Note>
