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

# Deploy Contract \[contract.deploy]

Deploys a contract and waits for the transaction receipt.

Constructor arguments are ABI-encoded with the deployment bytecode, then broadcast as a contract
creation transaction. Direct CREATE receipts include the deployed address in
`receipt.contractAddress`.

For CREATE2 deployments, `receipt.contractAddress` is `null` because the transaction targets the
deployer contract. Compute the address locally with `ContractAddress.fromCreate2`, as shown in the
[CREATE2 recipe](#deploy-deterministically-with-create2).

## Usage

Use `deploySync` to deploy a contract and wait for its transaction receipt.

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

const receipt = await client.contract.deploySync({
  abi: Abi.from(['constructor(address owner)']),
  args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
// @log: {
// @log:   contractAddress: '0x...',
// @log:   status: 'success',
// @log: }
```

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

export const client = Client.create({
  account: Account.fromPrivateKey('0x…'),
  chain: mainnet,
  transport: http(),
}).extend(walletActions())
```
:::

### Asynchronous Usage

Use `deploy` when deployment tracking happens elsewhere and the transaction hash is needed
immediately.

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

const hash = await client.contract.deploy({
  abi: Abi.from(['constructor(address owner)']),
  args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
// @log: "0x4ca7ee652d57678f26e887c19671f76c1aff..."
```

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

export const client = Client.create({
  account: Account.fromPrivateKey('0x…'),
  chain: mainnet,
  transport: http(),
}).extend(walletActions())
```
:::

### Standalone Action

Call `Actions.contract.deploySync` directly by passing the Client as the first argument. Use
`Actions.contract.deploy` for the asynchronous variant.

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

const receipt = await Actions.contract.deploySync(client, {
  abi: Abi.from(['constructor(address owner)']),
  args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
// @log: {
// @log:   contractAddress: '0x...',
// @log:   status: 'success',
// @log: }
```

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

export const client = Client.create({
  account: Account.fromPrivateKey('0x…'),
  chain: mainnet,
  transport: http(),
})
```
:::

## Recipes

### Deploy Deterministically with CREATE2

Pass a `salt` to deploy the contract at a deterministic address. Compute the address locally with `ContractAddress.fromCreate2`.

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

const bytecode = '0x608060405260405161083e38038061083e8339810160408190...'
const salt = Hash.keccak256(Hex.fromString('release-v1'))
const address = ContractAddress.fromCreate2({
  bytecode,
  from: client.chain.contracts.create2.address,
  salt,
})
// @log: "0x..."

const hash = await client.contract.deploy({
  abi: [],
  bytecode,
  salt, // [!code focus]
})
// @log: "0x4ca7ee652d57678f26e887c19671f76c1aff..."
```

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

export const client = Client.create({
  account: Account.fromPrivateKey('0x…'),
  chain: mainnet,
  transport: http(),
}).extend(walletActions())
```
:::

### Deploy with Blob Data

For a CREATE2 deployment, a Local Account can derive EIP-4844 blob fields from encoded blobs and a
KZG adapter. JSON-RPC Account sends ignore `kzg`.

:::code-group
```ts twoslash [example.ts]
import { Blobs, Hash, Hex, Kzg } from 'viem/utils'
import { client } from './viem.config'

const bytecode = '0x608060405260405161083e38038061083e8339810160408190...'
const salt = Hash.keccak256(Hex.fromString('release-v1'))

export function deployWithBlob(kzg: Kzg.Kzg) {
  return client.contract.deploy({
    abi: [],
    blobs: Blobs.from(Hex.fromString('Contract metadata')), // [!code focus]
    bytecode,
    kzg, // [!code focus]
    salt, // [!code focus]
  })
}
```

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

export const client = Client.create({
  account: Account.fromPrivateKey('0x…'),
  chain: mainnet,
  transport: http(),
}).extend(walletActions())
```
:::

## Return Value

### Synchronous

`TransactionReceipt`

The transaction receipt.

### Asynchronous

`Hex`

The transaction hash.

## Parameters

Both variants support the parameters below. `deploySync` also supports the sync parameters
documented for [`Actions.transaction.sendSync`](/docs/actions/wallet/transaction/send#parameters).

### abi

* **Type:** `Abi`

The contract's ABI. Constructor `args` are inferred from it.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor(address owner)']), // [!code focus]
  args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
```

### account

* **Type:** `Account | Address`
* **Default:** `client.account`

The account to send the deployment transaction from. Falls back to the account configured on the client.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  account: Account.fromPrivateKey('0x…'), // [!code focus]
  abi: Abi.from(['constructor(address owner)']),
  args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
```

### args

* **Type:** Inferred from `abi`.

The arguments to pass to the contract constructor. Omit when the ABI has no constructor or the constructor has no inputs.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor(address owner)']),
  args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], // [!code focus]
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
```

### assertChainId

* **Type:** `boolean`
* **Default:** `true`

Whether to verify that the Client's chain matches the connected network for a JSON-RPC Account.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  assertChainId: false, // [!code focus]
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
```

### authorizationList

* **Type:** `AuthorizationList`

The signed EIP-7702 authorization list to attach to the deployment transaction.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  authorizationList: [ // [!code focus]
    { // [!code focus]
      address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', // [!code focus]
      chainId: 1, // [!code focus]
      nonce: 0n, // [!code focus]
      r: '0x...', // [!code focus]
      s: '0x...', // [!code focus]
      yParity: 0, // [!code focus]
    }, // [!code focus]
  ], // [!code focus]
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
```

### blobs

* **Type:** `readonly Hex[]`

The blobs to attach to the deployment transaction (EIP-4844).

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  blobs: ['0x1234'], // [!code focus]
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
```

### blobVersionedHashes

* **Type:** `readonly Hex[]`

The EIP-4844 versioned hashes for the attached blobs.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  blobVersionedHashes: ['0x...'], // [!code focus]
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
})
```

### bytecode

* **Type:** `Hex`

The contract deployment bytecode.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor(address owner)']),
  args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...', // [!code focus]
})
```

### chain

* **Type:** `Chain | null`
* **Default:** `client.chain`

The chain the transaction targets. Pass `null` to skip the current-chain assertion.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor(address owner)']),
  args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  chain: null, // [!code focus]
})
```

### create2Address

* **Type:** `Address`
* **Default:** `chain.contracts.create2.address`

The CREATE2 deployer contract address. It is required with `salt` when the target chain does not configure `contracts.create2`.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { Hash, Hex } from 'viem/utils'

const client = Client.create({ transport: http() })
const salt = Hash.keccak256(Hex.fromString('release-v1'))
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: [],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  create2Address: '0x4e59b44847b379578588920ca78fbf26c0b4956c', // [!code focus]
  salt,
})
```

### dataSuffix

* **Type:** `Hex`
* **Default:** `client.dataSuffix`

The data to append to the deployment init code.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  dataSuffix: '0xdeadbeef', // [!code focus]
})
```

### gas

* **Type:** `bigint | number | Hex`

The gas limit for the deployment transaction.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  gas: 1_000_000n, // [!code focus]
})
```

### gasPrice

* **Type:** `bigint | number | Hex`

The gas price for a legacy or EIP-2930 deployment transaction.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  gasPrice: 20_000_000_000n, // [!code focus]
})
```

### kzg

* **Type:** `Kzg`

For a Local Account, the KZG context derives EIP-4844 blob fields during preparation and signing. JSON-RPC Account sends ignore this option.

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

declare const kzg: Kzg.Kzg
const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  blobs: ['0x1234'],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  kzg, // [!code focus]
})
```

### maxFeePerBlobGas

* **Type:** `bigint | number | Hex`

The maximum fee per blob gas for an EIP-4844 deployment transaction.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  maxFeePerBlobGas: 1_000_000_000n, // [!code focus]
})
```

### maxFeePerGas

* **Type:** `bigint | number | Hex`

The maximum total fee per gas for an EIP-1559 deployment transaction.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  maxFeePerGas: 20_000_000_000n, // [!code focus]
})
```

### maxPriorityFeePerGas

* **Type:** `bigint | number | Hex`

The maximum priority fee per gas for an EIP-1559 deployment transaction.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  maxPriorityFeePerGas: 1_000_000_000n, // [!code focus]
})
```

### nonce

* **Type:** `bigint | number | Hex`

The nonce to use for the deployment transaction.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  nonce: 69, // [!code focus]
})
```

### requestOptions

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

The options to pass to the underlying transport request.

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

const client = Client.create({ chain: mainnet, transport: http() })
const controller = new AbortController()
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  requestOptions: { signal: controller.signal }, // [!code focus]
})
```

### salt

* **Type:** `Hex`

The CREATE2 deployment salt. Salts shorter than 32 bytes are left-padded with zeroes.

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

const client = Client.create({ chain: mainnet, transport: http() })
const salt = Hash.keccak256(Hex.fromString('release-v1'))
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: [],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  salt, // [!code focus]
})
```

### type

* **Type:** `string`

The transaction type to use.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor()']),
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  type: 'eip1559', // [!code focus]
})
```

### value

* **Type:** `bigint | number | Hex`

The value (in wei) to send with the deployment transaction.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const hash = await Actions.contract.deploy(client, {
  abi: Abi.from(['constructor(address owner) payable']),
  args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'],
  bytecode: '0x608060405260405161083e38038061083e8339810160408190...',
  value: Value.fromEther('0.01'), // [!code focus]
})
```

## Errors

| Error | Description |
| --- | --- |
| `Account.NotFoundError` | No account was provided and the client has no configured account. |
| `Chain.DoesNotSupportContract` | `salt` was provided without `create2Address`, and the target chain does not configure `contracts.create2`. |
| `Chain.NotFoundError` | `salt` was provided without `create2Address`, and neither the action nor client specifies a chain. |
| `Hex.SizeOverflowError` | The CREATE2 salt exceeds 32 bytes. |
| `RpcError.ExecutionError` | The deployment transaction could not be sent or executed. |
| `Actions.transaction.Errors.TransactionReceiptRevertedError` | The transaction receipt status was `reverted` and `throwOnReceiptRevert` was enabled. |
