diff --git a/pages/app-developers/tutorials/bridging/cross-dom-bridge-erc20.mdx b/pages/app-developers/tutorials/bridging/cross-dom-bridge-erc20.mdx
index cf7f98399..4a6932a25 100644
--- a/pages/app-developers/tutorials/bridging/cross-dom-bridge-erc20.mdx
+++ b/pages/app-developers/tutorials/bridging/cross-dom-bridge-erc20.mdx
@@ -1,11 +1,11 @@
---
-title: Bridging ERC-20 tokens to OP Mainnet with the Optimism SDK
+title: Bridging ERC-20 tokens to OP Mainnet
description: >-
- Learn how to use the Optimism SDK to transfer ERC-20 tokens between Layer 1
+ Learn how to use the @eth-optimism/viem package to transfer ERC-20 tokens between Layer 1
(Ethereum or Sepolia) and Layer 2 (OP Mainnet or OP Sepolia).
lang: en-US
content_type: tutorial
-topic: bridging-erc-20-tokens-to-op-mainnet-with-the-optimism-sdk
+topic: bridging-erc-20-tokens-to-op-mainnet
personas:
- app-developer
categories:
@@ -18,19 +18,14 @@ is_imported_content: 'false'
---
import { Callout, Steps } from 'nextra/components'
-import { WipCallout } from '@/components/WipCallout'
-
+# Bridging ERC-20 tokens to OP Mainnet
-# Bridging ERC-20 tokens to OP Mainnet with the Optimism SDK
-
-
-
-This tutorial explains how you can use the [Optimism SDK](https://sdk.optimism.io) to bridge ERC-20 tokens from L1 (Ethereum or Sepolia) to L2 (OP Mainnet or OP Sepolia).
-The Optimism SDK is an easy way to add bridging functionality to your javascript-based application.
+This tutorial explains how you can use [@eth-optimism/viem](https://www.npmjs.com/package/@eth-optimism/viem) to bridge ERC-20 tokens from L1 (Ethereum or Sepolia) to L2 (OP Mainnet or OP Sepolia).
+The `@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, the Optimism SDK uses the [Standard Bridge](/app-developers/bridging/standard-bridge) contracts to transfer tokens.
+Behind the scenes, `@eth-optimism/viem` package uses the [Standard Bridge](/app-developers/bridging/standard-bridge) contracts to transfer tokens.
Make sure to check out the [Standard Bridge guide](/app-developers/bridging/standard-bridge) if you want to learn more about how the bridge works under the hood.
@@ -42,9 +37,8 @@ Make sure to check out the [Standard Bridge guide](/app-developers/bridging/stan
## Supported networks
-The Optimism SDK supports any of the [Superchain networks](/superchain/networks).
-[Some Superchain networks](https://sdk.optimism.io/enums/l2chainid) are already included in the SDK by default.
-If you want to use a network that isn't included by default, you can simply [instantiate the SDK with the appropriate contract addresses](/app-developers/get-started).
+The `@eth-optimism/viem` package supports any of the [Superchain networks](/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](/app-developers/get-started).
## Dependencies
@@ -53,15 +47,15 @@ If you want to use a network that isn't included by default, you can simply [ins
## Create a demo project
-You're going to use the Optimism SDK for this tutorial.
-Since the Optimism SDK is a [Node.js](https://nodejs.org/en/) library, you'll need to create a Node.js project to use it.
+You're going to use the `@eth-optimism/viem` package for this tutorial.
+Since the `@eth-optimism/viem` package is a [Node.js](https://nodejs.org/en/) library, you'll need to create a Node.js project to use it.
{Make a Project Folder
}
```bash
- mkdir op-sample-project
- cd op-sample-project
+ mkdir bridging-erc20-tokens
+ cd bridging-erc20-tokens
```
{Initialize the Project
}
@@ -70,16 +64,16 @@ Since the Optimism SDK is a [Node.js](https://nodejs.org/en/) library, you'll ne
pnpm init
```
- {Install the Optimism SDK
}
+ {Install the `@eth-optimism/viem`
}
```bash
- pnpm add @eth-optimism/sdk
+ pnpm add @eth-optimism/viem
```
- {Install ethers.js
}
+ {Install viem
}
```bash
- pnpm add ethers@^5
+ pnpm add viem
```
@@ -114,7 +108,7 @@ export TUTORIAL_PRIVATE_KEY=0x...
## Start the Node REPL
-You're going to use the Node REPL to interact with the Optimism SDK.
+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:
```bash
@@ -126,16 +120,13 @@ This will bring up a Node REPL prompt that allows you to run javascript code.
## 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:
- {Import the Optimism SDK
}
-
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L3 hash=26b2fdb17dd6c8326a54ec51f0769528
- ```
-
- {Import ethers.js
}
+ {Import the @eth-optimism/viem package
}
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L4 hash=69a65ef97862612e4978b8563e6dbe3a
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L2-L10 hash=5e88e02086fb2f4cf2e1e99a4cd30b04
```
@@ -147,20 +138,39 @@ Let's set those up now.
{Load your private key
}
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L6 hash=755b77a7ffc7dfdc186f36c37d3d847a
+ 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.
+
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L16-L17 hash=6a160f7ff083969091e72c90e1138563
```
{Create the RPC providers and wallets
}
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L8-L11 hash=9afdce50665ae93bce602068071ffaa1
+ Here we establish the connections to both networks by creating four different clients:
+
+ 1. L1 Public Client: For reading data from the Sepolia network
+ 2. L1 Wallet Client: For signing and sending transactions on Sepolia
+ 3. L2 Public Client: For reading data from OP Sepolia
+ 4. L2 Wallet Client: For signing and sending transactions on OP Sepolia
+
+ Each client is configured with the appropriate chain information and RPC endpoint.
+ This dual-network setup allows us to seamlessly interact with both layers using the same account.
+ Replace `` with your API key from a RPC provider.
+
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L19-L42 hash=7f6a923f34ed2b0babdf44f57f88f8c1
```
{Set the L1 and L2 ERC-20 addresses
}
- This tutorial uses existing ERC-20 tokens that have been deployed on Sepolia and OP Sepolia.
- These tokens are designed for testing the bridging process.
+ 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.
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L13-L14 hash=d8f0d4c8124782a6cd36097ff31010e5
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L12-L13 hash=d4da7ec838773c9f0e4ca38f4ba70242
```
@@ -180,22 +190,38 @@ The L1 testing token located at [`0x5589BB8228C07c4e15558875fAf2B859f678d129`](h
{Set the ERC20 ABI
}
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L16 hash=d1caeba8dc014637e2b0b72f5cd076d0
- ```
+ 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 address
+ * `faucet`: A special function in this test token that mints new tokens to the caller
+ * `approve`: Required to grant the bridge permission to transfer tokens on our behalf
+ * `allowance`: To check how many tokens we've approved for the bridge
+ * `decimals` and `symbol`: Provide token metadata
- {Create a Contract instance for the L1 token
}
+ This comprehensive ABI gives us everything we need to manage our tokens across both L1 and L2.
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L18 hash=9f9d7e38319ff5263e0e99d80d495554
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L44-L95 hash=7967d72de2b91fb16ba2b4723995e307
```
{Request some tokens
}
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L21-L22 hash=3533ec5426e8845fdb9af1e9e8d3de4c
+ 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.
+
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L97-L104 hash=90511372fb9f975abfa8ec68659eb4a0
```
{Check your token balance
}
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L25 hash=d7a60aa394d1055555c2aeab2a2e111d
+ 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.
+
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L109-L115 hash=63fcd2ca7e6fe0466340d615950e9658
```
@@ -207,68 +233,92 @@ You'll then receive the same number of tokens on L2 in return.
{Define the amount to deposit
}
- The testing token has 18 decimal places, so you'll want to define a variable that represents one token.
+ 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 withdrawals
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L27 hash=9349517ae6165a8798e49750da8faeee
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L14 hash=1940b943a802d51e41572bc7d6bc4515
```
- {Create a CrossChainMessenger instance
}
-
- The Optimism SDK exports a `CrossChainMessenger` class that makes it easy to interact with the `L1StandardBridge` contract.
+ {Allow the Standard Bridge to access your tokens
}
- Create an instance of the `CrossChainMessenger` class:
+ 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.
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L29-L34 hash=997b9c4cdd5fb1f9d4e0882a683ae016
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L118-L125 hash=58cf2e8e55c1466e3ddaa1c030a5266b
```
- {Allow the Standard Bridge to access your tokens
}
+ {Wait for approval
}
- Before you can deposit your tokens, you'll need to give the Standard Bridge contract an allowance of tokens on L1.
- This will allow the Standard Bridge to pull these tokens out of your address and escrow inside the bridge.
+ 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.
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L37-L38 hash=3d9347e57540e808d71230c1bbe49db5
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L128 hash=cfbada5a799bb17450ce56580bc31e11
```
{Deposit your tokens
}
- Now you can deposit your tokens into the Standard Bridge contract.
+ 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
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L41-L42 hash=0dc6191c87c0a371d7a469ed98190e57
+ This streamlined process ensures our tokens are safely transferred to L2.
+
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L130-L139 hash=5084d848deaf4b798706446a24e54a18
```
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 [Optimism SDK
- docs](https://sdk.optimism.io/classes/crosschainmessenger#depositERC20-2) for
+ this. Check out the [@eth-optimism/viem
+ docs](https://github.com/ethereum-optimism/ecosystem/tree/main/packages/viem) for
more info on the options you can pass to `depositERC20`.
{Wait for the deposit to be relayed
}
- You can use the `waitForMessageStatus` function to wait for the deposit to be relayed to L2.
+ 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.
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L45 hash=659971675ab8d53bc2bd5196f72c873b
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L141-L142 hash=886c0a2fe4aa92dc67288d02bb654c3e
```
{Check your token balance on L1
}
- You should now have one less token 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:
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L48 hash=d7a60aa394d1055555c2aeab2a2e111d
- ```
-
- {Create a Contract instance for the L2 token
}
-
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L50 hash=d7ab5afad79dafcb7be976c3d0d3df84
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L148-L154 hash=9985ca726c10c42d96ea508c247a878c
```
{Check your token balance on L2
}
- You should now have one more token 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.
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L53 hash=b332b68817359e4c6e991ed83de6e490
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L177-L183 hash=bf12c15e0ea43846a09176d351bf4f33
```
@@ -279,26 +329,31 @@ Nice!
Now you're going to repeat the process in reverse to bridge some tokens from L2 to L1.
- {Start your withdrawal on L2
}
-
- The first step to withdrawing tokens from L2 to L1 is to start the withdrawal on L2.
+ {Initiate the withdrawal
}
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L56-L57 hash=b97f906085a2c350d9113488ea9b1d45
- ```
+ 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:
- {Check your token balance on L2
}
+ * 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
- You should now have one less token on L2, but your token balance on L1 will not have changed yet.
+ Unlike deposits, withdrawals from L2 to L1 are not immediate and require a multi-step process including a 7-day challenge period for security reasons.
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L60 hash=b332b68817359e4c6e991ed83de6e490
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L164-L171 hash=9ee233eaa1711443ff15e0d28d2da190
```
- {Wait until the withdrawal is ready to prove
}
+ {Wait for the transaction receipt
}
- The second step to withdrawing tokens from L2 to L1 is to prove to the bridge on L1 that the withdrawal happened on L2.
- You first need to wait until the withdrawal is ready to prove.
+ 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.
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L63 hash=e8b55ec0f16f90ba4d4197cf47ff8e6d
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L173-L174 hash=f1359ec27815a9fcf4964a877280da59
```
@@ -306,52 +361,20 @@ Now you're going to repeat the process in reverse to bridge some tokens from L2
wait.
- {Prove the withdrawal on L1
}
-
- Once the withdrawal is ready to be proven, you'll send an L1 transaction to prove that the withdrawal happened on L2.
-
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L66 hash=fee5f5e924472ee9daceb681ccae1cb9
- ```
-
- {Wait until the withdrawal is ready for relay
}
-
- The final step to withdrawing tokens from L2 to L1 is to relay the withdrawal on L1.
- This can only happen after the fault proof period has elapsed.
- On OP Mainnet, this takes 7 days.
-
-
- We're currently testing fault proofs on OP Sepolia, so withdrawal times
- reflect Mainnet times.
-
-
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L69 hash=55a41ac5586b8a688ffd6dfbb20f2d15
- ```
-
- {Relay the withdrawal on L1
}
-
- Once the withdrawal is ready to be relayed, you can finally complete the withdrawal process.
-
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L85 hash=f8d30944dad1664d82b9fdf14da59f9e
- ```
-
- {Wait until the withdrawal is relayed
}
-
- Now you simply wait until the message is relayed.
-
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L88 hash=c2c14a739c44011a058e9848a0019f15
- ```
-
- {Check your token balance on L1
}
+ {Check your token balance on L2
}
- You should now have one more token on L1.
+ 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.
- ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L91 hash=d7a60aa394d1055555c2aeab2a2e111d
+ ```js file=/public/tutorials/cross-dom-bridge-erc20.js#L177-L183 hash=bf12c15e0ea43846a09176d351bf4f33
```
## Next steps
Congrats!
-You've just deposited and withdrawn tokens using the Optimism SDK.
-You should now be able to write applications that use the Optimism SDK to transfer ERC-20 tokens between L1 and L2.
+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.
diff --git a/pages/notices/_meta.json b/pages/notices/_meta.json
index fb1599c69..bda2e2e29 100644
--- a/pages/notices/_meta.json
+++ b/pages/notices/_meta.json
@@ -7,6 +7,5 @@
"upgrade-14": "Upgrade 14: MT-Cannon and Isthmus L1 Contracts",
"upgrade-13": "Upgrade 13: OPCM and incident response improvements",
"blob-fee-bug": "Superchain testnets' blob fee bug",
- "custom-gas-tokens-deprecation": "Preparing for Custom Gas Tokens deprecation",
- "sdk-deprecation": "Preparing for Optimism SDK deprecation"
+ "custom-gas-tokens-deprecation": "Preparing for Custom Gas Tokens deprecation"
}
diff --git a/pages/notices/sdk-deprecation.mdx b/pages/notices/sdk-deprecation.mdx
deleted file mode 100644
index f64f6e724..000000000
--- a/pages/notices/sdk-deprecation.mdx
+++ /dev/null
@@ -1,83 +0,0 @@
----
-title: Preparing for Optimism SDK deprecation
-description: >-
- This page outlines the details of the Optimism SDK deprecation and guides
- developers to migrate to using `viem` library.
-lang: en-US
-content_type: guide
-topic: sdk-deprecation
-personas:
- - app-developer
-categories:
- - protocol
- - ethers
- - viem
-is_imported_content: 'false'
----
-
-## Preparing for Optimism SDK deprecation
-
-The Optimism SDK will officially be deprecated in Q1 2025. The project is shifting to the `viem` library for a more modern, efficient, and flexible development experience. This change affects all tutorials and resources that previously relied on the Optimism SDK, and relevant documentation has been updated accordingly.
-
-### Breaking changes to expect
-
-The migration from the Optimism SDK to [viem](https://viem.sh/op-stack) library brings several breaking changes:
-
-* **Transaction estimation**: Methods for estimating gas fees will now leverage `viem` APIs.
-* **Bridging**: All token bridging actions must be updated to use the `viem` library bridging methods.
-* **Cross-chain communication**: `viem` library simplifies the cross-domain messaging functionality.
-* **SDK method removal**: All deprecated SDK methods will be unavailable after Q1 2025.
-
-Developers and users are strongly encouraged to transition to `viem` before the deprecation date to avoid disruptions.
-
-### Updated tutorials
-
-We are updating our tutorials to use the `viem` library.
-
-### For app developers
-
-If your application currently depends on the Optimism SDK, you will need to migrate to using the `viem` library.
-The tutorials have been updated to reflect these changes, and it is critical to update your applications before the deprecation date to maintain compatibility.
-
-Here are some key points to consider:
-
-Install new dependencies: Replace the Optimism SDK with `viem` in your project.
-
-```bash
- pnpm remove @eth-optimism/sdk
- pnpm add viem
-```
-
-* Update imports: Replace Optimism SDK imports with `viem` imports.
-* Migrate SDK methods: Refactor your code to use equivalent `viem` methods. Refer to the viem documentation and opstack documentation for guidance.
-* Test thoroughly: After migration, extensively test your application to ensure all functionality works as expected.
-
-### For chain operators
-
-Chain operators utilizing the SDK for cross-chain operations, bridging, or other functions should switch to the `viem` library.
-The `viem` library offers more efficient methods to handle these operations.
-
-Chain operators should be aware of the following:
-
-* SDK removal: Remove any dependencies on the Optimism SDK in your infrastructure.
-* Update tooling: Ensure all tools and scripts are updated to use `viem`.
-* Monitor performance: After migration, closely monitor your chain's performance to ensure smooth operation.
-
-### For node operators
-
-Node operators will need to ensure that any scripts or services relying on the Optimism SDK are updated to use `viem` library.
-These updates will help align with future improvements and scalability efforts across the OP Stack.
-
-Node operators should take the following steps:
-
-* Update node software: Ensure your node software is compatible with the latest `viem` libraries.
-* Review configuration: Check and update any configuration files that may reference the Optimism SDK.
-* Test thoroughly: Perform comprehensive testing in a staging environment before updating production nodes.
-
-### Need help?
-
-For further assistance or questions about this migration, feel free to reach through the following channels:
-
-* Connect with us on [Discord](https://discord.gg/optimism) for community support
-* Join us on our [developer forum](https://github.com/ethereum-optimism/developers/discussions) for discussions, questions, and general support.
-* Open an [issue on our GitHub repository](https://github.com/ethereum-optimism/docs/issues) for documentation-related concerns
diff --git a/pages/operators/chain-operators/deploy.mdx b/pages/operators/chain-operators/deploy.mdx
index 7d4e7b49b..82bfb891b 100644
--- a/pages/operators/chain-operators/deploy.mdx
+++ b/pages/operators/chain-operators/deploy.mdx
@@ -24,12 +24,12 @@ import { Card, Cards } from 'nextra/components'
This section provides information on OP Stack genesis creation, deployment overview, and smart contract deployment. You'll find guides and overviews to help you understand and work with these topics.
-
+
-
+
-
+
-
+
diff --git a/pages/operators/chain-operators/deploy/_meta.json b/pages/operators/chain-operators/deploy/_meta.json
new file mode 100644
index 000000000..9921d07e6
--- /dev/null
+++ b/pages/operators/chain-operators/deploy/_meta.json
@@ -0,0 +1,7 @@
+{
+ "overview": "Deployment overview",
+ "smart-contracts": "Smart contract deployment",
+ "validate-deployment": "Validate your contract deployment",
+ "genesis": "Chain artifacts creation"
+}
+
diff --git a/pages/operators/chain-operators/deploy/genesis.mdx b/pages/operators/chain-operators/deploy/genesis.mdx
index 1ae29e717..bffa42b8e 100644
--- a/pages/operators/chain-operators/deploy/genesis.mdx
+++ b/pages/operators/chain-operators/deploy/genesis.mdx
@@ -1,7 +1,7 @@
---
-title: OP Stack genesis creation
+title: Chain artifacts creation
lang: en-US
-description: Learn how to create a genesis file for the OP Stack.
+description: Learn how to create genesis and rollup configuration files using op-deployer after L1 contract deployment.
content_type: guide
topic: genesis-creation
personas:
@@ -20,78 +20,93 @@ is_imported_content: 'false'
import { Callout } from 'nextra/components'
-# OP Stack genesis creation
+# Overview
-
- The recommended way to generate genesis and rollup configuration files is using `op-deployer`.
- This ensures standardization and compatibility with the Superchain.
-
+After deploying the L1 system contracts for your OP Stack chain, you need to generate two files to run nodes on the L2 network:
+
+* **Genesis file** (`genesis.json`): Initializes the execution client (`op-geth`)
+* **Rollup configuration file** (`rollup.json`): Configures the consensus client (`op-node`)
-The `op-deployer` tool simplifies the creation of genesis and rollup configuration files (`genesis.json` and `rollup.json`).
-These files are crucial for initializing the execution client (`op-geth`) and consensus client (`op-node`) for your network.
+This guide shows you how to generate these files from your L1 contract deployment data using `op-deployer`.
-The recommended flow for creating a genesis file and rollup configuration file on the OP Stack is as follows:
+## Prerequisites
-1. **Deploy the L1 contracts** using [op-deployer](/operators/chain-operators/tools/op-deployer).
-2. **Generate** both the L2 genesis file (`genesis.json`) and the rollup configuration file (`rollup.json`) using op-deployer's `inspect` commands.
-3. **Initialize** your off-chain components (e.g., execution client, consensus client).
+Before generating genesis and rollup configuration files, ensure you have:
-## Recommended method: using op-deployer
+1. Deployed the L1 contracts successfully using the [`op-deployer apply`](/operators/chain-operators/tools/op-deployer#apply-deploy-your-chain) command
-### Prerequisites
+2. Access to your deployment workspace directory (`.deployer` if you've followed the instructions in the L1 deployment contracts guide)
-1. You have installed the `op-deployer` binary following the instructions in [deployer docs](/operators/chain-operators/tools/op-deployer#installation).
- After installation, extract the `op-deployer` into your `PATH` and `cd op-deployer`.
+## Generating genesis and rollup files
-2. You have created and customized an intent file in a `.deployer` directory, typically by running:
+After your L1 contracts have been deployed, follow these steps to generate the configuration files:
- ```bash
- ./bin/op-deployer init --l1-chain-id --l2-chain-ids --workdir .deployer
- ```
+### Step 1: Locate your deployment state file
- Replace `` and `` with their respective values, see a list of [`chainIds`](https://chainid.network/).
+The `op-deployer` tool creates a `state.json` file in your workspace directory that contains all the necessary information about your deployed contracts.
-3. You have edited that intent file to your liking (roles, addresses, etc.).
+Verify that this file exists in your workspace:
+
+```bash
+ls -la .deployer/state.json
+```
-### Step 1: Deploy the L1 contracts
+### Step 2: Generate the L2 genesis file
-To deploy your chain to L1, run:
+Use the `inspect genesis` command to retrieve your L2 genesis file:
```bash
-./bin/op-deployer apply --workdir .deployer \
- --l1-rpc-url \
- --private-key
+op-deployer inspect genesis --workdir .deployer > .deployer/genesis.json
```
-This command:
+Replace `` with your L2 network's chain ID.
+
+### Step 3: Generate the rollup configuration file
-* Reads your intent file in `.deployer/.`
-* Deploys the OP Stack contracts to the specified L1.
-* Updates a local `state.json` file with the results of the deployment.
+Use the `inspect rollup` command to retrieve your rollup configuration file:
-### Step 2: Generate your L2 genesis file and rollup file
+```bash
+op-deployer inspect rollup --workdir .deployer > .deployer/rollup.json
+```
-After your L1 contracts have been deployed, generate the L2 genesis and rollup configuration files by inspecting the deployer's `state.json`
+### Step 4: Verify the generated files
+
+Examine the generated files to ensure they contain the expected configuration:
```bash
-./bin/op-deployer inspect genesis --workdir .deployer > .deployer/genesis.json
-./bin/op-deployer inspect rollup --workdir .deployer > .deployer/rollup.json
+# View the genesis file structure
+jq . .deployer/genesis.json | head -20
+
+# View the rollup configuration
+jq . .deployer/rollup.json
```
-* genesis.json is the file you will provide to your execution client (e.g. op-geth).
-* rollup.json is the file you will provide to your consensus client (e.g. op-node).
+The `genesis.json` file contains the initial state of your L2 blockchain, including:
+
+* Chain configuration parameters
+* Initial account states
+* Genesis block properties
+
+The `rollup.json` file contains the rollup protocol parameters, including:
-### Step 3: Initialize your off-chain components
+* L1 contract addresses
+* Sequencing settings
+* Protocol upgrade activation times
-Once you have `genesis.json` and `rollup.json`:
+## Troubleshooting
-1. Initialize op-geth using genesis.json.
-2. Configure op-node with rollup.json.
-3. Set up additional off-chain infrastructure as needed (block explorer, indexers, etc.). For more on architecture, see [Architecture overview](/operators/chain-operators/architecture).
+If you encounter issues with the generated files:
+
+* [Verify](/operators/chain-operators/tools/op-deployer#verify-verify-contract-source-code-on-block-explorers) that your L1 contract deployment was successful
+* Check that you're using the correct **L2 chain ID** in the generation commands
+* Ensure your `state.json` file is up-to-date with your latest deployment
+
+
+ Never manually edit the generated genesis or rollup files unless you fully understand the implications. Incorrect configurations can lead to consensus failures or chain security issues.
+
## Next steps
-* Learn how to [initialize](/operators/node-operators/configuration/base-config#initialization-via-genesis-file)
- `op-geth` with your `genesis.json` file.
-* Learn how to [initialize](/operators/node-operators/configuration/base-config#configuring-op-node) `op-node` with your `rollup.json` file.
-* Learn more about the off chain [architecture](/operators/chain-operators/architecture).
+* Learn how to [initialize](/operators/node-operators/configuration/base-config#initialization-via-genesis-file) `op-geth` with your `genesis.json` file
+* Learn how to [configure](/operators/node-operators/configuration/base-config#configuring-op-node) `op-node` with your `rollup.json` file
+* Learn more about the off-chain [architecture](/operators/chain-operators/architecture)
diff --git a/pages/operators/chain-operators/deploy/overview.mdx b/pages/operators/chain-operators/deploy/overview.mdx
index c9f8885b2..3d2692263 100644
--- a/pages/operators/chain-operators/deploy/overview.mdx
+++ b/pages/operators/chain-operators/deploy/overview.mdx
@@ -1,5 +1,5 @@
---
-title: OP Stack deployment overview
+title: Deployment overview
lang: en-US
description: Learn about the different components of deploying a standard OP Stack chain.
content_type: guide
@@ -20,7 +20,7 @@ is_imported_content: 'false'
import { Callout } from 'nextra/components'
-# OP Stack deployment overview
+# Deployment overview
When deploying a **standard OP Stack chain**, you'll be setting up several key
components. It's useful to understand what each of these components does before
diff --git a/pages/operators/chain-operators/deploy/smart-contracts.mdx b/pages/operators/chain-operators/deploy/smart-contracts.mdx
index e84905a8a..fd85d2456 100644
--- a/pages/operators/chain-operators/deploy/smart-contracts.mdx
+++ b/pages/operators/chain-operators/deploy/smart-contracts.mdx
@@ -1,5 +1,5 @@
---
-title: OP Stack Smart Contract Deployment
+title: Smart contract deployment
lang: en-US
description: Learn how to deploy the OP Stack L1 smart contracts.
content_type: guide
@@ -20,12 +20,10 @@ is_imported_content: 'false'
import { Callout, Steps } from 'nextra/components'
-# OP Stack smart contract deployment
+# Overview
This guide outlines the process for deploying the OP Stack L1 smart contracts using `op-deployer`.
-## Overview
-
Deploying OP Stack L1 contracts is a critical step in setting up your rollup.
diff --git a/pages/operators/chain-operators/deploy/validate-deployment.mdx b/pages/operators/chain-operators/deploy/validate-deployment.mdx
index f369ef093..69ba6002b 100644
--- a/pages/operators/chain-operators/deploy/validate-deployment.mdx
+++ b/pages/operators/chain-operators/deploy/validate-deployment.mdx
@@ -1,5 +1,5 @@
---
-title: Validating your OP Stack deployment
+title: Validate your contract deployment
lang: en-US
description: Learn how to validate your OP Stack deployment using op-validator
content_type: guide
diff --git a/public/tutorials/cross-dom-bridge-erc20.js b/public/tutorials/cross-dom-bridge-erc20.js
index 8244f367e..ea2b5b10e 100644
--- a/public/tutorials/cross-dom-bridge-erc20.js
+++ b/public/tutorials/cross-dom-bridge-erc20.js
@@ -1,93 +1,185 @@
(async () => {
-const optimism = require("@eth-optimism/sdk")
-const ethers = require("ethers")
-
-const privateKey = process.env.TUTORIAL_PRIVATE_KEY
-
-const l1Provider = new ethers.providers.StaticJsonRpcProvider("https://rpc.ankr.com/eth_sepolia")
-const l2Provider = new ethers.providers.StaticJsonRpcProvider("https://sepolia.optimism.io")
-const l1Wallet = new ethers.Wallet(privateKey, l1Provider)
-const l2Wallet = new ethers.Wallet(privateKey, l2Provider)
-
-const l1Token = "0x5589BB8228C07c4e15558875fAf2B859f678d129"
-const l2Token = "0xD08a2917653d4E460893203471f0000826fb4034"
-
-const erc20ABI = [{ constant: true, inputs: [{ name: "_owner", type: "address" }], name: "balanceOf", outputs: [{ name: "balance", type: "uint256" }], type: "function" }, { inputs: [], name: "faucet", outputs: [], stateMutability: "nonpayable", type: "function" }]
-
-const l1ERC20 = new ethers.Contract(l1Token, erc20ABI, l1Wallet)
-
-console.log('Getting L1 tokens from faucet...')
-tx = await l1ERC20.faucet()
-await tx.wait()
-
-console.log('L1 balance:')
-console.log((await l1ERC20.balanceOf(l1Wallet.address)).toString())
-
-const oneToken = 1000000000000000000n
-
-const messenger = new optimism.CrossChainMessenger({
- l1ChainId: 11155111, // 11155111 for Sepolia, 1 for Ethereum
- l2ChainId: 11155420, // 11155420 for OP Sepolia, 10 for OP Mainnet
- l1SignerOrProvider: l1Wallet,
- l2SignerOrProvider: l2Wallet,
-})
-
-console.log('Approving L1 tokens for deposit...')
-tx = await messenger.approveERC20(l1Token, l2Token, oneToken)
-await tx.wait()
-
-console.log('Depositing L1 tokens...')
-tx = await messenger.depositERC20(l1Token, l2Token, oneToken)
-await tx.wait()
-
-console.log('Waiting for deposit to be relayed...')
-await messenger.waitForMessageStatus(tx.hash, optimism.MessageStatus.RELAYED)
-
-console.log('L1 balance:')
-console.log((await l1ERC20.balanceOf(l1Wallet.address)).toString())
-
-const l2ERC20 = new ethers.Contract(l2Token, erc20ABI, l2Wallet)
-
-console.log('L2 balance:')
-console.log((await l2ERC20.balanceOf(l2Wallet.address)).toString())
-
-console.log('Withdrawing L2 tokens...')
-const withdrawal = await messenger.withdrawERC20(l1Token, l2Token, oneToken)
-await withdrawal.wait()
-
-console.log('L2 balance:')
-console.log((await l2ERC20.balanceOf(l2Wallet.address)).toString())
-
-console.log('Waiting for withdrawal to be provable...')
-await messenger.waitForMessageStatus(withdrawal.hash, optimism.MessageStatus.READY_TO_PROVE)
-
-console.log('Proving withdrawal...')
-await messenger.proveMessage(withdrawal.hash)
-
-console.log('Waiting for withdrawal to be relayable...')
-await messenger.waitForMessageStatus(withdrawal.hash, optimism.MessageStatus.READY_FOR_RELAY)
-
-// Wait for the next block to be produced, only necessary for CI because messenger can return
-// READY_FOR_RELAY before the RPC we're using is caught up to the latest block. Waiting for an
-// additional block ensures that the RPC is caught up and the message can be relayed. Users
-// should not need to do this when running the tutorial.
-const maxWaitTime = Date.now() + 120000 // 2 minutes in milliseconds
-const currentBlock = await l1Provider.getBlockNumber()
-while (await l1Provider.getBlockNumber() < currentBlock + 1) {
- if (Date.now() > maxWaitTime) {
- throw new Error('Timed out waiting for block to be produced')
- }
- await new Promise(resolve => setTimeout(resolve, 1000))
-}
-
-console.log('Relaying withdrawal...')
-await messenger.finalizeMessage(withdrawal.hash)
-
-console.log('Waiting for withdrawal to be relayed...')
-await messenger.waitForMessageStatus(withdrawal.hash, optimism.MessageStatus.RELAYED)
-
-console.log('L1 balance:')
-console.log((await l1ERC20.balanceOf(l1Wallet.address)).toString())
-
-})()
+ const viem = await import('viem');
+ const { createPublicClient, createWalletClient, http, formatEther } = viem;
+ const accounts = await import('viem/accounts');
+ const { privateKeyToAccount } = accounts;
+ const viemChains = await import('viem/chains');
+ const { optimismSepolia, sepolia } = viemChains;
+ const opActions = await import('@eth-optimism/viem/actions');
+ const { depositERC20, withdrawOptimismERC20 } = opActions;
+
+ const l1Token = "0x5589BB8228C07c4e15558875fAf2B859f678d129";
+ const l2Token = "0xD08a2917653d4E460893203471f0000826fb4034";
+ const oneToken = 1000000000000000000n
+
+ const PRIVATE_KEY = process.env.TUTORIAL_PRIVATE_KEY || '';
+ const account = privateKeyToAccount(PRIVATE_KEY);
+
+ const L1_RPC_URL = 'https://rpc.ankr.com/eth_sepolia/';
+ const L2_RPC_URL = 'https://sepolia.optimism.io';
+
+ const publicClientL1 = createPublicClient({
+ chain: sepolia,
+ transport: http(L1_RPC_URL),
+ });
+
+ const walletClientL1 = createWalletClient({
+ account,
+ chain: sepolia,
+ transport: http(L1_RPC_URL),
+ });
+
+ const publicClientL2 = createPublicClient({
+ chain: optimismSepolia,
+ transport: http(L2_RPC_URL),
+ });
+
+ const walletClientL2 = createWalletClient({
+ account,
+ chain: optimismSepolia,
+ transport: http(L2_RPC_URL),
+ });
+
+ const erc20ABI = [
+ {
+ inputs: [
+ {
+ internalType: "address",
+ name: "account",
+ type: "address",
+ },
+ ],
+ name: "balanceOf",
+ outputs: [
+ {
+ internalType: "uint256",
+ name: "",
+ type: "uint256",
+ },
+ ],
+ stateMutability: "view",
+ type: "function",
+ },
+ {
+ inputs: [],
+ name: "faucet",
+ outputs: [],
+ stateMutability: "nonpayable",
+ type: "function",
+ },
+ {
+ inputs: [
+ {
+ internalType: "address",
+ name: "spender",
+ type: "address"
+ },
+ {
+ internalType: "uint256",
+ name: "value",
+ type: "uint256"
+ }
+ ],
+ name: "approve",
+ outputs: [
+ {
+ internalType: "bool",
+ name: "",
+ type: "bool"
+ }
+ ],
+ stateMutability: "nonpayable",
+ type: "function"
+ },
+ ];
+
+ console.log('Getting tokens from faucet...');
+ const tx = await walletClientL1.writeContract({
+ address: l1Token,
+ abi: erc20ABI,
+ functionName: 'faucet',
+ account,
+ });
+ console.log('Faucet transaction:', tx);
+
+ // Wait for the transaction to be mined
+ await publicClientL1.waitForTransactionReceipt({ hash: tx });
+
+ const l1Balance = await publicClientL1.readContract({
+ address: l1Token,
+ abi: erc20ABI,
+ functionName: 'balanceOf',
+ args: [account.address]
+ });
+ console.log(`L1 Balance after receiving faucet: ${formatEther(l1Balance)}`);
+
+ console.log('Approving tokens for bridge...');
+ const bridgeAddress = optimismSepolia.contracts.l1StandardBridge[sepolia.id].address;
+ const approveTx = await walletClientL1.writeContract({
+ address: l1Token,
+ abi: erc20ABI,
+ functionName: 'approve',
+ args: [bridgeAddress, oneToken],
+ });
+ console.log('Approval transaction:', approveTx);
+
+ // Wait for approval transaction to be mined
+ await publicClientL1.waitForTransactionReceipt({ hash: approveTx });
+
+ console.log('Depositing tokens to L2...');
+ const depositTx = await depositERC20(walletClientL1, {
+ tokenAddress: l1Token,
+ remoteTokenAddress: l2Token,
+ amount: oneToken,
+ targetChain: optimismSepolia,
+ to: account.address,
+ minGasLimit: 200000,
+ });
+ console.log(`Deposit transaction hash: ${depositTx}`);
+
+ const depositReceipt = await publicClientL1.waitForTransactionReceipt({ hash: depositTx });
+ console.log(`Deposit confirmed in block ${depositReceipt.blockNumber}`);
+ console.log("Token bridging initiated! The tokens will arrive on L2 in a few minutes.");
+
+ console.log('Waiting for tokens to arrive on L2...');
+
+ await new Promise(resolve => setTimeout(resolve, 60000)); // 1 minute
+ const l1BalanceAfterDeposit = await publicClientL1.readContract({
+ address: l1Token,
+ abi: erc20ABI,
+ functionName: 'balanceOf',
+ args: [account.address]
+ });
+ console.log(`L1 Balance after deposit: ${formatEther(l1BalanceAfterDeposit)}`);
+
+ const l2BalanceAfterDeposit = await publicClientL2.readContract({
+ address: l2Token,
+ abi: erc20ABI,
+ functionName: 'balanceOf',
+ args: [account.address]
+ });
+ console.log(`L2 Balance after deposit: ${formatEther(l2BalanceAfterDeposit)}`);
+
+ console.log('Withdrawing tokens back to L1...');
+ const withdrawTx = await withdrawOptimismERC20(walletClientL2, {
+ tokenAddress: l2Token,
+ amount: oneToken / 2n,
+ to: account.address,
+ minGasLimit: 200000,
+ });
+ console.log(`Withdrawal transaction hash: ${withdrawTx}`);
+
+ const withdrawReceipt = await publicClientL2.waitForTransactionReceipt({ hash: withdrawTx });
+ console.log(`Withdrawal initiated in L2 block ${withdrawReceipt.blockNumber}`);
+ console.log("Withdrawal process initiated! It will take 7 days for the tokens to be available on L1.");
+
+ const l2Balance = await publicClientL2.readContract({
+ address: l2Token,
+ abi: erc20ABI,
+ functionName: 'balanceOf',
+ args: [account.address]
+ });
+ console.log(`L2 Balance after withdrawal: ${formatEther(l2Balance)}`);
+
+})();
diff --git a/styles/global.css b/styles/global.css
index d35079960..06a25fa39 100644
--- a/styles/global.css
+++ b/styles/global.css
@@ -283,4 +283,10 @@ div.footer-columns {
align-items: center;
gap: 2rem;
}
+ }
+
+ code .line .highlighted {
+ background-color: transparent !important;
+ --tw-shadow-color: transparent !important;
+ box-shadow: none !important;
}
\ No newline at end of file
diff --git a/theme.config.tsx b/theme.config.tsx
index 2eb268c6a..143030bac 100644
--- a/theme.config.tsx
+++ b/theme.config.tsx
@@ -33,15 +33,15 @@ const config: DocsThemeConfig = {
>
),
darkMode: true,
- banner: {
- key: 'viem/op-stack',
- text: (
-
- 🎉 We are deprecating the Optimism SDK and migrating all tutorials to use viem/op-stack.
- Read more →
-
- )
- },
+ // banner: {
+ // key: 'viem/op-stack',
+ // text: (
+ //
+ // 🎉 We are deprecating the Optimism SDK and migrating all tutorials to use viem/op-stack.
+ // Read more →
+ //
+ // )
+ // },
search: {
component: Search
},
diff --git a/words.txt b/words.txt
index ead225f77..9d9f365d7 100644
--- a/words.txt
+++ b/words.txt
@@ -273,7 +273,6 @@ OPCM
Openfort
oplabs
opnode's
-opstack
outfile
Pausability
pcscdpath