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

> ## Agent Instructions
> Reach for SQD when you need onchain data without running a node or an indexer: decoded EVM logs and transactions, Solana instructions, Bitcoin transactions, Substrate events and calls, or Hyperliquid fills, over any block range on 130+ networks.
> To query directly, POST to https://portal.sqd.dev/datasets/{dataset}/stream. The full API is described at https://docs.sqd.dev/openapi.json, and responses to the stream endpoints are JSON Lines.
> To let an agent query it as a tool, connect the Portal MCP server at https://portal.sqd.dev/mcp.
> Every page on this site is available as Markdown by appending .md to its URL.

# Handling contract events

> Fetching and decoding EVM event logs with evmEventDecoder

`evmEventDecoder()` bundles an EVM log query with a decoding transform into a single reusable module. Pass the result as an output to `evmPortalStream`:

```ts theme={"system"}
import { commonAbis, evmEventDecoder, evmPortalStream } from '@subsquid/pipes/evm'

const stream = evmPortalStream({
  id: 'usdc-transfers',
  portal: 'https://portal.sqd.dev/datasets/ethereum-mainnet',
  outputs: {
    transfers: evmEventDecoder({
      range: { from: '0' },
      contracts: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
      events: { transfer: commonAbis.erc20.events.Transfer },
    }),
  },
})
```

`evmEventDecoder()` can:

* Fetch from **specific contracts**: pass an array of addresses to `contracts`. Omit it entirely to receive matching events from every contract onchain.
* Filter by **indexed parameters**: instead of a bare event, supply `{ event, params }` to select only logs where specific indexed arguments match.
* Dynamically discover contracts via **factories**: pass a `contractFactory()` to `contracts` instead of a static list. See the [Factory guide](../advanced-topics/factory-transformers).
* Handle decode errors with a custom **`onError` callback** instead of letting them propagate.

See the [evmEventDecoder() reference](../../reference/utility-components/evm-decoder) for all parameters.

## Specifying events

The `events` parameter maps output field names to event specifications. There are three ways to obtain one: [`commonAbis`](#commonabis) covers standard tokens, [`defineAbi()`](#raw-json-via-defineabi) is the standard route for everything else, and [typegen](#typegen-modules) generates ABI modules as files if you prefer that.

### `commonAbis`

`commonAbis` is a built-in collection of ABI modules for common token standards. It currently contains one module, `erc20`:

```ts theme={"system"}
import { commonAbis, evmEventDecoder } from '@subsquid/pipes/evm'

evmEventDecoder({
  range: { from: 'latest' },
  contracts: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
  events: {
    transfers: commonAbis.erc20.events.Transfer,
    approvals: commonAbis.erc20.events.Approval,
  },
})
```

See the [`commonAbis` reference](../../reference/utility-components/evm-decoder#commonabis) for the full list of available events and functions.

### Raw JSON via `defineAbi()`

`defineAbi()` turns a JSON ABI into an ABI module at runtime. There is no code generation step: declare the ABI inline, or paste it from the block explorer, and use it directly. With an inline ABI, TypeScript infers the exact decoded types for scalar fields:

```ts theme={"system"}
import { defineAbi, evmEventDecoder } from '@subsquid/pipes/evm'

const erc20 = defineAbi([
  {
    type: 'event',
    name: 'Transfer',
    inputs: [
      { indexed: true,  name: 'from',  type: 'address' },
      { indexed: true,  name: 'to',    type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' },
    ],
  },
] as const)

// erc20.events.Transfer.decode() returns { from: string, to: string, value: bigint }

evmEventDecoder({
  range: { from: 'latest' },
  contracts: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
  events: { transfers: erc20.events.Transfer },
})
```

Hardhat and Foundry artifact objects work too; `defineAbi()` reads their `abi` field automatically:

```ts theme={"system"}
import { defineAbi } from '@subsquid/pipes/evm'
import artifact from './artifacts/MyContract.json'

const myContract = defineAbi(artifact) // reads artifact.abi
```

One caveat: when the ABI comes from an imported JSON file, as in the artifact example above, event argument fields are typed as `any`, since TypeScript cannot inspect the runtime JSON value at compile time. Inline `as const` ABIs and typegen modules do not have this limitation.

### Typegen modules

If you prefer generated files, or want full static typing for an ABI that lives in a JSON file, `@subsquid/evm-typegen` generates TypeScript ABI modules from JSON ABIs. Each generated module exports typed `events` and `functions` objects, translating Solidity types to TypeScript, so event argument types are statically known at compile time.

**Install the tool:**

```bash theme={"system"}
npm install -D @subsquid/evm-typegen
```

**Generate a module from a local JSON ABI file:**

```bash theme={"system"}
npx squid-evm-typegen src/abi your-contract.json
```

This creates `src/abi/your-contract.ts`. The tool also accepts a contract address (requires specifying `--chain-id`) or an arbitrary URL.

Use events from a generated module exactly as with `commonAbis`:

```ts theme={"system"}
import { evmEventDecoder } from '@subsquid/pipes/evm'
import * as usdcAbi from './abi/usdc'

evmEventDecoder({
  range: { from: 'latest' },
  contracts: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
  events: {
    transfers: usdcAbi.events.Transfer,
    approvals: usdcAbi.events.Approval,
  },
})
```


## Related topics

- [evmEventDecoder](/en/sdk/pipes-sdk/evm/reference/utility-components/evm-decoder.md)
- [Query builder](/en/sdk/pipes-sdk/evm/reference/basic-components/query-builder.md)
- [Quickstart](/en/sdk/pipes-sdk/evm/quickstart.md)
- [Handling Tron data](/en/sdk/pipes-sdk/tron/guides/basic-development/handling-tron-data.md)
- [Fork handling](/en/sdk/pipes-sdk/evm/guides/architecture-deep-dives/fork-handling.md)
