Ethers v5 → viem Migration Guide 
This is a long document. Feel free to use the search bar above (⌘ K) or the Table of Contents to the side. If there is an API you need which is missing or cannot find, create a Parity Request here.
You may notice some of the APIs in viem are a little more verbose than Ethers. We prefer boring code and we want to strongly embrace clarity & composability. We believe that verbose APIs are more flexible to move, change and remove compared to code that is prematurely abstracted and hard to change.
Provider → Client 
getDefaultProvider 
Ethers 
import { getDefaultProvider } from 'ethers'
const provider = getDefaultProvider()viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
  chain: mainnet,
  transport: http()
})We are more verbose here – we want to be explicit and clear what chain you are connecting to & what transport you are using to avoid any confusion. 😃
JsonRpcProvider 
Ethers 
This is also interchangeable with StaticJsonRpcProvider.
import { providers } from 'ethers'
const provider = new providers.JsonRpcProvider('https://cloudflare-eth.com')Custom Chain:
import { providers } from 'ethers'
const provider = new providers.JsonRpcProvider('https://rpc.ankr.com/fantom/', {
  name: 'Fantom',
  id: 250
})viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
  chain: mainnet,
  transport: http('https://cloudflare-eth.com')
})Custom Chain:
import { createPublicClient, http } from 'viem'
import { fantom } from 'viem/chains'
const client = createPublicClient({
  chain: fantom,
  transport: http('https://rpc.ankr.com/fantom/')
})viem exports custom EVM chains in the
viem/chainsentrypoint.
InfuraProvider 
Ethers 
import { providers } from 'ethers'
const provider = new providers.InfuraProvider('homestead', '<apiKey>')viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
  chain: mainnet,
  transport: http('https://mainnet.infura.io/v3/<apiKey>')
})viem does not have custom API Provider clients – you can just pass in their RPC URL.
AlchemyProvider 
Ethers 
import { providers } from 'ethers'
const provider = new providers.AlchemyProvider('homestead', '<apiKey>')viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
  chain: mainnet,
  transport: http('https://eth-mainnet.g.alchemy.com/v2/<apiKey>')
})viem does not have custom API Provider clients – you can just pass in their RPC URL.
CloudflareProvider 
Ethers 
import { providers } from 'ethers'
const provider = new providers.CloudflareProvider()viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
  chain: mainnet,
  transport: http('https://cloudflare-eth.com/')
})viem does not have custom API Provider clients – you can just pass in their RPC URL.
PocketProvider 
Ethers 
import { providers } from 'ethers'
const provider = new providers.PocketProvider('homestead', '<apiKey>')viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
  chain: mainnet,
  transport: http('https://eth-mainnet.gateway.pokt.network/v1/lb/<apiKey>')
})viem does not have custom API Provider clients – you can just pass in their RPC URL.
AnkrProvider 
Ethers 
import { providers } from 'ethers'
const provider = new providers.AnkrProvider('homestead', '<apiKey>')viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
  chain: mainnet,
  transport: http('https://rpc.ankr.com/eth/<apiKey>')
})viem does not have custom API Provider clients – you can just pass in their RPC URL.
FallbackProvider 
Ethers 
import { providers } from 'ethers'
const alchemy = new providers.AlchemyProvider('homestead', '<apiKey>')
const infura = new providers.InfuraProvider('homestead', '<apiKey>')
const provider = new providers.FallbackProvider([alchemy, infura])viem 
import { createPublicClient, http, fallback } from 'viem'
import { mainnet } from 'viem/chains'
const alchemy = http('https://eth-mainnet.g.alchemy.com/v2/<apiKey>')
const infura = http('https://mainnet.infura.io/v3/<apiKey>')
const client = createPublicClient({
  chain: mainnet,
  transport: fallback([alchemy, infura])
})IpcProvider 
Coming soon.
JsonRpcBatchProvider 
Coming soon.
Web3Provider 
Ethers 
import { providers } from 'ethers'
const provider = new providers.Web3Provider(window.ethereum)viem 
import { createWalletClient, custom } from 'viem'
import { mainnet } from 'viem/chains'
const client = createWalletClient({
  chain: mainnet,
  transport: custom(window.ethereum)
})WebSocketProvider 
Ethers 
import { providers } from 'ethers'
const provider = new providers.WebSocketProvider('wss://eth-mainnet.g.alchemy.com/v2/<apiKey>')viem 
import { createPublicClient, webSocket } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
  chain: mainnet,
  transport: webSocket('wss://eth-mainnet.g.alchemy.com/v2/<apiKey>')
})Signers → Accounts 
JsonRpcSigner 
Ethers 
import { providers } from 'ethers'
const provider = new providers.Web3Provider(window.ethereum)
const [address] = await provider.listAccounts()
const signer = provider.getSigner(address)
signer.sendTransaction({ ... })viem 
import { createWalletClient, custom } from 'viem'
import { mainnet } from 'viem/chains'
const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' })
const client = createWalletClient({
  account,
  chain: mainnet,
  transport: custom(window.ethereum)
})
client.sendTransaction({ ... })viem uses the term "Account" rather than "Signer".
Wallet 
Ethers 
import { providers, Wallet } from 'ethers'
const provider = new providers.Web3Provider(window.ethereum)
const wallet = new Wallet('0x...', provider)
wallet.sendTransaction({ ... })viem 
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
const account = privateKeyToAccount('0x...')
 
const client = createWalletClient({
  account,
  chain: mainnet,
  transport: custom(window.ethereum)
})
client.sendTransaction({ ... })viem uses the term "Account" rather than "Signer".
Provider Methods 
Ethers 
import { getDefaultProvider } from 'ethers'
const provider = getDefaultProvider()
provider.getBlock(...)
provider.getTransaction(...)
...viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
  chain: mainnet,
  transport: http()
})
client.getBlock(...)
client.getTransaction(...)
...Methods that extend off the Public Client are Public Actions. Read more.
There are API differences in all of these methods. Use the search bar at the top of the page to learn more about them.
Signer Methods 
JsonRpcSigner 
Ethers 
import { providers } from 'ethers'
const provider = new providers.Web3Provider(window.ethereum)
const [address] = await provider.listAccounts()
const signer = provider.getSigner(address)
signer.sendTransaction(...)
signer.signMessage(...)
...viem 
import { createWalletClient, custom } from 'viem'
import { mainnet } from 'viem/chains'
const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' })
const client = createWalletClient({
  account,
  chain: mainnet,
  transport: custom(window.ethereum)
})
client.sendTransaction({ ... })
client.signMessage({ ... })
...Methods that extend off the Wallet Client are Wallet Actions. Read more.
There are API differences in all of these methods. Use the search bar at the top of the page to learn more about them.
Contract Interaction 
Reading from Contracts 
Ethers 
import { getDefaultProvider } from 'ethers'
import { wagmiContractConfig } from './abi'
const provider = getDefaultProvider()
const { abi, address } = wagmiContractConfig
const contract = new Contract(address, abi, provider)
const supply = await contract.totalSupply()viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { wagmiContractConfig } from './abi'
const client = createPublicClient({
  chain: mainnet,
  transport: http()
})
const supply = await client.readContract({
  ...wagmiContractConfig,
  functionName: 'totalSupply'
})Writing to Contracts 
Ethers 
import { Contract, providers } from 'ethers'
import { wagmiContractConfig } from './abi'
const provider = new providers.Web3Provider(window.ethereum)
const [address] = await provider.listAccounts()
const signer = provider.getSigner(address)
const { abi, address } = wagmiContractConfig
const contract = new Contract(address, abi, signer)
const hash = await contract.mint()viem 
import { createPublicClient, createWalletClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { wagmiContractConfig } from './abi'
const publicClient = createPublicClient({
  chain: mainnet,
  transport: http()
})
const walletClient = createWalletClient({
  chain: mainnet,
  transport: custom(window.ethereum)
})
const [address] = await walletClient.getAddresses()
const { request } = await publicClient.simulateContract({
  ...wagmiContractConfig,
  functionName: 'mint',
  account: address,
})
const hash = await walletClient.writeContract(request)Deploying Contracts 
Ethers 
import { ContractFactory, providers } from 'ethers'
import { abi, bytecode } from './abi'
const provider = new providers.Web3Provider(window.ethereum)
const [address] = await provider.listAccounts()
const signer = provider.getSigner(address)
const contract = new ContractFactory(abi, bytecode, signer)
await contract.deploy()viem 
import { createWalletClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { abi, bytecode } from './abi'
const walletClient = createWalletClient({
  chain: mainnet,
  transport: custom(window.ethereum)
})
const [address] = await walletClient.getAddresses()
await walletClient.deployContract({
  abi,
  account: address,
  bytecode,
})Contract Events 
Ethers 
import { getDefaultProvider } from 'ethers'
import { wagmiContractConfig } from './abi'
const provider = getDefaultProvider()
const { abi, address } = wagmiContractConfig
const contract = new Contract(address, abi, provider)
 
const listener = (from, to, amount, event) => {
  // ...
}
contract.on('Transfer', listener)
 
// unsubscribe
contract.off('Transfer', listener)viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { wagmiContractConfig } from './abi'
const client = createPublicClient({
  chain: mainnet,
  transport: http()
})
const unwatch = client.watchContractEvent({
  ...wagmiContractConfig,
  eventName: 'Transfer',
  onLogs: logs => {
    const { args: { from, to, amount }, eventName } = logs[0]
    // ...
  },
})
 
// unsubscribe
unwatch()Note: Logs are batched between polling intervals in viem to avoid excessive callback invocations. You can disable this behavior with
batch: falsehowever.
Gas Estimation 
Ethers 
import { getDefaultProvider } from 'ethers'
import { wagmiContractConfig } from './abi'
const provider = getDefaultProvider()
const { abi, address } = wagmiContractConfig
const contract = new Contract(address, abi, provider)
const gas = await contract.estimateGas.mint()viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { wagmiContractConfig } from './abi'
const client = createPublicClient({
  chain: mainnet,
  transport: http()
})
const gas = await client.estimateContractGas({
  ...wagmiContractConfig, 
  functionName: 'mint'
})Call 
Ethers 
import { getDefaultProvider } from 'ethers'
import { wagmiContractConfig } from './abi'
const provider = getDefaultProvider()
const { abi, address } = wagmiContractConfig
const contract = new Contract(address, abi, provider)
await contract.callStatic.mint()viem 
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { wagmiContractConfig } from './abi'
const client = createPublicClient({
  chain: mainnet,
  transport: http()
})
await client.simulateContract({
  ...wagmiContractConfig, 
  functionName: 'mint'
})Contract Instances 
Ethers 
import { getDefaultProvider } from 'ethers'
import { wagmiContractConfig } from './abi'
const provider = getDefaultProvider()
const { abi, address } = wagmiContractConfig
const contract = new Contract(address, abi, provider)
const supply = await contract.totalSupply()
const listener = (from, to, amount, event) => {
  // ...
}
contract.on('Transfer', listener)
contract.off('Transfer', listener)viem 
import { createPublicClient, http, getContract } from 'viem'
import { mainnet } from 'viem/chains'
import { wagmiContractConfig } from './abi'
const client = createPublicClient({
  chain: mainnet,
  transport: http()
})
const contract = getContract({
  ...wagmiContractConfig,
  publicClient: client,
})
const supply = await contract.read.totalSupply()
const unwatch = contract.watchEvent.Transfer({
  onLogs: logs => {
    const { args: { from, to, amount }, eventName } = logs[0]
    // ...
  },
})
unwatch()ABI Utilities 
abiCoder.encode 
Ethers 
import { utils } from 'ethers'
const abiCoder = utils.defaultAbiCoder()
// Object
abiCoder.encode(
  [{ type: 'uint', name: 'x' }, { type: 'string', name: 'y' }],
  [1234, 'Hello world']
)
// Human Readable
abiCoder.encode(
  ['uint', 'string'], 
  [1234, 'Hello World']
);viem 
import { encodeAbiParameters, parseAbiParameters } from 'viem'
// Object
encodeAbiParameters(
  [{ type: 'uint', name: 'x' }, { type: 'string', name: 'y' }],
  [1234, 'Hello world']
)
// Human Readable
encodeAbiParameters(
  parseAbiParameters('uint, string'),
  [1234, 'Hello world']
)abiCoder.decode 
Ethers 
import { utils } from 'ethers'
const abiCoder = utils.defaultAbiCoder()
// Object
abiCoder.decode(
  [{ type: 'uint', name: 'x' }, { type: 'string', name: 'y' }],
  '0x00000000000000000000000000000000000000000000000000000000000004d20000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'
)
// Human Readable
abiCoder.decode(
  ['uint', 'string'], 
  '0x00000000000000000000000000000000000000000000000000000000000004d20000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'
);viem 
import { decodeAbiParameters, parseAbiParameters } from 'viem'
// Object
decodeAbiParameters(
  [{ type: 'uint', name: 'x' }, { type: 'string', name: 'y' }],
  '0x00000000000000000000000000000000000000000000000000000000000004d20000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'
)
// Human Readable
decodeAbiParameters(
  parseAbiParameters('uint, string'),
  '0x00000000000000000000000000000000000000000000000000000000000004d20000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'
)Notice: different from ethers, viem only supports standard tuple expression for Human Readable. example: (uint a, string b) is valid, but tuple(uint a, string b) is not.
Fragments & Interfaces 
In viem, there is no concept of "fragments" & "interfaces". We want to stick as close to the wire as possible and not introduce middleware abstractions and extra layers over ABIs. Instead of working with "fragments", we encourage you to work with the ABI itself. We provide utilities such as getAbiItem, parseAbi parseAbiItem, parseAbiParameters and parseAbiParameter which covers the use cases of interfaces & fragments.
Interface.format 
viem only supports Human Readable → Object format.
Ethers 
import { utils } from 'ethers'
const interface = new Interface([
  'constructor(string symbol, string name)',
  'function transferFrom(address from, address to, uint amount)',
  'function transferFrom(address from, address to, uint amount, bool x)',
  'function mint(uint amount) payable',
  'function balanceOf(address owner) view returns (uint)'
])
const json = interface.format(utils.FormatTypes.json)viem 
import { parseAbi } from 'viem'
const json = parseAbi([
  'constructor(string symbol, string name)',
  'function transferFrom(address from, address to, uint amount)',
  'function transferFrom(address from, address to, uint amount, bool x)',
  'function mint(uint amount) payable',
  'function balanceOf(address owner) view returns (uint)',
  'event Transfer(address indexed from, address indexed to, uint256 amount)'
])Fragment.from 
ethers 
import { utils } from 'ethers'
const fragment = utils.Fragment.from('function balanceOf(address owner) view returns (uint)')viem 
import { parseAbiItem } from 'viem'
const abiItem = parseAbiItem('function balanceOf(address owner) view returns (uint)')ParamType.from 
ethers 
import { utils } from 'ethers'
const param = utils.ParamType.from('address owner')viem 
import { parseAbiParameter } from 'viem'
const param = parseAbiParameter('address owner')Fragment Access 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const interface = new utils.Interface(abi) 
interface.getFunction('transferFrom')
interface.getEvent('Transfer')viem 
import { getAbiItem } from 'viem'
import { abi } from './abi'
getAbiItem({ abi, name: 'transferFrom' }) 
getAbiItem({ abi, name: 'Transfer' })Interface.encodeDeploy 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const iface = new utils.Interface(abi); 
const data = iface.encodeDeploy(['SYM', 'Some Name'])viem 
import { encodeDeployData } from 'viem'
import { abi, bytecode } from './abi'
const data = encodeDeployData({ 
  abi,
  bytecode,
  args: ['SYM', 'Some Name']
})Note: viem concatinates the contract bytecode onto the ABI encoded data.
Interface.encodeErrorResult 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const iface = new utils.Interface(abi); 
const data = iface.encodeErrorResult('AccountLocked', [
  '0x8ba1f109551bD432803012645Ac136ddd64DBA72',
  utils.parseEther('1.0')
]);viem 
import { encodeErrorResult, parseEther } from 'viem'
import { abi } from './abi'
const data = encodeErrorResult({ 
  abi: wagmiAbi,
  errorName: 'AccountLocked',
  args: [
    '0x8ba1f109551bD432803012645Ac136ddd64DBA72',
    parseEther('1.0')
  ]
})Interface.encodeFilterTopics 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const iface = new utils.Interface(abi); 
const data = iface.encodeFilterTopics('Transfer', [
  null,
  '0x8ba1f109551bD432803012645Ac136ddd64DBA72'
])viem 
import { encodeEventTopics } from 'viem'
import { abi } from './abi'
const data = encodeEventTopics({ 
  abi,
  eventName: 'Transfer',
  args: {
    to: '0x8ba1f109551bD432803012645Ac136ddd64DBA72'
  }
})Interface.encodeFunctionData 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const iface = new utils.Interface(abi); 
const data = iface.encodeFunctionData('transferFrom', [
  '0x8ba1f109551bD432803012645Ac136ddd64DBA72',
  '0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C',
  parseEther('1.0')
])viem 
import { encodeFunctionData, parseEther } from 'viem'
import { abi } from './abi'
const data = encodeFunctionData({ 
  abi,
  functionName: 'transferFrom',
  args: [
    '0x8ba1f109551bD432803012645Ac136ddd64DBA72',
    '0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C',
    parseEther('1.0')
  ]
})Interface.encodeFunctionResult 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const iface = new utils.Interface(abi); 
const data = iface.encodeFunctionResult('balanceOf', [
  '0x8ba1f109551bD432803012645Ac136ddd64DBA72'
])viem 
import { encodeFunctionResult, parseEther } from 'viem'
import { abi } from './abi'
const data = encodeFunctionResult({ 
  abi,
  functionName: 'balanceOf',
  value: ['0x8ba1f109551bD432803012645Ac136ddd64DBA72']
})Interface.decodeErrorResult 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const iface = new utils.Interface(abi); 
const result = iface.decodeErrorResult("AccountLocked", '0xf7c3865a0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000000de0b6b3a7640000')viem 
import { decodeErrorResult, parseEther } from 'viem'
import { abi } from './abi'
const result = decodeErrorResult({ 
  abi,
  data: '0xf7c3865a0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000000de0b6b3a7640000'
})Interface.decodeEventLog 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const iface = new utils.Interface(abi); 
const result = iface.decodeEventLog(
  'Transfer', 
  data: '0x0000000000000000000000000000000000000000000000000de0b6b3a7640000', 
  topics: [
    '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
    '0x0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72',
    '0x000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c'
  ]
);viem 
import { decodeEventLog, parseEther } from 'viem'
import { abi } from './abi'
const result = decodeEventLog({ 
  abi,
  data: '0x0000000000000000000000000000000000000000000000000de0b6b3a7640000', 
  topics: [
    '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
    '0x0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72',
    '0x000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c'
  ]
})Interface.decodeFunctionData 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const iface = new utils.Interface(abi); 
const result = iface.decodeFunctionData('transferFrom', '0x23b872dd0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c0000000000000000000000000000000000000000000000000de0b6b3a7640000');viem 
import { decodeFunctionData, parseEther } from 'viem'
import { abi } from './abi'
const result = decodeFunctionData({ 
  abi,
  data: '0x23b872dd0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c0000000000000000000000000000000000000000000000000de0b6b3a7640000',
})Interface.decodeFunctionResult 
Ethers 
import { utils } from 'ethers'
import { abi } from './abi'
const iface = new utils.Interface(abi); 
const result = iface.decodeFunctionResult('balanceOf', '0x0000000000000000000000000000000000000000000000000de0b6b3a7640000');viem 
import { decodeFunctionResult, parseEther } from 'viem'
import { abi } from './abi'
const result = decodeFunctionResult({ 
  abi,
  functionName: 'balanceOf',
  data: '0x0000000000000000000000000000000000000000000000000de0b6b3a7640000',
})Address Utilities 
getAddress 
Ethers 
import { utils } from 'ethers'
const address = utils.getAddress('0x8ba1f109551bd432803012645ac136ddd64dba72')viem 
import { getAddress } from 'viem'
const address = getAddress('0x8ba1f109551bd432803012645ac136ddd64dba72')isAddress 
Ethers 
import { utils } from 'ethers'
const address = utils.isAddress('0x8ba1f109551bd432803012645ac136ddd64dba72')viem 
import { isAddress } from 'viem'
const address = isAddress('0x8ba1f109551bd432803012645ac136ddd64dba72')getContractAddress 
Ethers 
import { utils } from 'ethers'
const address = utils.getContractAddress({ from: '0x...', nonce: 5 });viem 
import { getContractAddress } from 'viem'
const address = getContractAddress({ from: '0x...', nonce: 5 })getCreate2Address 
Ethers 
import { utils } from 'ethers'
const from = '0x8ba1f109551bD432803012645Ac136ddd64DBA72';
const salt = '0x7c5ea36004851c764c44143b1dcb59679b11c9a68e5f41497f6cf3d480715331';
const initCode = '0x6394198df16000526103ff60206004601c335afa6040516060f3';
const initCodeHash = utils.keccak256(initCode);
 
const address = utils.getCreate2Address(from, salt, initCodeHash);viem 
import { getContractAddress } from 'viem'
const address = getContractAddress({
  bytecode: '0x6394198df16000526103ff60206004601c335afa6040516060f3',
  from: '0x8ba1f109551bD432803012645Ac136ddd64DBA72',
  opcode: 'CREATE2',
  salt: '0x7c5ea36004851c764c44143b1dcb59679b11c9a68e5f41497f6cf3d480715331',
});BigNumber Utilities 
Ethers 
Many.
viem 
None. We use browser native BigInt.
Byte Manipulation Utilities 
isBytes 
Ethers 
import { utils } from 'ethers'
utils.isBytes(new Uint8Array([1, 69, 420]))viem 
import { isBytes } from 'viem'
isBytes(new Uint8Array([1, 69, 420]))isHexString 
Ethers 
import { utils } from 'ethers'
utils.isHexString('0xdeadbeef')viem 
import { isHex } from 'viem'
isHex('0xdeadbeef')isBytesLike 
Ethers 
import { utils } from 'ethers'
utils.isBytesLike('0xdeadbeef')viem 
import { isBytes, isHex } from 'viem'
isBytes('0xdeadbeef') || isHex('0xdeadbeef')arrayify 
Ethers 
import { utils } from 'ethers'
utils.arrayify('0xdeadbeef')viem 
import { toBytes } from 'viem'
toBytes('0xdeadbeef')hexlify 
Ethers 
import { utils } from 'ethers'
utils.hexlify(new Uint8Array([1, 69, 420]))viem 
import { toHex } from 'viem'
toHex(new Uint8Array([1, 69, 420]))hexValue 
Ethers 
import { utils } from 'ethers'
utils.hexValue(1)viem 
import { toHex } from 'viem'
toHex(1)formatBytes32String 
Ethers 
import { utils } from 'ethers'
utils.formatBytes32String('Hello world')
// 0x48656c6c6f20776f726c642e0000000000000000000000000000000000000000viem 
import { stringToHex } from 'viem'
stringToHex(
  'Hello world', 
  { size: 32 }
)
// 0x48656c6c6f20776f726c642e0000000000000000000000000000000000000000parseBytes32String 
Ethers 
import { utils } from 'ethers'
utils.parseBytes32String('0x48656c6c6f20776f726c642e0000000000000000000000000000000000000000')
// "Hello world"viem 
import { hexToString } from 'viem'
hexToString(
  '0x48656c6c6f20776f726c642e0000000000000000000000000000000000000000', 
  { size: 32 }
)
// "Hello world"concat 
Ethers 
import { utils } from 'ethers'
utils.concat([new Uint8Array([69]), new Uint8Array([420])])viem 
import { concat, toBytes } from 'viem'
concat([new Uint8Array([69]), new Uint8Array([420])])stripZeros 
Ethers 
import { utils } from 'ethers'
utils.stripZeros(new Uint8Array([0, 0, 0, 0, 0, 69]))viem 
import { trim } from 'viem'
trim(new Uint8Array([0, 0, 0, 0, 0, 69]))zeroPad 
Ethers 
import { utils } from 'ethers'
utils.zeroPad(new Uint8Array([69]), 32)viem 
import { pad } from 'viem'
pad(new Uint8Array([69]), { size: 32 })hexConcat 
Ethers 
import { utils } from 'ethers'
utils.hexConcat(['0x00000069', '0x00000420'])viem 
import { concat, toBytes } from 'viem'
concat(['0x00000069', '0x00000420'])hexDataLength 
Ethers 
import { utils } from 'ethers'
utils.hexDataLength('0x00000069')viem 
import { size } from 'viem'
size('0x00000069')hexDataSlice 
Ethers 
import { utils } from 'ethers'
utils.hexDataSlice('0x00000069', 4)viem 
import { slice } from 'viem'
slice('0x00000069', 4)hexStripZeros 
Ethers 
import { utils } from 'ethers'
utils.hexStripZeros('0x00000069')viem 
import { trim } from 'viem'
trim('0x00000069')hexZeroPad 
Ethers 
import { utils } from 'ethers'
utils.hexZeroPad('0x69', 32)viem 
import { pad } from 'viem'
pad('0x69', { size: 32 })Display Logic & Input Utilities 
formatUnits 
Ethers 
import { utils } from 'ethers'
utils.formatUnits(BigNumber.from('1000000000'), 9)viem 
import { formatUnits } from 'viem'
formatUnits(1000000000n, 9)formatEther 
Ethers 
import { utils } from 'ethers'
utils.formatEther(BigNumber.from('1000000000000000000'))viem 
import { formatEther } from 'viem'
formatEther(1000000000000000000n)parseUnits 
Ethers 
import { utils } from 'ethers'
utils.parseUnits('1.0', 18)viem 
import { parseUnits } from 'viem'
parseUnits('1', 18)parseEther 
Ethers 
import { utils } from 'ethers'
utils.parseEther('1.0')viem 
import { parseEther } from 'viem'
parseEther('1')Encoding Utilities 
RLP.encode 
Ethers 
import { utils } from 'ethers'
utils.RLP.encode('0x12345678')viem 
import { toRlp } from 'viem'
toRlp('0x12345678')RLP.decode 
Ethers 
import { utils } from 'ethers'
utils.RLP.decode('0x8412345678')viem 
import { fromRlp } from 'viem'
fromRlp('0x8412345678')Hashing Utilities 
id 
Ethers 
import { utils } from 'ethers'
utils.id('function ownerOf(uint256 tokenId)')
// hash utf-8 data
utils.id('hello world')viem 
import { getFunctionSelector, keccak256, toHex } from 'viem'
getFunctionSelector('function ownerOf(uint256 tokenId)')
// hash utf-8 data
keccak256(toHex('hello world'))keccak256 
Ethers 
import { utils } from 'ethers'
utils.keccak256(utils.toUtf8Bytes('hello world'))viem 
import { keccak256, toBytes } from 'viem'
keccak256(toBytes('hello world'))encodeBase64/decodeBase64 
viem does not provide Base64 encoding utilities.
You can use browser native atob and btoa instead.
encodeBase58/decodeBase58 
viem does not provide Base58 encoding utilities.
You can use libraries such as base58-js or bs58 instead.
namehash 
Ethers 
import { utils } from 'ethers'
utils.namehash('awkweb.eth')viem 
import { namehash } from 'viem'
namehash('awkweb.eth')solidityPack & solidityKeccak256 
Ethers 
import { utils } from 'ethers'
utils.solidityPack(['int16', 'uint48'], [-1, 12])
utils.solidityKeccak256(['int16', 'uint48'], [-1, 12])viem 
import { encodePacked, keccak256 } from 'viem'
encodePacked(['int16', 'uint48'], [-1, 12])
keccak256(encodePacked(['int16', 'uint48'], [-1, 12]))String Utilities 
toUtf8Bytes 
Ethers 
import { utils } from 'ethers'
utils.toUtf8Bytes('Hello World')viem 
import { stringToBytes } from 'viem'
stringToBytes('Hello World')toUtf8String 
Ethers 
import { utils } from 'ethers'
utils.toUtf8String(new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]))viem 
import { bytesToString } from 'viem'
bytesToString(new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]))Transaction Utilities 
serializeTransaction 
Ethers 
import { utils } from 'ethers'
const serialized = utils.serializeTransaction({
  chainId: 1,
  maxFeePerGas: utils.parseGwei('20'),
  maxPriorityFeePerGas: utils.parseGwei('2'),
  nonce: 69,
  to: "0x1234512345123451234512345123451234512345",
  type: 2,
  value: utils.parseEther('0.01'),
})viem 
import { serializeTransaction, parseEther, parseGwei } from 'viem'
const serialized = serializeTransaction({
  chainId: 1,
  gas: 21001n,
  maxFeePerGas: parseGwei('20'),
  maxPriorityFeePerGas: parseGwei('2'),
  nonce: 69,
  to: "0x1234512345123451234512345123451234512345",
  value: parseEther('0.01'),
})parseTransaction 
Ethers 
import { utils } from 'ethers'
const transaction = utils.parseTransaction('0x02ef0182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0')viem 
import { parseTransaction } from 'viem'
const transaction = parseTransaction('0x02ef0182031184773594008477359400809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c0')