Commit 846cec96 authored by smartcontracts's avatar smartcontracts Committed by GitHub

feat: update op-e2e for FPAC (#9366)

parent 9a71fed9
...@@ -178,7 +178,13 @@ jobs: ...@@ -178,7 +178,13 @@ jobs:
FOUNDRY_PROFILE: ci FOUNDRY_PROFILE: ci
command: pnpm build command: pnpm build
- run: - run:
name: Generate allocs name: Generate FPAC allocs
command: DEVNET_FPAC="true" make devnet-allocs
- run:
name: Copy FPAC allocs to .devnet-fpac
command: cp -r .devnet/ .devnet-fault-proofs/
- run:
name: Generate non-FPAC allocs
command: make devnet-allocs command: make devnet-allocs
- persist_to_workspace: - persist_to_workspace:
root: "." root: "."
...@@ -191,6 +197,8 @@ jobs: ...@@ -191,6 +197,8 @@ jobs:
- "packages/contracts-bedrock/tsconfig.build.tsbuildinfo" - "packages/contracts-bedrock/tsconfig.build.tsbuildinfo"
- ".devnet/allocs-l1.json" - ".devnet/allocs-l1.json"
- ".devnet/addresses.json" - ".devnet/addresses.json"
- ".devnet-fault-proofs/allocs-l1.json"
- ".devnet-fault-proofs/addresses.json"
- "packages/contracts-bedrock/deploy-config/devnetL1.json" - "packages/contracts-bedrock/deploy-config/devnetL1.json"
- "packages/contracts-bedrock/deployments/devnetL1" - "packages/contracts-bedrock/deployments/devnetL1"
...@@ -799,6 +807,9 @@ jobs: ...@@ -799,6 +807,9 @@ jobs:
go-e2e-test: go-e2e-test:
parameters: parameters:
fpac:
type: string
default: ''
module: module:
description: Go Module Name description: Go Module Name
type: string type: string
...@@ -813,6 +824,9 @@ jobs: ...@@ -813,6 +824,9 @@ jobs:
description: Whether to notify on failure description: Whether to notify on failure
type: boolean type: boolean
default: false default: false
environment:
DEVNET_FPAC: 'false'
OP_E2E_USE_FPAC: 'false'
docker: docker:
- image: <<pipeline.parameters.ci_builder_image>> - image: <<pipeline.parameters.ci_builder_image>>
resource_class: xlarge resource_class: xlarge
...@@ -824,6 +838,16 @@ jobs: ...@@ -824,6 +838,16 @@ jobs:
parallelism: <<parameters.parallelism>> parallelism: <<parameters.parallelism>>
steps: steps:
- checkout - checkout
- when:
condition:
equal: ['-fault-proofs', <<parameters.fpac>>]
steps:
- run:
name: Set DEVNET_FPAC = true
command: echo 'export DEVNET_FPAC=true' >> $BASH_ENV
- run:
name: Set OP_E2E_USE_FPAC = true
command: echo 'export OP_E2E_USE_FPAC=true' >> $BASH_ENV
- check-changed: - check-changed:
patterns: op-(.+),cannon,contracts-bedrock patterns: op-(.+),cannon,contracts-bedrock
- run: - run:
...@@ -841,8 +865,8 @@ jobs: ...@@ -841,8 +865,8 @@ jobs:
name: Load devnet-allocs name: Load devnet-allocs
command: | command: |
mkdir -p .devnet mkdir -p .devnet
cp /tmp/workspace/.devnet/allocs-l1.json .devnet/allocs-l1.json cp /tmp/workspace/.devnet<<parameters.fpac>>/allocs-l1.json .devnet/allocs-l1.json
cp /tmp/workspace/.devnet/addresses.json .devnet/addresses.json cp /tmp/workspace/.devnet<<parameters.fpac>>/addresses.json .devnet/addresses.json
cp /tmp/workspace/packages/contracts-bedrock/deploy-config/devnetL1.json packages/contracts-bedrock/deploy-config/devnetL1.json cp /tmp/workspace/packages/contracts-bedrock/deploy-config/devnetL1.json packages/contracts-bedrock/deploy-config/devnetL1.json
cp -r /tmp/workspace/packages/contracts-bedrock/deployments/devnetL1 packages/contracts-bedrock/deployments/devnetL1 cp -r /tmp/workspace/packages/contracts-bedrock/deployments/devnetL1 packages/contracts-bedrock/deployments/devnetL1
- run: - run:
...@@ -917,12 +941,29 @@ jobs: ...@@ -917,12 +941,29 @@ jobs:
working_directory: <<parameters.working_directory>> working_directory: <<parameters.working_directory>>
indexer-tests: indexer-tests:
parameters:
fpac:
type: string
default: ''
environment:
DEVNET_FPAC: 'false'
OP_E2E_USE_FPAC: 'false'
docker: docker:
- image: <<pipeline.parameters.ci_builder_image>> - image: <<pipeline.parameters.ci_builder_image>>
- image: cimg/postgres:14.1 - image: cimg/postgres:14.1
resource_class: xlarge resource_class: xlarge
steps: steps:
- checkout - checkout
- when:
condition:
equal: ['fault-proofs', <<parameters.fpac>>]
steps:
- run:
name: Set DEVNET_FPAC = true
command: echo 'export DEVNET_FPAC=true' >> $BASH_ENV
- run:
name: Set OP_E2E_USE_FPAC = true
command: echo 'export OP_E2E_USE_FPAC=true' >> $BASH_ENV
- check-changed: - check-changed:
patterns: indexer patterns: indexer
- run: - run:
...@@ -1021,7 +1062,7 @@ jobs: ...@@ -1021,7 +1062,7 @@ jobs:
machine: machine:
image: <<pipeline.parameters.base_image>> image: <<pipeline.parameters.base_image>>
parameters: parameters:
devnet_fpac: fpac:
type: string type: string
environment: environment:
DOCKER_BUILDKIT: 1 DOCKER_BUILDKIT: 1
...@@ -1032,7 +1073,7 @@ jobs: ...@@ -1032,7 +1073,7 @@ jobs:
- checkout - checkout
- when: - when:
condition: condition:
equal: ['fault-proofs', <<parameters.devnet_fpac>>] equal: ['-fault-proofs', <<parameters.fpac>>]
steps: steps:
- run: - run:
name: Set DEVNET_FPAC = true name: Set DEVNET_FPAC = true
...@@ -1460,7 +1501,11 @@ workflows: ...@@ -1460,7 +1501,11 @@ workflows:
name: proxyd-tests name: proxyd-tests
binary_name: proxyd binary_name: proxyd
working_directory: proxyd working_directory: proxyd
- indexer-tests - indexer-tests:
name: indexer-tests<< matrix.fpac >>
matrix:
parameters:
fpac: ["", "-fault-proofs"]
- semgrep-scan - semgrep-scan
- go-mod-download - go-mod-download
- fuzz-golang: - fuzz-golang:
...@@ -1533,7 +1578,10 @@ workflows: ...@@ -1533,7 +1578,10 @@ workflows:
module: op-service module: op-service
requires: ["go-mod-download"] requires: ["go-mod-download"]
- go-e2e-test: - go-e2e-test:
name: op-e2e-HTTP-tests name: op-e2e-HTTP-tests<< matrix.fpac >>
matrix:
parameters:
fpac: ["", "-fault-proofs"]
module: op-e2e module: op-e2e
target: test-http target: test-http
parallelism: 4 parallelism: 4
...@@ -1541,7 +1589,10 @@ workflows: ...@@ -1541,7 +1589,10 @@ workflows:
- go-mod-download - go-mod-download
- pnpm-monorepo - pnpm-monorepo
- go-e2e-test: - go-e2e-test:
name: op-e2e-action-tests name: op-e2e-action-tests<< matrix.fpac >>
matrix:
parameters:
fpac: ["", "-fault-proofs"]
module: op-e2e module: op-e2e
target: test-actions target: test-actions
parallelism: 1 parallelism: 1
...@@ -1557,7 +1608,10 @@ workflows: ...@@ -1557,7 +1608,10 @@ workflows:
- pnpm-monorepo - pnpm-monorepo
- cannon-prestate - cannon-prestate
- go-e2e-test: - go-e2e-test:
name: op-e2e-ext-geth-tests name: op-e2e-ext-geth-tests<< matrix.fpac >>
matrix:
parameters:
fpac: ["", "-fault-proofs"]
module: op-e2e module: op-e2e
target: test-external-geth target: test-external-geth
requires: requires:
...@@ -1649,7 +1703,7 @@ workflows: ...@@ -1649,7 +1703,7 @@ workflows:
- devnet: - devnet:
matrix: matrix:
parameters: parameters:
devnet_fpac: ["legacy", "fault-proofs"] fpac: ["legacy", "fault-proofs"]
requires: requires:
- pnpm-monorepo - pnpm-monorepo
- op-batcher-docker-build - op-batcher-docker-build
......
...@@ -31,8 +31,9 @@ type L1Contracts struct { ...@@ -31,8 +31,9 @@ type L1Contracts struct {
SystemConfigProxy common.Address `toml:"system-config"` SystemConfigProxy common.Address `toml:"system-config"`
// rollup state // rollup state
OptimismPortalProxy common.Address `toml:"optimism-portal"` OptimismPortalProxy common.Address `toml:"optimism-portal"`
L2OutputOracleProxy common.Address `toml:"l2-output-oracle"` L2OutputOracleProxy common.Address `toml:"l2-output-oracle"`
DisputeGameFactoryProxy common.Address `toml:"dispute-game-factory"`
// bridging // bridging
L1CrossDomainMessengerProxy common.Address `toml:"l1-cross-domain-messenger"` L1CrossDomainMessengerProxy common.Address `toml:"l1-cross-domain-messenger"`
......
...@@ -98,6 +98,7 @@ func TestLoadConfigWithoutPreset(t *testing.T) { ...@@ -98,6 +98,7 @@ func TestLoadConfigWithoutPreset(t *testing.T) {
l2-output-oracle = "0x42097868233d1aa22e815a266982f2cf17685a27" l2-output-oracle = "0x42097868233d1aa22e815a266982f2cf17685a27"
l1-cross-domain-messenger = "0x420ce71c97B33Cc4729CF772ae268934F7ab5fA1" l1-cross-domain-messenger = "0x420ce71c97B33Cc4729CF772ae268934F7ab5fA1"
l1-standard-bridge = "0x4209fc46f92E8a1c0deC1b1747d010903E884bE1" l1-standard-bridge = "0x4209fc46f92E8a1c0deC1b1747d010903E884bE1"
dispute-game-factory = "0x4209fc46f92E8a1c0deC1b1747d010903E884bE1"
[rpcs] [rpcs]
l1-rpc = "https://l1.example.com" l1-rpc = "https://l1.example.com"
......
...@@ -25,6 +25,7 @@ var Presets = map[int]Preset{ ...@@ -25,6 +25,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1"), L1CrossDomainMessengerProxy: common.HexToAddress("0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1"),
L1StandardBridgeProxy: common.HexToAddress("0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1"), L1StandardBridgeProxy: common.HexToAddress("0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1"),
L1ERC721BridgeProxy: common.HexToAddress("0x5a7749f83b81B301cAb5f48EB8516B986DAef23D"), L1ERC721BridgeProxy: common.HexToAddress("0x5a7749f83b81B301cAb5f48EB8516B986DAef23D"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
// pre-bedrock // pre-bedrock
LegacyCanonicalTransactionChain: common.HexToAddress("0x5e4e65926ba27467555eb562121fac00d24e9dd2"), LegacyCanonicalTransactionChain: common.HexToAddress("0x5e4e65926ba27467555eb562121fac00d24e9dd2"),
...@@ -49,6 +50,7 @@ var Presets = map[int]Preset{ ...@@ -49,6 +50,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"), L1CrossDomainMessengerProxy: common.HexToAddress("0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"),
L1StandardBridgeProxy: common.HexToAddress("0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"), L1StandardBridgeProxy: common.HexToAddress("0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"),
L1ERC721BridgeProxy: common.HexToAddress("0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9"), L1ERC721BridgeProxy: common.HexToAddress("0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
// pre-bedrock // pre-bedrock
LegacyCanonicalTransactionChain: common.HexToAddress("0x607F755149cFEB3a14E1Dc3A4E2450Cde7dfb04D"), LegacyCanonicalTransactionChain: common.HexToAddress("0x607F755149cFEB3a14E1Dc3A4E2450Cde7dfb04D"),
...@@ -73,6 +75,7 @@ var Presets = map[int]Preset{ ...@@ -73,6 +75,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef"), L1CrossDomainMessengerProxy: common.HexToAddress("0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef"),
L1StandardBridgeProxy: common.HexToAddress("0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1"), L1StandardBridgeProxy: common.HexToAddress("0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1"),
L1ERC721BridgeProxy: common.HexToAddress("0xd83e03D576d23C9AEab8cC44Fa98d058D2176D1f"), L1ERC721BridgeProxy: common.HexToAddress("0xd83e03D576d23C9AEab8cC44Fa98d058D2176D1f"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
}, },
L1StartingHeight: 4071408, L1StartingHeight: 4071408,
L1ConfirmationDepth: 10, L1ConfirmationDepth: 10,
...@@ -91,6 +94,7 @@ var Presets = map[int]Preset{ ...@@ -91,6 +94,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0x866E82a600A1414e583f7F13623F1aC5d58b0Afa"), L1CrossDomainMessengerProxy: common.HexToAddress("0x866E82a600A1414e583f7F13623F1aC5d58b0Afa"),
L1StandardBridgeProxy: common.HexToAddress("0x3154Cf16ccdb4C6d922629664174b904d80F2C35"), L1StandardBridgeProxy: common.HexToAddress("0x3154Cf16ccdb4C6d922629664174b904d80F2C35"),
L1ERC721BridgeProxy: common.HexToAddress("0x608d94945A64503E642E6370Ec598e519a2C1E53"), L1ERC721BridgeProxy: common.HexToAddress("0x608d94945A64503E642E6370Ec598e519a2C1E53"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
}, },
L1StartingHeight: 17481768, L1StartingHeight: 17481768,
L1ConfirmationDepth: 10, L1ConfirmationDepth: 10,
...@@ -109,6 +113,7 @@ var Presets = map[int]Preset{ ...@@ -109,6 +113,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0x8e5693140eA606bcEB98761d9beB1BC87383706D"), L1CrossDomainMessengerProxy: common.HexToAddress("0x8e5693140eA606bcEB98761d9beB1BC87383706D"),
L1StandardBridgeProxy: common.HexToAddress("0xfA6D8Ee5BE770F84FC001D098C4bD604Fe01284a"), L1StandardBridgeProxy: common.HexToAddress("0xfA6D8Ee5BE770F84FC001D098C4bD604Fe01284a"),
L1ERC721BridgeProxy: common.HexToAddress("0x5E0c967457347D5175bF82E8CCCC6480FCD7e568"), L1ERC721BridgeProxy: common.HexToAddress("0x5E0c967457347D5175bF82E8CCCC6480FCD7e568"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
}, },
L1StartingHeight: 8410981, L1StartingHeight: 8410981,
L1ConfirmationDepth: 10, L1ConfirmationDepth: 10,
...@@ -127,6 +132,7 @@ var Presets = map[int]Preset{ ...@@ -127,6 +132,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0xC34855F4De64F1840e5686e64278da901e261f20"), L1CrossDomainMessengerProxy: common.HexToAddress("0xC34855F4De64F1840e5686e64278da901e261f20"),
L1StandardBridgeProxy: common.HexToAddress("0xfd0Bf71F60660E2f608ed56e1659C450eB113120"), L1StandardBridgeProxy: common.HexToAddress("0xfd0Bf71F60660E2f608ed56e1659C450eB113120"),
L1ERC721BridgeProxy: common.HexToAddress("0x21eFD066e581FA55Ef105170Cc04d74386a09190"), L1ERC721BridgeProxy: common.HexToAddress("0x21eFD066e581FA55Ef105170Cc04d74386a09190"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
}, },
L1StartingHeight: 4370868, L1StartingHeight: 4370868,
L1ConfirmationDepth: 10, L1ConfirmationDepth: 10,
...@@ -145,6 +151,7 @@ var Presets = map[int]Preset{ ...@@ -145,6 +151,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0xdC40a14d9abd6F410226f1E6de71aE03441ca506"), L1CrossDomainMessengerProxy: common.HexToAddress("0xdC40a14d9abd6F410226f1E6de71aE03441ca506"),
L1StandardBridgeProxy: common.HexToAddress("0x3e2Ea9B92B7E48A52296fD261dc26fd995284631"), L1StandardBridgeProxy: common.HexToAddress("0x3e2Ea9B92B7E48A52296fD261dc26fd995284631"),
L1ERC721BridgeProxy: common.HexToAddress("0x83A4521A3573Ca87f3a971B169C5A0E1d34481c3"), L1ERC721BridgeProxy: common.HexToAddress("0x83A4521A3573Ca87f3a971B169C5A0E1d34481c3"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
}, },
L1StartingHeight: 17473923, L1StartingHeight: 17473923,
L1ConfirmationDepth: 10, L1ConfirmationDepth: 10,
...@@ -163,6 +170,7 @@ var Presets = map[int]Preset{ ...@@ -163,6 +170,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0xD87342e16352D33170557A7dA1e5fB966a60FafC"), L1CrossDomainMessengerProxy: common.HexToAddress("0xD87342e16352D33170557A7dA1e5fB966a60FafC"),
L1StandardBridgeProxy: common.HexToAddress("0x7CC09AC2452D6555d5e0C213Ab9E2d44eFbFc956"), L1StandardBridgeProxy: common.HexToAddress("0x7CC09AC2452D6555d5e0C213Ab9E2d44eFbFc956"),
L1ERC721BridgeProxy: common.HexToAddress("0x57C1C6b596ce90C0e010c358DD4Aa052404bB70F"), L1ERC721BridgeProxy: common.HexToAddress("0x57C1C6b596ce90C0e010c358DD4Aa052404bB70F"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
}, },
L1StartingHeight: 8942381, L1StartingHeight: 8942381,
L1ConfirmationDepth: 10, L1ConfirmationDepth: 10,
...@@ -181,6 +189,7 @@ var Presets = map[int]Preset{ ...@@ -181,6 +189,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0x97BAf688E5d0465E149d1d5B497Ca99392a6760e"), L1CrossDomainMessengerProxy: common.HexToAddress("0x97BAf688E5d0465E149d1d5B497Ca99392a6760e"),
L1StandardBridgeProxy: common.HexToAddress("0xD0204B9527C1bA7bD765Fa5CCD9355d38338272b"), L1StandardBridgeProxy: common.HexToAddress("0xD0204B9527C1bA7bD765Fa5CCD9355d38338272b"),
L1ERC721BridgeProxy: common.HexToAddress("0xaFF0F8aaB6Cc9108D34b3B8423C76d2AF434d115"), L1ERC721BridgeProxy: common.HexToAddress("0xaFF0F8aaB6Cc9108D34b3B8423C76d2AF434d115"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
}, },
L1StartingHeight: 17672702, L1StartingHeight: 17672702,
L1ConfirmationDepth: 10, L1ConfirmationDepth: 10,
...@@ -199,6 +208,7 @@ var Presets = map[int]Preset{ ...@@ -199,6 +208,7 @@ var Presets = map[int]Preset{
L1CrossDomainMessengerProxy: common.HexToAddress("0x97f3558Ce48FE71B8CeFA5497708A49531D5A8E1"), L1CrossDomainMessengerProxy: common.HexToAddress("0x97f3558Ce48FE71B8CeFA5497708A49531D5A8E1"),
L1StandardBridgeProxy: common.HexToAddress("0xFaE6abCAF30D23e233AC7faF747F2fC3a5a6Bfa3"), L1StandardBridgeProxy: common.HexToAddress("0xFaE6abCAF30D23e233AC7faF747F2fC3a5a6Bfa3"),
L1ERC721BridgeProxy: common.HexToAddress("0xBA8397B6f255618D5985d0fB427D8c0496F3a5FA"), L1ERC721BridgeProxy: common.HexToAddress("0xBA8397B6f255618D5985d0fB427D8c0496F3a5FA"),
DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"),
}, },
L1StartingHeight: 17672702, L1StartingHeight: 17672702,
L1ConfirmationDepth: 10, L1ConfirmationDepth: 10,
......
...@@ -169,7 +169,7 @@ func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) { ...@@ -169,7 +169,7 @@ func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) {
// (2) Process RelayedMessage on withdrawal finalization // (2) Process RelayedMessage on withdrawal finalization
require.Nil(t, sentMessage.RelayedMessageEventGUID) require.Nil(t, sentMessage.RelayedMessageEventGUID)
_, finalizedReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, sentMsgReceipt) _, finalizedReceipt, _, _ := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, sentMsgReceipt)
// wait for processor catchup // wait for processor catchup
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
......
...@@ -163,7 +163,7 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) { ...@@ -163,7 +163,7 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) {
// Test Withdrawal Finalized // Test Withdrawal Finalized
require.Nil(t, withdraw.FinalizedL1EventGUID) require.Nil(t, withdraw.FinalizedL1EventGUID)
finalizeReceipt := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpCfg.Secrets.Alice, proveReceipt, withdrawParams) finalizeReceipt, _, _ := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpCfg.Secrets.Alice, proveReceipt, withdrawParams)
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
...@@ -207,7 +207,7 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserFailedWithdrawal(t *testing.T) ...@@ -207,7 +207,7 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserFailedWithdrawal(t *testing.T)
require.NoError(t, err) require.NoError(t, err)
// Prove&Finalize withdrawal // Prove&Finalize withdrawal
_, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, withdrawReceipt) _, finalizeReceipt, _, _ := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, withdrawReceipt)
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
......
...@@ -300,7 +300,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { ...@@ -300,7 +300,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
require.Empty(t, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash) require.Empty(t, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash)
// wait for processor catchup // wait for processor catchup
proveReceipt, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, withdrawReceipt) proveReceipt, finalizeReceipt, _, _ := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, withdrawReceipt)
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
...@@ -388,7 +388,7 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) { ...@@ -388,7 +388,7 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) {
require.Empty(t, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash) require.Empty(t, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash)
// wait for processor catchup // wait for processor catchup
proveReceipt, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, l2ToL1WithdrawReceipt) proveReceipt, finalizeReceipt, _, _ := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, l2ToL1WithdrawReceipt)
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
...@@ -601,7 +601,7 @@ func TestClientBridgeFunctions(t *testing.T) { ...@@ -601,7 +601,7 @@ func TestClientBridgeFunctions(t *testing.T) {
s.proven = new(big.Int).Add(s.proven, actor.amt) s.proven = new(big.Int).Add(s.proven, actor.amt)
finalReceipt := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, actor.priv, proveReceipt, params) finalReceipt, _, _ := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, actor.priv, proveReceipt, params)
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header
seen := l1Header != nil && l1Header.Number.Uint64() >= finalReceipt.BlockNumber.Uint64() seen := l1Header != nil && l1Header.Number.Uint64() >= finalReceipt.BlockNumber.Uint64()
......
...@@ -8,7 +8,10 @@ import ( ...@@ -8,7 +8,10 @@ import (
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindingspreview"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
...@@ -24,9 +27,29 @@ func TestE2EETL(t *testing.T) { ...@@ -24,9 +27,29 @@ func TestE2EETL(t *testing.T) {
l2OutputOracle, err := bindings.NewL2OutputOracle(testSuite.OpCfg.L1Deployments.L2OutputOracleProxy, testSuite.L1Client) l2OutputOracle, err := bindings.NewL2OutputOracle(testSuite.OpCfg.L1Deployments.L2OutputOracleProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(testSuite.OpCfg.L1Deployments.DisputeGameFactoryProxy, testSuite.L1Client)
require.NoError(t, err)
optimismPortal, err := bindingspreview.NewOptimismPortal2Caller(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err)
// wait for at least 10 L2 blocks posted on L1 // wait for at least 10 L2 blocks posted on L1
require.NoError(t, wait.For(context.Background(), time.Second, func() (bool, error) { require.NoError(t, wait.For(context.Background(), time.Second, func() (bool, error) {
l2Height, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{Context: context.Background()}) var l2Height *big.Int
var err error
if e2eutils.UseFPAC() {
gameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{Context: context.Background()})
require.NoError(t, err)
if gameCount.Cmp(big.NewInt(0)) == 0 {
return false, nil
}
latestGame, err := withdrawals.FindLatestGame(context.Background(), disputeGameFactory, optimismPortal)
require.NoError(t, err)
l2Height = new(big.Int).SetBytes(latestGame.ExtraData[0:32])
} else {
l2Height, err = l2OutputOracle.LatestBlockNumber(&bind.CallOpts{Context: context.Background()})
}
return l2Height != nil && l2Height.Uint64() >= 9, err return l2Height != nil && l2Height.Uint64() >= 9, err
})) }))
......
...@@ -107,6 +107,7 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { ...@@ -107,6 +107,7 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
L1CrossDomainMessengerProxy: opCfg.L1Deployments.L1CrossDomainMessengerProxy, L1CrossDomainMessengerProxy: opCfg.L1Deployments.L1CrossDomainMessengerProxy,
L1StandardBridgeProxy: opCfg.L1Deployments.L1StandardBridgeProxy, L1StandardBridgeProxy: opCfg.L1Deployments.L1StandardBridgeProxy,
L1ERC721BridgeProxy: opCfg.L1Deployments.L1ERC721BridgeProxy, L1ERC721BridgeProxy: opCfg.L1Deployments.L1ERC721BridgeProxy,
DisputeGameFactoryProxy: opCfg.L1Deployments.DisputeGameFactoryProxy,
}, },
}, },
HTTPServer: config.ServerConfig{Host: "127.0.0.1", Port: 0}, HTTPServer: config.ServerConfig{Host: "127.0.0.1", Port: 0},
......
SHELL := /usr/bin/env bash SHELL := /usr/bin/env bash
pkg := bindings pkg := bindings
pkg-preview := bindingspreview
monorepo-base := $(shell dirname $(realpath .)) monorepo-base := $(shell dirname $(realpath .))
contracts-dir := $(monorepo-base)/packages/contracts-bedrock contracts-dir := $(monorepo-base)/packages/contracts-bedrock
contracts-list := ./artifacts.json contracts-list := ./artifacts.json
contracts-list-preview := ./artifacts-preview.json
log-level := info log-level := info
ETHERSCAN_APIKEY_ETH ?= ETHERSCAN_APIKEY_ETH ?=
ETHERSCAN_APIKEY_OP ?= ETHERSCAN_APIKEY_OP ?=
...@@ -21,9 +23,9 @@ compile: ...@@ -21,9 +23,9 @@ compile:
forge clean && \ forge clean && \
pnpm build pnpm build
bindings: bindgen-local bindings: bindgen-local bindgen-preview
bindings-build: bindgen-generate-local bindings-build: bindgen-generate-local bindgen-generate-preview
bindgen: compile bindgen-generate-all bindgen: compile bindgen-generate-all
...@@ -53,6 +55,18 @@ bindgen-generate-local: ...@@ -53,6 +55,18 @@ bindgen-generate-local:
local \ local \
--forge-artifacts $(contracts-dir)/forge-artifacts --forge-artifacts $(contracts-dir)/forge-artifacts
bindgen-preview: compile bindgen-generate-preview
bindgen-generate-preview:
go run ./cmd \
generate \
--metadata-out ./$(pkg-preview) \
--bindings-package $(pkg-preview) \
--contracts-list $(contracts-list-preview) \
--log.level $(log-level) \
local \
--forge-artifacts $(contracts-dir)/forge-artifacts
bindgen-remote: bindgen-remote:
go run ./cmd/ \ go run ./cmd/ \
generate \ generate \
......
{
"local": [
"OptimismPortal2"
],
"remote": []
}
This source diff could not be displayed because it is too large. You can view the blob instead.
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindingspreview
import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const OptimismPortal2StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1020_storage\"},{\"astId\":1003,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)48_storage\"},{\"astId\":1004,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"50\",\"type\":\"t_address\"},{\"astId\":1005,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":1006,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"spacer_52_0_32\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_bytes32\"},{\"astId\":1007,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"spacer_53_0_1\",\"offset\":0,\"slot\":\"53\",\"type\":\"t_bool\"},{\"astId\":1008,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"superchainConfig\",\"offset\":1,\"slot\":\"53\",\"type\":\"t_contract(SuperchainConfig)1017\"},{\"astId\":1009,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"spacer_54_0_20\",\"offset\":0,\"slot\":\"54\",\"type\":\"t_address\"},{\"astId\":1010,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"systemConfig\",\"offset\":0,\"slot\":\"55\",\"type\":\"t_contract(SystemConfig)1018\"},{\"astId\":1011,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"disputeGameFactory\",\"offset\":0,\"slot\":\"56\",\"type\":\"t_contract(DisputeGameFactory)1015\"},{\"astId\":1012,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"provenWithdrawals\",\"offset\":0,\"slot\":\"57\",\"type\":\"t_mapping(t_bytes32,t_struct(ProvenWithdrawal)1019_storage)\"},{\"astId\":1013,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"disputeGameBlacklist\",\"offset\":0,\"slot\":\"58\",\"type\":\"t_mapping(t_contract(IDisputeGame)1016,t_bool)\"},{\"astId\":1014,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"respectedGameType\",\"offset\":0,\"slot\":\"59\",\"type\":\"t_userDefinedValueType(GameType)1021\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)48_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[48]\",\"numberOfBytes\":\"1536\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_contract(DisputeGameFactory)1015\":{\"encoding\":\"inplace\",\"label\":\"contract DisputeGameFactory\",\"numberOfBytes\":\"20\"},\"t_contract(IDisputeGame)1016\":{\"encoding\":\"inplace\",\"label\":\"contract IDisputeGame\",\"numberOfBytes\":\"20\"},\"t_contract(SuperchainConfig)1017\":{\"encoding\":\"inplace\",\"label\":\"contract SuperchainConfig\",\"numberOfBytes\":\"20\"},\"t_contract(SystemConfig)1018\":{\"encoding\":\"inplace\",\"label\":\"contract SystemConfig\",\"numberOfBytes\":\"20\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_mapping(t_bytes32,t_struct(ProvenWithdrawal)1019_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e struct OptimismPortal2.ProvenWithdrawal)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_struct(ProvenWithdrawal)1019_storage\"},\"t_mapping(t_contract(IDisputeGame)1016,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(contract IDisputeGame =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_contract(IDisputeGame)1016\",\"value\":\"t_bool\"},\"t_struct(ProvenWithdrawal)1019_storage\":{\"encoding\":\"inplace\",\"label\":\"struct OptimismPortal2.ProvenWithdrawal\",\"numberOfBytes\":\"32\"},\"t_struct(ResourceParams)1020_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceParams\",\"numberOfBytes\":\"32\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"},\"t_userDefinedValueType(GameType)1021\":{\"encoding\":\"inplace\",\"label\":\"GameType\",\"numberOfBytes\":\"4\"}}}"
var OptimismPortal2StorageLayout = new(solc.StorageLayout)
var OptimismPortal2DeployedBin = "0x6080604052600436106101b05760003560e01c80638b4c40b0116100ec578063bf653a5c1161008a578063e965084c11610064578063e965084c14610608578063e9e05c42146106a4578063f0498750146106b7578063f2b4e617146106e257600080fd5b8063bf653a5c14610514578063c0c53b8b14610547578063cff0ab961461056757600080fd5b80639bf62d82116100c65780639bf62d8214610469578063a14238e714610496578063a27778e5146104c6578063a35d99df146104db57600080fd5b80638b4c40b0146101d55780638c3152e91461040c578063952b27971461042c57600080fd5b80634870496f11610159578063724c184c11610133578063724c184c146103975780637af1906d146103ac5780637d6be8dc146103cc5780637fc48504146103ec57600080fd5b80634870496f1461030c57806354fd4d501461032c5780635c975abb1461038257600080fd5b80633c9f397c1161018a5780633c9f397c14610285578063452a9320146102b757806345884d32146102cc57600080fd5b806303869d7c146101dc57806333d7e2bd146101fc57806335e80ab31461025357600080fd5b366101d7576101d53334620186a060006040518060200160405280600081525061070f565b005b600080fd5b3480156101e857600080fd5b506101d56101f7366004614e0f565b6109aa565b34801561020857600080fd5b506037546102299073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561025f57600080fd5b5060355461022990610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561029157600080fd5b50603b546102a29063ffffffff1681565b60405163ffffffff909116815260200161024a565b3480156102c357600080fd5b50610229610a71565b3480156102d857600080fd5b506102fc6102e7366004614e4d565b603a6020526000908152604090205460ff1681565b604051901515815260200161024a565b34801561031857600080fd5b506101d5610327366004615025565b610b09565b34801561033857600080fd5b506103756040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161024a9190615177565b34801561038e57600080fd5b506102fc61137a565b3480156103a357600080fd5b5061022961140d565b3480156103b857600080fd5b506101d56103c7366004614e0f565b611417565b3480156103d857600080fd5b506101d56103e7366004614e4d565b611b6b565b3480156103f857600080fd5b506101d561040736600461519c565b611c4b565b34801561041857600080fd5b506101d56104273660046151b9565b611d15565b34801561043857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405190815260200161024a565b34801561047557600080fd5b506032546102299073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104a257600080fd5b506102fc6104b1366004614e0f565b60336020526000908152604090205460ff1681565b3480156104d257600080fd5b5061dead610229565b3480156104e757600080fd5b506104fb6104f636600461520c565b611fed565b60405167ffffffffffffffff909116815260200161024a565b34801561052057600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061045b565b34801561055357600080fd5b506101d5610562366004615229565b61200c565b34801561057357600080fd5b506001546105cf906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161024a565b34801561061457600080fd5b5061066f610623366004614e0f565b60396020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161024a565b6101d56106b2366004615282565b61070f565b3480156106c357600080fd5b5060375473ffffffffffffffffffffffffffffffffffffffff16610229565b3480156106ee57600080fd5b506038546102299073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905083156107c65773ffffffffffffffffffffffffffffffffffffffff8716156107c657604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b6107d08351611fed565b67ffffffffffffffff168567ffffffffffffffff161015610873576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c000000000000000000000000000000000000000000000000000000000060648201526084016107bd565b6201d4c0835111156108e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c61726765000060448201526064016107bd565b33328114610902575033731111000000000000000000000000000000001111015b6000348888888860405160200161091d959493929190615301565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161098d9190615177565b60405180910390a450506109a18282612276565b50505050505050565b3361dead14610a3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4f7074696d69736d506f7274616c3a206f6e6c7920736175726f6e2063616e2060448201527f64656c6574652070726f76656e207769746864726177616c730000000000000060648201526084016107bd565b600090815260396020526040902080547fffffffff00000000000000000000000000000000000000000000000000000000169055565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190615366565b905090565b610b1161137a565b15610b78576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a207061757365640000000000000000000060448201526064016107bd565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016107bd565b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa158015610cab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccf9190615383565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4591906153c5565b603b5490915060ff848116911614610ddf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a20696e76616c69642067616d652074797060448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016107bd565b610df6610df1368890038801886153de565b6125a3565b8114610e84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016107bd565b6000610e8f896125ff565b60008181526039602090815260409182902082518084019093525473ffffffffffffffffffffffffffffffffffffffff81168084527401000000000000000000000000000000000000000090910467ffffffffffffffff169183018290529293509091901580610f7e575060018573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6b9190615473565b6002811115610f7c57610f7c615444565b145b80610fae575073ffffffffffffffffffffffffffffffffffffffff85166000908152603a602052604090205460ff165b806110415750603b5463ffffffff1660ff1661103b8273ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561100e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110329190615494565b63ffffffff1690565b60ff1614155b6110f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605860248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e2c20616e642064697360648201527f707574652067616d65206973206e6f7420696e76616c69640000000000000000608482015260a4016107bd565b60408051602081018590526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506111bc9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152906111b28b8d6154b1565b8d6040013561262f565b611248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016107bd565b60405180604001604052808773ffffffffffffffffffffffffffffffffffffffff1681526020014267ffffffffffffffff168152506039600086815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055509050508b6040015173ffffffffffffffffffffffffffffffffffffffff168c6020015173ffffffffffffffffffffffffffffffffffffffff16857f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6260405160405180910390a4505050505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190615535565b6000610b04610a71565b600081815260396020908152604080832081518083018352905473ffffffffffffffffffffffffffffffffffffffff81168083527401000000000000000000000000000000000000000090910467ffffffffffffffff1682850152808552603a90935292205460ff161561150d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652068617360448201527f206265656e20626c61636b6c697374656400000000000000000000000000000060648201526084016107bd565b816020015167ffffffffffffffff166000036115ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e20796574000000000000000000000000000060648201526084016107bd565b61162a8173ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161d9190615552565b67ffffffffffffffff1690565b67ffffffffffffffff16826020015167ffffffffffffffff16116116f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4016107bd565b7f0000000000000000000000000000000000000000000000000000000000000000826020015167ffffffffffffffff1642611731919061559e565b116117be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d61747572656420796574000000000000000000000060648201526084016107bd565b60028173ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561180b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182f9190615473565b600281111561184057611840615444565b146118cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f686173206e6f74206265656e2066696e616c697a65642079657400000000000060648201526084016107bd565b603b5463ffffffff1660ff166119278273ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561100e573d6000803e3d6000fd5b60ff16146119b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a20696e76616c69642067616d652074797060448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016107bd565b7f0000000000000000000000000000000000000000000000000000000000000000611a268273ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115f9573d6000803e3d6000fd5b611a3a9067ffffffffffffffff164261559e565b11611ac7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d6761700000000000000000000000000000000000000000000060648201526084016107bd565b60008381526033602052604090205460ff1615611b66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016107bd565b505050565b3361dead14611bfc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a206f6e6c7920736175726f6e2063616e2060448201527f626c61636b6c69737420646973707574652067616d657300000000000000000060648201526084016107bd565b73ffffffffffffffffffffffffffffffffffffffff166000908152603a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b3361dead14611cdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4f7074696d69736d506f7274616c3a206f6e6c7920736175726f6e2063616e2060448201527f73657420746865207265737065637465642067616d652074797065000000000060648201526084016107bd565b603b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff92909216919091179055565b565b611d1d61137a565b15611d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a207061757365640000000000000000000060448201526064016107bd565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14611e2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016107bd565b6000611e38826125ff565b9050611e4381611417565b600081815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558301516080840151606085015160a0860151611ee593929190612653565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611f4a90841515815260200190565b60405180910390a280158015611f605750326001145b15611b66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f640000000000000000000000000000000000000000000000000000000000000060648201526084016107bd565b6000611ffa8260106155b5565b612006906152086155e5565b92915050565b600054610100900460ff161580801561202c5750600054600160ff909116105b806120465750303b158015612046575060005460ff166001145b6120d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561213057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010085841602179055603254166121e957603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b6121f16126b1565b801561225457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6001546000906122ac907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361559e565b905060006122b86127c4565b90506000816020015160ff16826000015163ffffffff166122d99190615640565b9050821561241057600154600090612310908390700100000000000000000000000000000000900467ffffffffffffffff166156a8565b90506000836040015160ff1683612327919061571c565b6001546123479084906fffffffffffffffffffffffffffffffff1661571c565b6123519190615640565b6001549091506000906123a29061237b9084906fffffffffffffffffffffffffffffffff166157d8565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612885565b905060018611156123d1576123ce61237b82876040015160ff1660018a6123c9919061559e565b6128a4565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090612443908490700100000000000000000000000000000000900467ffffffffffffffff166155e5565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315612526576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016107bd565b600154600090612552906fffffffffffffffffffffffffffffffff1667ffffffffffffffff881661584c565b9050600061256448633b9aca006128f9565b61256e9083615889565b905060005a61257d908861559e565b90508082111561259957612599612594828461559e565b612910565b5050505050505050565b600081600001518260200151836040015184606001516040516020016125e2949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a088015193516000976125e297909695910161589d565b60008061263b86612939565b90506126498186868661296b565b9695505050505050565b600080600061266386600061299b565b905080612699576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff16612748576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bd565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff16600003611d135760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612861573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b04919061590a565b600061289a61289485856129b9565b836129c9565b90505b9392505050565b6000670de0b6b3a76400006128e56128bc8583615640565b6128ce90670de0b6b3a76400006156a8565b6128e085670de0b6b3a764000061571c565b6129d8565b6128ef908661571c565b61289a9190615640565b600081831015612909578161289d565b5090919050565b6000805a90505b825a612923908361559e565b1015611b6657612932826159c6565b9150612917565b6060818051906020012060405160200161295591815260200190565b6040516020818303038152906040529050919050565b60006129928461297c878686612a09565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b600081831215612909578161289d565b6000818312612909578161289d565b600061289d670de0b6b3a7640000836129f086613487565b6129fa919061571c565b612a049190615640565b6136cb565b60606000845111612a76576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b6579000000000000000000000060448201526064016107bd565b6000612a818461390a565b90506000612a8e866139f6565b9050600084604051602001612aa591815260200190565b60405160208183030381529060405290506000805b84518110156133fe576000858281518110612ad757612ad76159fe565b602002602001015190508451831115612b72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e67746800000000000000000000000000000000000060648201526084016107bd565b82600003612c2b5780518051602091820120604051612bc092612b9a92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612c26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016107bd565b612d82565b805151602011612ce15780518051602091820120604051612c5592612b9a92910190815260200190565b612c26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016107bd565b805184516020808701919091208251919092012014612d82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016107bd565b612d8e60106001615a2d565b81602001515103612f6a5784518303612f0257612dc88160200151601081518110612dbb57612dbb6159fe565b6020026020010151613a59565b96506000875111612e5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e636829000000000060648201526084016107bd565b60018651612e69919061559e565b8214612ef7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e63682900000000000060648201526084016107bd565b50505050505061289d565b6000858481518110612f1657612f166159fe565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110612f4157612f416159fe565b60200260200101519050612f5481613bb9565b9550612f61600186615a2d565b945050506133eb565b600281602001515103613363576000612f8282613bde565b9050600081600081518110612f9957612f996159fe565b016020015160f81c90506000612fb0600283615a45565b612fbb906002615a67565b90506000612fcc848360ff16613c02565b90506000612fda8a89613c02565b90506000612fe88383613c38565b90508083511461307a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b657900000000000060648201526084016107bd565b60ff85166002148061308f575060ff85166003145b1561327e5780825114613124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e64657200000060648201526084016107bd565b61313e8760200151600181518110612dbb57612dbb6159fe565b9c5060008d51116131d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c656166290000000000000060648201526084016107bd565b60018c516131df919061559e565b881461326d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c65616629000000000000000060648201526084016107bd565b50505050505050505050505061289d565b60ff85161580613291575060ff85166001145b156132d0576132bd87602001516001815181106132b0576132b06159fe565b6020026020010151613bb9565b99506132c9818a615a2d565b9850613358565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016107bd565b5050505050506133eb565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016107bd565b50806133f6816159c6565b915050612aba565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e747300000000000000000000000000000000000000000000000000000060648201526084016107bd565b60008082136134f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016107bd565b600060606134ff84613cec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136136fc57506000919050565b680755bf798b4a1bf1e5821261376e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016107bd565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff81111561392857613928614e6a565b60405190808252806020026020018201604052801561396d57816020015b60408051808201909152606080825260208201528152602001906001900390816139465790505b50915060005b818110156139ef576040518060400160405280858381518110613998576139986159fe565b602002602001015181526020016139c78684815181106139ba576139ba6159fe565b6020026020010151613dc2565b8152508382815181106139dc576139dc6159fe565b6020908102919091010152600101613973565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613a4e578060011b82018184015160001a8060041c8253600f811660018301535050600101613a20565b509295945050505050565b60606000806000613a6985613dd5565b919450925090506000816001811115613a8457613a84615444565b14613b11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016107bd565b613b1b8284615a2d565b855114613baa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e64657200000000000000000000000060648201526084016107bd565b61299285602001518484614842565b60606020826000015110613bd557613bd082613a59565b612006565b612006826148d6565b6060612006613bfd8360200151600081518110612dbb57612dbb6159fe565b6139f6565b606082518210613c215750604080516020810190915260008152612006565b61289d8383848651613c33919061559e565b6148ec565b6000808251845110613c4b578251613c4e565b83515b90505b8082108015613cd55750828281518110613c6d57613c6d6159fe565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613cac57613cac6159fe565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613ce557816001019150613c51565b5092915050565b6000808211613d57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016107bd565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b6060612006613dd083614ac4565b614bad565b600080600080846000015111613e93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016107bd565b6020840151805160001a607f8111613eb857600060016000945094509450505061483b565b60b781116140c6576000613ecd60808361559e565b905080876000015111613f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a4016107bd565b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214158061400157507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b6140b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a4016107bd565b506001955093506000925061483b915050565b60bf81116144145760006140db60b78361559e565b905080876000015111614196576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a4016107bd565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614274576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a4016107bd565b600184015160088302610100031c60378111614338576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a4016107bd565b6143428184615a2d565b8951116143f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a4016107bd565b614402836001615a2d565b975095506000945061483b9350505050565b60f781116144f557600061442960c08361559e565b9050808760000151116144e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a4016107bd565b60019550935084925061483b915050565b600061450260f78361559e565b9050808760000151116145bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a4016107bd565b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361469b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a4016107bd565b600184015160088302610100031c6037811161475f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a4016107bd565b6147698184615a2d565b89511161481e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a4016107bd565b614829836001615a2d565b975095506001945061483b9350505050565b9193909250565b60608167ffffffffffffffff81111561485d5761485d614e6a565b6040519080825280601f01601f191660200182016040528015614887576020820181803683370190505b509050811561289d57600061489c8486615a2d565b90506020820160005b848110156148bd5782810151828201526020016148a5565b848111156148cc576000858301525b5050509392505050565b6060612006826020015160008460000151614842565b60608182601f01101561495b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016107bd565b8282840110156149c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016107bd565b81830184511015614a34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016107bd565b606082158015614a535760405191506000825260208201604052614abb565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614a8c578051835260209283019201614a74565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201526000825111614b8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016107bd565b50604080518082019091528151815260209182019181019190915290565b60606000806000614bbd85613dd5565b919450925090506001816001811115614bd857614bd8615444565b14614c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016107bd565b8451614c718385615a2d565b14614cfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e646572000000000000000000000000000060648201526084016107bd565b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d155790505093506000835b8651811015614e0357600080614d886040518060400160405280858c60000151614d6c919061559e565b8152602001858c60200151614d819190615a2d565b9052613dd5565b509150915060405180604001604052808383614da49190615a2d565b8152602001848b60200151614db99190615a2d565b815250888581518110614dce57614dce6159fe565b6020908102919091010152614de4600185615a2d565b9350614df08183615a2d565b614dfa9084615a2d565b92505050614d42565b50845250919392505050565b600060208284031215614e2157600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114614e4a57600080fd5b50565b600060208284031215614e5f57600080fd5b813561289d81614e28565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614ee057614ee0614e6a565b604052919050565b600082601f830112614ef957600080fd5b813567ffffffffffffffff811115614f1357614f13614e6a565b614f4460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614e99565b818152846020838601011115614f5957600080fd5b816020850160208301376000918101602001919091529392505050565b600060c08284031215614f8857600080fd5b60405160c0810167ffffffffffffffff8282108183111715614fac57614fac614e6a565b816040528293508435835260208501359150614fc782614e28565b81602084015260408501359150614fdd82614e28565b816040840152606085013560608401526080850135608084015260a085013591508082111561500b57600080fd5b5061501885828601614ee8565b60a0830152505092915050565b600080600080600085870360e081121561503e57600080fd5b863567ffffffffffffffff8082111561505657600080fd5b6150628a838b01614f76565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561509b57600080fd5b60408901955060c08901359250808311156150b557600080fd5b828901925089601f8401126150c957600080fd5b82359150808211156150da57600080fd5b508860208260051b84010111156150f057600080fd5b959894975092955050506020019190565b60005b8381101561511c578181015183820152602001615104565b838111156122545750506000910152565b60008151808452615145816020860160208601615101565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061289d602083018461512d565b63ffffffff81168114614e4a57600080fd5b6000602082840312156151ae57600080fd5b813561289d8161518a565b6000602082840312156151cb57600080fd5b813567ffffffffffffffff8111156151e257600080fd5b6151ee84828501614f76565b949350505050565b67ffffffffffffffff81168114614e4a57600080fd5b60006020828403121561521e57600080fd5b813561289d816151f6565b60008060006060848603121561523e57600080fd5b833561524981614e28565b9250602084013561525981614e28565b9150604084013561526981614e28565b809150509250925092565b8015158114614e4a57600080fd5b600080600080600060a0868803121561529a57600080fd5b85356152a581614e28565b94506020860135935060408601356152bc816151f6565b925060608601356152cc81615274565b9150608086013567ffffffffffffffff8111156152e857600080fd5b6152f488828901614ee8565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251615355816049850160208701615101565b919091016049019695505050505050565b60006020828403121561537857600080fd5b815161289d81614e28565b60008060006060848603121561539857600080fd5b83516153a38161518a565b60208501519093506153b4816151f6565b604085015190925061526981614e28565b6000602082840312156153d757600080fd5b5051919050565b6000608082840312156153f057600080fd5b6040516080810181811067ffffffffffffffff8211171561541357615413614e6a565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561548557600080fd5b81516003811061289d57600080fd5b6000602082840312156154a657600080fd5b815161289d8161518a565b600067ffffffffffffffff808411156154cc576154cc614e6a565b8360051b60206154dd818301614e99565b8681529185019181810190368411156154f557600080fd5b865b848110156155295780358681111561550f5760008081fd5b61551b36828b01614ee8565b8452509183019183016154f7565b50979650505050505050565b60006020828403121561554757600080fd5b815161289d81615274565b60006020828403121561556457600080fd5b815161289d816151f6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156155b0576155b061556f565b500390565b600067ffffffffffffffff808316818516818304811182151516156155dc576155dc61556f565b02949350505050565b600067ffffffffffffffff8083168185168083038211156156085761560861556f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261564f5761564f615611565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156156a3576156a361556f565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156156e2576156e261556f565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156157165761571661556f565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561575d5761575d61556f565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156157985761579861556f565b600087129250878205871284841616156157b4576157b461556f565b878505871281841616156157ca576157ca61556f565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156158125761581261556f565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156158465761584661556f565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156158845761588461556f565b500290565b60008261589857615898615611565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526158e860c083018461512d565b98975050505050505050565b805160ff8116811461590557600080fd5b919050565b600060c0828403121561591c57600080fd5b60405160c0810181811067ffffffffffffffff8211171561593f5761593f614e6a565b604052825161594d8161518a565b815261595b602084016158f4565b602082015261596c604084016158f4565b6040820152606083015161597f8161518a565b606082015260808301516159928161518a565b608082015260a08301516fffffffffffffffffffffffffffffffff811681146159ba57600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036159f7576159f761556f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008219821115615a4057615a4061556f565b500190565b600060ff831680615a5857615a58615611565b8060ff84160691505092915050565b600060ff821660ff841680821015615a8157615a8161556f565b9003939250505056fea164736f6c634300080f000a"
func init() {
if err := json.Unmarshal([]byte(OptimismPortal2StorageLayoutJSON), OptimismPortal2StorageLayout); err != nil {
panic(err)
}
layouts["OptimismPortal2"] = OptimismPortal2StorageLayout
deployedBytecodes["OptimismPortal2"] = OptimismPortal2DeployedBin
immutableReferences["OptimismPortal2"] = true
}
package bindingspreview
import (
"fmt"
"strings"
"github.com/ethereum-optimism/superchain-registry/superchain"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
"github.com/ethereum/go-ethereum/common"
)
// layouts respresents the set of storage layouts. It is populated in an init function.
var layouts = make(map[string]*solc.StorageLayout)
// deployedBytecodes represents the set of deployed bytecodes. It is populated
// in an init function.
var deployedBytecodes = make(map[string]string)
var initBytecodes = make(map[string]string)
var deploymentSalts = make(map[string]string)
var deployers = make(map[string]string)
// immutableReferences represents the set of immutable references. It is populated
// in an init function.
var immutableReferences = make(map[string]bool)
// Create2DeployerCodeHash represents the codehash of the Create2Deployer contract.
var Create2DeployerCodeHash = common.HexToHash("0xb0550b5b431e30d38000efb7107aaa0ade03d48a7198a140edda9d27134468b2")
func init() {
code, err := superchain.LoadContractBytecode(superchain.Hash(Create2DeployerCodeHash))
if err != nil {
panic(err)
}
deployedBytecodes["Create2Deployer"] = common.Bytes2Hex(code)
}
// GetStorageLayout returns the storage layout of a contract by name.
func GetStorageLayout(name string) (*solc.StorageLayout, error) {
layout := layouts[name]
if layout == nil {
return nil, fmt.Errorf("%s: storage layout not found", name)
}
return layout, nil
}
// GetDeployedBytecode returns the deployed bytecode of a contract by name.
func GetDeployedBytecode(name string) ([]byte, error) {
bc := deployedBytecodes[name]
if bc == "" {
return nil, fmt.Errorf("%s: deployed bytecode not found", name)
}
if !isHex(bc) {
return nil, fmt.Errorf("%s: invalid deployed bytecode", name)
}
return common.FromHex(bc), nil
}
// HasImmutableReferences returns the immutable references of a contract by name.
func HasImmutableReferences(name string) (bool, error) {
has, ok := immutableReferences[name]
if !ok {
return false, fmt.Errorf("%s: immutable reference not found", name)
}
return has, nil
}
func GetInitBytecode(name string) ([]byte, error) {
bc := initBytecodes[name]
if bc == "" {
return nil, fmt.Errorf("%s: init bytecode not found", name)
}
if !isHex(bc) {
return nil, fmt.Errorf("%s: invalid init bytecode", name)
}
return common.FromHex(bc), nil
}
func GetDeployerAddress(name string) ([]byte, error) {
addr := deployers[name]
if addr == "" {
return nil, fmt.Errorf("%s: deployer address not found", name)
}
if !common.IsHexAddress(addr) {
return nil, fmt.Errorf("%s: invalid deployer address", name)
}
return common.FromHex(addr), nil
}
func GetDeploymentSalt(name string) ([]byte, error) {
salt := deploymentSalts[name]
if salt == "" {
return nil, fmt.Errorf("%s: deployment salt not found", name)
}
if !isHex(salt) {
return nil, fmt.Errorf("%s: invalid deployment salt", name)
}
return common.FromHex(salt), nil
}
// isHexCharacter returns bool of c being a valid hexadecimal.
func isHexCharacter(c byte) bool {
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
}
// isHex validates whether each byte is valid hexadecimal string.
func isHex(str string) bool {
if len(str)%2 != 0 {
return false
}
str = strings.TrimPrefix(str, "0x")
for _, c := range []byte(str) {
if !isHexCharacter(c) {
return false
}
}
return true
}
...@@ -18,9 +18,11 @@ import ( ...@@ -18,9 +18,11 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-proposer/metrics" "github.com/ethereum-optimism/optimism/op-proposer/metrics"
"github.com/ethereum-optimism/optimism/op-proposer/proposer" "github.com/ethereum-optimism/optimism/op-proposer/proposer"
"github.com/ethereum-optimism/optimism/op-service/dial" "github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
) )
...@@ -35,14 +37,16 @@ type ProposerCfg struct { ...@@ -35,14 +37,16 @@ type ProposerCfg struct {
} }
type L2Proposer struct { type L2Proposer struct {
log log.Logger log log.Logger
l1 *ethclient.Client l1 *ethclient.Client
driver *proposer.L2OutputSubmitter driver *proposer.L2OutputSubmitter
contract *bindings.L2OutputOracleCaller l2OutputOracle *bindings.L2OutputOracleCaller
address common.Address l2OutputOracleAddr *common.Address
privKey *ecdsa.PrivateKey disputeGameFactory *bindings.DisputeGameFactoryCaller
contractAddr common.Address disputeGameFactoryAddr *common.Address
lastTx common.Hash address common.Address
privKey *ecdsa.PrivateKey
lastTx common.Hash
} }
type fakeTxMgr struct { type fakeTxMgr struct {
...@@ -85,28 +89,34 @@ func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Cl ...@@ -85,28 +89,34 @@ func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Cl
RollupProvider: rollupProvider, RollupProvider: rollupProvider,
} }
if cfg.OutputOracleAddr == nil {
panic("L2OutputOracle address must be set in op-e2e test harness. The DisputeGameFactory is not yet supported as a proposal destination.")
}
dr, err := proposer.NewL2OutputSubmitter(driverSetup) dr, err := proposer.NewL2OutputSubmitter(driverSetup)
require.NoError(t, err) require.NoError(t, err)
contract, err := bindings.NewL2OutputOracleCaller(*cfg.OutputOracleAddr, l1)
require.NoError(t, err)
address := crypto.PubkeyToAddress(cfg.ProposerKey.PublicKey) address := crypto.PubkeyToAddress(cfg.ProposerKey.PublicKey)
proposer, err := contract.PROPOSER(&bind.CallOpts{})
require.NoError(t, err) var l2OutputOracle *bindings.L2OutputOracleCaller
require.Equal(t, proposer, address, "PROPOSER must be the proposer's address") var disputeGameFactory *bindings.DisputeGameFactoryCaller
if e2eutils.UseFPAC() {
disputeGameFactory, err = bindings.NewDisputeGameFactoryCaller(*cfg.DisputeGameFactoryAddr, l1)
require.NoError(t, err)
} else {
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(*cfg.OutputOracleAddr, l1)
require.NoError(t, err)
proposer, err := l2OutputOracle.PROPOSER(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, proposer, address, "PROPOSER must be the proposer's address")
}
return &L2Proposer{ return &L2Proposer{
log: log, log: log,
l1: l1, l1: l1,
driver: dr, driver: dr,
contract: contract, l2OutputOracle: l2OutputOracle,
address: address, l2OutputOracleAddr: cfg.OutputOracleAddr,
privKey: cfg.ProposerKey, disputeGameFactory: disputeGameFactory,
contractAddr: *cfg.OutputOracleAddr, disputeGameFactoryAddr: cfg.DisputeGameFactoryAddr,
address: address,
privKey: cfg.ProposerKey,
} }
} }
...@@ -122,9 +132,16 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) { ...@@ -122,9 +132,16 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) {
nonce, err := p.l1.NonceAt(t.Ctx(), p.address, nil) nonce, err := p.l1.NonceAt(t.Ctx(), p.address, nil)
require.NoError(t, err) require.NoError(t, err)
var addr common.Address
if e2eutils.UseFPAC() {
addr = *p.disputeGameFactoryAddr
} else {
addr = *p.l2OutputOracleAddr
}
gasLimit, err := estimateGasPending(t.Ctx(), p.l1, ethereum.CallMsg{ gasLimit, err := estimateGasPending(t.Ctx(), p.l1, ethereum.CallMsg{
From: p.address, From: p.address,
To: &p.contractAddr, To: &addr,
GasFeeCap: gasFeeCap, GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap, GasTipCap: gasTipCap,
Data: data, Data: data,
...@@ -133,7 +150,7 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) { ...@@ -133,7 +150,7 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) {
rawTx := &types.DynamicFeeTx{ rawTx := &types.DynamicFeeTx{
Nonce: nonce, Nonce: nonce,
To: &p.contractAddr, To: &addr,
Data: data, Data: data,
GasFeeCap: gasFeeCap, GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap, GasTipCap: gasTipCap,
...@@ -145,7 +162,6 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) { ...@@ -145,7 +162,6 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) {
require.NoError(t, err, "need to sign tx") require.NoError(t, err, "need to sign tx")
err = p.l1.SendTransaction(t.Ctx(), tx) err = p.l1.SendTransaction(t.Ctx(), tx)
log.Info("Proposer sent tx", "hash", tx.Hash(), "to", p.contractAddr)
require.NoError(t, err, "need to send tx") require.NoError(t, err, "need to send tx")
p.lastTx = tx.Hash() p.lastTx = tx.Hash()
...@@ -184,21 +200,56 @@ func toCallArg(msg ethereum.CallMsg) interface{} { ...@@ -184,21 +200,56 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
return arg return arg
} }
func (p *L2Proposer) fetchNextOutput(t Testing) (*eth.OutputResponse, bool, error) {
if e2eutils.UseFPAC() {
blockNumber, err := p.driver.FetchCurrentBlockNumber(t.Ctx())
if err != nil {
return nil, false, err
}
output, _, err := p.driver.FetchOutput(t.Ctx(), blockNumber)
if err != nil {
return nil, false, err
}
encodedBlockNumber := make([]byte, 32)
copy(encodedBlockNumber[32-len(blockNumber.Bytes()):], blockNumber.Bytes())
game, err := p.disputeGameFactory.Games(&bind.CallOpts{}, p.driver.Cfg.DisputeGameType, output.OutputRoot, encodedBlockNumber)
if err != nil {
return nil, false, err
}
if game.Timestamp != 0 {
return nil, false, nil
}
return output, true, nil
} else {
return p.driver.FetchNextOutputInfo(t.Ctx())
}
}
func (p *L2Proposer) CanPropose(t Testing) bool { func (p *L2Proposer) CanPropose(t Testing) bool {
_, shouldPropose, err := p.driver.FetchNextOutputInfo(t.Ctx()) _, shouldPropose, err := p.fetchNextOutput(t)
require.NoError(t, err) require.NoError(t, err)
return shouldPropose return shouldPropose
} }
func (p *L2Proposer) ActMakeProposalTx(t Testing) { func (p *L2Proposer) ActMakeProposalTx(t Testing) {
output, shouldPropose, err := p.driver.FetchNextOutputInfo(t.Ctx()) output, shouldPropose, err := p.fetchNextOutput(t)
require.NoError(t, err)
if !shouldPropose { if !shouldPropose {
return return
} }
require.NoError(t, err)
txData, err := p.driver.ProposeL2OutputTxData(output) var txData []byte
require.NoError(t, err) if e2eutils.UseFPAC() {
txData, _, err = p.driver.ProposeL2OutputDGFTxData(output)
require.NoError(t, err)
} else {
txData, err = p.driver.ProposeL2OutputTxData(output)
require.NoError(t, err)
}
// Note: Use L1 instead of the output submitter's transaction manager because // Note: Use L1 instead of the output submitter's transaction manager because
// this is non-blocking while the txmgr is blocking & deadlocks the tests // this is non-blocking while the txmgr is blocking & deadlocks the tests
......
package actions package actions
import ( import (
"math/big"
"testing" "testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindingspreview"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
...@@ -51,11 +55,22 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -51,11 +55,22 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
proposer := NewL2Proposer(t, log, &ProposerCfg{ var proposer *L2Proposer
OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, if e2eutils.UseFPAC() {
ProposerKey: dp.Secrets.Proposer, proposer = NewL2Proposer(t, log, &ProposerCfg{
AllowNonFinalized: false, DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy,
}, miner.EthClient(), sequencer.RollupClient()) ProposalInterval: 6 * time.Second,
DisputeGameType: 0,
ProposerKey: dp.Secrets.Proposer,
AllowNonFinalized: true,
}, miner.EthClient(), rollupSeqCl)
} else {
proposer = NewL2Proposer(t, log, &ProposerCfg{
OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy,
ProposerKey: dp.Secrets.Proposer,
AllowNonFinalized: false,
}, miner.EthClient(), rollupSeqCl)
}
// L1 block // L1 block
miner.ActEmptyBlock(t) miner.ActEmptyBlock(t)
...@@ -94,17 +109,41 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -94,17 +109,41 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
} }
// check that L1 stored the expected output root // check that L1 stored the expected output root
outputOracleContract, err := bindings.NewL2OutputOracle(sd.DeploymentsL1.L2OutputOracleProxy, miner.EthClient()) if e2eutils.UseFPAC() {
require.NoError(t, err) optimismPortal2Contract, err := bindingspreview.NewOptimismPortal2(sd.DeploymentsL1.OptimismPortalProxy, miner.EthClient())
blockNumber, err := outputOracleContract.LatestBlockNumber(&bind.CallOpts{}) require.NoError(t, err)
require.NoError(t, err) respectedGameType, err := optimismPortal2Contract.RespectedGameType(&bind.CallOpts{})
require.Greater(t, int64(blockNumber.Uint64()), int64(0), "latest block number must be greater than 0") require.NoError(t, err)
block, err := seqEngine.EthClient().BlockByNumber(t.Ctx(), blockNumber) disputeGameFactoryContract, err := bindings.NewDisputeGameFactory(sd.DeploymentsL1.DisputeGameFactoryProxy, miner.EthClient())
require.NoError(t, err) require.NoError(t, err)
outputOnL1, err := outputOracleContract.GetL2OutputAfter(&bind.CallOpts{}, blockNumber) gameCount, err := disputeGameFactoryContract.GameCount(&bind.CallOpts{})
require.NoError(t, err) require.NoError(t, err)
require.Less(t, block.Time(), outputOnL1.Timestamp.Uint64(), "output is registered with L1 timestamp of proposal tx, past L2 block") require.Greater(t, gameCount.Uint64(), uint64(0), "game count must be greater than 0")
outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), blockNumber.Uint64()) latestGames, err := disputeGameFactoryContract.FindLatestGames(&bind.CallOpts{}, respectedGameType, new(big.Int).Sub(gameCount, common.Big1), common.Big1)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, eth.Bytes32(outputOnL1.OutputRoot), outputComputed.OutputRoot, "output roots must match") require.Greater(t, len(latestGames), 0, "latest games must be greater than 0")
latestGame := latestGames[0]
gameBlockNumber := new(big.Int)
gameBlockNumber.SetBytes(latestGame.ExtraData[0:32])
block, err := seqEngine.EthClient().BlockByNumber(t.Ctx(), gameBlockNumber)
require.NoError(t, err)
require.Less(t, block.Time(), latestGame.Timestamp, "output is registered with L1 timestamp of proposal tx, past L2 block")
outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), gameBlockNumber.Uint64())
require.NoError(t, err)
require.Equal(t, eth.Bytes32(latestGame.RootClaim), outputComputed.OutputRoot, "output roots must match")
} else {
outputOracleContract, err := bindings.NewL2OutputOracle(sd.DeploymentsL1.L2OutputOracleProxy, miner.EthClient())
require.NoError(t, err)
blockNumber, err := outputOracleContract.LatestBlockNumber(&bind.CallOpts{})
require.NoError(t, err)
require.Greater(t, int64(blockNumber.Uint64()), int64(0), "latest block number must be greater than 0")
block, err := seqEngine.EthClient().BlockByNumber(t.Ctx(), blockNumber)
require.NoError(t, err)
outputOnL1, err := outputOracleContract.GetL2OutputAfter(&bind.CallOpts{}, blockNumber)
require.NoError(t, err)
require.Less(t, block.Time(), outputOnL1.Timestamp.Uint64(), "output is registered with L1 timestamp of proposal tx, past L2 block")
outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), blockNumber.Uint64())
require.NoError(t, err)
require.Equal(t, eth.Bytes32(outputOnL1.OutputRoot), outputComputed.OutputRoot, "output roots must match")
}
} }
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"math/rand" "math/rand"
"time"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
...@@ -18,17 +19,21 @@ import ( ...@@ -18,17 +19,21 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindingspreview"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum-optimism/optimism/op-node/withdrawals"
) )
type L1Bindings struct { type L1Bindings struct {
// contract bindings // contract bindings
OptimismPortal *bindings.OptimismPortal OptimismPortal *bindings.OptimismPortal
L2OutputOracle *bindings.L2OutputOracle
L2OutputOracle *bindings.L2OutputOracle OptimismPortal2 *bindingspreview.OptimismPortal2
DisputeGameFactory *bindings.DisputeGameFactory
} }
func NewL1Bindings(t Testing, l1Cl *ethclient.Client) *L1Bindings { func NewL1Bindings(t Testing, l1Cl *ethclient.Client) *L1Bindings {
...@@ -38,9 +43,17 @@ func NewL1Bindings(t Testing, l1Cl *ethclient.Client) *L1Bindings { ...@@ -38,9 +43,17 @@ func NewL1Bindings(t Testing, l1Cl *ethclient.Client) *L1Bindings {
l2OutputOracle, err := bindings.NewL2OutputOracle(config.L1Deployments.L2OutputOracleProxy, l1Cl) l2OutputOracle, err := bindings.NewL2OutputOracle(config.L1Deployments.L2OutputOracleProxy, l1Cl)
require.NoError(t, err) require.NoError(t, err)
optimismPortal2, err := bindingspreview.NewOptimismPortal2(config.L1Deployments.OptimismPortalProxy, l1Cl)
require.NoError(t, err)
disputeGameFactory, err := bindings.NewDisputeGameFactory(config.L1Deployments.DisputeGameFactoryProxy, l1Cl)
require.NoError(t, err)
return &L1Bindings{ return &L1Bindings{
OptimismPortal: optimismPortal, OptimismPortal: optimismPortal,
L2OutputOracle: l2OutputOracle, L2OutputOracle: l2OutputOracle,
OptimismPortal2: optimismPortal2,
DisputeGameFactory: disputeGameFactory,
} }
} }
...@@ -392,39 +405,89 @@ func (s *CrossLayerUser) Address() common.Address { ...@@ -392,39 +405,89 @@ func (s *CrossLayerUser) Address() common.Address {
return s.L1.address return s.L1.address
} }
// ActCompleteWithdrawal creates a L1 proveWithdrawal tx for latest withdrawal. func (s *CrossLayerUser) getLatestWithdrawalParams(t Testing) (*withdrawals.ProvenWithdrawalParameters, error) {
// The tx hash is remembered as the last L1 tx, to check as L1 actor. receipt := s.L2.CheckReceipt(t, true, s.lastL2WithdrawalTxHash)
func (s *CrossLayerUser) ActProveWithdrawal(t Testing) {
s.L1.lastTxHash = s.ProveWithdrawal(t, s.lastL2WithdrawalTxHash)
}
// ProveWithdrawal creates a L1 proveWithdrawal tx for the given L2 withdrawal tx, returning the tx hash.
func (s *CrossLayerUser) ProveWithdrawal(t Testing, l2TxHash common.Hash) common.Hash {
// Figure out when our withdrawal was included
receipt := s.L2.CheckReceipt(t, true, l2TxHash)
l2WithdrawalBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), receipt.BlockNumber) l2WithdrawalBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), receipt.BlockNumber)
require.NoError(t, err) require.NoError(t, err)
// Figure out what the Output oracle on L1 has seen so far var l2OutputBlockNr *big.Int
l2OutputBlockNr, err := s.L1.env.Bindings.L2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) var l2OutputBlock *types.Block
require.NoError(t, err) if e2eutils.UseFPAC() {
l2OutputBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), l2OutputBlockNr) latestGame, err := withdrawals.FindLatestGame(t.Ctx(), &s.L1.env.Bindings.DisputeGameFactory.DisputeGameFactoryCaller, &s.L1.env.Bindings.OptimismPortal2.OptimismPortal2Caller)
require.NoError(t, err) require.NoError(t, err)
l2OutputIndex, err := s.L1.env.Bindings.L2OutputOracle.GetL2OutputIndexAfter(&bind.CallOpts{}, l2OutputBlockNr) l2OutputBlockNr = new(big.Int).SetBytes(latestGame.ExtraData[0:32])
require.NoError(t, err) l2OutputBlock, err = s.L2.env.EthCl.BlockByNumber(t.Ctx(), l2OutputBlockNr)
require.NoError(t, err)
} else {
l2OutputBlockNr, err = s.L1.env.Bindings.L2OutputOracle.LatestBlockNumber(&bind.CallOpts{})
require.NoError(t, err)
l2OutputBlock, err = s.L2.env.EthCl.BlockByNumber(t.Ctx(), l2OutputBlockNr)
require.NoError(t, err)
}
// Check if the L2 output is even old enough to include the withdrawal
if l2OutputBlock.NumberU64() < l2WithdrawalBlock.NumberU64() { if l2OutputBlock.NumberU64() < l2WithdrawalBlock.NumberU64() {
t.InvalidAction("the latest L2 output is %d and is not past L2 block %d that includes the withdrawal yet, no withdrawal can be proved yet", l2OutputBlock.NumberU64(), l2WithdrawalBlock.NumberU64()) return nil, fmt.Errorf("the latest L2 output is %d and is not past L2 block %d that includes the withdrawal yet, no withdrawal can be proved yet", l2OutputBlock.NumberU64(), l2WithdrawalBlock.NumberU64())
return common.Hash{} }
if !e2eutils.UseFPAC() {
finalizationPeriod, err := s.L1.env.Bindings.L2OutputOracle.FINALIZATIONPERIODSECONDS(&bind.CallOpts{})
require.NoError(t, err)
l1Head, err := s.L1.env.EthCl.HeaderByNumber(t.Ctx(), nil)
require.NoError(t, err)
if l2OutputBlock.Time()+finalizationPeriod.Uint64() >= l1Head.Time {
return nil, fmt.Errorf("L2 output block %d (time %d) is not past finalization period %d from L2 block %d (time %d) at head %d (time %d)", l2OutputBlock.NumberU64(), l2OutputBlock.Time(), finalizationPeriod.Uint64(), l2WithdrawalBlock.NumberU64(), l2WithdrawalBlock.Time(), l1Head.Number.Uint64(), l1Head.Time)
}
} }
// We generate a proof for the latest L2 output, which shouldn't require archive-node data if it's recent enough.
header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr) header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr)
require.NoError(t, err) require.NoError(t, err)
params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller) params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller, &s.L1.env.Bindings.DisputeGameFactory.DisputeGameFactoryCaller, &s.L1.env.Bindings.OptimismPortal.OptimismPortalCaller, &s.L1.env.Bindings.OptimismPortal2.OptimismPortal2Caller)
require.NoError(t, err) require.NoError(t, err)
return &params, nil
}
func (s *CrossLayerUser) getDisputeGame(t Testing, params withdrawals.ProvenWithdrawalParameters) (*bindings.FaultDisputeGame, error) {
wd := crossdomain.Withdrawal{
Nonce: params.Nonce,
Sender: &params.Sender,
Target: &params.Target,
Value: params.Value,
GasLimit: params.GasLimit,
Data: params.Data,
}
portal2, err := bindingspreview.NewOptimismPortal2(config.L1Deployments.OptimismPortalProxy, s.L1.env.EthCl)
require.Nil(t, err)
wdHash, err := wd.Hash()
require.Nil(t, err)
game, err := portal2.ProvenWithdrawals(&bind.CallOpts{}, wdHash)
require.Nil(t, err)
require.NotNil(t, game, "withdrawal should be proven")
proxy, err := bindings.NewFaultDisputeGame(game.DisputeGameProxy, s.L1.env.EthCl)
require.Nil(t, err)
return proxy, nil
}
// ActCompleteWithdrawal creates a L1 proveWithdrawal tx for latest withdrawal.
// The tx hash is remembered as the last L1 tx, to check as L1 actor.
func (s *CrossLayerUser) ActProveWithdrawal(t Testing) {
s.L1.lastTxHash = s.ProveWithdrawal(t, s.lastL2WithdrawalTxHash)
}
// ProveWithdrawal creates a L1 proveWithdrawal tx for the given L2 withdrawal tx, returning the tx hash.
func (s *CrossLayerUser) ProveWithdrawal(t Testing, l2TxHash common.Hash) common.Hash {
params, err := s.getLatestWithdrawalParams(t)
if err != nil {
t.InvalidAction("cannot prove withdrawal: %v", err)
return common.Hash{}
}
// Create the prove tx // Create the prove tx
tx, err := s.L1.env.Bindings.OptimismPortal.ProveWithdrawalTransaction( tx, err := s.L1.env.Bindings.OptimismPortal.ProveWithdrawalTransaction(
&s.L1.txOpts, &s.L1.txOpts,
...@@ -436,7 +499,7 @@ func (s *CrossLayerUser) ProveWithdrawal(t Testing, l2TxHash common.Hash) common ...@@ -436,7 +499,7 @@ func (s *CrossLayerUser) ProveWithdrawal(t Testing, l2TxHash common.Hash) common
GasLimit: params.GasLimit, GasLimit: params.GasLimit,
Data: params.Data, Data: params.Data,
}, },
l2OutputIndex, params.L2OutputIndex,
params.OutputRootProof, params.OutputRootProof,
params.WithdrawalProof, params.WithdrawalProof,
) )
...@@ -458,44 +521,12 @@ func (s *CrossLayerUser) ActCompleteWithdrawal(t Testing) { ...@@ -458,44 +521,12 @@ func (s *CrossLayerUser) ActCompleteWithdrawal(t Testing) {
// CompleteWithdrawal creates a L1 withdrawal finalization tx for the given L2 withdrawal tx, returning the tx hash. // CompleteWithdrawal creates a L1 withdrawal finalization tx for the given L2 withdrawal tx, returning the tx hash.
// It's an invalid action to attempt to complete a withdrawal that has not passed the L1 finalization period yet // It's an invalid action to attempt to complete a withdrawal that has not passed the L1 finalization period yet
func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) common.Hash { func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) common.Hash {
finalizationPeriod, err := s.L1.env.Bindings.L2OutputOracle.FINALIZATIONPERIODSECONDS(&bind.CallOpts{}) params, err := s.getLatestWithdrawalParams(t)
require.NoError(t, err) if err != nil {
t.InvalidAction("cannot complete withdrawal: %v", err)
// Figure out when our withdrawal was included
receipt := s.L2.CheckReceipt(t, true, l2TxHash)
l2WithdrawalBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), receipt.BlockNumber)
require.NoError(t, err)
// Figure out what the Output oracle on L1 has seen so far
l2OutputBlockNr, err := s.L1.env.Bindings.L2OutputOracle.LatestBlockNumber(&bind.CallOpts{})
require.NoError(t, err)
l2OutputBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), l2OutputBlockNr)
require.NoError(t, err)
// Check if the L2 output is even old enough to include the withdrawal
if l2OutputBlock.NumberU64() < l2WithdrawalBlock.NumberU64() {
t.InvalidAction("the latest L2 output is %d and is not past L2 block %d that includes the withdrawal yet, no withdrawal can be completed yet", l2OutputBlock.NumberU64(), l2WithdrawalBlock.NumberU64())
return common.Hash{}
}
l1Head, err := s.L1.env.EthCl.HeaderByNumber(t.Ctx(), nil)
require.NoError(t, err)
// Check if the withdrawal may be completed yet
if l2OutputBlock.Time()+finalizationPeriod.Uint64() >= l1Head.Time {
t.InvalidAction("withdrawal tx %s was included in L2 block %d (time %d) but L1 only knows of L2 proposal %d (time %d) at head %d (time %d) which has not reached output confirmation yet (period is %d)",
l2TxHash, l2WithdrawalBlock.NumberU64(), l2WithdrawalBlock.Time(), l2OutputBlock.NumberU64(), l2OutputBlock.Time(), l1Head.Number.Uint64(), l1Head.Time, finalizationPeriod.Uint64())
return common.Hash{} return common.Hash{}
} }
// We generate a proof for the latest L2 output, which shouldn't require archive-node data if it's recent enough.
// Note that for the `FinalizeWithdrawalTransaction` function, this proof isn't needed. We simply use some of the
// params for the `WithdrawalTransaction` type generated in the bindings.
header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr)
require.NoError(t, err)
params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller)
require.NoError(t, err)
// Create the withdrawal tx // Create the withdrawal tx
tx, err := s.L1.env.Bindings.OptimismPortal.FinalizeWithdrawalTransaction( tx, err := s.L1.env.Bindings.OptimismPortal.FinalizeWithdrawalTransaction(
&s.L1.txOpts, &s.L1.txOpts,
...@@ -515,3 +546,57 @@ func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) com ...@@ -515,3 +546,57 @@ func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) com
require.NoError(t, err, "must send finalize tx") require.NoError(t, err, "must send finalize tx")
return tx.Hash() return tx.Hash()
} }
// ActResolveClaim creates a L1 resolveClaim tx for the latest withdrawal.
func (s *CrossLayerUser) ActResolveClaim(t Testing) {
s.L1.lastTxHash = s.ResolveClaim(t, s.lastL2WithdrawalTxHash)
}
// ResolveClaim creates a L1 resolveClaim tx for the given L2 withdrawal tx, returning the tx hash.
func (s *CrossLayerUser) ResolveClaim(t Testing, l2TxHash common.Hash) common.Hash {
params, err := s.getLatestWithdrawalParams(t)
if err != nil {
t.InvalidAction("cannot resolve claim: %v", err)
return common.Hash{}
}
game, err := s.getDisputeGame(t, *params)
require.NoError(t, err)
expiry, err := game.GameDuration(&bind.CallOpts{})
require.Nil(t, err)
time.Sleep(time.Duration(expiry) * time.Second)
resolveClaimTx, err := game.ResolveClaim(&s.L1.txOpts, common.Big0)
require.Nil(t, err)
err = s.L1.env.EthCl.SendTransaction(t.Ctx(), resolveClaimTx)
require.Nil(t, err)
return resolveClaimTx.Hash()
}
// ActResolve creates a L1 resolve tx for the latest withdrawal.
// Resolve is different than resolving a claim, the root claim must be resolved first and then
// the game itself can be resolved.
func (s *CrossLayerUser) ActResolve(t Testing) {
s.L1.lastTxHash = s.Resolve(t, s.lastL2WithdrawalTxHash)
}
// Resolve creates a L1 resolve tx for the given L2 withdrawal tx, returning the tx hash.
func (s *CrossLayerUser) Resolve(t Testing, l2TxHash common.Hash) common.Hash {
params, err := s.getLatestWithdrawalParams(t)
if err != nil {
t.InvalidAction("cannot resolve game: %v", err)
return common.Hash{}
}
game, err := s.getDisputeGame(t, *params)
require.NoError(t, err)
resolveTx, err := game.Resolve(&s.L1.txOpts)
require.Nil(t, err)
err = s.L1.env.EthCl.SendTransaction(t.Ctx(), resolveTx)
require.Nil(t, err)
return resolveTx.Hash()
}
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"math/rand" "math/rand"
"testing" "testing"
"time"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -131,11 +132,23 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { ...@@ -131,11 +132,23 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) {
miner, seqEngine, seq := setupSequencerTest(t, sd, log) miner, seqEngine, seq := setupSequencerTest(t, sd, log)
batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp),
seq.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) seq.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))
proposer := NewL2Proposer(t, log, &ProposerCfg{
OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, var proposer *L2Proposer
ProposerKey: dp.Secrets.Proposer, if e2eutils.UseFPAC() {
AllowNonFinalized: true, proposer = NewL2Proposer(t, log, &ProposerCfg{
}, miner.EthClient(), seq.RollupClient()) DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy,
ProposalInterval: 6 * time.Second,
DisputeGameType: 0,
ProposerKey: dp.Secrets.Proposer,
AllowNonFinalized: true,
}, miner.EthClient(), seq.RollupClient())
} else {
proposer = NewL2Proposer(t, log, &ProposerCfg{
OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy,
ProposerKey: dp.Secrets.Proposer,
AllowNonFinalized: true,
}, miner.EthClient(), seq.RollupClient())
}
// need to start derivation before we can make L2 blocks // need to start derivation before we can make L2 blocks
seq.ActL2PipelineFull(t) seq.ActL2PipelineFull(t)
...@@ -266,6 +279,25 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { ...@@ -266,6 +279,25 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) {
miner.ActL1StartBlock(13)(t) miner.ActL1StartBlock(13)(t)
miner.ActL1EndBlock(t) miner.ActL1EndBlock(t)
// If using FPAC we need to resolve the game
if e2eutils.UseFPAC() {
// Resolve the root claim
alice.ActResolveClaim(t)
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(alice.Address())(t)
miner.ActL1EndBlock(t)
// Resolve the game
alice.L1.ActCheckReceiptStatusOfLastTx(true)(t)
alice.ActResolve(t)
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(alice.Address())(t)
miner.ActL1EndBlock(t)
// Create an empty block to pass the air-gap window
alice.L1.ActCheckReceiptStatusOfLastTx(true)(t)
miner.ActL1StartBlock(13)(t)
miner.ActL1EndBlock(t)
}
// make the L1 finalize withdrawal tx // make the L1 finalize withdrawal tx
alice.ActCompleteWithdrawal(t) alice.ActCompleteWithdrawal(t)
// include completed withdrawal in new L1 block // include completed withdrawal in new L1 block
......
...@@ -204,3 +204,7 @@ func ApplyDeployConfigForks(deployConfig *genesis.DeployConfig) { ...@@ -204,3 +204,7 @@ func ApplyDeployConfigForks(deployConfig *genesis.DeployConfig) {
deployConfig.L2GenesisCanyonTimeOffset = new(hexutil.Uint64) deployConfig.L2GenesisCanyonTimeOffset = new(hexutil.Uint64)
deployConfig.L2GenesisRegolithTimeOffset = new(hexutil.Uint64) deployConfig.L2GenesisRegolithTimeOffset = new(hexutil.Uint64)
} }
func UseFPAC() bool {
return os.Getenv("OP_E2E_USE_FPAC") == "true"
}
...@@ -7,9 +7,13 @@ import ( ...@@ -7,9 +7,13 @@ import (
"time" "time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindingspreview"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
) )
// ForOutputRootPublished waits until there is an output published for an L2 block number larger than the supplied l2BlockNumber // ForOutputRootPublished waits until there is an output published for an L2 block number larger than the supplied l2BlockNumber
...@@ -69,3 +73,56 @@ func ForFinalizationPeriod(ctx context.Context, client *ethclient.Client, l1Prov ...@@ -69,3 +73,56 @@ func ForFinalizationPeriod(ctx context.Context, client *ethclient.Client, l1Prov
return header.Time > targetTimestamp.Uint64(), nil return header.Time > targetTimestamp.Uint64(), nil
}) })
} }
// ForGamePublished waits until a game is published on L1 for the given l2BlockNumber.
func ForGamePublished(ctx context.Context, client *ethclient.Client, optimismPortalAddr common.Address, disputeGameFactoryAddr common.Address, l2BlockNumber *big.Int) (uint64, error) {
l2BlockNumber = new(big.Int).Set(l2BlockNumber) // Don't clobber caller owned l2BlockNumber
optimismPortal2Contract, err := bindingspreview.NewOptimismPortal2Caller(optimismPortalAddr, client)
if err != nil {
return 0, err
}
disputeGameFactoryContract, err := bindings.NewDisputeGameFactoryCaller(disputeGameFactoryAddr, client)
if err != nil {
return 0, err
}
getL2BlockFromLatestGame := func() (*big.Int, error) {
latestGame, err := withdrawals.FindLatestGame(ctx, disputeGameFactoryContract, optimismPortal2Contract)
if err != nil {
return big.NewInt(-1), nil
}
gameBlockNumber := new(big.Int).SetBytes(latestGame.ExtraData[0:32])
return gameBlockNumber, nil
}
outputBlockNum, err := AndGet(ctx, time.Second, getL2BlockFromLatestGame, func(latest *big.Int) bool {
return latest.Cmp(l2BlockNumber) >= 0
})
if err != nil {
return 0, err
}
return outputBlockNum.Uint64(), nil
}
// ForWithdrawalCheck waits until the withdrawal check in the portal succeeds.
func ForWithdrawalCheck(ctx context.Context, client *ethclient.Client, withdrawal crossdomain.Withdrawal, optimismPortalAddr common.Address) error {
opts := &bind.CallOpts{Context: ctx}
portal, err := bindingspreview.NewOptimismPortal2Caller(optimismPortalAddr, client)
if err != nil {
return fmt.Errorf("create portal caller: %w", err)
}
return For(ctx, time.Second, func() (bool, error) {
log.Warn("checking withdrawal!")
wdHash, err := withdrawal.Hash()
if err != nil {
return false, fmt.Errorf("hash withdrawal: %w", err)
}
err = portal.CheckWithdrawal(opts, wdHash)
log.Warn("checking withdrawal", "hash", wdHash, "err", err)
return err == nil, nil
})
}
...@@ -39,6 +39,18 @@ func UsesCannon(t e2eutils.TestingBase, opts *testopts) { ...@@ -39,6 +39,18 @@ func UsesCannon(t e2eutils.TestingBase, opts *testopts) {
} }
} }
func SkipOnFPAC(t e2eutils.TestingBase, opts *testopts) {
if e2eutils.UseFPAC() {
t.Skip("Skipping test for FPAC")
}
}
func SkipOnNotFPAC(t e2eutils.TestingBase, opts *testopts) {
if !e2eutils.UseFPAC() {
t.Skip("Skipping test for non-FPAC")
}
}
// UseExecutor allows manually splitting tests between circleci executors // UseExecutor allows manually splitting tests between circleci executors
// //
// Tests default to run on the first executor but can be moved to the second with: // Tests default to run on the first executor but can be moved to the second with:
......
...@@ -747,17 +747,35 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste ...@@ -747,17 +747,35 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
} }
// L2Output Submitter // L2Output Submitter
proposerCLIConfig := &l2os.CLIConfig{ var proposerCLIConfig *l2os.CLIConfig
L1EthRpc: sys.EthInstances["l1"].WSEndpoint(), if e2eutils.UseFPAC() {
RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), proposerCLIConfig = &l2os.CLIConfig{
L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(), L1EthRpc: sys.EthInstances["l1"].WSEndpoint(),
PollInterval: 50 * time.Millisecond, RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(),
TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Proposer), DGFAddress: config.L1Deployments.DisputeGameFactoryProxy.Hex(),
AllowNonFinalized: cfg.NonFinalizedProposals, ProposalInterval: 6 * time.Second,
LogConfig: oplog.CLIConfig{ DisputeGameType: 0,
Level: log.LevelInfo, PollInterval: 50 * time.Millisecond,
Format: oplog.FormatText, TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Proposer),
}, AllowNonFinalized: cfg.NonFinalizedProposals,
LogConfig: oplog.CLIConfig{
Level: log.LvlInfo,
Format: oplog.FormatText,
},
}
} else {
proposerCLIConfig = &l2os.CLIConfig{
L1EthRpc: sys.EthInstances["l1"].WSEndpoint(),
RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(),
L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(),
PollInterval: 50 * time.Millisecond,
TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Proposer),
AllowNonFinalized: cfg.NonFinalizedProposals,
LogConfig: oplog.CLIConfig{
Level: log.LvlInfo,
Format: oplog.FormatText,
},
}
} }
proposer, err := l2os.ProposerServiceFromCLIConfig(context.Background(), "0.0.1", proposerCLIConfig, sys.Cfg.Loggers["proposer"]) proposer, err := l2os.ProposerServiceFromCLIConfig(context.Background(), "0.0.1", proposerCLIConfig, sys.Cfg.Loggers["proposer"])
if err != nil { if err != nil {
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
...@@ -90,7 +91,7 @@ func TestMain(m *testing.M) { ...@@ -90,7 +91,7 @@ func TestMain(m *testing.M) {
} }
func TestL2OutputSubmitter(t *testing.T) { func TestL2OutputSubmitter(t *testing.T) {
InitParallel(t) InitParallel(t, SkipOnFPAC)
cfg := DefaultSystemConfig(t) cfg := DefaultSystemConfig(t)
cfg.NonFinalizedProposals = true // speed up the time till we see output proposals cfg.NonFinalizedProposals = true // speed up the time till we see output proposals
...@@ -158,6 +159,66 @@ func TestL2OutputSubmitter(t *testing.T) { ...@@ -158,6 +159,66 @@ func TestL2OutputSubmitter(t *testing.T) {
} }
} }
func TestL2OutputSubmitterFPAC(t *testing.T) {
InitParallel(t, SkipOnNotFPAC)
cfg := DefaultSystemConfig(t)
cfg.NonFinalizedProposals = true // speed up the time till we see output proposals
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l1Client := sys.Clients["l1"]
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client)
require.Nil(t, err)
initialGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{})
require.Nil(t, err)
l2Verif := sys.Clients["verifier"]
_, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second)
require.Nil(t, err)
timeoutCh := time.After(15 * time.Second)
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
latestGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{})
require.Nil(t, err)
if latestGameCount.Cmp(initialGameCount) > 0 {
committedL2Output, err := disputeGameFactory.GameAtIndex(&bind.CallOpts{}, new(big.Int).Sub(latestGameCount, common.Big1))
require.Nil(t, err)
proxy, err := bindings.NewFaultDisputeGameCaller(committedL2Output.Proxy, l1Client)
require.Nil(t, err)
committedOutputRoot, err := proxy.RootClaim(&bind.CallOpts{})
require.Nil(t, err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
extradata, err := proxy.ExtraData(&bind.CallOpts{})
require.Nil(t, err)
gameBlockNumber := new(big.Int).SetBytes(extradata[0:32])
l2Output, err := rollupClient.OutputAtBlock(ctx, gameBlockNumber.Uint64())
require.Nil(t, err)
require.Equal(t, l2Output.OutputRoot[:], committedOutputRoot[:])
break
}
select {
case <-timeoutCh:
t.Fatalf("State root oracle not updated")
case <-ticker.C:
}
}
}
func TestSystemE2EDencunAtGenesis(t *testing.T) { func TestSystemE2EDencunAtGenesis(t *testing.T) {
InitParallel(t) InitParallel(t)
...@@ -1075,7 +1136,7 @@ func TestWithdrawals(t *testing.T) { ...@@ -1075,7 +1136,7 @@ func TestWithdrawals(t *testing.T) {
startBalanceBeforeFinalize, err := l1Client.BalanceAt(ctx, fromAddr, nil) startBalanceBeforeFinalize, err := l1Client.BalanceAt(ctx, fromAddr, nil)
require.Nil(t, err) require.Nil(t, err)
proveReceipt, finalizeReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", ethPrivKey, receipt) proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", ethPrivKey, receipt)
// Verify balance after withdrawal // Verify balance after withdrawal
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
...@@ -1090,6 +1151,12 @@ func TestWithdrawals(t *testing.T) { ...@@ -1090,6 +1151,12 @@ func TestWithdrawals(t *testing.T) {
proveFee := new(big.Int).Mul(new(big.Int).SetUint64(proveReceipt.GasUsed), proveReceipt.EffectiveGasPrice) proveFee := new(big.Int).Mul(new(big.Int).SetUint64(proveReceipt.GasUsed), proveReceipt.EffectiveGasPrice)
finalizeFee := new(big.Int).Mul(new(big.Int).SetUint64(finalizeReceipt.GasUsed), finalizeReceipt.EffectiveGasPrice) finalizeFee := new(big.Int).Mul(new(big.Int).SetUint64(finalizeReceipt.GasUsed), finalizeReceipt.EffectiveGasPrice)
fees = new(big.Int).Add(proveFee, finalizeFee) fees = new(big.Int).Add(proveFee, finalizeFee)
if e2eutils.UseFPAC() {
resolveClaimFee := new(big.Int).Mul(new(big.Int).SetUint64(resolveClaimReceipt.GasUsed), resolveClaimReceipt.EffectiveGasPrice)
resolveFee := new(big.Int).Mul(new(big.Int).SetUint64(resolveReceipt.GasUsed), resolveReceipt.EffectiveGasPrice)
fees = new(big.Int).Add(fees, resolveClaimFee)
fees = new(big.Int).Add(fees, resolveFee)
}
withdrawAmount = withdrawAmount.Sub(withdrawAmount, fees) withdrawAmount = withdrawAmount.Sub(withdrawAmount, fees)
require.Equal(t, withdrawAmount, diff) require.Equal(t, withdrawAmount, diff)
} }
......
...@@ -11,7 +11,9 @@ import ( ...@@ -11,7 +11,9 @@ import (
"time" "time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindingspreview"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
...@@ -446,6 +448,15 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -446,6 +448,15 @@ func TestMixedWithdrawalValidity(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, cfg.DeployConfig.FinalizationPeriodSeconds, finalizationPeriod.Uint64()) require.Equal(t, cfg.DeployConfig.FinalizationPeriodSeconds, finalizationPeriod.Uint64())
disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client)
require.NoError(t, err)
optimismPortal, err := bindings.NewOptimismPortalCaller(cfg.L1Deployments.OptimismPortalProxy, l1Client)
require.NoError(t, err)
optimismPortal2, err := bindingspreview.NewOptimismPortal2Caller(cfg.L1Deployments.OptimismPortalProxy, l1Client)
require.NoError(t, err)
// Create a struct used to track our transactors and their transactions sent. // Create a struct used to track our transactors and their transactions sent.
type TestAccountState struct { type TestAccountState struct {
Account *TestAccount Account *TestAccount
...@@ -535,10 +546,15 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -535,10 +546,15 @@ func TestMixedWithdrawalValidity(t *testing.T) {
transactor.ExpectedL2Nonce = transactor.ExpectedL2Nonce + 1 transactor.ExpectedL2Nonce = transactor.ExpectedL2Nonce + 1
// Wait for the finalization period, then we can finalize this withdrawal. // Wait for the finalization period, then we can finalize this withdrawal.
ctx, withdaralCancel := context.WithTimeout(context.Background(), 40*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) ctx, withdrawalCancel := context.WithTimeout(context.Background(), 60*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.NotEqual(t, cfg.L1Deployments.L2OutputOracleProxy, common.Address{}) require.NotEqual(t, cfg.L1Deployments.L2OutputOracleProxy, common.Address{})
blockNumber, err := wait.ForOutputRootPublished(ctx, l1Client, cfg.L1Deployments.L2OutputOracleProxy, receipt.BlockNumber) var blockNumber uint64
withdaralCancel() if e2eutils.UseFPAC() {
blockNumber, err = wait.ForGamePublished(ctx, l1Client, cfg.L1Deployments.OptimismPortalProxy, cfg.L1Deployments.DisputeGameFactoryProxy, receipt.BlockNumber)
} else {
blockNumber, err = wait.ForOutputRootPublished(ctx, l1Client, cfg.L1Deployments.L2OutputOracleProxy, receipt.BlockNumber)
}
withdrawalCancel()
require.Nil(t, err) require.Nil(t, err)
ctx, txCancel = context.WithTimeout(context.Background(), txTimeoutDuration) ctx, txCancel = context.WithTimeout(context.Background(), txTimeoutDuration)
...@@ -550,20 +566,22 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -550,20 +566,22 @@ func TestMixedWithdrawalValidity(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
proofCl := gethclient.New(rpcClient) proofCl := gethclient.New(rpcClient)
receiptCl := ethclient.NewClient(rpcClient) receiptCl := ethclient.NewClient(rpcClient)
blockCl := ethclient.NewClient(rpcClient)
// Now create the withdrawal // Now create the withdrawal
params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, tx.Hash(), header, l2OutputOracle) params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, tx.Hash(), header, l2OutputOracle, disputeGameFactory, optimismPortal, optimismPortal2)
require.Nil(t, err) require.Nil(t, err)
// Obtain our withdrawal parameters // Obtain our withdrawal parameters
withdrawalTransaction := &bindings.TypesWithdrawalTransaction{ withdrawal := crossdomain.Withdrawal{
Nonce: params.Nonce, Nonce: params.Nonce,
Sender: params.Sender, Sender: &params.Sender,
Target: params.Target, Target: &params.Target,
Value: params.Value, Value: params.Value,
GasLimit: params.GasLimit, GasLimit: params.GasLimit,
Data: params.Data, Data: params.Data,
} }
withdrawalTransaction := withdrawal.WithdrawalTransaction()
l2OutputIndexParam := params.L2OutputIndex l2OutputIndexParam := params.L2OutputIndex
outputRootProofParam := params.OutputRootProof outputRootProofParam := params.OutputRootProof
withdrawalProofParam := params.WithdrawalProof withdrawalProofParam := params.WithdrawalProof
...@@ -626,7 +644,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -626,7 +644,7 @@ func TestMixedWithdrawalValidity(t *testing.T) {
// Prove withdrawal. This checks the proof so we only finalize if this succeeds // Prove withdrawal. This checks the proof so we only finalize if this succeeds
tx, err = depositContract.ProveWithdrawalTransaction( tx, err = depositContract.ProveWithdrawalTransaction(
transactor.Account.L1Opts, transactor.Account.L1Opts,
*withdrawalTransaction, withdrawalTransaction,
l2OutputIndexParam, l2OutputIndexParam,
outputRootProofParam, outputRootProofParam,
withdrawalProofParam, withdrawalProofParam,
...@@ -661,15 +679,20 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -661,15 +679,20 @@ func TestMixedWithdrawalValidity(t *testing.T) {
require.Nil(t, err, "prove withdrawal") require.Nil(t, err, "prove withdrawal")
// Wait for finalization and then create the Finalized Withdrawal Transaction // Wait for finalization and then create the Finalized Withdrawal Transaction
ctx, withdrawalCancel := context.WithTimeout(context.Background(), 45*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) ctx, withdrawalCancel := context.WithTimeout(context.Background(), 60*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
defer withdrawalCancel() defer withdrawalCancel()
err = wait.ForFinalizationPeriod(ctx, l1Client, header.Number, cfg.L1Deployments.L2OutputOracleProxy) if e2eutils.UseFPAC() {
require.Nil(t, err) err = wait.ForWithdrawalCheck(ctx, l1Client, withdrawal, cfg.L1Deployments.OptimismPortalProxy)
require.Nil(t, err)
} else {
err = wait.ForFinalizationPeriod(ctx, l1Client, header.Number, cfg.L1Deployments.L2OutputOracleProxy)
require.Nil(t, err)
}
// Finalize withdrawal // Finalize withdrawal
_, err = depositContract.FinalizeWithdrawalTransaction( _, err = depositContract.FinalizeWithdrawalTransaction(
transactor.Account.L1Opts, transactor.Account.L1Opts,
*withdrawalTransaction, withdrawalTransaction,
) )
require.NoError(t, err) require.NoError(t, err)
} }
......
...@@ -8,8 +8,11 @@ import ( ...@@ -8,8 +8,11 @@ import (
"time" "time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindingspreview"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum-optimism/optimism/op-node/withdrawals"
...@@ -82,10 +85,10 @@ func defaultWithdrawalTxOpts() *WithdrawalTxOpts { ...@@ -82,10 +85,10 @@ func defaultWithdrawalTxOpts() *WithdrawalTxOpts {
} }
} }
func ProveAndFinalizeWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (*types.Receipt, *types.Receipt) { func ProveAndFinalizeWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (*types.Receipt, *types.Receipt, *types.Receipt, *types.Receipt) {
params, proveReceipt := ProveWithdrawal(t, cfg, clients, l2NodeName, ethPrivKey, l2WithdrawalReceipt) params, proveReceipt := ProveWithdrawal(t, cfg, clients, l2NodeName, ethPrivKey, l2WithdrawalReceipt)
finalizeReceipt := FinalizeWithdrawal(t, cfg, clients.NodeClient("l1"), ethPrivKey, proveReceipt, params) finalizeReceipt, resolveClaimReceipt, resolveReceipt := FinalizeWithdrawal(t, cfg, clients.NodeClient("l1"), ethPrivKey, proveReceipt, params)
return proveReceipt, finalizeReceipt return proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt
} }
func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (withdrawals.ProvenWithdrawalParameters, *types.Receipt) { func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (withdrawals.ProvenWithdrawalParameters, *types.Receipt) {
...@@ -94,10 +97,18 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N ...@@ -94,10 +97,18 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N
defer cancel() defer cancel()
l1Client := clients.NodeClient("l1") l1Client := clients.NodeClient("l1")
blockNumber, err := wait.ForOutputRootPublished(ctx, l1Client, config.L1Deployments.L2OutputOracleProxy, l2WithdrawalReceipt.BlockNumber) var blockNumber uint64
require.Nil(t, err) var err error
if e2eutils.UseFPAC() {
blockNumber, err = wait.ForGamePublished(ctx, l1Client, config.L1Deployments.OptimismPortalProxy, config.L1Deployments.DisputeGameFactoryProxy, l2WithdrawalReceipt.BlockNumber)
require.Nil(t, err)
} else {
blockNumber, err = wait.ForOutputRootPublished(ctx, l1Client, config.L1Deployments.L2OutputOracleProxy, l2WithdrawalReceipt.BlockNumber)
require.Nil(t, err)
}
receiptCl := clients.NodeClient(l2NodeName) receiptCl := clients.NodeClient(l2NodeName)
blockCl := clients.NodeClient(l2NodeName)
proofCl := gethclient.New(receiptCl.Client()) proofCl := gethclient.New(receiptCl.Client())
ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
...@@ -106,11 +117,19 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N ...@@ -106,11 +117,19 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N
header, err := receiptCl.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNumber)) header, err := receiptCl.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNumber))
require.Nil(t, err) require.Nil(t, err)
// Now create withdrawal
oracle, err := bindings.NewL2OutputOracleCaller(config.L1Deployments.L2OutputOracleProxy, l1Client) oracle, err := bindings.NewL2OutputOracleCaller(config.L1Deployments.L2OutputOracleProxy, l1Client)
require.Nil(t, err) require.Nil(t, err)
params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, l2WithdrawalReceipt.TxHash, header, oracle) factory, err := bindings.NewDisputeGameFactoryCaller(config.L1Deployments.DisputeGameFactoryProxy, l1Client)
require.Nil(t, err)
portal1, err := bindings.NewOptimismPortalCaller(config.L1Deployments.OptimismPortalProxy, l1Client)
require.Nil(t, err)
portal2, err := bindingspreview.NewOptimismPortal2Caller(config.L1Deployments.OptimismPortalProxy, l1Client)
require.Nil(t, err)
params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, l2WithdrawalReceipt.TxHash, header, oracle, factory, portal1, portal2)
require.Nil(t, err) require.Nil(t, err)
portal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client) portal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client)
...@@ -143,35 +162,76 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N ...@@ -143,35 +162,76 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N
return params, proveReceipt return params, proveReceipt
} }
func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, privKey *ecdsa.PrivateKey, withdrawalProofReceipt *types.Receipt, params withdrawals.ProvenWithdrawalParameters) *types.Receipt { func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, privKey *ecdsa.PrivateKey, withdrawalProofReceipt *types.Receipt, params withdrawals.ProvenWithdrawalParameters) (*types.Receipt, *types.Receipt, *types.Receipt) {
// Wait for finalization and then create the Finalized Withdrawal Transaction // Wait for finalization and then create the Finalized Withdrawal Transaction
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
defer cancel() defer cancel()
err := wait.ForFinalizationPeriod(ctx, l1Client, withdrawalProofReceipt.BlockNumber, config.L1Deployments.L2OutputOracleProxy) wd := crossdomain.Withdrawal{
require.Nil(t, err) Nonce: params.Nonce,
Sender: &params.Sender,
Target: &params.Target,
Value: params.Value,
GasLimit: params.GasLimit,
Data: params.Data,
}
opts, err := bind.NewKeyedTransactorWithChainID(privKey, cfg.L1ChainIDBig()) opts, err := bind.NewKeyedTransactorWithChainID(privKey, cfg.L1ChainIDBig())
require.Nil(t, err) require.Nil(t, err)
var resolveClaimReceipt *types.Receipt
var resolveReceipt *types.Receipt
if e2eutils.UseFPAC() {
portal2, err := bindingspreview.NewOptimismPortal2(config.L1Deployments.OptimismPortalProxy, l1Client)
require.Nil(t, err)
wdHash, err := wd.Hash()
require.Nil(t, err)
game, err := portal2.ProvenWithdrawals(&bind.CallOpts{}, wdHash)
require.Nil(t, err)
require.NotNil(t, game, "withdrawal should be proven")
proxy, err := bindings.NewFaultDisputeGame(game.DisputeGameProxy, l1Client)
require.Nil(t, err)
expiry, err := proxy.GameDuration(&bind.CallOpts{})
require.Nil(t, err)
time.Sleep(time.Duration(expiry) * time.Second)
resolveClaimTx, err := proxy.ResolveClaim(opts, common.Big0)
require.Nil(t, err)
resolveClaimReceipt, err = wait.ForReceiptOK(ctx, l1Client, resolveClaimTx.Hash())
require.Nil(t, err, "resolve claim")
require.Equal(t, types.ReceiptStatusSuccessful, resolveClaimReceipt.Status)
resolveTx, err := proxy.Resolve(opts)
require.Nil(t, err)
resolveReceipt, err = wait.ForReceiptOK(ctx, l1Client, resolveTx.Hash())
require.Nil(t, err, "resolve")
require.Equal(t, types.ReceiptStatusSuccessful, resolveReceipt.Status)
}
if e2eutils.UseFPAC() {
err := wait.ForWithdrawalCheck(ctx, l1Client, wd, config.L1Deployments.OptimismPortalProxy)
require.Nil(t, err)
} else {
err := wait.ForFinalizationPeriod(ctx, l1Client, withdrawalProofReceipt.BlockNumber, config.L1Deployments.L2OutputOracleProxy)
require.Nil(t, err)
}
portal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client) portal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client)
require.Nil(t, err) require.Nil(t, err)
// Finalize withdrawal // Finalize withdrawal
tx, err := portal.FinalizeWithdrawalTransaction( tx, err := portal.FinalizeWithdrawalTransaction(opts, wd.WithdrawalTransaction())
opts,
bindings.TypesWithdrawalTransaction{
Nonce: params.Nonce,
Sender: params.Sender,
Target: params.Target,
Value: params.Value,
GasLimit: params.GasLimit,
Data: params.Data,
},
)
require.Nil(t, err) require.Nil(t, err)
// Ensure that our withdrawal was finalized successfully // Ensure that our withdrawal was finalized successfully
finalizeReceipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) finalizeReceipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash())
require.Nil(t, err, "finalize withdrawal") require.Nil(t, err, "finalize withdrawal")
require.Equal(t, types.ReceiptStatusSuccessful, finalizeReceipt.Status) require.Equal(t, types.ReceiptStatusSuccessful, finalizeReceipt.Status)
return finalizeReceipt return finalizeReceipt, resolveClaimReceipt, resolveReceipt
} }
...@@ -15,7 +15,9 @@ import ( ...@@ -15,7 +15,9 @@ import (
"github.com/ethereum/go-ethereum/ethclient/gethclient" "github.com/ethereum/go-ethereum/ethclient/gethclient"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindingspreview"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
) )
var MessagePassedTopic = crypto.Keccak256Hash([]byte("MessagePassed(uint256,address,address,uint256,uint256,bytes,bytes32)")) var MessagePassedTopic = crypto.Keccak256Hash([]byte("MessagePassed(uint256,address,address,uint256,uint256,bytes,bytes32)"))
...@@ -28,6 +30,10 @@ type ReceiptClient interface { ...@@ -28,6 +30,10 @@ type ReceiptClient interface {
TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error) TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error)
} }
type BlockClient interface {
BlockByNumber(context.Context, *big.Int) (*types.Block, error)
}
// ProvenWithdrawalParameters is the set of parameters to pass to the ProveWithdrawalTransaction // ProvenWithdrawalParameters is the set of parameters to pass to the ProveWithdrawalTransaction
// and FinalizeWithdrawalTransaction functions // and FinalizeWithdrawalTransaction functions
type ProvenWithdrawalParameters struct { type ProvenWithdrawalParameters struct {
...@@ -45,7 +51,7 @@ type ProvenWithdrawalParameters struct { ...@@ -45,7 +51,7 @@ type ProvenWithdrawalParameters struct {
// ProveWithdrawalParameters queries L1 & L2 to generate all withdrawal parameters and proof necessary to prove a withdrawal on L1. // ProveWithdrawalParameters queries L1 & L2 to generate all withdrawal parameters and proof necessary to prove a withdrawal on L1.
// The header provided is very important. It should be a block (timestamp) for which there is a submitted output in the L2 Output Oracle // The header provided is very important. It should be a block (timestamp) for which there is a submitted output in the L2 Output Oracle
// contract. If not, the withdrawal will fail as it the storage proof cannot be verified if there is no submitted state root. // contract. If not, the withdrawal will fail as it the storage proof cannot be verified if there is no submitted state root.
func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, txHash common.Hash, header *types.Header, l2OutputOracleContract *bindings.L2OutputOracleCaller) (ProvenWithdrawalParameters, error) { func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, l2BlockCl BlockClient, txHash common.Hash, header *types.Header, l2OutputOracleContract *bindings.L2OutputOracleCaller, disputeGameFactoryContract *bindings.DisputeGameFactoryCaller, optimismPortalContract *bindings.OptimismPortalCaller, optimismPortal2Contract *bindingspreview.OptimismPortal2Caller) (ProvenWithdrawalParameters, error) {
// Transaction receipt // Transaction receipt
receipt, err := l2ReceiptCl.TransactionReceipt(ctx, txHash) receipt, err := l2ReceiptCl.TransactionReceipt(ctx, txHash)
if err != nil { if err != nil {
...@@ -65,18 +71,33 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei ...@@ -65,18 +71,33 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei
return ProvenWithdrawalParameters{}, err return ProvenWithdrawalParameters{}, err
} }
slot := StorageSlotOfWithdrawalHash(withdrawalHash) slot := StorageSlotOfWithdrawalHash(withdrawalHash)
p, err := proofCl.GetProof(ctx, predeploys.L2ToL1MessagePasserAddr, []string{slot.String()}, header.Number)
if err != nil { var l2OutputIndex *big.Int
return ProvenWithdrawalParameters{}, err var l2BlockNumber *big.Int
if e2eutils.UseFPAC() {
latestGame, err := FindLatestGame(ctx, disputeGameFactoryContract, optimismPortal2Contract)
if err != nil {
return ProvenWithdrawalParameters{}, fmt.Errorf("failed to find latest game: %w", err)
}
l2BlockNumber = new(big.Int).SetBytes(latestGame.ExtraData[0:32])
l2OutputIndex = latestGame.Index
} else {
l2OutputIndex, err = l2OutputOracleContract.GetL2OutputIndexAfter(&bind.CallOpts{}, header.Number)
if err != nil {
return ProvenWithdrawalParameters{}, fmt.Errorf("failed to get l2OutputIndex: %w", err)
}
l2BlockNumber = header.Number
} }
// Fetch the L2OutputIndex from the L2 Output Oracle caller (on L1) // Fetch the block from the L2 node
l2OutputIndex, err := l2OutputOracleContract.GetL2OutputIndexAfter(&bind.CallOpts{}, header.Number) l2Block, err := l2BlockCl.BlockByNumber(ctx, l2BlockNumber)
if err != nil { if err != nil {
return ProvenWithdrawalParameters{}, fmt.Errorf("failed to get l2OutputIndex: %w", err) return ProvenWithdrawalParameters{}, fmt.Errorf("failed to get l2Block: %w", err)
} }
// TODO: Could skip this step, but it's nice to double check it
err = VerifyProof(header.Root, p) p, err := proofCl.GetProof(ctx, predeploys.L2ToL1MessagePasserAddr, []string{slot.String()}, l2Block.Number())
if err != nil { if err != nil {
return ProvenWithdrawalParameters{}, err return ProvenWithdrawalParameters{}, err
} }
...@@ -84,6 +105,11 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei ...@@ -84,6 +105,11 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei
return ProvenWithdrawalParameters{}, errors.New("invalid amount of storage proofs") return ProvenWithdrawalParameters{}, errors.New("invalid amount of storage proofs")
} }
err = VerifyProof(l2Block.Root(), p)
if err != nil {
return ProvenWithdrawalParameters{}, err
}
// Encode it as expected by the contract // Encode it as expected by the contract
trieNodes := make([][]byte, len(p.StorageProof[0].Proof)) trieNodes := make([][]byte, len(p.StorageProof[0].Proof))
for i, s := range p.StorageProof[0].Proof { for i, s := range p.StorageProof[0].Proof {
...@@ -100,14 +126,42 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei ...@@ -100,14 +126,42 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei
Data: ev.Data, Data: ev.Data,
OutputRootProof: bindings.TypesOutputRootProof{ OutputRootProof: bindings.TypesOutputRootProof{
Version: [32]byte{}, // Empty for version 1 Version: [32]byte{}, // Empty for version 1
StateRoot: header.Root, StateRoot: l2Block.Root(),
MessagePasserStorageRoot: p.StorageHash, MessagePasserStorageRoot: p.StorageHash,
LatestBlockhash: header.Hash(), LatestBlockhash: l2Block.Hash(),
}, },
WithdrawalProof: trieNodes, WithdrawalProof: trieNodes,
}, nil }, nil
} }
// FindLatestGame finds the latest game in the DisputeGameFactory contract.
func FindLatestGame(ctx context.Context, disputeGameFactoryContract *bindings.DisputeGameFactoryCaller, optimismPortal2Contract *bindingspreview.OptimismPortal2Caller) (*bindings.IDisputeGameFactoryGameSearchResult, error) {
respectedGameType, err := optimismPortal2Contract.RespectedGameType(&bind.CallOpts{})
if err != nil {
return nil, fmt.Errorf("failed to get respected game type: %w", err)
}
gameCount, err := disputeGameFactoryContract.GameCount(&bind.CallOpts{})
if err != nil {
return nil, fmt.Errorf("failed to get game count: %w", err)
}
if gameCount.Cmp(common.Big0) == 0 {
return nil, errors.New("no games")
}
searchStart := new(big.Int).Sub(gameCount, common.Big1)
latestGames, err := disputeGameFactoryContract.FindLatestGames(&bind.CallOpts{}, respectedGameType, searchStart, common.Big1)
if err != nil {
return nil, fmt.Errorf("failed to get latest games: %w", err)
}
if len(latestGames) == 0 {
return nil, errors.New("no latest games")
}
latestGame := latestGames[0]
return &latestGame, nil
}
// Standard ABI types copied from golang ABI tests // Standard ABI types copied from golang ABI tests
var ( var (
Uint256Type, _ = abi.NewType("uint256", "", nil) Uint256Type, _ = abi.NewType("uint256", "", nil)
......
...@@ -238,7 +238,7 @@ func (l *L2OutputSubmitter) FetchNextOutputInfo(ctx context.Context) (*eth.Outpu ...@@ -238,7 +238,7 @@ func (l *L2OutputSubmitter) FetchNextOutputInfo(ctx context.Context) (*eth.Outpu
return nil, false, nil return nil, false, nil
} }
return l.fetchOutput(ctx, nextCheckpointBlock) return l.FetchOutput(ctx, nextCheckpointBlock)
} }
// FetchCurrentBlockNumber gets the current block number from the [L2OutputSubmitter]'s [RollupClient]. If the `AllowNonFinalized` configuration // FetchCurrentBlockNumber gets the current block number from the [L2OutputSubmitter]'s [RollupClient]. If the `AllowNonFinalized` configuration
...@@ -267,7 +267,7 @@ func (l *L2OutputSubmitter) FetchCurrentBlockNumber(ctx context.Context) (*big.I ...@@ -267,7 +267,7 @@ func (l *L2OutputSubmitter) FetchCurrentBlockNumber(ctx context.Context) (*big.I
return currentBlockNumber, nil return currentBlockNumber, nil
} }
func (l *L2OutputSubmitter) fetchOutput(ctx context.Context, block *big.Int) (*eth.OutputResponse, bool, error) { func (l *L2OutputSubmitter) FetchOutput(ctx context.Context, block *big.Int) (*eth.OutputResponse, bool, error) {
ctx, cancel := context.WithTimeout(ctx, l.Cfg.NetworkTimeout) ctx, cancel := context.WithTimeout(ctx, l.Cfg.NetworkTimeout)
defer cancel() defer cancel()
...@@ -451,7 +451,7 @@ func (l *L2OutputSubmitter) loopDGF(ctx context.Context) { ...@@ -451,7 +451,7 @@ func (l *L2OutputSubmitter) loopDGF(ctx context.Context) {
break break
} }
output, shouldPropose, err := l.fetchOutput(ctx, blockNumber) output, shouldPropose, err := l.FetchOutput(ctx, blockNumber)
if err != nil || !shouldPropose { if err != nil || !shouldPropose {
break break
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment