writeContract
Executes a write function on a contract.
A "write" function on a Solidity contract modifies the state of the blockchain. These types of functions require gas to be executed, and hence a Transaction is needed to be broadcast in order to change the state.
Internally, writeContract
uses a Wallet Client to call the sendTransaction
action with ABI-encoded data
.
WARNING
The writeContract
internally sends a transaction – it does not validate if the contract write will succeed (the contract may throw an error). It is highly recommended to simulate the contract write with simulateContract
before you execute it.
Usage
Below is a very basic example of how to execute a write function on a contract (with no arguments).
While you can use writeContract
by itself, it is highly recommended to pair it with simulateContract
to validate that the contract write will execute without errors.
import { account, publicClient, walletClient } from './config'
import { wagmiAbi } from './abi'
const { request } = await publicClient.simulateContract({
account,
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
})
await walletClient.writeContract(request)
import { account, publicClient, walletClient } from './config'
import { wagmiAbi } from './abi'
const { request } = await publicClient.simulateContract({
account,
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
})
await walletClient.writeContract(request)
export const wagmiAbi = [
...
{
inputs: [],
name: "mint",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
...
] as const;
export const wagmiAbi = [
...
{
inputs: [],
name: "mint",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
...
] as const;
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
export const walletClient = createWalletClient({
chain: mainnet,
transport: custom(window.ethereum)
})
// JSON-RPC Account
export const [account] = await walletClient.getAddresses()
// Local Account
export const account = privateKeyToAccount(...)
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
export const walletClient = createWalletClient({
chain: mainnet,
transport: custom(window.ethereum)
})
// JSON-RPC Account
export const [account] = await walletClient.getAddresses()
// Local Account
export const account = privateKeyToAccount(...)
Passing Arguments
If your function requires argument(s), you can pass them through with the args
attribute.
TypeScript types for args
will be inferred from the function name & ABI, to guard you from inserting the wrong values.
For example, the mint
function name below requires a tokenId argument, and it is typed as [number]
.
import { account, walletClient } from './client'
import { wagmiAbi } from './abi'
const { request } = await publicClient.simulateContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
account
})
await walletClient.writeContract(request)
import { account, walletClient } from './client'
import { wagmiAbi } from './abi'
const { request } = await publicClient.simulateContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
account
})
await walletClient.writeContract(request)
export const wagmiAbi = [
...
{
inputs: [{ name: "tokenId", type: "uint32" }],
name: "mint",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
...
] as const;
export const wagmiAbi = [
...
{
inputs: [{ name: "tokenId", type: "uint32" }],
name: "mint",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
...
] as const;
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
export const walletClient = createWalletClient({
chain: mainnet,
transport: custom(window.ethereum)
})
// JSON-RPC Account
export const [account] = await walletClient.getAddresses()
// Local Account
export const account = privateKeyToAccount('0x...')
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
export const walletClient = createWalletClient({
chain: mainnet,
transport: custom(window.ethereum)
})
// JSON-RPC Account
export const [account] = await walletClient.getAddresses()
// Local Account
export const account = privateKeyToAccount('0x...')
Standalone
If you don't need to perform validation on the contract write, you can also use it by itself:
import { account, walletClient } from './config'
import { wagmiAbi } from './abi'
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
account,
})
import { account, walletClient } from './config'
import { wagmiAbi } from './abi'
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
account,
})
export const wagmiAbi = [
...
{
inputs: [],
name: "mint",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
...
] as const;
export const wagmiAbi = [
...
{
inputs: [],
name: "mint",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
...
] as const;
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
export const walletClient = createWalletClient({
chain: mainnet,
transport: custom(window.ethereum)
})
// JSON-RPC Account
export const [account] = await walletClient.getAddresses()
// Local Account
export const account = privateKeyToAccount('0x...')
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
export const walletClient = createWalletClient({
chain: mainnet,
transport: custom(window.ethereum)
})
// JSON-RPC Account
export const [account] = await walletClient.getAddresses()
// Local Account
export const account = privateKeyToAccount('0x...')
Return Value
Unlike readContract
, writeContract
only returns a Transaction Hash. If you would like to retrieve the return data of a write function, you can use the simulateContract
action – this action does not execute a transaction, and does not require gas (it is very similar to readContract
).
Parameters
address
- Type:
Address
The contract address.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420]
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420]
})
abi
- Type:
Abi
The contract's ABI.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420]
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420]
})
functionName
- Type:
string
A function to extract from the ABI.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420]
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420]
})
account
- Type:
Account | Address
The Account to write to the contract from.
Accepts a JSON-RPC Account or Local Account (Private Key, etc).
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
})
accessList (optional)
- Type:
AccessList
The access list.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
accessList: [{
address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
storageKeys: ['0x1'],
}],
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
accessList: [{
address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
storageKeys: ['0x1'],
}],
})
args (optional)
- Type: Inferred from ABI.
Arguments to pass to function call.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420]
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420]
})
chain (optional)
- Type:
Chain
- Default:
walletClient.chain
The target chain. If there is a mismatch between the wallet's current chain & the target chain, an error will be thrown.
The chain is also used to infer its request type (e.g. the Celo chain has a gatewayFee
that you can pass through to sendTransaction
).
import { optimism } from 'viem/chains'
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
chain: optimism,
})
import { optimism } from 'viem/chains'
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
chain: optimism,
})
dataSuffix
- Type:
Hex
Data to append to the end of the calldata. Useful for adding a "domain" tag.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
dataSuffix: '0xdeadbeef'
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
dataSuffix: '0xdeadbeef'
})
gas (optional)
- Type:
bigint
The gas limit for the transaction. Note that passing a gas limit also skips the gas estimation step.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
gas: 69420n,
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
gas: 69420n,
})
gasPrice (optional)
- Type:
bigint
The price (in wei) to pay per gas. Only applies to Legacy Transactions.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
gasPrice: parseGwei('20'),
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
gasPrice: parseGwei('20'),
})
maxFeePerGas (optional)
- Type:
bigint
Total fee per gas (in wei), inclusive of maxPriorityFeePerGas
. Only applies to EIP-1559 Transactions
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
maxFeePerGas: parseGwei('20'),
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
maxFeePerGas: parseGwei('20'),
})
maxPriorityFeePerGas (optional)
- Type:
bigint
Max priority fee per gas (in wei). Only applies to EIP-1559 Transactions
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
maxFeePerGas: parseGwei('20'),
maxPriorityFeePerGas: parseGwei('2'),
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
maxFeePerGas: parseGwei('20'),
maxPriorityFeePerGas: parseGwei('2'),
})
nonce (optional)
- Type:
number
Unique number identifying this transaction.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
nonce: 69
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
nonce: 69
})
value (optional)
- Type:
number
Value in wei sent with this transaction.
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
value: parseEther('1')
})
await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: wagmiAbi,
functionName: 'mint',
args: [69420],
value: parseEther('1')
})
Live Example
Check out the usage of writeContract
in the live Writing to Contracts Example below.