Skip to content

Commit 0f08d4b

Browse files
authored
Merge pull request #1569 from ethereum-optimism/harry/update_tutorials
fix(interop): update outdated interop manual relay and viem tutorials
2 parents 827e7b5 + bda418b commit 0f08d4b

File tree

6 files changed

+167
-106
lines changed

6 files changed

+167
-106
lines changed

Diff for: pages/interop/tutorials/bridge-crosschain-eth.mdx

+5-5
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ The tutorial uses these primary tools:
203203

204204
3. Place this in `src/transfer-eth.mts`:
205205

206-
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts hash=f71ba1d6d6b4adf8cb3283792abac853
206+
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts hash=9f19c28046ed792e3f04aefd8fb4453e
207207
```
208208

209209
<details>
@@ -214,25 +214,25 @@ The tutorial uses these primary tools:
214214

215215
Import all chain definitions from `@eth-optimism/viem`.
216216

217-
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts#L29-L32 hash=e8c21357997ea12151305337eced7d71
217+
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts#L29-L32 hash=2c2dd55bc8c8122fe2991ab38cc9c1ac
218218
```
219219

220220
If the address we use is `0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266`, one of the prefunded addresses on `anvil`, assume we're using Supersim.
221221
Otherwise, use Interop devnet.
222222

223-
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts#L78-L80 hash=4933c70a9078c2369ef90bfe163f5fd7
223+
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts#L78-L80 hash=c5c2f87d5f6bb564376016ac62712501
224224
```
225225

226226
To relay a message we need the information in the receipt.
227227
Also, we need to wait until the transaction with the relayed message is actually part of a block.
228228

229-
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts#L87-L89 hash=573f22b2b21415ff51c59c713fda07d1
229+
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts#L86-L89 hash=db8b76c8ca3304dd485f4a33a1dc8580
230230
```
231231

232232
A single transaction can send multiple messages.
233233
But here we know we sent just one, so we look for the first one in the list.
234234

235-
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts#L90-L96 hash=4b26775b46c116262af4c7299d6f1127
235+
```typescript file=<rootDir>/public/tutorials/transfer-eth.mts#L90-L96 hash=d650e8c2b31d75d82ba4c5e4519c028d
236236
```
237237

238238
This is how you use `@eth-optimism/viem` to create an executing message.

Diff for: pages/interop/tutorials/relay-messages-cast.mdx

+104-25
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Sending an interop message using the `L2ToL2CrossDomainMessenger`:
4747

4848
### On source chain (OPChainA 901)
4949

50-
1. Invoke `L2NativeSuperchainERC20.sentERC20` to bridge funds
50+
1. Invoke `L2NativeSuperchainERC20.sendERC20` to bridge funds
5151
* this leverages `L2ToL2CrossDomainMessenger.sendMessage` to make the cross chain call
5252
2. Retrieve the log identifier and the message payload for the `SentMessage` event.
5353

@@ -98,34 +98,47 @@ struct Identifier {
9898

9999
### Get the log emitted by the `L2ToL2CrossDomainMessenger`
100100

101-
The token contract calls the [L2ToL2CrossDomainMessenger](https://github.com/ethereum-optimism/optimism/blob/92ed64e171c6eb9c6a080c626640e8836f0653cc/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol), which emits a message (log) that can be relayed on the destination chain.
101+
The token contract calls the [L2ToL2CrossDomainMessenger](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol), which emits a message (log) that can be relayed on the destination chain.
102102

103103
```sh
104-
$ cast logs --address 0x4200000000000000000000000000000000000023 --rpc-url http://127.0.0.1:9545
104+
cast logs --address 0x4200000000000000000000000000000000000023 --rpc-url http://127.0.0.1:9545
105+
```
106+
107+
Sample output:
105108

109+
```
106110
address: 0x4200000000000000000000000000000000000023
107-
blockHash: 0x3905831f1b109ce787d180c1ed977ebf0ff1a6334424a0ae8f3731b035e3f708
108-
blockNumber: 4
109-
data: 0x000000000000000000000000420beef00000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000064d9f50046000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000
110-
logIndex: 1
111+
blockHash: 0x311f8ccea3fc121aa3af18e0a87766ae56ed3f1d08cae91ec29f34a9919abcc0
112+
blockNumber: 14
113+
data: 0x0000000000000000000000004200000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000847cfd6dbc000000000000000000000000420beef000000000000000000000000000000001000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000
114+
logIndex: 2
115+
removed: false
111116
topics: [
112-
0x382409ac69001e11931a28435afef442cbfd20d9891907e8fa373ba7d351f320
113-
0x0000000000000000000000000000000000000000000000000000000000000386
114-
0x000000000000000000000000420beef000000000000000000000000000000001
115-
0x0000000000000000000000000000000000000000000000000000000000000000
117+
0x382409ac69001e11931a28435afef442cbfd20d9891907e8fa373ba7d351f320
118+
0x0000000000000000000000000000000000000000000000000000000000000386
119+
0x0000000000000000000000004200000000000000000000000000000000000028
120+
0x0000000000000000000000000000000000000000000000000000000000000000
116121
]
117-
...
122+
transactionHash: 0x746a3e8a3a0ed0787367c3476269fa3050a2f9113637b563a4579fbc03efe5c4
123+
transactionIndex: 0
118124
```
119125

120126
### Retrieve the block timestamp the log was emitted in
121127

122128
Since the message identifier requires the block timestamp, fetch the block info to get the timestamp.
123129

124130
```sh
125-
$ cast block 0xREPLACE_WITH_CORRECT_BLOCKHASH --rpc-url http://127.0.0.1:9545
126-
...
127-
timestamp 1728507703
128-
...
131+
cast block 0xREPLACE_WITH_CORRECT_BLOCKHASH --rpc-url http://127.0.0.1:9545
132+
```
133+
134+
Sample output:
135+
136+
```
137+
// (truncated for brevity)
138+
139+
timestamp 1743801675
140+
141+
// ...
129142
```
130143

131144
### Prepare the message identifier & payload
@@ -144,17 +157,82 @@ struct Identifier {
144157

145158
```
146159
0x + 382409ac69001e11931a28435afef442cbfd20d9891907e8fa373ba7d351f320
147-
+ 0000000000000000000000000000000000000000000000000000000000000386
148-
+ 000000000000000000000000420beef000000000000000000000000000000001
149-
+ 0000000000000000000000000000000000000000000000000000000000000000
150-
+ 000000000000000000000000420beef00000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000064d9f50046000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000
160+
+ 0000000000000000000000000000000000000000000000000000000000000386
161+
+ 0000000000000000000000004200000000000000000000000000000000000028
162+
+ 0000000000000000000000000000000000000000000000000000000000000000
163+
+ 0000000000000000000000004200000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000847cfd6dbc000000000000000000000000420beef000000000000000000000000000000001000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000
164+
```
165+
166+
Payload: ` 0x382409ac69001e11931a28435afef442cbfd20d9891907e8fa373ba7d351f3200000000000000000000000000000000000000000000000000000000000000386000000000000000000000000420000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000847cfd6dbc000000000000000000000000420beef000000000000000000000000000000001000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000`
167+
168+
### Construct the access list for the message
169+
170+
An access list must be passed along with the relay message tx. There are two admin RPC methods that can be used to construct the access list: `admin_getAccessListByMsgHash` and `admin_getAccessListForIdentifier` and.
171+
172+
a. To get the access list using the `admin_getAccessListByMsgHash` RPC method, call the method with the message hash.
173+
174+
1. Retrieve the message hash from the supersim logs
175+
176+
```sh
177+
INFO [04-04|14:21:15.587] L2ToL2CrossChainMessenger#SentMessage sourceChainID=901 destinationChainID=902 nonce=0 sender=0x4200000000000000000000000000000000000028 target=0x4200000000000000000000000000000000000028 msgHash=0xccff97c17ef11d659d319cbc5780235ea03ef34b0fa34f40b208a9519f257379 txHash=0x746a3e8a3a0ed0787367c3476269fa3050a2f9113637b563a4579fbc03efe5c4
151178
```
152179

153-
Payload: `0x382409ac69001e11931a28435afef442cbfd20d9891907e8fa373ba7d351f3200000000000000000000000000000000000000000000000000000000000000386000000000000000000000000420beef0000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000420beef00000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000064d9f50046000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000`
180+
2. Call `admin_getAccessListByMsgHash` with the message hash.
181+
182+
```sh
183+
cast rpc admin_getAccessListByMsgHash 0xccff97c17ef11d659d319cbc5780235ea03ef34b0fa34f40b208a9519f257379 --rpc-url http://localhost:8420
184+
```
185+
186+
Sample output:
187+
188+
```
189+
{
190+
"accessList": [
191+
{
192+
"address": "0x4200000000000000000000000000000000000022",
193+
"storageKeys": [
194+
"0x010000000000000000000385000000000000000e0000000067f04d4b00000002",
195+
"0x03c6d2648cef120ce1d7ccf9f8d4042d6b25ff30a02e22d9ea2a47d2677ccb8d"
196+
]
197+
}
198+
]
199+
}
200+
```
201+
202+
b. To get the access list using the `admin_getAccessListForIdentifier` RPC method, call the method with the identifier and the message payload.
203+
204+
```sh
205+
cast rpc admin_getAccessListForIdentifier \
206+
'{
207+
"origin": "0x4200000000000000000000000000000000000023",
208+
"blockNumber": "14",
209+
"logIndex": "2",
210+
"timestamp": "1743801675",
211+
"chainId": "901",
212+
"payload": "0x382409ac69001e11931a28435afef442cbfd20d9891907e8fa373ba7d351f3200000000000000000000000000000000000000000000000000000000000000386000000000000000000000000420000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000847cfd6dbc000000000000000000000000420beef000000000000000000000000000000001000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000"
213+
}' \
214+
--rpc-url http://localhost:8420
215+
```
216+
217+
Sample output:
218+
219+
```
220+
{
221+
"accessList": [
222+
{
223+
"address": "0x4200000000000000000000000000000000000022",
224+
"storageKeys": [
225+
"0x010000000000000000000385000000000000000e0000000067f04d4b00000002",
226+
"0x03c6d2648cef120ce1d7ccf9f8d4042d6b25ff30a02e22d9ea2a47d2677ccb8d"
227+
]
228+
}
229+
]
230+
}
231+
```
154232

155233
### Send the relayMessage transaction
156234

157-
Call `relayMessage` on the [L2ToL2CrossDomainMessenger](https://github.com/ethereum-optimism/optimism/blob/92ed64e171c6eb9c6a080c626640e8836f0653cc/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol#L126)
235+
Call `relayMessage` on the [L2ToL2CrossDomainMessenger](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol) with the access list.
158236

159237
```solidity
160238
// L2ToL2CrossDomainMessenger.sol (truncated for brevity)
@@ -180,10 +258,11 @@ struct Identifier {
180258
Below is an example call, but make sure to replace them with the correct values you received in previous steps.
181259

182260
```sh
183-
$ cast send 0x4200000000000000000000000000000000000023 --gas-limit 200000 \
261+
cast send 0x4200000000000000000000000000000000000023 \
184262
"relayMessage((address, uint256, uint256, uint256, uint256), bytes)" \
185-
"(0x4200000000000000000000000000000000000023, 4, 1, 1728507703, 901)" \
186-
0x382409ac69001e11931a28435afef442cbfd20d9891907e8fa373ba7d351f3200000000000000000000000000000000000000000000000000000000000000386000000000000000000000000420beef0000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000420beef00000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000064d9f50046000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000 \
263+
"(0x4200000000000000000000000000000000000023, 14, 2, 1743801675, 901)" \
264+
0x382409ac69001e11931a28435afef442cbfd20d9891907e8fa373ba7d351f3200000000000000000000000000000000000000000000000000000000000000386000000000000000000000000420000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000847cfd6dbc000000000000000000000000420beef000000000000000000000000000000001000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000 \
265+
--access-list '[{"address":"0x4200000000000000000000000000000000000022","storageKeys":["0x010000000000000000000385000000000000000e0000000067f04d4b00000002", "0x03c6d2648cef120ce1d7ccf9f8d4042d6b25ff30a02e22d9ea2a47d2677ccb8d"]}]' \
187266
--rpc-url http://127.0.0.1:9546 \
188267
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
189268
```

Diff for: pages/interop/tutorials/relay-messages-viem.mdx

+21-33
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ import {
6969
walletActionsL2,
7070
supersimL2A,
7171
supersimL2B,
72-
createInteropSentL2ToL2Messages,
73-
decodeRelayedL2ToL2Messages,
7472
} from "@eth-optimism/viem";
7573

7674
// SuperERC20 is in development so we manually define the address here
@@ -121,21 +119,20 @@ await opChainAClient.waitForTransactionReceipt({ hash: mintTxHash });
121119
// 2. Initiate sendERC20 tx to bridge funds to chain B
122120

123121
console.log("Initiating sendERC20 on OPChainA to OPChainB...");
124-
const sendERC20TxHash = await opChainAClient.writeContract({
125-
address: SUPERCHAIN_TOKEN_BRIDGE_ADDRESS,
126-
abi: parseAbi([
127-
"function sendERC20(address _token, address _to, uint256 _amount, uint256 _chainId)",
128-
]),
129-
functionName: "sendERC20",
130-
args: [L2_NATIVE_SUPERCHAINERC20_ADDRESS, account.address, 1000n, BigInt(supersimL2B.id)],
122+
const sendERC20TxHash = await opChainAClient.interop.sendSuperchainERC20({
123+
tokenAddress: SUPERSIM_SUPERC20_ADDRESS,
124+
to: testAccount.address,
125+
amount: AMOUNT_TO_SEND,
126+
chainId: supersimL2B.id,
131127
});
132128

133129
const sendERC20Receipt = await opChainAClient.waitForTransactionReceipt({ hash: sendERC20TxHash });
134130

135131
// 3. Construct the interoperable log data from the sent message
136132

137-
const { sentMessages } = await createInteropSentL2ToL2Messages(opChainAClient, { receipt: sendERC20Receipt })
133+
const sentMessages = await opChainAClient.interop.getCrossDomainMessages({ logs: sendERC20Receipt.logs })
138134
const sentMessage = sentMessages[0] // We only sent 1 message
135+
const relayMessageParams = await opChainAClient.interop.buildExecutingMessage({ log: sentMessage.log })
139136
```
140137

141138
### Relay the sent message on the destination chain
@@ -148,17 +145,14 @@ const sentMessage = sentMessages[0] // We only sent 1 message
148145
// 4. Relay the sent message
149146

150147
console.log("Relaying message on OPChainB...");
151-
const relayTxHash = await opChainBClient.relayL2ToL2Message({
152-
sentMessageId: sentMessage.id,
153-
sentMessagePayload: sentMessage.payload,
154-
});
148+
const relayTxHash = await opChainBClient.interop.relayCrossDomainMessage(relayMessageParams);
155149

156150
const relayReceipt = await opChainBClient.waitForTransactionReceipt({ hash: relayTxHash });
157151

158152
// 5. Ensure the message was relayed successfully
159153

160-
const { successfulMessages, failedMessages } = decodeRelayedL2ToL2Messages({ receipt: relayReceipt });
161-
if (successfulMessages.length != 1) {
154+
const status = await opChainBClient.interop.getCrossDomainMessageStatus({ message: sentMessage })
155+
if (status != 'relayed') {
162156
throw new Error("failed to relay message!")
163157
}
164158

@@ -202,8 +196,6 @@ import {
202196
walletActionsL2,
203197
supersimL2A,
204198
supersimL2B,
205-
createInteropSentL2ToL2Messages,
206-
decodeRelayedL2ToL2Messages,
207199
} from "@eth-optimism/viem";
208200

209201
// SuperERC20 is in development so we manually define the address here
@@ -250,22 +242,21 @@ await opChainAClient.waitForTransactionReceipt({ hash: mintTxHash });
250242

251243
// 2. Initiate sendERC20 tx to bridge funds to chain B
252244

253-
console.log("Initiating sendERC20 on OPChainA...");
254-
const sendERC20TxHash = await opChainAClient.writeContract({
255-
address: SUPERCHAIN_TOKEN_BRIDGE_ADDRESS,
256-
abi: parseAbi([
257-
"function sendERC20(address _token, address _to, uint256 _amount, uint256 _chainId)",
258-
]),
259-
functionName: "sendERC20",
260-
args: [L2_NATIVE_SUPERCHAINERC20_ADDRESS, account.address, 1000n, BigInt(supersimL2B.id)],
245+
console.log("Initiating sendERC20 on OPChainA to OPChainB...");
246+
const sendERC20TxHash = await opChainAClient.interop.sendSuperchainERC20({
247+
tokenAddress: SUPERSIM_SUPERC20_ADDRESS,
248+
to: testAccount.address,
249+
amount: AMOUNT_TO_SEND,
250+
chainId: supersimL2B.id,
261251
});
262252

263253
const sendERC20Receipt = await opChainAClient.waitForTransactionReceipt({ hash: sendERC20TxHash });
264254

265255
// 3. Construct the interoperable log data from the sent message
266256

267-
const { sentMessages } = await createInteropSentL2ToL2Messages(opChainAClient, { receipt: sendERC20Receipt })
257+
const sentMessages = await opChainAClient.interop.getCrossDomainMessages({ logs: sendERC20Receipt.logs })
268258
const sentMessage = sentMessages[0] // We only sent 1 message
259+
const relayMessageParams = await opChainAClient.interop.buildExecutingMessage({ log: sentMessage.log })
269260

270261
// ##########
271262
// OP Chain B
@@ -274,17 +265,14 @@ const sentMessage = sentMessages[0] // We only sent 1 message
274265
// 4. Relay the sent message
275266

276267
console.log("Relaying message on OPChainB...");
277-
const relayTxHash = await opChainBClient.relayL2ToL2Message({
278-
sentMessageId: sentMessage.id,
279-
sentMessagePayload: sentMessage.payload,
280-
});
268+
const relayTxHash = await opChainBClient.interop.relayCrossDomainMessage(relayMessageParams);
281269

282270
const relayReceipt = await opChainBClient.waitForTransactionReceipt({ hash: relayTxHash });
283271

284272
// 5. Ensure the message was relayed successfully
285273

286-
const { successfulMessages, failedMessages } = decodeRelayedL2ToL2Messages({ receipt: relayReceipt });
287-
if (successfulMessages.length != 1) {
274+
const status = await opChainBClient.interop.getCrossDomainMessageStatus({ message: sentMessage })
275+
if (status != 'relayed') {
288276
throw new Error("failed to relay message!")
289277
}
290278

0 commit comments

Comments
 (0)