@eth-optimism/viem
package is an easy way to add bridging functionality to your javascript-based application.
It also provides some safety rails to prevent common mistakes that could cause tokens to be made inaccessible.
Behind the scenes, @eth-optimism/viem
package uses the Standard Bridge contracts to transfer tokens.
Make sure to check out the Standard Bridge guide if you want to learn more about how the bridge works under the hood.
The Standard Bridge does not support fee on transfer
tokens or rebasing
tokens
because they can cause bridge accounting errors.
Supported networks
The@eth-optimism/viem
package supports any of the Superchain networks.
If you want to use a network that isn’t included by default, you can simply instantiate the package with the appropriate contract addresses.
Dependencies
Create a demo project
You’re going to use the@eth-optimism/viem
package for this tutorial.
Since the @eth-optimism/viem
package is a Node.js library, you’ll need to create a Node.js project to use it.
1
Make a Project Folder
2
Initialize the Project
3
Install the `@eth-optimism/viem`
4
Install viem
Want to create a new wallet for this tutorial? If you have
cast
installed
you can run cast wallet new
in your terminal to create a new wallet and get
the private key.Get ETH on Sepolia and OP Sepolia
This tutorial explains how to bridge tokens from Sepolia to OP Sepolia. You will need to get some ETH on both of these testnets.You can use this faucet to get ETH on Sepolia.
You can use the Superchain
Faucet to get ETH on OP
Sepolia.
Add a private key to your environment
You need a private key to sign transactions. Set your private key as an environment variable with theexport
command.
Make sure this private key corresponds to an address that has ETH on both Sepolia and OP Sepolia.
Start the Node REPL
You’re going to use the Node REPL to interact with the@eth-optimism/viem
.
To start the Node REPL, run the following command in your terminal:
Import dependencies
You need to import some dependencies into your Node REPL session. The@eth-optimism/viem
package uses ESM modules, and to use in the Node.js REPL, you need to use dynamic imports with await.
Here’s how to do it:
1
Import the @eth-optimism/viem package
Set session variables
You’ll need a few variables throughout this tutorial. Let’s set those up now.1
Load your private key
This step retrieves your private key from the environment variable you set earlier and converts it into an account object that Viem can use for transaction signing.The private key is essential for authorizing transactions on both L1 and L2 networks.
For security reasons, we access it from an environment variable rather than hardcoding it.
2
Create the RPC providers and wallets
Here we establish the connections to both networks by creating four different clients:
- L1 Public Client: For reading data from the Sepolia network
- L1 Wallet Client: For signing and sending transactions on Sepolia
- L2 Public Client: For reading data from OP Sepolia
- L2 Wallet Client: For signing and sending transactions on OP Sepolia
<YOUR_API_KEY>
with your API key from a RPC provider.3
Set the L1 and L2 ERC-20 addresses
We define the addresses of the ERC-20 tokens on both networks.
These are specially deployed test tokens with corresponding implementations on both L1 (Sepolia) and L2 (OP Sepolia).The L2 token is configured to recognize deposits from its L1 counterpart.
We also define a constant
oneToken
representing the full unit (10^18 wei) to simplify our deposit and withdrawal operations.If you’re coming from the Bridging Your Standard ERC-20 Token to OP Mainnet
Using the Standard Bridge or Bridging Your
Custom ERC-20 Token to OP Mainnet Using the Standard
Bridge tutorials, you can use the addresses
of your own ERC-20 tokens here instead.
Get L1 tokens
You’re going to need some tokens on L1 that you can bridge to L2. The L1 testing token located at0x5589BB8228C07c4e15558875fAf2B859f678d129
has a faucet
function that makes it easy to get tokens.
1
Set the ERC20 ABI
The Application Binary Interface (ABI) defines how to interact with the smart contract functions. This ERC-20 ABI includes several critical functions:
balanceOf
: Allows us to check token balances for any addressfaucet
: A special function in this test token that mints new tokens to the callerapprove
: Required to grant the bridge permission to transfer tokens on our behalfallowance
: To check how many tokens we’ve approved for the bridgedecimals
andsymbol
: Provide token metadata
2
Request some tokens
Now we’ll call the
faucet
function on the L1 test token contract to receive free tokens for testing.
This transaction will mint new tokens directly to our wallet address.The function doesn’t require any parameters - it simply credits a predetermined amount to whoever calls it.
We store the transaction hash for later reference and wait for the transaction to be confirmed.3
Check your token balance
After using the faucet, we verify our token balance by calling the
balanceOf
function on the L1 token contract.This step confirms that we’ve successfully received tokens before proceeding with the bridging process.
The balance is returned in the smallest unit (wei), but we format it into a more readable form using the formatEther
utility function from viem
, since this token uses 18 decimal places.Deposit tokens
Now that you have some tokens on L1, you can deposit those tokens into theL1StandardBridge
contract.
You’ll then receive the same number of tokens on L2 in return.
1
Define the amount to deposit
We define a variable
oneToken
that represents 1 full token in its base units (wei).
ERC-20 tokens typically use 18 decimal places, so 1 token equals 10^18 wei.This constant helps us work with precise token amounts in our transactions, avoiding rounding errors and ensuring exact value transfers.
We’ll use this value for both deposits and withdrawals2
Allow the Standard Bridge to access your tokens
ERC-20 tokens require a two-step process for transferring tokens on behalf of a user.
First, we must grant permission to the bridge contract to spend our tokens by calling the
approve
function on the token contract.We specify the bridge address from the chain configuration and the exact amount we want to bridge.
This approval transaction must be confirmed before the bridge can move our tokens.3
Wait for approval
After submitting the approval transaction, we need to wait for it to be confirmed on L1.
We use the
waitForTransactionReceipt
function to monitor the transaction until it’s included in a block.The receipt provides confirmation details, including which block includes our transaction.
This step ensures our approval is finalized before attempting to bridge tokens.4
Deposit your tokens
Now we can execute the actual bridging operation using the
depositERC20
function from the @eth-optimism/viem
package.This function handles all the complex interactions with the L1StandardBridge
contract for us.
We provide:- The addresses of both the L1 and L2 tokens
- The amount to bridge
- The target chain (OP Sepolia)
- Our wallet address as the recipient on L2
- A minimum gas limit for the L2 transaction
Using a smart contract wallet? As a safety measure,
depositERC20
will fail
if you try to deposit ETH from a smart contract wallet without specifying a
recipient
. Add the recipient
option to the depositERC20
call to fix
this. Check out the @eth-optimism/viem
docs for
more info on the options you can pass to depositERC20
.5
Wait for the deposit to be relayed
After initiating the deposit, we need to wait for the L1 transaction to be confirmed.
This function tracks the transaction until it’s included in an L1 block.Note that while this confirms the deposit was accepted on L1, there will still be a short delay (typically a few minutes) before the tokens appear on L2, as the transaction needs to be processed by the Optimism sequencer.
6
Check your token balance on L1
After the deposit transaction is confirmed, we check our token balance on L1 again to verify that the tokens have been deducted.This balance should be lower by the amount we bridged, as those tokens are now escrowed in the
L1StandardBridge
contract.
This step helps confirm that the first part of the bridging process completed successfully:7
Check your token balance on L2
After allowing some time for the L2 transaction to be processed, we check our token balance on L2 to verify that we’ve received the bridged tokens.The newly minted L2 tokens should appear in our wallet at the same address we used on L1.
This step confirms the complete success of the bridge operation from L1 to L2.
Withdraw tokens
You just bridged some tokens from L1 to L2. Nice! Now you’re going to repeat the process in reverse to bridge some tokens from L2 to L1.1
Initiate the withdrawal
To move tokens back to L1, we use the
withdrawOptimismERC20
function from the @eth-optimism/viem
package.
This function interacts with the L2StandardBridge
contract to initialize the withdrawal process.
We specify:- The L2 token address
- The amount to withdraw (we’re using half of a token in this tutorial)
- Our address as the recipient on L1
- A minimum gas limit for the transaction
2
Wait for the transaction receipt
Similar to deposits, we wait for the withdrawal transaction to be confirmed on L2.
This receipt provides confirmation that the withdrawal has been initiated.The transaction logs contain critical information that will be used later in the withdrawal verification process.
This is only the first step in the withdrawal - the tokens are now locked on L2, but not yet available on L1.
This step can take a few minutes. Feel free to take a quick break while you
wait.
3
Check your token balance on L2
After the withdrawal transaction is confirmed, we check our token balance on L2 again to verify that the tokens have been deducted.
Our L2 balance should now be lower by the amount we initiated for withdrawal.At this point, the withdrawal process has begun, but the tokens are not yet available on L1 - they will become accessible after the 7-day challenge period and after completing the “prove” and “finalize” withdrawal steps.
Next steps
Congrats! You’ve just deposited and withdrawn tokens using@eth-optimism/viem
package.
You should now be able to write applications that use the @eth-optimism/viem
package to transfer ERC-20 tokens between L1 and L2.
Although this tutorial used Sepolia and OP Sepolia, the same process works for Ethereum and OP Mainnet.