> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://v3.viem.sh/api/mcp` to find what you need.

# Customizing Fees

## Overview

A [Chain](/docs/chains) can define fee derivation through the optional `fees` property. Use this
property for nonstandard fee markets or a project-wide fee policy.

`fees` has three optional slots:

* **`maxPriorityFeePerGas`**: the default priority fee, consumed by [`estimateMaxPriorityFeePerGas`](/docs/actions/public/fee/estimateMaxPriorityFeePerGas).
* **`baseFeeMultiplier`**: a multiplier applied to the base fee to account for fluctuations.
* **`estimateFeesPerGas`**: full control over the derived `maxFeePerGas`/`maxPriorityFeePerGas` (or legacy `gasPrice`).

```ts twoslash
import { Chain } from 'viem'

const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: { // [!code focus]
    baseFeeMultiplier: 1.2, // [!code focus]
    maxPriorityFeePerGas: 1_000_000_000n, // [!code focus]
  }, // [!code focus]
})
```

## Recipes

### Setting a Default Priority Fee

Set `fees.maxPriorityFeePerGas` to a fixed value in wei to skip the
`eth_maxPriorityFeePerGas` RPC call.

[`Actions.fee.estimateMaxPriorityFeePerGas`](/docs/actions/public/fee/estimateMaxPriorityFeePerGas)
returns this value unchanged.

```ts twoslash
import { Chain } from 'viem'

const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: {
    maxPriorityFeePerGas: 1_000_000_000n, // [!code focus]
  },
})
```

### Deriving the Priority Fee Dynamically

Provide a function for `fees.maxPriorityFeePerGas` to compute the priority fee from the latest block
and Client.

Return `null` to use the default derivation: `eth_maxPriorityFeePerGas`, followed by
`gasPrice - baseFeePerGas` when needed.

```ts twoslash
import { Chain } from 'viem'

const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: {
    async maxPriorityFeePerGas({ block }) { // [!code focus]
      if (typeof block.baseFeePerGas !== 'bigint') return null // [!code focus]
      return block.baseFeePerGas / 10n // [!code focus]
    }, // [!code focus]
  },
})
```

### Adjusting the Base Fee Multiplier

Set `fees.baseFeeMultiplier` to scale the base fee when estimating `maxFeePerGas`. The additional
amount accounts for base-fee changes between blocks.

The default multiplier is `1.2`.

```ts twoslash
import { Chain } from 'viem'

const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: {
    baseFeeMultiplier: 1.5, // [!code focus]
  },
})
```

A function can compute the multiplier from the latest block and the Client, for example to widen the buffer when the network is congested.

```ts twoslash
import { Chain } from 'viem'

const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: {
    baseFeeMultiplier({ block }) { // [!code focus]
      const congested = block.gasUsed > block.gasLimit / 2n // [!code focus]
      return congested ? 1.5 : 1.2 // [!code focus]
    }, // [!code focus]
  },
})
```

### Fully Customizing Fee Estimation

Provide `fees.estimateFeesPerGas` to control the derived fee values. Use `multiply` to apply
`baseFeeMultiplier`, and use `type` to select the fee shape.

Return `null` to use the default derivation.

```ts twoslash
import { Chain } from 'viem'

const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: {
    async estimateFeesPerGas({ block, multiply, type }) { // [!code focus]
      if (type === 'legacy') return null // [!code focus]
      const baseFeePerGas = block.baseFeePerGas ?? 0n // [!code focus]
      const maxPriorityFeePerGas = 1_000_000_000n // [!code focus]
      return { // [!code focus]
        maxFeePerGas: multiply(baseFeePerGas) + maxPriorityFeePerGas, // [!code focus]
        maxPriorityFeePerGas, // [!code focus]
      } // [!code focus]
    }, // [!code focus]
  },
})
```

### Set Fees from the Transaction Request

Fee callbacks receive the transaction `request` when the caller provides one. Use the request to
apply a transaction-specific fee policy.

```ts twoslash
import { Chain } from 'viem'

const priorityAddress = '0x0000000000000000000000000000000000000001'

const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: {
    maxPriorityFeePerGas({ request }) { // [!code focus]
      if (request?.to === priorityAddress) return 2_000_000_000n // [!code focus]
      return null // [!code focus]
    }, // [!code focus]
  },
})
```

## `Chain.Fees`

Configuration describing how fees are derived for a [Chain](/docs/chains).

### fees.baseFeeMultiplier

* **Type:** `number | ((args: { block: Block; client: Client; request?: TransactionRequest.toRpc.Input }) => number | Promise<number>)`
* **Default:** `1.2`

The multiplier applied to the base fee when estimating `maxFeePerGas`. Pass a number or a function
that receives the latest block, Client, and optional transaction request.

```ts twoslash
import { Chain } from 'viem'
// ---cut---
const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: {
    baseFeeMultiplier: 1.5, // [!code focus]
  },
})
```

### fees.estimateFeesPerGas

* **Type:** `(args: { block: Block; client: Client; multiply: (x: bigint) => bigint; request?: TransactionRequest.toRpc.Input; type: 'legacy' | 'eip1559' | 'eip4844' }) => FeeValues | null | Promise<FeeValues | null>`
* **Optional**

Controls the derived fee values. The `multiply` helper applies `baseFeeMultiplier`, and `type`
selects the fee shape. The optional `request` contains the transaction request when available.

Return `null` to use the default derivation.

```ts twoslash
import { Chain } from 'viem'
// ---cut---
const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: {
    async estimateFeesPerGas({ block, multiply, type }) { // [!code focus]
      if (type === 'legacy') return null // [!code focus]
      const maxPriorityFeePerGas = 1_000_000_000n // [!code focus]
      return { // [!code focus]
        maxFeePerGas: multiply(block.baseFeePerGas ?? 0n) + maxPriorityFeePerGas, // [!code focus]
        maxPriorityFeePerGas, // [!code focus]
      } // [!code focus]
    }, // [!code focus]
  },
})
```

### fees.maxPriorityFeePerGas

* **Type:** `bigint | ((args: { block: Block; client: Client; request?: TransactionRequest.toRpc.Input }) => bigint | null | Promise<bigint | null>)`
* **Optional**

The default `maxPriorityFeePerGas` in wei. This value overrides
[`Actions.fee.estimateMaxPriorityFeePerGas`](/docs/actions/public/fee/estimateMaxPriorityFeePerGas).

A function receives the latest block, Client, and optional transaction request. It can return
`null` to use the default derivation.

```ts twoslash
import { Chain } from 'viem'
// ---cut---
const chain = Chain.from({
  id: 1,
  name: 'Ethereum',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { http: 'https://eth.merkle.io' },
  fees: {
    maxPriorityFeePerGas: 1_000_000_000n, // [!code focus]
  },
})
```
