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

# Fees

The Orderbook supports multiple fee types—protocol fees, royalties, and marketplace fees—that are automatically distributed when trades execute.

## Fee Types

| Fee              | Recipient           | Set By              |
| ---------------- | ------------------- | ------------------- |
| **Protocol Fee** | Immutable           | Fixed by protocol   |
| **Royalty Fee**  | NFT Creator         | Set on NFT contract |
| **Maker Fee**    | Listing marketplace | Order creator       |
| **Taker Fee**    | Filling marketplace | Order filler        |

## How Fees Work

When a trade executes, fees are deducted from the payment. **All fees are paid by the buyer**, and the seller receives the sale price minus the deducted fees.

```mermaid theme={null}
graph TB
    A[1.00 IMX Payment] --> B[Protocol: 0.02]
    A --> C[Royalty: 0.05]
    A --> D[Maker Fee: 0.01]
    A --> E[Taker Fee: 0.01]
    A --> F[Seller: 0.91]
```

<Info>
  **Fee Units:** Fees are specified in the **smallest unit** of the currency (wei for native tokens, smallest decimal unit for ERC-20s). For example:

  * 1 IMX = 1,000,000,000,000,000,000 wei (18 decimals)
  * Fee of "10000000000000000" = 0.01 IMX

  Fees are **notional amounts**, not percentages. If an order is partially filled, fees are automatically **pro-rated** by the orderbook.
</Info>

## Protocol Fee

The protocol fee is a small percentage that supports the Immutable ecosystem.

| Network | Protocol Fee |
| ------- | ------------ |
| Mainnet | 2%           |
| Testnet | 2%           |

<Info>
  The protocol fee is non-negotiable and applies to all trades on the Orderbook.
</Info>

## Royalties

Royalties ensure creators earn from secondary sales. They're set on the NFT contract and enforced by the Orderbook.

### Setting Royalties

Royalties are configured when deploying your NFT contract. For complete setup instructions, see [Deploying Contracts with Royalties](/docs/products/asset-contracts/deploy-contracts-with-hardhat) and [Royalty Configuration](/docs/products/asset-contracts/royalties).

```solidity theme={null}
// In your ERC-721 contract
function royaltyInfo(uint256 tokenId, uint256 salePrice)
    external
    view
    returns (address receiver, uint256 royaltyAmount)
{
    // 5% royalty to the creator
    return (creatorAddress, (salePrice * 500) / 10000);
}
```

### Typical Royalty Rates

| Game Type    | Typical Royalty |
| ------------ | --------------- |
| Gaming items | 2-5%            |
| Collectibles | 5-10%           |
| Art          | 5-15%           |

<Warning>
  **Royalty Enforcement:**

  * Royalties must be implemented via the [Operator Allowlist](/docs/products/asset-contracts/operator-allowlist) to be enforced
  * The orderbook automatically queries royalty information using the ERC-2981 interface when creating orders
  * Royalty amounts are re-validated during order fulfillment
  * **zkEVM limitation:** Royalties can only be paid to a **single wallet address**. If you need to split royalties among multiple wallets, contact your Immutable account manager about fee splitter contracts.
</Warning>

## Marketplace Fees

Marketplaces can add their own fees on top of protocol fees and royalties.

### Maker Fees

Set by the marketplace where the order is created:

```typescript theme={null}
const { result } = await orderbookClient.createListing({
  orderComponents: prepareListing.orderComponents,
  orderHash: prepareListing.orderHash,
  orderSignature: signature,
  makerFees: [
    {
      recipientAddress: MARKETPLACE_FEE_WALLET,
      amount: '10000000000000000', // 0.01 IMX flat fee
    },
  ],
});
```

### Taker Fees

Set by the marketplace where the order is filled:

```typescript theme={null}
const { actions } = await orderbookClient.fulfillOrder(
  orderId,
  buyerAddress,
  [
    {
      recipientAddress: MARKETPLACE_FEE_WALLET,
      amount: '10000000000000000', // 0.01 IMX flat fee
    },
  ]
);
```

### Maker vs Taker Fee Flexibility

| Fee Type      | When Set             | Can Change?                                                   |
| ------------- | -------------------- | ------------------------------------------------------------- |
| **Maker Fee** | At listing creation  | ❌ **Immutable** - To change, must cancel and recreate listing |
| **Taker Fee** | At order fulfillment | ✅ **Flexible** - Can be different for each fulfillment        |

<Tip>
  **Maker** = Liquidity provider (creates order, adds to orderbook)
  **Taker** = Liquidity consumer (fills order, removes from orderbook)

  Marketplaces typically charge makers lower fees to incentivize listing creation.
</Tip>

### ERC-1155 Partial Fill Fee Rules

For ERC-1155 tokens that support partial fills, **taker fees must reflect the full order amount**, not the partial fill amount:

```typescript theme={null}
// ❌ WRONG: Scaling fee for partial fill
const listing = { sell: { amount: '10' }, buy: { amount: '1000000000000000000' } }; // 10 items at 0.1 IMX each
const amountToFill = '5'; // Buying 5 of 10
const takerFee = '5000000000000000'; // 0.005 IMX (scaled) - INCORRECT

// ✅ CORRECT: Fee for full order amount
const takerFee = '10000000000000000'; // 0.01 IMX (1% of full order) - CORRECT
// The orderbook will automatically pro-rate this to 0.005 IMX for the partial fill
```

<Warning>
  For ERC-1155 orders, **always provide taker fees for the complete order**, even when partially filling. The orderbook automatically pro-rates the fee based on the quantity executed. Setting a scaled-down fee will result in incorrect marketplace compensation.
</Warning>

### Fee Validation and Expiration

When fulfilling an order, the orderbook provides up-to-date fee information and validates all fees server-side:

```typescript theme={null}
const { actions, order, expiration } = await orderbookClient.fulfillOrder(
  orderId,
  buyerAddress,
  [] // taker fees array
);

console.log({
  order: order,           // Order with CURRENT fees (may differ from listing query)
  expiration: expiration  // Transaction must be submitted within 3 minutes
});

// User must complete transaction before expiration
// After 3 minutes, request new fulfillment data
```

<Warning>
  **Important Fee Timing Rules:**

  1. **Fee changes:** Fees at fulfillment time may differ from when the order was queried (e.g., promotional periods with reduced protocol fees)
  2. **3-minute expiration:** Transaction data expires 3 minutes after generation. After expiration, request new fulfillment data with updated fees.
  3. **Display to users:** Always show users the final fee breakdown from the `fulfillOrder` response before they sign, not from the listing query.
</Warning>

### Percentage-Based Fees

Calculate fees as a percentage of the order value:

```typescript theme={null}
function calculateFee(orderAmount: string, percentageBps: number): string {
  // BPS = basis points (100 bps = 1%)
  const amount = BigInt(orderAmount);
  const fee = (amount * BigInt(percentageBps)) / BigInt(10000);
  return fee.toString();
}

// 2.5% marketplace fee
const fee = calculateFee(listing.buy.amount, 250);

const { actions } = await orderbookClient.fulfillOrder(
  orderId,
  buyerAddress,
  [{ recipientAddress: MARKETPLACE_WALLET, amount: fee }]
);
```

## Fee Splitting

Distribute fees to multiple recipients:

```typescript theme={null}
const makerFees = [
  {
    recipientAddress: PLATFORM_WALLET,
    amount: calculateFee(price, 100), // 1% to platform
  },
  {
    recipientAddress: AFFILIATE_WALLET,
    amount: calculateFee(price, 50),  // 0.5% to affiliate
  },
];

await orderbookClient.createListing({
  // ...
  makerFees,
});
```

## Displaying Fees to Users

Show users the fee breakdown before they trade:

```typescript theme={null}
interface FeeBreakdown {
  protocolFee: bigint;
  royalty: bigint;
  makerFee: bigint;
  takerFee: bigint;
  sellerReceives: bigint;
}

function calculateFeeBreakdown(
  salePrice: bigint,
  royaltyBps: number,
  makerFeeBps: number,
  takerFeeBps: number
): FeeBreakdown {
  const protocolFee = (salePrice * 200n) / 10000n; // 2%
  const royalty = (salePrice * BigInt(royaltyBps)) / 10000n;
  const makerFee = (salePrice * BigInt(makerFeeBps)) / 10000n;
  const takerFee = (salePrice * BigInt(takerFeeBps)) / 10000n;
  
  const sellerReceives = salePrice - protocolFee - royalty - makerFee;
  
  return { protocolFee, royalty, makerFee, takerFee, sellerReceives };
}
```

### Example UI

```
You're selling: Sword of Power #123
Price: 1.00 IMX

Fee Breakdown:
  Protocol Fee (2%):     -0.02 IMX
  Creator Royalty (5%):  -0.05 IMX
  Marketplace Fee (1%):  -0.01 IMX
  ─────────────────────────────────
  You'll receive:         0.92 IMX
```

## Fee Limits

| Fee Type   | Maximum                           |
| ---------- | --------------------------------- |
| Royalty    | 10% recommended, contract-defined |
| Maker Fee  | No protocol limit                 |
| Taker Fee  | No protocol limit                 |
| Total Fees | Should not exceed sale price      |

<Tip>
  Keep total fees reasonable (under 15%) to maintain a healthy marketplace. High fees discourage trading.
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="Create Listings" icon="tag" href="/docs/products/orderbook/create-listings">
    Set maker fees when creating listings
  </Card>

  <Card title="Fill Orders" icon="cart-shopping" href="/docs/products/orderbook/fill-orders">
    Add taker fees when buying NFTs
  </Card>

  <Card title="Bulk Operations" icon="layer-group" href="/docs/products/orderbook/bulk-operations">
    Calculate fees for shopping carts
  </Card>

  <Card title="Royalties Guide" icon="percent" href="/docs/products/asset-contracts/royalties">
    Configure royalties on your contracts
  </Card>
</CardGroup>
