Using the OP Stack Client SDK
# Natively supported chains
The OP Stack Client SDK (opens new window) natively supports multiple OP Chains: OP, Base, etc. To see whether a specific OP Chain is supported directly, see the documentation (opens new window).
# Not natively supported chains
If you are using a chain that is not natively supported, for example an OP Stack chain you just created, you can continue to use the OP Stack Client SDK (opens new window).
You just need to provide some contract addresses to the CrossDomainMessenger
because they aren't preconfigured.
# Getting contract addresses
# L1 contract addresses
If you followed the directions in Getting Started, the contract addresses are in .../optimism/packages/contracts-bedrock/deployments/getting-started
, which you created when you deployed the L1 contracts.
Contract name when creating CrossDomainMessenger | File with address |
---|---|
AddressManager | Lib_AddressManager.json |
L1CrossDomainMessenger | Proxy__OVM_L1CrossDomainMessenger.json |
L1StandardBridge | Proxy__OVM_L1StandardBridge.json |
OptimismPortal | OptimismPortalProxy.json |
L2OutputOracle | L2OutputOracleProxy.json |
# Unneeded contract addresses
Some contracts are required by the SDK as a sanity check, but are not actually used. For these contracts you can just specify the zero address:
StateCommitmentChain
CanonicalTransactionChain
BondManager
In JavaScript you can create the zero address using the expression "0x".padEnd(42, "0")
.
# The CrossChainMessenger object
These directions assume you are inside the Hardhat console (opens new window).
They further assume that your project already includes the Optimism SDK @eth-optimism/sdk
(opens new window).
Import the SDK
optimismSDK = require("@eth-optimism/sdk")
1Set the configuration parameters.
Variable name Value l1Url
URL to an RPC provider for L1, for example https://eth-goerli.g.alchemy.com/v2/<api key>
l2Url
URL to your OP Stack. If running on the same computer, it is http://localhost:8545
privKey
The private key for an account that has some ETH on the L1 Create the providers (opens new window) and signers (opens new window).
l1Provider = new ethers.providers.JsonRpcProvider(l1Url) l2Provider = new ethers.providers.JsonRpcProvider(l2Url) l1Signer = new ethers.Wallet(privKey).connect(l1Provider) l2Signer = new ethers.Wallet(privKey).connect(l2Provider)
1
2
3
4Create the L1 contracts structure.
zeroAddr = "0x".padEnd(42, "0") l1Contracts = { StateCommitmentChain: zeroAddr, CanonicalTransactionChain: zeroAddr, BondManager: zeroAddr, // These contracts have the addresses you found out earlier. AddressManager: "0x....", // Lib_AddressManager.json L1CrossDomainMessenger: "0x....", // Proxy__OVM_L1CrossDomainMessenger.json L1StandardBridge: "0x....", // Proxy__OVM_L1StandardBridge.json OptimismPortal: "0x....", // OptimismPortalProxy.json L2OutputOracle: "0x....", // L2OutputOracleProxy.json }
1
2
3
4
5
6
7
8
9
10
11
12Create the data structure for the standard bridge.
bridges = { Standard: { l1Bridge: l1Contracts.L1StandardBridge, l2Bridge: "0x4200000000000000000000000000000000000010", Adapter: optimismSDK.StandardBridgeAdapter }, ETH: { l1Bridge: l1Contracts.L1StandardBridge, l2Bridge: "0x4200000000000000000000000000000000000010", Adapter: optimismSDK.ETHBridgeAdapter } }
1
2
3
4
5
6
7
8
9
10
11
12Create the
CrossChainMessenger
(opens new window) object.crossChainMessenger = new optimismSDK.CrossChainMessenger({ bedrock: true, contracts: { l1: l1Contracts }, bridges: bridges, l1ChainId: await l1Signer.getChainId(), l2ChainId: await l2Signer.getChainId(), l1SignerOrProvider: l1Signer, l2SignerOrProvider: l2Signer, })
1
2
3
4
5
6
7
8
9
10
11
# Verify SDK functionality
To verify the SDK's functionality, transfer some ETH from L1 to L2.
Get the current balances.
balances0 = [ await l1Provider.getBalance(l1Signer.address), await l2Provider.getBalance(l1Signer.address) ]
1
2
3
4Transfer 1 gwei.
tx = await crossChainMessenger.depositETH(1e9) rcpt = await tx.wait()
1
2Get the balances after the transfer.
balances1 = [ await l1Provider.getBalance(l1Signer.address), await l2Provider.getBalance(l1Signer.address) ]
1
2
3
4See that the L1 balance changed (probably by a lot more than 1 gwei because of the cost of the transaction).
(balances0[0]-balances1[0])/1e9
1See that the L2 balance changed (it might take a few minutes).
((await l2Provider.getBalance(l1Signer.address))-balances0[1])/1e9
1