# verifyMessage

Verify that a message was signed by the provided address.

Supports verification of:

* **Externally Owned Accounts**
* **Smart Contract Accounts:**
  * **Deployed** (via [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271))
  * **Pre-deployed** (via [ERC-6492](https://eips.ethereum.org/EIPS/eip-6492))
  * **Pre-delegated** (via [ERC-8010](https://github.com/ethereum/ERCs/pull/1186))

:::info
**Why should I use this over the [`verifyMessage`](/docs/utilities/verifyMessage) util?**

This Action supports verifying messages that were signed by either a Smart Contract Account or Externally Owned Account. The [`verifyMessage`](/docs/utilities/verifyMessage.md) util only supports Externally Owned Accounts. This is getting increasingly important as more wallets implement [Account Abstraction](https://eips.ethereum.org/EIPS/eip-4337).
:::

## Usage

:::code-group
```ts twoslash [example.ts]
import { account, walletClient, publicClient } from './client'

const signature = await walletClient.signMessage({
  account,
  message: 'hello world',
})
// [!code focus:99]
const valid = await publicClient.verifyMessage({
  address: account.address,
  message: 'hello world',
  signature,
})
// @log: true
```

```ts twoslash [client.ts] filename="client.ts"
import 'viem/window'
// ---cut---
import { createPublicClient, createWalletClient, custom, http } from 'viem'
import { mainnet } from 'viem/chains'

export const publicClient = createPublicClient({
  chain: mainnet,
  transport: http()
})

export const walletClient = createWalletClient({
  transport: custom(window.ethereum!)
})

// @log: ↓ JSON-RPC Account
export const [account] = await walletClient.getAddresses()

// @log: ↓ Local Account
// export const account = privateKeyToAccount(...)
```
:::

## Returns

`boolean`

Whether the signed message is valid for the given address.

## Parameters

### address

* **Type:** [`Address`](/docs/glossary/types#address)

The Ethereum address that signed the original message.

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const valid = await publicClient.verifyMessage({
  address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', // [!code focus:1]
  message: 'hello world',
  signature:
    '0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

### message

* **Type:** `string`

The message to be verified.

By default, viem verifies the UTF-8 representation of the message.

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const valid = await publicClient.verifyMessage({
  address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  message: 'hello world', // [!code focus:1]
  signature:
    '0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

To verify the data representation of the message, you can use the `raw` attribute.

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const valid = await publicClient.verifyMessage({
  address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  message: { raw: '0x68656c6c6f20776f726c64' }, // [!code focus:1]
  signature:
    '0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

### signature

* **Type:** `Hex | ByteArray | Signature`

The signature that was generated by signing the message with the address's signer.

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const valid = await publicClient.verifyMessage({
  address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  message: 'hello world',
  signature: // [!code focus:2]
    '0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c', 
})
```

### mode (optional)

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

Chooses which verification path to try first before falling back.

Use `'eoa'` when you already know the signature should be verified as an Externally Owned Account and want to avoid unnecessary onchain verification attempts.

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const valid = await publicClient.verifyMessage({
  address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  message: 'hello world',
  signature:
    '0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
  mode: 'eoa', // [!code focus]
})
```

### blockNumber (optional)

* **Type:** `bigint`

Only used when verifying a message that was signed by a Smart Contract Account. The block number to check if the contract was already deployed.

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const valid = await publicClient.verifyMessage({
  blockNumber: 42069n, // [!code focus]
  address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  message: 'hello world',
  signature:
    '0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

### blockTag (optional)

* **Type:** `'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'`
* **Default:** `'latest'`

Only used when verifying a message that was signed by a Smart Contract Account. The block tag to check if the contract was already deployed.

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const valid = await publicClient.verifyMessage({
  blockTag: 'safe', // [!code focus]
  address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  message: 'hello world',
  signature:
    '0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

### blockHash (optional)

* **Type:** `Hash`

Only used when verifying a message that was signed by a Smart Contract Account. The block hash to check if the contract was already deployed. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const valid = await publicClient.verifyMessage({
  blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d', // [!code focus]
  address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  message: 'hello world',
  signature:
    '0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

### requireCanonical (optional)

* **Type:** `boolean`

Whether or not to require the block to be in the canonical chain. If the block is not canonical, verification fails and returns `false` instead of being evaluated against it. Only allowed in conjunction with `blockHash`. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const valid = await publicClient.verifyMessage({
  blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d',
  requireCanonical: true, // [!code focus]
  address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  message: 'hello world',
  signature:
    '0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```
