The following steps describe how to simulate an L2 deposit transaction prior to L1 task execution. The TransferL2PAOFromL1.sol transfers the ownership of a L2PAO from a current aliased L1 address to a new aliased L1 address. This template executes an L1 transaction, which is later forwarded to the L2 by the op-node. To gain additional confidence that the L2 deposit transaction works as expected, we manually simulate it and record the results in the task’s VALIDATION.md file.
-
Simulate the task that uses the TransferL2PAOFromL1.sol template.
-
In the terminal output, copy the Tenderly link and open it in your browser.

-
In Tenderly, open the
Eventstab and look for theTransactionDepositedevent.
{ "from": "0x7e6c183f538abb8572f5cd17109c617b994d6944", "to": "0x4200000000000000000000000000000000000018", "version": "0", "opaqueData": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d4000f2fde38b0000000000000000000000006b1bae59d09fccbddb6c6cceb07b7279367c4e3b" } -
Using the data in the
TransactionDepositedevent, create a new Tenderly simulation by opening the Simulator and filling in the form using the fields below. Setgas priceandvalueto0. Thefromaddress andgaswill be derived from the event data and filled in step 9. -
Insert the
toaddress (0x4200000000000000000000000000000000000018) as the destination address and select the correct L2 network. -
Next, we need to create the calldata from the
opaqueDatafield in theTransactionDepositedevent. This is going to go into theEnter raw input datafield. We know this particular transaction is atransferOwnershipcall to theProxyAdmincontract. We can identify the start of the relevant calldata by extracting the function selector:cast sig "transferOwnership(address)" # returns: 0xf2fde38b
Now that we know the function selector, we can extract the calldata from the
opaqueDatafield and run the following cast command:cast calldata-decode "transferOwnership(address)" 0xf2fde38b0000000000000000000000006b1bae59d09fccbddb6c6cceb07b7279367c4e3b # returns: 0x6B1BAE59D09fCcbdDB6C6cceb07B7279367C4E3b
We must put
0xf2fde38b0000000000000000000000006b1bae59d09fccbddb6c6cceb07b7279367c4e3bin theEnter raw input datafield.
-
Double-check that the address returned from the
cast calldata-decodestep matches the aliased new L1 ProxyAdmin owner (L1PAO) for the target chain. In this case, the L1PAO is0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A. Confirm this by manually unaliasing the address using chisel.> uint160 constant offset = uint160(0x1111000000000000000000000000000000001111) > function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { unchecked { l1Address = address(uint160(l2Address) - offset); } } > undoL1ToL2Alias(0x6B1BAE59D09fCcbdDB6C6cceb07B7279367C4E3b) # returns: 0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A
-
Next we need to fill out the
Transaction Parameterssection on the right of the UI. Specifically, fill out theFromaddress andGasfields. TheFromaddress should be the aliased old L1PAO address obtained as thefromfield in theTransactionDepositedevent (i.e.0x6B1BAE59D09fCcbdDB6C6cceb07B7279367C4E3b). TheGasfield should be set to200000. You can get this number by further parsing the opaque data and extracting the gas limit.cast --to-dec 0x30d40 # returns: 200000 -
Click
Simulate Transactionand you should see the transaction succeed. -
Finally, check the
Statetab and ensure the state changes are as expected. Specifically, confirm that theProxyAdmincontract reflects the new, expected owner.
