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

# Verify Hash \[verifyHash]

Verifies a signature over a hash onchain, supporting Smart Contract Accounts (ERC-1271), counterfactual accounts (ERC-6492), delegated accounts (ERC-8010), and Externally Owned Accounts.

Without a chain-specific hook, ERC-1271 and ERC-6492 checks use the ERC-6492 universal validator. Viem uses a deployless call unless you set [`erc6492VerifierAddress`](#erc6492verifieraddress).

ERC-8010 signatures verify their delegation authorization and call `isValidSignature` on the delegated account. ECDSA recovery verifies signatures from externally owned accounts.

## Usage

This example verifies a signature over a hash for an address.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const valid = await client.verifyHash({
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
// @log: true
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, http, publicActions } from 'viem'
import { mainnet } from 'viem/chains'

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

### Standalone Action

Call `Actions.verifyHash` directly by passing the Client as the first argument.

:::code-group
```ts twoslash [example.ts]
import { Actions } from 'viem'
import { client } from './viem.config'

const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
// @log: true
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, http } from 'viem'
import { mainnet } from 'viem/chains'

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

## Recipes

### Prefer EOA Verification

Set `mode: 'eoa'` to try local ECDSA recovery before onchain verification.

```ts twoslash
import { Client, http, publicActions } from 'viem'
import { mainnet } from 'viem/chains'

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

const valid = await client.verifyHash({
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  mode: 'eoa', // [!code focus]
  signature: '0x…',
})
```

### Verify a Counterfactual Account

Pass the deployment factory and calldata when the smart account has not been deployed.

```ts twoslash
import { Client, http, publicActions } from 'viem'
import { mainnet } from 'viem/chains'

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

const valid = await client.verifyHash({
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  factory: '0x0000000000FFe8B47B3e2130213B802212439497', // [!code focus]
  factoryData: '0xdeadbeef', // [!code focus]
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
```

### Verify Against a Canonical Block

Pass `blockHash` with `requireCanonical` when verification must use a canonical block.

```ts twoslash
import { Client, http, publicActions } from 'viem'
import { mainnet } from 'viem/chains'

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

const valid = await client.verifyHash({
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  blockHash: '0x4ca7ee652d57678f26e887c149ab0735f41de37bcad58c9f6d3ed5824f15b74d', // [!code focus]
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  requireCanonical: true, // [!code focus]
  signature: '0x…',
})
```

## Return Value

`boolean`

Whether the signature is valid for the given hash and address.

## Parameters

### address

* **Type:** `Address`

The address that signed the hash.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', // [!code focus]
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
```

### blockHash

* **Type:** `Hex`

Verifies against the state at a block identified by its hash.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  blockHash: '0x4ca7ee652d57678f26e887c149ab0735f41de37bcad58c9f6d3ed5824f15b74d', // [!code focus]
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
```

### blockNumber

* **Type:** `bigint`

Verifies against the state at a given block number.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  blockNumber: 42069n, // [!code focus]
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
```

### blockTag

* **Type:** `'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'`
* **Default:** `client.blockTag ?? 'latest'`

Verifies against the state at a given block tag.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  blockTag: 'pending', // [!code focus]
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
```

### erc6492VerifierAddress

* **Type:** `Address`
* **Default:** `client.chain.contracts.erc6492Verifier.address`

Deployed ERC-6492 signature verifier contract. When absent, verification runs as a deployless call.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  erc6492VerifierAddress: '0x64926492649264926492649264926492649264926', // [!code focus]
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
```

### factory

* **Type:** `Address`

Deployment factory of a counterfactual (undeployed) smart account. Pass together with [`factoryData`](#factorydata); the signature is wrapped per ERC-6492 for counterfactual validation.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  factory: '0x0000000000FFe8B47B3e2130213B802212439497', // [!code focus]
  factoryData: '0xdeadbeef', // [!code focus]
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
```

### factoryData

* **Type:** `Hex`

Deployment calldata for the counterfactual smart account. See [`factory`](#factory).

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  factory: '0x0000000000FFe8B47B3e2130213B802212439497',
  factoryData: '0xdeadbeef', // [!code focus]
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…',
})
```

### hash

* **Type:** `Hex`
* **Required:** Yes

The hash that was signed.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68', // [!code focus]
  signature: '0x…',
})
```

### mode

* **Type:** `'auto' | 'eoa' | string`
* **Default:** `'auto'`

The verification path to try first.

`'eoa'` attempts local ECDSA recovery before onchain verification. A successful recovery does not make an RPC request.

`'auto'` verifies onchain, then falls back to ECDSA recovery. A chain with a custom `verifyHash` hook can define additional modes.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  mode: 'eoa', // [!code focus]
  signature: '0x…',
})
```

### multicallAddress

* **Type:** `Address`
* **Default:** `client.chain.contracts.multicall3.address`

Multicall3 address used for ERC-8010 (delegated account) verification.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  multicallAddress: '0xcA11bde05977b3631167028862bE2a173976CA11', // [!code focus]
  signature: '0x…',
})
```

### requestOptions

* **Type:** `{ dedupe?: boolean; signal?: AbortSignal; ... }`

Per-request transport options (for example, an `AbortSignal` to cancel the request).

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const controller = new AbortController()
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  requestOptions: { signal: controller.signal }, // [!code focus]
  signature: '0x…',
})
```

### requireCanonical

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

Requires [`blockHash`](#blockhash) to identify a block in the canonical chain.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  blockHash: '0x4ca7ee652d57678f26e887c149ab0735f41de37bcad58c9f6d3ed5824f15b74d',
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  requireCanonical: true, // [!code focus]
  signature: '0x…',
})
```

### signature

* **Type:** `Hex | Bytes | Signature`

The signature to verify. Accepts a hex value, byte array, or signature object; ERC-6492 wrapped and ERC-8010 wrapped signatures are detected automatically.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const valid = await Actions.verifyHash(client, {
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
  signature: '0x…', // [!code focus]
})
```

## Errors

| Error | Description |
| --- | --- |
| `BlockParameter.RequireCanonicalError` | `requireCanonical` was provided without a `blockHash`. |
| `RpcError.ExecutionError` | An RPC request failed without being handled as an invalid signature. |
