Skip to content
On this page

writeDepositTransaction

Excutes a depositTransaction call to the OptimismPortal contract.

Unlike writeSendMessage, using this call does not offer replayability on L2 in the case the L2 tx fails. But this call has the advantage that, if the caller is an EOA, msg.sender of the L2 tx will be the caller address. Allowing users to fully tranasact on L2 from L1, which is a critical security property.

If the caller is not an EOA, e.g. if the caller is a smart contract wallet, msg.sender on L2 will be alias of the caller address.

WARNING

From Viem writeContract, which this function uses internally.

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.

In this case, you can use simulateSendMessage.

ts
import { DepositTransactionParameters } from 'op-viem'
import { base } from 'op-viem/chains'
import { account, l2PublicClient, opStackL1WalletClient } from './config'

const args: DepositTransactionParameters = {
  to: account,
  value: 1n,
  data: '0x',
  gasLimit: 0n,
  isCreation: false,
}

const gas = await l2PublicClient.estimateGas({
  account,
  to: args.to,
  value: args.value,
  data: args.data,
})

args.gasLimit = gas

const hash = await opStackL1WalletClient.writeDepositTransaction({
  args,
  l2Chain: base,
  value: 1n,
})
ts
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { base } from 'op-viem/chains'
import { mainnet } from 'viem/chains'
import { walletL1OpStackActions } from 'op-viem'

export const l2PublicClient = createPublicClient({
  chain: base,
  transport: http()
})

export const opStackL1WalletClient = createWalletClient({
  chain: mainnet,
  transport: custom(window.ethereum)
}).extend(walletL1OpStackActions)

// JSON-RPC Account
export const [account] = await walletClient.getAddresses()
// Local Account
export const account = privateKeyToAccount(...)

Return Value

Hash

A Transaction Hash.

writeContract only returns a Transaction Hash. If you would like to retrieve the return data of a write function, you can use the [simulateUnsafeDepositTransaction action] – this action does not execute a transaction, and does not require gas.

Parameters

args

  • to

    • Type: Address
    • The address the L2 transaction will be sent.
  • gasLimit

    • Type: bigint
    • The gas limit of the L2 transaction
  • value (optional)

    • Type: bigint
    • Default: 0
    • Value in wei of the L2 transaction.
  • isCreation (optional)

    • Type: boolean
    • Default: false
    • Whether the L2 tx is creating a new contract
  • data (optional)

    • Type: Hex
    • Default: 0x
    • The calldata of the L2 transaction
ts
await walletClient.writeDepositTransaction({
  args: { 
    to: account.address,
    value: 1n,
    data: '0x',
    gasLimit: 21000n,
    isCreation: false,
  },
  l2Chain: base,
})

l2Chain (optional)

  • Type: OpStackChain

The destination L2 chain of the deposit transaction. l2Chain.opStackConfig.l1.chainId must match chain.id (from client.chain or chain passed explicitly as an arg). The address at l2Chain.opStackConfig.l1.contracts.optimismPortal.address will be used for the contract call. If this is argument not passed or if no such contract definition exists, optimismPortalAddress must be passed explicitly.

ts
await walletClient.writeDepositTransaction({
  args,
  l2Chain: base, 
})

optimismPortalAddress (optional)

The OptimismPortal contract where the depositTransaction call should be made.

ts
await walletClient.writeDepositTransaction({
  args,
  optimismPortalAddress: portal, 
})

value (optional)

  • Type: number

Value in wei sent with this transaction. This value will be credited to the balance of the caller address on L2 before the L2 transaction created by this transaction is made.

ts
await walletClient.writeDepositTransaction({
  args,
  optimismPortalAddress: portal,
  value: parseEther(1), 
})

TIP

account, accessList, chain, dataSuffix, gasPrice, maxFeePerGas, maxPriorityFeePerGas, and nonce can all also be passed and behave as with any viem writeContract call. See their documentation for more details.