> **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.

# Reading Contract Event Logs

## Overview

Use [`contract.getLogs.<event>`](#contractgetlogs) to fetch and decode historical logs for one event in the contract's ABI.

The instance supplies `abi`, `address`, and `eventName` to [`Actions.contract.getLogs`](/docs/actions/public/contract/getLogs).

Pass options to filter indexed arguments, select blocks, or require strict decoding.

## Recipes

### Filter by Indexed Arguments

Use `args` to match indexed event fields. Only indexed fields from the selected ABI event are accepted.

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })

const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})

const logs = await contract.getLogs.Transfer({
  args: { // [!code focus]
    from: '0xA9D1e08C7793af67e9d92fe308d5697FB81d3E43', // [!code focus]
    to: '0xe101FCCf415bBdE559C82acC9076d983D50af730', // [!code focus]
  }, // [!code focus]
  fromBlock: 20_000_042n,
  toBlock: 20_000_042n,
})
```

### Read a Block Range

Set `fromBlock` and `toBlock` together to bound the query. Both bounds are inclusive.

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })

const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})

const logs = await contract.getLogs.Transfer({
  fromBlock: 20_000_000n, // [!code focus]
  toBlock: 20_000_100n, // [!code focus]
})
```

### Read One Block by Hash

Use `blockHash` for logs from one known block. Do not combine it with `fromBlock` or `toBlock`.

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })

const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})

const logs = await contract.getLogs.Transfer({
  blockHash: '0xb8c596f163b7d383fab2b4ca3c6c440d89d44a442597c0cf2e2b02b12e588f79', // [!code focus]
})
```

### Require Strict Decoding

Set `strict` to exclude logs that do not fully conform to the event ABI. The returned `args` remain fully decoded.

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })

const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})

const logs = await contract.getLogs.Transfer({
  fromBlock: 20_000_000n,
  strict: true, // [!code focus]
  toBlock: 20_000_100n,
})
```

## `contract.getLogs`

Returns decoded logs for one event from the contract instance.

### Usage

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })

const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})

const logs = await contract.getLogs.Transfer({
  args: {
    from: '0xA9D1e08C7793af67e9d92fe308d5697FB81d3E43',
    to: '0xe101FCCf415bBdE559C82acC9076d983D50af730',
  },
  fromBlock: 20_000_042n,
  toBlock: 20_000_042n,
})
// @log: [
// @log:   {
// @log:     address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
// @log:     args: {
// @log:       from: '0xA9D1e08C7793af67e9d92fe308d5697FB81d3E43',
// @log:       to: '0xe101FCCf415bBdE559C82acC9076d983D50af730',
// @log:       value: 956_430_444n,
// @log:     },
// @log:     blockHash: '0xb8c596f163b7d383fab2b4ca3c6c440d89d44a442597c0cf2e2b02b12e588f79',
// @log:     blockNumber: 20_000_042n,
// @log:     blockTimestamp: 1_717_281_911n,
// @log:     data: '0x000000000000000000000000000000000000000000000000000000003901f86c',
// @log:     eventName: 'Transfer',
// @log:     logIndex: 122,
// @log:     removed: false,
// @log:     topics: [
// @log:       '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
// @log:       '0x000000000000000000000000a9d1e08c7793af67e9d92fe308d5697fb81d3e43',
// @log:       '0x000000000000000000000000e101fccf415bbde559c82acc9076d983d50af730',
// @log:     ],
// @log:     transactionHash: '0x64954ad3979908df220b893cf810cff9f52e6704df647e9a7f93f1b8b4a07d58',
// @log:     transactionIndex: 77,
// @log:   },
// @log: ]
```

### Parameters

The instance supplies `abi`, `address`, and `eventName`. Choose `blockHash` or a `fromBlock` and
`toBlock` range. `strict` defaults to `false`.

#### options.args

* **Type:** Inferred from the selected ABI event
* **Optional**

Indexed argument values to match. Pass an array for one argument to match any listed value.

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})
// ---cut---
const logs = await contract.getLogs.Transfer({
  args: { // [!code focus]
    from: '0xA9D1e08C7793af67e9d92fe308d5697FB81d3E43', // [!code focus]
  }, // [!code focus]
})
```

#### options.blockHash

* **Type:** `Hex`
* **Optional**

The hash of one block to query. Do not combine `blockHash` with `fromBlock` or `toBlock`.

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})
// ---cut---
const logs = await contract.getLogs.Transfer({
  blockHash: '0xb8c596f163b7d383fab2b4ca3c6c440d89d44a442597c0cf2e2b02b12e588f79', // [!code focus]
})
```

#### options.fromBlock

* **Type:** `bigint | 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'`
* **Optional**

The inclusive block number or tag at which the query starts.

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})
// ---cut---
const logs = await contract.getLogs.Transfer({
  fromBlock: 20_000_000n, // [!code focus]
})
```

#### options.strict

* **Type:** `boolean`
* **Default:** `false`

Whether logs must match all indexed and non-indexed event arguments.

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})
// ---cut---
const logs = await contract.getLogs.Transfer({
  strict: true, // [!code focus]
})
```

#### options.toBlock

* **Type:** `bigint | 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'`
* **Optional**

The inclusive block number or tag at which the query ends.

```ts twoslash
import { Client, Contract, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Abis } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
const contract = Contract.from({
  abi: Abis.erc20,
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  client,
})
// ---cut---
const logs = await contract.getLogs.Transfer({
  toBlock: 20_000_100n, // [!code focus]
})
```

### Return Value

`Promise<Actions.contract.getLogs.ReturnType>`

A `readonly` array of decoded logs. The event name and `args` types are inferred from the selected ABI event.

### Errors

| Error | Description |
| --- | --- |
| `AbiItem.NotFoundError` | The selected event is missing from the runtime ABI. |
| `AbiEvent.FilterTypeNotSupportedError` | `args` includes an indexed tuple or array, which event topic filters do not support. |
| `AbiParameters.InvalidTypeError` | `args` includes an indexed ABI type that the topic encoder does not support. |
| `Address.InvalidAddressError` | `args` includes an invalid indexed address. |
| `Hex.IntegerOutOfRangeError` | `args` includes an indexed integer outside the supported 256-bit range. |
| `Hex.SizeExceedsPaddingSizeError` | An indexed fixed-bytes value exceeds the 32-byte topic size. |
