diff --git official optimism/.circleci/config.yml SWC optimism/.circleci/config.yml
index b468093883fdc3fc819f39497c9efebe7e7fe66f..e80275ed8bc88015bc81f12b36346338842d861e 100644
--- official optimism/.circleci/config.yml
+++ SWC optimism/.circleci/config.yml
@@ -69,7 +69,7 @@ gcp-cli: circleci/gcp-cli@3.0.1
slack: circleci/slack@5.1.1
shellcheck: circleci/shellcheck@3.2.0
codecov: codecov/codecov@5.0.3
- utils: ethereum-optimism/circleci-utils@1.0.20
+ utils: qkc/circleci-utils@0.0.1
docker: circleci/docker@2.8.2
github-cli: circleci/github-cli@2.7.0
@@ -180,7 +180,7 @@ - slack/notify:
channel: << parameters.channel >>
event: fail
template: basic_fail_1
- branch_pattern: develop
+ branch_pattern: op-es
mentions: "<< parameters.mentions >>"
# Notifies us on Discord when a build fails on develop
@@ -319,7 +319,7 @@ - "."
cannon-go-lint-and-test:
machine: true
- resource_class: ethereum-optimism/latitude-1
+ resource_class: qkc/ax101
parameters:
skip_slow_tests:
type: boolean
@@ -379,7 +379,7 @@ mentions: "@proofs-team"
diff-asterisc-bytecode:
machine: true
- resource_class: ethereum-optimism/latitude-1
+ resource_class: qkc/ax101
steps:
- checkout-from-workspace
- run:
@@ -417,9 +417,8 @@ - notify-failures-on-develop:
mentions: "@clabby @proofs-team"
contracts-bedrock-build:
- docker:
- - image: <<pipeline.parameters.default_docker_image>>
- resource_class: xlarge
+ machine: true
+ resource_class: qkc/ax101
parameters:
build_args:
description: Forge build arguments
@@ -649,7 +648,7 @@ - "<<parameters.release>>"
- and:
- "<<parameters.publish>>"
- or:
- - equal: [develop, << pipeline.git.branch >>]
+ - equal: [op-es, << pipeline.git.branch >>]
- matches: { pattern: "^proposal/.*", value: << pipeline.git.branch >> }
steps:
- gcp-oidc-authenticate:
@@ -790,7 +789,7 @@ command: |
TEST_FILES=$(<<parameters.test_list>>)
if [ -z "$TEST_FILES" ]; then
echo "No test files to run. Exiting early."
- circleci-agent step halt
+ exit 0
fi
working_directory: packages/contracts-bedrock
- check-changed:
@@ -815,7 +814,10 @@ - run:
name: Run tests
command: |
TEST_FILES=$(<<parameters.test_list>>)
- TEST_FILES=$(echo "$TEST_FILES" | circleci tests split --split-by=timings)
+ if [ -z "$TEST_FILES" ]; then
+ echo "No test files to run. Skipping forge test."
+ exit 0
+ fi
TEST_FILES=$(echo "$TEST_FILES" | sed 's|^test/||')
MATCH_PATH="./test/{$(echo "$TEST_FILES" | paste -sd "," -)}"
forge <<parameters.test_command>> <<parameters.test_flags>> --match-path "$MATCH_PATH"
@@ -1007,7 +1009,7 @@ - notify-failures-on-develop
contracts-bedrock-checks:
machine: true
- resource_class: ethereum-optimism/latitude-1
+ resource_class: qkc/ax101
steps:
- checkout-from-workspace
- check-changed:
@@ -1074,9 +1076,8 @@ uses_artifacts:
description: should load in foundry artifacts
type: boolean
default: false
- docker:
- - image: <<pipeline.parameters.default_docker_image>>
- resource_class: xlarge
+ machine: true
+ resource_class: qkc/ax101
steps:
- checkout-from-workspace
- check-changed:
@@ -1101,9 +1102,8 @@ path: ./fuzzdata
when: always
go-lint:
- docker:
- - image: <<pipeline.parameters.default_docker_image>>
- resource_class: large
+ machine: true
+ resource_class: qkc/ax101
steps:
- checkout-from-workspace
- restore_cache:
@@ -1130,7 +1130,7 @@ default: ""
resource_class:
description: Machine resource class
type: string
- default: ethereum-optimism/latitude-1-go-e2e
+ default: qkc/ax101
no_output_timeout:
description: Timeout for when CircleCI kills the job if there's no output
type: string
@@ -1405,9 +1405,8 @@ mentions: "Platforms (<@225161927351992320>) & Protocol (<@590878816004603924>)" # stefano, changwan
message: "Acceptance tests failed for gate <<parameters.gate>> on devnet <<parameters.devnet>>"
sanitize-op-program:
- docker:
- - image: <<pipeline.parameters.default_docker_image>>
- resource_class: large
+ machine: true
+ resource_class: qkc/ax101
steps:
- checkout-from-workspace
- run:
@@ -1428,7 +1427,7 @@ working_directory: cannon
cannon-prestate-quick:
machine: true
- resource_class: ethereum-optimism/latitude-1
+ resource_class: qkc/ax101
steps:
- checkout-from-workspace
- restore_cache:
@@ -1470,7 +1469,7 @@ - "op-program/bin/meta*"
publish-cannon-prestates:
machine: true
- resource_class: ethereum-optimism/latitude-1
+ resource_class: qkc/ax101
steps:
- utils/checkout-with-mise
- attach_workspace:
@@ -1553,7 +1552,7 @@ semgrep-scan:
parameters:
diff_branch:
type: string
- default: develop
+ default: op-es
scan_command:
type: string
default: semgrep ci --timeout=100
@@ -1570,7 +1569,7 @@ - checkout # no need to use mise here since the docker image contains the only dependency
- unless:
condition:
or:
- - equal: ["develop", << pipeline.git.branch >>]
+ - equal: ["op-es", << pipeline.git.branch >>]
- matches: { pattern: "^proposal/.*", value: << pipeline.git.branch >> }
steps:
- run:
@@ -1617,7 +1616,7 @@ working_directory: op-program
op-program-compat:
machine: true
- resource_class: ethereum-optimism/latitude-1
+ resource_class: qkc/ax101
steps:
- checkout-from-workspace
- run:
@@ -1628,7 +1627,7 @@ working_directory: op-program
check-generated-mocks-op-node:
machine: true
- resource_class: ethereum-optimism/latitude-1
+ resource_class: qkc/ax101
steps:
- checkout-from-workspace
- check-changed:
@@ -1639,7 +1638,7 @@ command: make generate-mocks-op-node && git diff --exit-code
check-generated-mocks-op-service:
machine: true
- resource_class: ethereum-optimism/latitude-1
+ resource_class: qkc/ax101
steps:
- checkout-from-workspace
- check-changed:
@@ -1682,7 +1681,7 @@ - notify-failures-on-develop
publish-contract-artifacts:
machine: true
- resource_class: ethereum-optimism/latitude-1
+ resource_class: qkc/ax101
steps:
- gcp-cli/install
- gcp-oidc-authenticate:
@@ -1858,12 +1857,14 @@
workflows:
main:
when:
- or:
- - equal: ["webhook",<< pipeline.trigger_source >>]
- - and:
- - equal: [true, <<pipeline.parameters.main_dispatch>>]
- - equal: ["api",<< pipeline.trigger_source >>]
- - equal: [<< pipeline.parameters.github-event-type >>, "__not_set__"] #this is to prevent triggering this workflow as the default value is always set for main_dispatch
+ and:
+ - or:
+ # Trigger on new commits
+ # - equal: [ webhook, << pipeline.trigger_source >> ]
+ # Trigger on manual triggers if explicitly requested
+ - equal: [true, << pipeline.parameters.main_dispatch >>]
+ - not:
+ equal: [scheduled_pipeline, << pipeline.trigger_source >>]
jobs:
- initialize:
context:
@@ -1901,8 +1902,8 @@ - initialize
- contracts-bedrock-tests:
# Heavily fuzz any fuzz tests within added or modified test files.
name: contracts-bedrock-tests-heavy-fuzz-modified
- test_list: git diff origin/develop...HEAD --name-only --diff-filter=AM -- './test/**/*.t.sol' | sed 's|packages/contracts-bedrock/||'
- test_timeout: 1h
+ test_list: git diff origin/op-es...HEAD --name-only --diff-filter=AM -- './test/**/*.t.sol' | sed 's|packages/contracts-bedrock/||'
+ test_timeout: 3h
test_profile: ciheavy
context:
- circleci-repo-readonly-authenticated-github-token
@@ -1939,11 +1940,13 @@ requires:
- contracts-bedrock-build
context:
- circleci-repo-readonly-authenticated-github-token
- - contracts-bedrock-frozen-code:
- requires:
- - contracts-bedrock-build
- context:
- - circleci-repo-readonly-authenticated-github-token
+ - discord
+ # Skip frozen check for op-es
+ # - contracts-bedrock-frozen-code:
+ # requires:
+ # - contracts-bedrock-build
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
- diff-fetcher-forge-artifacts:
context:
- circleci-repo-readonly-authenticated-github-token
@@ -2120,603 +2123,603 @@ ignore-dirs: ./packages/contracts-bedrock/lib
context:
- circleci-repo-readonly-authenticated-github-token
- go-release-op-deployer:
- jobs:
- - initialize:
- filters:
- tags:
- only: /^op-deployer.*/
- branches:
- ignore: /.*/
- context:
- - circleci-repo-readonly-authenticated-github-token
- - contracts-bedrock-build:
- name: build-contracts-go-release-op-deployer
- filters:
- tags:
- only: /^op-deployer.*/
- branches:
- ignore: /.*/
- build_args: --skip test
- context:
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- - go-release:
- filters:
- tags:
- only: /^op-deployer.*/
- branches:
- ignore: /.*/
- module: op-deployer
- context:
- - oplabs-gcr-release
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - build-contracts-go-release-op-deployer
+ # go-release-op-deployer:
+ # jobs:
+ # - initialize:
+ # filters:
+ # tags:
+ # only: /^op-deployer.*/
+ # branches:
+ # ignore: /.*/
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - contracts-bedrock-build:
+ # name: build-contracts-go-release-op-deployer
+ # filters:
+ # tags:
+ # only: /^op-deployer.*/
+ # branches:
+ # ignore: /.*/
+ # build_args: --skip test
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # - go-release:
+ # filters:
+ # tags:
+ # only: /^op-deployer.*/
+ # branches:
+ # ignore: /.*/
+ # module: op-deployer
+ # context:
+ # - oplabs-gcr-release
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - build-contracts-go-release-op-deployer
- go-release-op-up:
- jobs:
- - initialize:
- filters:
- tags:
- only: /^op-up.*/
- branches:
- ignore: /.*/
- context:
- - circleci-repo-readonly-authenticated-github-token
- - contracts-bedrock-build:
- name: build-contracts-go-release-op-up
- filters:
- tags:
- only: /^op-up.*/
- branches:
- ignore: /.*/
- build_args: --skip test
- context:
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- - go-release:
- filters:
- tags:
- only: /^op-up.*/
- branches:
- ignore: /.*/
- module: op-up
- context:
- - oplabs-gcr-release
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - build-contracts-go-release-op-up
+ # go-release-op-up:
+ # jobs:
+ # - initialize:
+ # filters:
+ # tags:
+ # only: /^op-up.*/
+ # branches:
+ # ignore: /.*/
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - contracts-bedrock-build:
+ # name: build-contracts-go-release-op-up
+ # filters:
+ # tags:
+ # only: /^op-up.*/
+ # branches:
+ # ignore: /.*/
+ # build_args: --skip test
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # - go-release:
+ # filters:
+ # tags:
+ # only: /^op-up.*/
+ # branches:
+ # ignore: /.*/
+ # module: op-up
+ # context:
+ # - oplabs-gcr-release
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - build-contracts-go-release-op-up
- release:
- when:
- not:
- equal: [scheduled_pipeline, << pipeline.trigger_source >>]
- jobs:
- # Wait for approval on the release
- - hold:
- type: approval
- filters:
- tags:
- only: /^(da-server|cannon|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/
- branches:
- ignore: /.*/
- - initialize:
- requires:
- - hold
- context:
- - circleci-repo-readonly-authenticated-github-token
- filters:
- tags:
- only: /^(da-server|cannon|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/
- branches:
- ignore: /.*/
- # Standard (medium) cross-platform docker images go here
- - docker-build:
- matrix:
- parameters:
- docker_name:
- - op-node
- - op-batcher
- - op-faucet
- - op-proposer
- - op-challenger
- - op-dispute-mon
- - op-conductor
- - da-server
- - op-ufm
- - op-supervisor
- - op-test-sequencer
- - op-deployer
- - cannon
- - op-dripper
- - op-interop-mon
- name: <<matrix.docker_name>>-docker-release
- docker_tags: <<pipeline.git.revision>>
- platforms: "linux/amd64,linux/arm64"
- publish: true
- release: true
- filters:
- tags:
- only: /^<<matrix.docker_name>>\/v.*/
- branches:
- ignore: /.*/
- context:
- - oplabs-gcr-release
- requires:
- - initialize
- # Checks for cross-platform images go here
- - check-cross-platform:
- matrix:
- parameters:
- op_component:
- - op-node
- - op-batcher
- - op-faucet
- - op-proposer
- - op-challenger
- - op-dispute-mon
- - op-conductor
- - da-server
- - op-ufm
- - op-supervisor
- - op-test-sequencer
- - op-deployer
- - cannon
- - op-dripper
- - op-interop-mon
- name: <<matrix.op_component>>-cross-platform
- requires:
- - op-node-docker-release
- - op-batcher-docker-release
- - op-faucet-docker-release
- - op-proposer-docker-release
- - op-challenger-docker-release
- - op-dispute-mon-docker-release
- - op-conductor-docker-release
- - da-server-docker-release
- - op-ufm-docker-release
- - op-supervisor-docker-release
- - op-test-sequencer-docker-release
- - cannon-docker-release
- - op-dripper-docker-release
- - op-interop-mon-docker-release
- context:
- - circleci-repo-readonly-authenticated-github-token
- - cannon-prestate:
- filters:
- tags:
- only: /^op-program\/v.*/
- branches:
- ignore: /.*/
- context:
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- - publish-cannon-prestates:
- context:
- - circleci-repo-readonly-authenticated-github-token
- - slack
- - oplabs-network-optimism-io-bucket
- requires:
- - cannon-prestate
- filters:
- tags:
- only: /^op-program\/v.*/
- branches:
- ignore: /.*/
+ # release:
+ # when:
+ # not:
+ # equal: [scheduled_pipeline, << pipeline.trigger_source >>]
+ # jobs:
+ # # Wait for approval on the release
+ # - hold:
+ # type: approval
+ # filters:
+ # tags:
+ # only: /^(da-server|cannon|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/
+ # branches:
+ # ignore: /.*/
+ # - initialize:
+ # requires:
+ # - hold
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # filters:
+ # tags:
+ # only: /^(da-server|cannon|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/
+ # branches:
+ # ignore: /.*/
+ # # Standard (medium) cross-platform docker images go here
+ # - docker-build:
+ # matrix:
+ # parameters:
+ # docker_name:
+ # - op-node
+ # - op-batcher
+ # - op-faucet
+ # - op-proposer
+ # - op-challenger
+ # - op-dispute-mon
+ # - op-conductor
+ # - da-server
+ # - op-ufm
+ # - op-supervisor
+ # - op-test-sequencer
+ # - op-deployer
+ # - cannon
+ # - op-dripper
+ # - op-interop-mon
+ # name: <<matrix.docker_name>>-docker-release
+ # docker_tags: <<pipeline.git.revision>>
+ # platforms: "linux/amd64,linux/arm64"
+ # publish: true
+ # release: true
+ # filters:
+ # tags:
+ # only: /^<<matrix.docker_name>>\/v.*/
+ # branches:
+ # ignore: /.*/
+ # context:
+ # - oplabs-gcr-release
+ # requires:
+ # - initialize
+ # # Checks for cross-platform images go here
+ # - check-cross-platform:
+ # matrix:
+ # parameters:
+ # op_component:
+ # - op-node
+ # - op-batcher
+ # - op-faucet
+ # - op-proposer
+ # - op-challenger
+ # - op-dispute-mon
+ # - op-conductor
+ # - da-server
+ # - op-ufm
+ # - op-supervisor
+ # - op-test-sequencer
+ # - op-deployer
+ # - cannon
+ # - op-dripper
+ # - op-interop-mon
+ # name: <<matrix.op_component>>-cross-platform
+ # requires:
+ # - op-node-docker-release
+ # - op-batcher-docker-release
+ # - op-faucet-docker-release
+ # - op-proposer-docker-release
+ # - op-challenger-docker-release
+ # - op-dispute-mon-docker-release
+ # - op-conductor-docker-release
+ # - da-server-docker-release
+ # - op-ufm-docker-release
+ # - op-supervisor-docker-release
+ # - op-test-sequencer-docker-release
+ # - cannon-docker-release
+ # - op-dripper-docker-release
+ # - op-interop-mon-docker-release
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - cannon-prestate:
+ # filters:
+ # tags:
+ # only: /^op-program\/v.*/
+ # branches:
+ # ignore: /.*/
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # - publish-cannon-prestates:
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - slack
+ # - oplabs-network-optimism-io-bucket
+ # requires:
+ # - cannon-prestate
+ # filters:
+ # tags:
+ # only: /^op-program\/v.*/
+ # branches:
+ # ignore: /.*/
- scheduled-todo-issues:
- when:
- or:
- - equal: [build_four_hours, <<pipeline.schedule.name>>]
- - and:
- - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
- - equal: ["webhook",<< pipeline.trigger_source >>]
- jobs:
- - todo-issues:
- name: todo-issue-checks
- context:
- - slack
- - circleci-repo-readonly-authenticated-github-token
+ # scheduled-todo-issues:
+ # when:
+ # or:
+ # - equal: [build_four_hours, <<pipeline.schedule.name>>]
+ # - and:
+ # - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
+ # - equal: ["webhook",<< pipeline.trigger_source >>]
+ # jobs:
+ # - todo-issues:
+ # name: todo-issue-checks
+ # context:
+ # - slack
+ # - circleci-repo-readonly-authenticated-github-token
- develop-publish-contract-artifacts:
- when:
- or:
- - and:
- - or:
- - equal: ["develop", <<pipeline.git.branch>>]
- - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
- - equal: ["webhook",<< pipeline.trigger_source >>]
- - and:
- - equal: [true, <<pipeline.parameters.publish_contract_artifacts_dispatch>>]
- - equal: ["api",<< pipeline.trigger_source >>]
- jobs:
- - publish-contract-artifacts:
- context:
- - circleci-repo-readonly-authenticated-github-token
+ # develop-publish-contract-artifacts:
+ # when:
+ # or:
+ # - and:
+ # - or:
+ # - equal: ["develop", <<pipeline.git.branch>>]
+ # - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
+ # - equal: ["webhook",<< pipeline.trigger_source >>]
+ # - and:
+ # - equal: [true, <<pipeline.parameters.publish_contract_artifacts_dispatch>>]
+ # - equal: ["api",<< pipeline.trigger_source >>]
+ # jobs:
+ # - publish-contract-artifacts:
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
- develop-fault-proofs:
- when:
- or:
- - and:
- - or:
- - equal: ["develop", <<pipeline.git.branch>>]
- - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
- - equal: ["webhook",<< pipeline.trigger_source >>]
- - and:
- - equal: [true, <<pipeline.parameters.fault_proofs_dispatch>>]
- - equal: ["api",<< pipeline.trigger_source >>]
- jobs:
- - initialize:
- context:
- - circleci-repo-readonly-authenticated-github-token
- - cannon-prestate:
- context:
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- - cannon-stf-verify:
- context:
- - slack
- - circleci-repo-readonly-authenticated-github-token
- - contracts-bedrock-build:
- build_args: --deny-warnings --skip test
- context:
- - slack
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- - go-tests-with-fault-proof-deps:
- name: op-e2e-cannon-tests
- notify: true
- mentions: "@proofs-team"
- no_output_timeout: 90m
- test_timeout: 480m
- resource_class: ethereum-optimism/latitude-fps-1
- context:
- - slack
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - contracts-bedrock-build
- - cannon-prestate
- - publish-cannon-prestates:
- context:
- - slack
- - oplabs-network-optimism-io-bucket
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - cannon-prestate
- - op-e2e-cannon-tests
+ # develop-fault-proofs:
+ # when:
+ # or:
+ # - and:
+ # - or:
+ # - equal: ["develop", <<pipeline.git.branch>>]
+ # - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
+ # - equal: ["webhook",<< pipeline.trigger_source >>]
+ # - and:
+ # - equal: [true, <<pipeline.parameters.fault_proofs_dispatch>>]
+ # - equal: ["api",<< pipeline.trigger_source >>]
+ # jobs:
+ # - initialize:
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - cannon-prestate:
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # - cannon-stf-verify:
+ # context:
+ # - slack
+ # - circleci-repo-readonly-authenticated-github-token
+ # - contracts-bedrock-build:
+ # build_args: --deny-warnings --skip test
+ # context:
+ # - slack
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # - go-tests-with-fault-proof-deps:
+ # name: op-e2e-cannon-tests
+ # notify: true
+ # mentions: "@proofs-team"
+ # no_output_timeout: 90m
+ # test_timeout: 480m
+ # resource_class: ethereum-optimism/latitude-fps-1
+ # context:
+ # - slack
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - contracts-bedrock-build
+ # - cannon-prestate
+ # - publish-cannon-prestates:
+ # context:
+ # - slack
+ # - oplabs-network-optimism-io-bucket
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - cannon-prestate
+ # - op-e2e-cannon-tests
- develop-kontrol-tests:
- when:
- or:
- - and:
- - or:
- - equal: ["develop", <<pipeline.git.branch>>]
- - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
- - equal: ["webhook",<< pipeline.trigger_source >>]
- - and:
- - equal: [true, <<pipeline.parameters.kontrol_dispatch>>]
- - equal: ["api",<< pipeline.trigger_source >>]
- jobs:
- - kontrol-tests:
- context:
- - slack
- - runtimeverification
- - circleci-repo-readonly-authenticated-github-token
+ # develop-kontrol-tests:
+ # when:
+ # or:
+ # - and:
+ # - or:
+ # - equal: ["develop", <<pipeline.git.branch>>]
+ # - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
+ # - equal: ["webhook",<< pipeline.trigger_source >>]
+ # - and:
+ # - equal: [true, <<pipeline.parameters.kontrol_dispatch>>]
+ # - equal: ["api",<< pipeline.trigger_source >>]
+ # jobs:
+ # - kontrol-tests:
+ # context:
+ # - slack
+ # - runtimeverification
+ # - circleci-repo-readonly-authenticated-github-token
- scheduled-cannon-full-tests:
- when:
- or:
- - equal: [build_four_hours, <<pipeline.schedule.name>>]
- - equal: [true, << pipeline.parameters.cannon_full_test_dispatch >>]
- - and:
- - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
- - equal: ["webhook",<< pipeline.trigger_source >>]
- jobs:
- - initialize:
- context:
- - circleci-repo-readonly-authenticated-github-token
- - contracts-bedrock-build:
- build_args: --deny-warnings --skip test
- context:
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- - cannon-go-lint-and-test:
- requires:
- - contracts-bedrock-build
- skip_slow_tests: false
- no_output_timeout: 30m
- notify: true
- context:
- - slack
- - circleci-repo-readonly-authenticated-github-token
+ # scheduled-cannon-full-tests:
+ # when:
+ # or:
+ # - equal: [build_four_hours, <<pipeline.schedule.name>>]
+ # - equal: [true, << pipeline.parameters.cannon_full_test_dispatch >>]
+ # - and:
+ # - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
+ # - equal: ["webhook",<< pipeline.trigger_source >>]
+ # jobs:
+ # - initialize:
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - contracts-bedrock-build:
+ # build_args: --deny-warnings --skip test
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # - cannon-go-lint-and-test:
+ # requires:
+ # - contracts-bedrock-build
+ # skip_slow_tests: false
+ # no_output_timeout: 30m
+ # notify: true
+ # context:
+ # - slack
+ # - circleci-repo-readonly-authenticated-github-token
- scheduled-docker-publish:
- when:
- or:
- - equal: [build_daily, <<pipeline.schedule.name>>]
- # Trigger on manual triggers if explicitly requested
- - equal: [true, << pipeline.parameters.docker_publish_dispatch >>]
- - and:
- - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
- - equal: ["webhook",<< pipeline.trigger_source >>]
- jobs:
- - initialize:
- context:
- - circleci-repo-readonly-authenticated-github-token
- - docker-build:
- matrix:
- parameters:
- docker_name:
- - op-node
- - op-batcher
- - op-faucet
- - op-program
- - op-proposer
- - op-challenger
- - op-dispute-mon
- - op-conductor
- - op-supervisor
- - op-test-sequencer
- - cannon
- - op-dripper
- - op-interop-mon
- name: <<matrix.docker_name>>-docker-publish
- docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
- platforms: "linux/amd64,linux/arm64"
- publish: true
- context:
- - oplabs-gcr
- - slack
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- - check-cross-platform:
- matrix:
- parameters:
- op_component:
- - op-node
- - op-batcher
- - op-faucet
- - op-program
- - op-proposer
- - op-challenger
- - op-dispute-mon
- - op-conductor
- - op-supervisor
- - op-test-sequencer
- - cannon
- - op-dripper
- - op-interop-mon
- name: <<matrix.op_component>>-cross-platform
- requires:
- - <<matrix.op_component>>-docker-publish
- context:
- - circleci-repo-readonly-authenticated-github-token
+ # scheduled-docker-publish:
+ # when:
+ # or:
+ # - equal: [build_daily, <<pipeline.schedule.name>>]
+ # # Trigger on manual triggers if explicitly requested
+ # - equal: [true, << pipeline.parameters.docker_publish_dispatch >>]
+ # - and:
+ # - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
+ # - equal: ["webhook",<< pipeline.trigger_source >>]
+ # jobs:
+ # - initialize:
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - docker-build:
+ # matrix:
+ # parameters:
+ # docker_name:
+ # - op-node
+ # - op-batcher
+ # - op-faucet
+ # - op-program
+ # - op-proposer
+ # - op-challenger
+ # - op-dispute-mon
+ # - op-conductor
+ # - op-supervisor
+ # - op-test-sequencer
+ # - cannon
+ # - op-dripper
+ # - op-interop-mon
+ # name: <<matrix.docker_name>>-docker-publish
+ # docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
+ # platforms: "linux/amd64,linux/arm64"
+ # publish: true
+ # context:
+ # - oplabs-gcr
+ # - slack
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # - check-cross-platform:
+ # matrix:
+ # parameters:
+ # op_component:
+ # - op-node
+ # - op-batcher
+ # - op-faucet
+ # - op-program
+ # - op-proposer
+ # - op-challenger
+ # - op-dispute-mon
+ # - op-conductor
+ # - op-supervisor
+ # - op-test-sequencer
+ # - cannon
+ # - op-dripper
+ # - op-interop-mon
+ # name: <<matrix.op_component>>-cross-platform
+ # requires:
+ # - <<matrix.op_component>>-docker-publish
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
- scheduled-preimage-reproducibility:
- when:
- or:
- - equal: [build_daily, <<pipeline.schedule.name>>]
- # Trigger on manual triggers if explicitly requested
- - equal: [true, << pipeline.parameters.reproducibility_dispatch >>]
- - and:
- - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
- - equal: ["webhook",<< pipeline.trigger_source >>]
- jobs:
- - preimage-reproducibility:
- context:
- - slack
- - circleci-repo-readonly-authenticated-github-token
+ # scheduled-preimage-reproducibility:
+ # when:
+ # or:
+ # - equal: [build_daily, <<pipeline.schedule.name>>]
+ # # Trigger on manual triggers if explicitly requested
+ # - equal: [true, << pipeline.parameters.reproducibility_dispatch >>]
+ # - and:
+ # - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
+ # - equal: ["webhook",<< pipeline.trigger_source >>]
+ # jobs:
+ # - preimage-reproducibility:
+ # context:
+ # - slack
+ # - circleci-repo-readonly-authenticated-github-token
- scheduled-stale-check:
- when:
- or:
- - equal: [build_daily, <<pipeline.schedule.name>>]
- # Trigger on manual triggers if explicitly requested
- - equal: [true, << pipeline.parameters.stale_check_dispatch >>]
- - and:
- - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
- - equal: ["webhook",<< pipeline.trigger_source >>]
- jobs:
- - stale-check:
- context:
- - circleci-repo-optimism
+ # scheduled-stale-check:
+ # when:
+ # or:
+ # - equal: [build_daily, <<pipeline.schedule.name>>]
+ # # Trigger on manual triggers if explicitly requested
+ # - equal: [true, << pipeline.parameters.stale_check_dispatch >>]
+ # - and:
+ # - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
+ # - equal: ["webhook",<< pipeline.trigger_source >>]
+ # jobs:
+ # - stale-check:
+ # context:
+ # - circleci-repo-optimism
- # Acceptance tests (post-merge to develop)
- acceptance-tests:
- when:
- or:
- - and:
- - or:
- - equal: ["develop", <<pipeline.git.branch>>]
- - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
- - equal: ["webhook",<< pipeline.trigger_source >>]
- - and:
- - equal: [true, <<pipeline.parameters.acceptance_tests_dispatch>>]
- - equal: ["api",<< pipeline.trigger_source >>]
- jobs:
- - initialize:
- context:
- - circleci-repo-readonly-authenticated-github-token
- - contracts-bedrock-build: # needed for sysgo tests
- context:
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- - cannon-prestate-quick: # needed for sysgo tests
- context:
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- # IN-PROCESS (base)
- - op-acceptance-tests:
- # Acceptance Testing params
- name: memory-base
- gate: base
- # CircleCI params
- no_output_timeout: 10m
- context:
- - circleci-repo-readonly-authenticated-github-token
- - discord
- requires:
- - contracts-bedrock-build
- - cannon-prestate-quick
- # KURTOSIS (Simple)
- - op-acceptance-tests:
- # Acceptance Testing params
- name: kurtosis-simple
- devnet: simple
- gate: base
- # CircleCI params
- no_output_timeout: 30m
- context:
- - circleci-repo-readonly-authenticated-github-token
- - discord
- requires:
- - initialize
- # KURTOSIS (Isthmus)
- - op-acceptance-tests:
- # Acceptance Testing params
- name: kurtosis-isthmus
- devnet: isthmus
- gate: isthmus
- # CircleCI params
- no_output_timeout: 30m
- context:
- - circleci-repo-readonly-authenticated-github-token
- - discord
- requires:
- - initialize
- # KURTOSIS (Interop)
- - op-acceptance-tests:
- # Acceptance Testing params
- name: kurtosis-interop
- devnet: interop
- gate: interop
- # CircleCI params
- no_output_timeout: 30m
- context:
- - circleci-repo-readonly-authenticated-github-token
- - discord
- requires:
- - initialize
- # Generate flaky test report
- - generate-flaky-report:
- name: generate-flaky-tests-report
- context:
- - circleci-repo-readonly-authenticated-github-token
- - circleci-api-token
+ # # Acceptance tests (post-merge to develop)
+ # acceptance-tests:
+ # when:
+ # or:
+ # - and:
+ # - or:
+ # - equal: ["develop", <<pipeline.git.branch>>]
+ # - matches: { pattern: "^proposal/.*", value: <<pipeline.git.branch>> }
+ # - equal: ["webhook",<< pipeline.trigger_source >>]
+ # - and:
+ # - equal: [true, <<pipeline.parameters.acceptance_tests_dispatch>>]
+ # - equal: ["api",<< pipeline.trigger_source >>]
+ # jobs:
+ # - initialize:
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - contracts-bedrock-build: # needed for sysgo tests
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # - cannon-prestate-quick: # needed for sysgo tests
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # # IN-PROCESS (base)
+ # - op-acceptance-tests:
+ # # Acceptance Testing params
+ # name: memory-base
+ # gate: base
+ # # CircleCI params
+ # no_output_timeout: 10m
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - discord
+ # requires:
+ # - contracts-bedrock-build
+ # - cannon-prestate-quick
+ # # KURTOSIS (Simple)
+ # - op-acceptance-tests:
+ # # Acceptance Testing params
+ # name: kurtosis-simple
+ # devnet: simple
+ # gate: base
+ # # CircleCI params
+ # no_output_timeout: 30m
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - discord
+ # requires:
+ # - initialize
+ # # KURTOSIS (Isthmus)
+ # - op-acceptance-tests:
+ # # Acceptance Testing params
+ # name: kurtosis-isthmus
+ # devnet: isthmus
+ # gate: isthmus
+ # # CircleCI params
+ # no_output_timeout: 30m
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - discord
+ # requires:
+ # - initialize
+ # # KURTOSIS (Interop)
+ # - op-acceptance-tests:
+ # # Acceptance Testing params
+ # name: kurtosis-interop
+ # devnet: interop
+ # gate: interop
+ # # CircleCI params
+ # no_output_timeout: 30m
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - discord
+ # requires:
+ # - initialize
+ # # Generate flaky test report
+ # - generate-flaky-report:
+ # name: generate-flaky-tests-report
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - circleci-api-token
- # Acceptance tests (pre-merge to develop)
- acceptance-tests-pr:
- when:
- not:
- equal: [<< pipeline.git.branch >>, "develop"]
- jobs:
- - initialize:
- context:
- - circleci-repo-readonly-authenticated-github-token
- - contracts-bedrock-build: # needed for sysgo tests
- context:
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- - cannon-prestate-quick: # needed for sysgo tests
- context:
- - circleci-repo-readonly-authenticated-github-token
- requires:
- - initialize
- # IN-PROCESS (base)
- - op-acceptance-tests:
- # Acceptance Testing params
- name: memory-base
- gate: base
- # CircleCI params
- no_output_timeout: 10m
- context:
- - circleci-repo-readonly-authenticated-github-token
- - discord
- requires:
- - contracts-bedrock-build
- - cannon-prestate-quick
- # KURTOSIS (Simple)
- - op-acceptance-tests:
- # Acceptance Testing params
- name: kurtosis-simple
- devnet: simple
- gate: base
- # CircleCI params
- no_output_timeout: 30m
- context:
- - circleci-repo-readonly-authenticated-github-token
- - discord
- requires:
- - initialize
- # KURTOSIS (Isthmus)
- - op-acceptance-tests:
- # Acceptance Testing params
- name: kurtosis-isthmus
- devnet: isthmus
- gate: isthmus
- # CircleCI params
- no_output_timeout: 30m
- context:
- - circleci-repo-readonly-authenticated-github-token
- - discord
- requires:
- - initialize
- # KURTOSIS (Interop)
- - op-acceptance-tests:
- # Acceptance Testing params
- name: kurtosis-interop
- devnet: interop
- gate: interop
- # CircleCI params
- no_output_timeout: 30m
- context:
- - circleci-repo-readonly-authenticated-github-token
- - discord
- requires:
- - initialize
- # Generate flaky test report
- - generate-flaky-report:
- name: generate-flaky-tests-report
- context:
- - circleci-repo-readonly-authenticated-github-token
- - circleci-api-token
+ # # Acceptance tests (pre-merge to develop)
+ # acceptance-tests-pr:
+ # when:
+ # not:
+ # equal: [<< pipeline.git.branch >>, "develop"]
+ # jobs:
+ # - initialize:
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - contracts-bedrock-build: # needed for sysgo tests
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # - cannon-prestate-quick: # needed for sysgo tests
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # requires:
+ # - initialize
+ # # IN-PROCESS (base)
+ # - op-acceptance-tests:
+ # # Acceptance Testing params
+ # name: memory-base
+ # gate: base
+ # # CircleCI params
+ # no_output_timeout: 10m
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - discord
+ # requires:
+ # - contracts-bedrock-build
+ # - cannon-prestate-quick
+ # # KURTOSIS (Simple)
+ # - op-acceptance-tests:
+ # # Acceptance Testing params
+ # name: kurtosis-simple
+ # devnet: simple
+ # gate: base
+ # # CircleCI params
+ # no_output_timeout: 30m
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - discord
+ # requires:
+ # - initialize
+ # # KURTOSIS (Isthmus)
+ # - op-acceptance-tests:
+ # # Acceptance Testing params
+ # name: kurtosis-isthmus
+ # devnet: isthmus
+ # gate: isthmus
+ # # CircleCI params
+ # no_output_timeout: 30m
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - discord
+ # requires:
+ # - initialize
+ # # KURTOSIS (Interop)
+ # - op-acceptance-tests:
+ # # Acceptance Testing params
+ # name: kurtosis-interop
+ # devnet: interop
+ # gate: interop
+ # # CircleCI params
+ # no_output_timeout: 30m
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - discord
+ # requires:
+ # - initialize
+ # # Generate flaky test report
+ # - generate-flaky-report:
+ # name: generate-flaky-tests-report
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - circleci-api-token
- close-issue-workflow:
- when:
- and:
- - equal: [<< pipeline.trigger_source >>, "api"]
- - equal: [<< pipeline.parameters.github-event-type >>, "pull_request"]
- - equal: [<< pipeline.parameters.github-event-action >>, "labeled"]
- jobs:
- - close-issue:
- label_name: "auto-close-trivial-contribution"
- message: "Thank you for your interest in contributing!
- At this time, we are not accepting contributions that primarily fix spelling, stylistic, or grammatical errors in documentation, code, or elsewhere.
- Please check our [contribution guidelines](https://github.com/ethereum-optimism/optimism/blob/develop/CONTRIBUTING.md#contributions-related-to-spelling-and-grammar) for more information.
- This issue will be closed now."
- context:
- - circleci-repo-optimism
+ # close-issue-workflow:
+ # when:
+ # and:
+ # - equal: [<< pipeline.trigger_source >>, "api"]
+ # - equal: [<< pipeline.parameters.github-event-type >>, "pull_request"]
+ # - equal: [<< pipeline.parameters.github-event-action >>, "labeled"]
+ # jobs:
+ # - close-issue:
+ # label_name: "auto-close-trivial-contribution"
+ # message: "Thank you for your interest in contributing!
+ # At this time, we are not accepting contributions that primarily fix spelling, stylistic, or grammatical errors in documentation, code, or elsewhere.
+ # Please check our [contribution guidelines](https://github.com/ethereum-optimism/optimism/blob/develop/CONTRIBUTING.md#contributions-related-to-spelling-and-grammar) for more information.
+ # This issue will be closed now."
+ # context:
+ # - circleci-repo-optimism
- devnet-metrics-collect:
- when:
- or:
- - equal: [<< pipeline.trigger_source >>, "webhook"]
- - and:
- - equal: [true, << pipeline.parameters.devnet-metrics-collect >>]
- - equal: [<< pipeline.trigger_source >>, "api"]
- jobs:
- - devnet-metrics-collect-authorship:
- context:
- - circleci-repo-readonly-authenticated-github-token
- - oplabs-tools-data-public-metrics-bucket
+ # devnet-metrics-collect:
+ # when:
+ # or:
+ # - equal: [<< pipeline.trigger_source >>, "webhook"]
+ # - and:
+ # - equal: [true, << pipeline.parameters.devnet-metrics-collect >>]
+ # - equal: [<< pipeline.trigger_source >>, "api"]
+ # jobs:
+ # - devnet-metrics-collect-authorship:
+ # context:
+ # - circleci-repo-readonly-authenticated-github-token
+ # - oplabs-tools-data-public-metrics-bucket
diff --git official optimism/.github/workflows/publish-op-challenger.yml SWC optimism/.github/workflows/publish-op-challenger.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e7bf2f6a000b0e138bb17d421a002f0fea1d7379
--- /dev/null
+++ SWC optimism/.github/workflows/publish-op-challenger.yml
@@ -0,0 +1,71 @@
+# This workflow will publish a github release for op-challenger
+
+name: Publish
+run-name: ${{ github.actor }} is publishing an op-challenger release 🚀
+on:
+ push:
+ tags:
+ - 'op-challenger/v*'
+
+# Always wait for previous release to finish before releasing again
+concurrency: ${{ github.workflow }}-${{ github.ref }}
+
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest]
+ arch: [amd64, arm64]
+ exclude:
+ - os: ubuntu-latest
+ arch: arm64
+ env:
+ BUILD_DIR: ${{ github.ref_name }}
+ BIN_DIR: ${{ github.ref_name }}/build/bin
+ steps:
+ - name: Set file name
+ run: |
+ # replace "op-challenger/v*" with "op-challenger.v*" since `actions/upload-artifact@v4` doesn't support slashes in file names
+ FILE_NAME="op-challenger.${GITHUB_REF_NAME:14}.${{ matrix.os == 'ubuntu-latest' && 'linux' || 'darwin' }}-${{ matrix.arch }}.tar.gz"
+ echo "FILE_NAME=$FILE_NAME" >> $GITHUB_ENV
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup go
+ uses: actions/setup-go@v5
+ with:
+ go-version: '1.22.7'
+
+ - uses: extractions/setup-just@v2
+
+ - name: Build
+ run: |
+ TARGETOS=${{ matrix.os == 'ubuntu-latest' && 'linux' || 'darwin' }} TARGETARCH=${{ matrix.arch }} make op-challenger
+ mkdir -p ${{ env.BIN_DIR }}
+ mv op-challenger/bin/op-challenger ${{ env.BIN_DIR }}/
+ tar -czvf ${{ env.FILE_NAME }} ${{ env.BUILD_DIR }}
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ env.FILE_NAME }}
+ path: ${{ env.FILE_NAME }}
+
+ release:
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download artifact
+ uses: actions/download-artifact@v4
+
+ - name: Create release
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: ${{ github.ref }}
+ name: Release ${{ github.ref_name }}
+ files: |
+ **/*
+ fail_on_unmatched_files: true
+ generate_release_notes: true
diff --git official optimism/.github/workflows/publish-op-node.yml SWC optimism/.github/workflows/publish-op-node.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6b0a2e9d91e6cd8c9a5b2f4e73fcc0017f11fba2
--- /dev/null
+++ SWC optimism/.github/workflows/publish-op-node.yml
@@ -0,0 +1,71 @@
+# This workflow will publish a github release for op-node
+
+name: Publish
+run-name: ${{ github.actor }} is publishing an op-node release 🚀
+on:
+ push:
+ tags:
+ - 'op-node/v*'
+
+# Always wait for previous release to finish before releasing again
+concurrency: ${{ github.workflow }}-${{ github.ref }}
+
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest]
+ arch: [amd64, arm64]
+ exclude:
+ - os: ubuntu-latest
+ arch: arm64
+ env:
+ BUILD_DIR: ${{ github.ref_name }}
+ BIN_DIR: ${{ github.ref_name }}/build/bin
+ steps:
+ - name: Set file name
+ run: |
+ # replace "op-node/v*" with "op-node.v*" since `actions/upload-artifact@v4` doesn't support slashes in file names
+ FILE_NAME="op-node.${GITHUB_REF_NAME:8}.${{ matrix.os == 'ubuntu-latest' && 'linux' || 'darwin' }}-${{ matrix.arch }}.tar.gz"
+ echo "FILE_NAME=$FILE_NAME" >> $GITHUB_ENV
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup go
+ uses: actions/setup-go@v5
+ with:
+ go-version: '1.22.7'
+
+ - uses: extractions/setup-just@v2
+
+ - name: Build
+ run: |
+ TARGETOS=${{ matrix.os == 'ubuntu-latest' && 'linux' || 'darwin' }} TARGETARCH=${{ matrix.arch }} make op-node
+ mkdir -p ${{ env.BIN_DIR }}
+ mv op-node/bin/op-node ${{ env.BIN_DIR }}/
+ tar -czvf ${{ env.FILE_NAME }} ${{ env.BUILD_DIR }}
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ env.FILE_NAME }}
+ path: ${{ env.FILE_NAME }}
+
+ release:
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download artifact
+ uses: actions/download-artifact@v4
+
+ - name: Create release
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: ${{ github.ref }}
+ name: Release ${{ github.ref_name }}
+ files: |
+ **/*
+ fail_on_unmatched_files: true
+ generate_release_notes: true
diff --git official optimism/.mise-tasks/dev-test.sh SWC optimism/.mise-tasks/dev-test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0445739d61852784a24e4050d695f2be82a457a0
--- /dev/null
+++ SWC optimism/.mise-tasks/dev-test.sh
@@ -0,0 +1,100 @@
+#!/usr/bin/env bash
+
+#MISE description="Developers' local tests"
+#MISE alias="dt"
+
+set -e
+SECONDS=0
+
+error_handler() {
+ echo "Execution time: ${SECONDS} seconds"
+ exit 1
+}
+
+trap 'error_handler' ERR
+
+# Environment tests
+
+forge --version
+
+for var in SEPOLIA_RPC_URL MAINNET_RPC_URL; do
+ if [ -z "${!var}" ]; then
+ echo "Error: $var is not set."
+ exit 1
+ fi
+done
+
+STATUS=$(kurtosis engine status)
+if echo "$STATUS" | grep -q "1.4.3"; then
+ echo "Kurtosis engine is running."
+else
+ echo "The Kurtosis engine is not running, or there is a version mismatch."
+ exit 1
+fi
+
+# Runs semgrep tests on the entire monorepo
+
+just semgrep
+just semgrep-test
+
+# Solidity
+
+cd packages/contracts-bedrock
+just lint-check
+just pre-pr
+just test
+
+# Go
+
+cd ../..
+make lint-go
+make build-go
+
+cd op-program && make op-program-client && cd ..
+cd cannon && make elf && cd ..
+cd op-e2e && make pre-test && cd ..
+
+make devnet-allocs
+
+export ENABLE_KURTOSIS=true
+export OP_E2E_CANNON_ENABLED="false"
+export OP_E2E_SKIP_SLOW_TEST=true
+export OP_E2E_USE_HTTP=true
+export ENABLE_ANVIL=true
+
+# Note: not all packages are tested.
+# For example the test `TestFinalization` in `op-alt-da` package fails even in upstream.
+packages=(
+ op-batcher
+ op-chain-ops
+ op-node
+ op-proposer
+ op-challenger
+ op-dispute-mon
+ op-conductor
+ op-program
+ op-service
+ op-supervisor
+ op-deployer
+ op-e2e/system
+ op-e2e/e2eutils
+ op-e2e/opgeth
+ op-e2e/interop
+ op-e2e/actions
+ op-e2e/faultproofs
+ op-e2e/l2blob
+ op-e2e/inbox
+ op-e2e/sgt
+ packages/contracts-bedrock/scripts/checks
+)
+formatted_packages=""
+for package in "${packages[@]}"; do
+ formatted_packages="$formatted_packages ./$package/..."
+done
+
+gotestsum --no-summary=skipped,output \
+ --packages="$formatted_packages" \
+ --format=short-verbose \
+ --rerun-fails=2
+
+echo "Execution time: $((SECONDS / 60)) minute(s) and $((SECONDS % 60)) second(s)"
\ No newline at end of file
diff --git official optimism/.semgrep/rules/sol-rules.yaml SWC optimism/.semgrep/rules/sol-rules.yaml
index a65b0cc792f316fdf7630170e7f60508095bb072..a7c38af01ce9570b6e302d59aba698f31a0b935b 100644
--- official optimism/.semgrep/rules/sol-rules.yaml
+++ SWC optimism/.semgrep/rules/sol-rules.yaml
@@ -323,6 +323,7 @@ - packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol
- packages/contracts-bedrock/src/L2/FeeVault.sol
- packages/contracts-bedrock/src/L2/OptimismMintableERC721.sol
- packages/contracts-bedrock/src/L2/OptimismMintableERC721Factory.sol
+ - packages/contracts-bedrock/src/L2/SoulGasToken.sol
- packages/contracts-bedrock/src/cannon/MIPS64.sol
- packages/contracts-bedrock/src/cannon/PreimageOracle.sol
- packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol
@@ -335,7 +336,6 @@ - packages/contracts-bedrock/src/governance/MintManager.sol
- packages/contracts-bedrock/src/periphery/TransferOnion.sol
- packages/contracts-bedrock/src/periphery/faucet/Faucet.sol
- packages/contracts-bedrock/src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol
- - packages/contracts-bedrock/src/safe/DeputyGuardianModule.sol
- packages/contracts-bedrock/src/safe/DeputyPauseModule.sol
- packages/contracts-bedrock/src/safe/LivenessGuard.sol
- packages/contracts-bedrock/src/safe/LivenessModule.sol
diff --git official optimism/devnet-sdk/system/txprocessor.go SWC optimism/devnet-sdk/system/txprocessor.go
index 1279aadffc1b6e289c4a6d57cc5bb6a0abcf95e4..0d5f9c40a5feabc18a42cb6b8d8044025feb86e3 100644
--- official optimism/devnet-sdk/system/txprocessor.go
+++ SWC optimism/devnet-sdk/system/txprocessor.go
@@ -45,7 +45,7 @@
var signer types.Signer
switch tx.Type() {
case types.SetCodeTxType:
- signer = types.NewIsthmusSigner(p.chainID)
+ signer = types.NewIsthmusSigner(p.chainID, false)
case types.DynamicFeeTxType:
signer = types.NewLondonSigner(p.chainID)
case types.AccessListTxType:
diff --git official optimism/devnet-sdk/system/wallet.go SWC optimism/devnet-sdk/system/wallet.go
index 147aea26d470f16bde1c627e79b6cf8c7737faa3..1851fd3893a98320b21b7a60fd7d2c18777eea2f 100644
--- official optimism/devnet-sdk/system/wallet.go
+++ SWC optimism/devnet-sdk/system/wallet.go
@@ -284,7 +284,7 @@
var signer coreTypes.Signer
switch tx.Type() {
case coreTypes.SetCodeTxType:
- signer = coreTypes.NewIsthmusSigner(w.chain.ID())
+ signer = coreTypes.NewIsthmusSigner(w.chain.ID(), false)
case coreTypes.DynamicFeeTxType:
signer = coreTypes.NewLondonSigner(w.chain.ID())
case coreTypes.AccessListTxType:
diff --git official optimism/go.mod SWC optimism/go.mod
index d2df6e7cf5fdb2c6b0eda2dd75717fd2d567490f..9c99ebaf979796ab050da3abe37b59b5bc33bfc7 100644
--- official optimism/go.mod
+++ SWC optimism/go.mod
@@ -22,6 +22,7 @@ github.com/docker/go-connections v0.5.0
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum-optimism/superchain-registry/validation v0.0.0-20250603144016-9c45ca7d4508
github.com/ethereum/go-ethereum v1.15.11
+ github.com/ethstorage/da-server v0.0.0-20241224013916-2bd2256b6a70
github.com/fatih/color v1.18.0
github.com/fsnotify/fsnotify v1.9.0
github.com/go-task/slim-sprig/v3 v3.0.0
@@ -304,9 +305,9 @@ lukechampine.com/blake3 v1.3.0 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)
-replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101511.1-dev.1.0.20250710181308-c6e05723600e
+replace github.com/ethereum/go-ethereum => github.com/Quarkchain/op-geth v0.0.0-20250728040603-bb068d7c4868
-//replace github.com/ethereum/go-ethereum => ../op-geth
+// replace github.com/ethereum/go-ethereum => ../op-geth
// replace github.com/ethereum-optimism/superchain-registry/superchain => ../superchain-registry/superchain
diff --git official optimism/go.sum SWC optimism/go.sum
index e078da3a917b57791082766d2df1c00437b273e3..21c9eaccb6be5e5cd1c591238fa68f4a0c0fa393 100644
--- official optimism/go.sum
+++ SWC optimism/go.sum
@@ -37,6 +37,8 @@ github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/Quarkchain/op-geth v0.0.0-20250728040603-bb068d7c4868 h1:DtNvO7rj/pf3y2L1P1BKqDj9U4jVZ96E4WMSDnyA3MI=
+github.com/Quarkchain/op-geth v0.0.0-20250728040603-bb068d7c4868/go.mod h1:SkytozVEPtnUeBlquwl0Qv5JKvrN/Y5aqh+VkQo/EOI=
github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
@@ -228,14 +230,14 @@ github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo=
github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
-github.com/ethereum-optimism/op-geth v1.101511.1-dev.1.0.20250710181308-c6e05723600e h1:Ur5vjH2RmYqspDBIZH4RymNB6viHFheZkvvHt9W3spQ=
-github.com/ethereum-optimism/op-geth v1.101511.1-dev.1.0.20250710181308-c6e05723600e/go.mod h1:SkytozVEPtnUeBlquwl0Qv5JKvrN/Y5aqh+VkQo/EOI=
github.com/ethereum-optimism/superchain-registry/validation v0.0.0-20250603144016-9c45ca7d4508 h1:A/3QVFt+Aa9ozpPVXxUTLui8honBjSusAaiCVRbafgs=
github.com/ethereum-optimism/superchain-registry/validation v0.0.0-20250603144016-9c45ca7d4508/go.mod h1:NZ816PzLU1TLv1RdAvYAb6KWOj4Zm5aInT0YpDVml2Y=
github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w=
github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E=
github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
+github.com/ethstorage/da-server v0.0.0-20241224013916-2bd2256b6a70 h1:g3H1N+WC/nDFL1H+rpKwsSKT0cCWu1fTHjKDqEMyuq0=
+github.com/ethstorage/da-server v0.0.0-20241224013916-2bd2256b6a70/go.mod h1:4VnU8W5POGWvaUKd+SDns3cooFGU5wWpIu9M1KhEe1s=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
diff --git official optimism/kurtosis-devnet/optimism-package-trampoline/kurtosis.yml SWC optimism/kurtosis-devnet/optimism-package-trampoline/kurtosis.yml
index 06e9db8afd93d243f1a50e36ebe254b20846c6d8..58f2cc557a9f554f3ad178f520e17666fc11e42e 100644
--- official optimism/kurtosis-devnet/optimism-package-trampoline/kurtosis.yml
+++ SWC optimism/kurtosis-devnet/optimism-package-trampoline/kurtosis.yml
@@ -2,7 +2,7 @@ name: github.com/ethereum-optimism/optimism/kurtosis-devnet/optimism-package-trampoline
description: |-
A trampoline package for optimism-package. This one is reproducible, due to the replace directives below.
replace:
- github.com/ethpandaops/optimism-package: github.com/ethpandaops/optimism-package@89e0b8cacab9f7e9f74d53b72d4870092825d577
+ github.com/QuarkChain/optimism-package: github.com/QuarkChain/optimism-package@9553f5f6a70068139d1709b77665314c5ebbb78e
github.com/ethpandaops/ethereum-package: github.com/ethpandaops/ethereum-package@83830d44823767af65eda7dfe6b26c87c536c4cf
github.com/kurtosis-tech/prometheus-package: github.com/kurtosis-tech/prometheus-package@637c9dea933be18e47f96cadc0d9bb0e3a5aa9d6 # v1.0.0
github.com/kurtosis-tech/postgres-package: github.com/kurtosis-tech/postgres-package@9cbdde2c55e8d1656deb87821465a2ad244d8b33 # v1.0.0
diff --git official optimism/kurtosis-devnet/optimism-package-trampoline/main.star SWC optimism/kurtosis-devnet/optimism-package-trampoline/main.star
index d1b2d34b0331ff62fd68ac85443bc21824454ab5..626771cda5d112e1b57923dc5968893579bad0d2 100644
--- official optimism/kurtosis-devnet/optimism-package-trampoline/main.star
+++ SWC optimism/kurtosis-devnet/optimism-package-trampoline/main.star
@@ -1,4 +1,4 @@
-optimism_package = import_module("github.com/ethpandaops/optimism-package/main.star")
+optimism_package = import_module("github.com/QuarkChain/optimism-package/main.star")
def run(plan, args):
# just delegate to optimism-package
diff --git official optimism/kurtosis-devnet/simple.yaml SWC optimism/kurtosis-devnet/simple.yaml
index 456448eeb0101fd0c72a704c5d1db78654a2215c..041553a780c86b91bdaf091910df4b005bd98c68 100644
--- official optimism/kurtosis-devnet/simple.yaml
+++ SWC optimism/kurtosis-devnet/simple.yaml
@@ -22,6 +22,7 @@ max_mem: 0
cl:
type: op-node
image: {{ localDockerImage "op-node" }}
+ is_qkc: true
log_level: ""
extra_env_vars: {}
extra_labels: {}
@@ -65,6 +66,10 @@ l1_artifacts_locator: {{ localContractArtifacts "l1" }}
l2_artifacts_locator: {{ localContractArtifacts "l2" }}
overrides:
faultGameAbsolutePrestate: {{ localPrestate.Hashes.prestate_mt64 }}
+ deploySoulGasToken: true
+ soulGasTokenTimeOffset: "0x0"
+ isSoulBackedByNative: true
+ l2GenesisBlobTimeOffset: "0x0"
global_log_level: "info"
global_node_selectors: {}
global_tolerations: []
diff --git official optimism/op-batcher/batcher/driver.go SWC optimism/op-batcher/batcher/driver.go
index 4630df4a6f3bdd88aaa6e9a1f71ec43323b95150..308c1abbc73f9a2aa7495578afd2d0e15d2fb34e 100644
--- official optimism/op-batcher/batcher/driver.go
+++ SWC optimism/op-batcher/batcher/driver.go
@@ -32,8 +32,9 @@ "github.com/ethereum-optimism/optimism/op-service/txmgr"
)
var (
- ErrBatcherNotRunning = errors.New("batcher is not running")
- emptyTxData = txData{
+ ErrBatcherNotRunning = errors.New("batcher is not running")
+ ErrInboxTransactionFailed = errors.New("inbox transaction failed")
+ emptyTxData = txData{
frames: []frameData{
{
data: []byte{},
@@ -71,6 +72,7 @@
type L1Client interface {
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)
+ CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
}
type L2Client interface {
@@ -985,6 +987,10 @@ }
candidate = l.calldataTxCandidate(txdata.CallData())
}
+ if *candidate.To != l.RollupConfig.BatchInboxAddress {
+ return fmt.Errorf("candidate.To is not inbox")
+ }
+
l.sendTx(txdata, false, candidate, queue, receiptsCh)
return nil
}
@@ -996,12 +1002,15 @@
// sendTx uses the txmgr queue to send the given transaction candidate after setting its
// gaslimit. It will block if the txmgr queue has reached its MaxPendingTransactions limit.
func (l *BatchSubmitter) sendTx(txdata txData, isCancel bool, candidate *txmgr.TxCandidate, queue TxSender[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) {
- floorDataGas, err := core.FloorDataGas(candidate.TxData)
- if err != nil {
- // We log instead of return an error here because the txmgr will do its own gas estimation.
- l.Log.Warn("Failed to calculate floor data gas", "err", err)
- } else {
- candidate.GasLimit = floorDataGas
+ // Leave GasLimit unset when inbox is contract so that later on `EstimateGas` will be called
+ if !l.RollupConfig.UseInboxContract() {
+ floorDataGas, err := core.FloorDataGas(candidate.TxData)
+ if err != nil {
+ // We log instead of return an error here because the txmgr will do its own gas estimation.
+ l.Log.Warn("Failed to calculate floor data gas", "err", err)
+ } else {
+ candidate.GasLimit = floorDataGas
+ }
}
queue.Send(txRef{id: txdata.ID(), isCancel: isCancel, isBlob: txdata.asBlob}, *candidate, receiptsCh)
@@ -1036,6 +1045,12 @@ // Record TX Status
if r.Err != nil {
l.recordFailedTx(r.ID.id, r.Err)
} else if r.Receipt != nil {
+ // check tx status
+ if l.RollupConfig.UseInboxContract() && r.Receipt.Status == types.ReceiptStatusFailed {
+ l.recordFailedTx(r.ID.id, ErrInboxTransactionFailed)
+ return
+ }
+
l.recordConfirmedTx(r.ID.id, r.Receipt)
}
// Both r.Err and r.Receipt can be nil, in which case we do nothing.
@@ -1053,6 +1068,7 @@
func (l *BatchSubmitter) recordFailedTx(id txID, err error) {
l.channelMgrMutex.Lock()
defer l.channelMgrMutex.Unlock()
+
l.Log.Warn("Transaction failed to send", logFields(id, err)...)
l.channelMgr.TxFailed(id)
}
diff --git official optimism/op-chain-ops/cmd/check-derivation/main.go SWC optimism/op-chain-ops/cmd/check-derivation/main.go
index 026e821c01effaf7d4764c44636590b7a836927b..6ce6a3ce9801ca1d5ac8b8bebcdf9da5aaebb52c 100644
--- official optimism/op-chain-ops/cmd/check-derivation/main.go
+++ SWC optimism/op-chain-ops/cmd/check-derivation/main.go
@@ -302,7 +302,7 @@ }
tx := types.NewTx(txData)
- signer := types.NewIsthmusSigner(chainId)
+ signer := types.NewIsthmusSigner(chainId, false)
if !protected {
if txType == types.LegacyTxType {
signer = types.HomesteadSigner{}
diff --git official optimism/op-chain-ops/cmd/check-ecotone/main.go SWC optimism/op-chain-ops/cmd/check-ecotone/main.go
index 5e18e800a04dee3227bb28be0ad4845b14b08445..12f701c9c2146ce6f7833947bf9fb227a8dfe0ca 100644
--- official optimism/op-chain-ops/cmd/check-ecotone/main.go
+++ SWC optimism/op-chain-ops/cmd/check-ecotone/main.go
@@ -786,7 +786,7 @@ Value: big.NewInt(3 * params.GWei),
Data: []byte("hello"),
AccessList: nil,
}
- tx, err := types.SignNewTx(env.key, types.NewIsthmusSigner(txData.ChainID), txData)
+ tx, err := types.SignNewTx(env.key, types.NewIsthmusSigner(txData.ChainID, false), txData)
if err != nil {
return fmt.Errorf("failed to sign test tx: %w", err)
}
diff --git official optimism/op-chain-ops/cmd/check-fjord/checks/checks.go SWC optimism/op-chain-ops/cmd/check-fjord/checks/checks.go
index a7063bbde9436164e6bf34267d48dd7d192c1f9e..6220067cf57225c89cf81381d1c6fab968f0309b 100644
--- official optimism/op-chain-ops/cmd/check-fjord/checks/checks.go
+++ SWC optimism/op-chain-ops/cmd/check-fjord/checks/checks.go
@@ -283,7 +283,8 @@ costFunc := types.NewL1CostFuncFjord(
l1BaseFee,
blobBaseFee,
new(big.Int).SetUint64(uint64(baseFeeScalar)),
- new(big.Int).SetUint64(uint64(blobBaseFeeScalar)))
+ new(big.Int).SetUint64(uint64(blobBaseFeeScalar)),
+ big.NewInt(1), big.NewInt(1))
fee, _ := costFunc(types.RollupCostData{FastLzSize: fastLzSize})
return fee, nil
diff --git official optimism/op-chain-ops/genesis/config.go SWC optimism/op-chain-ops/genesis/config.go
index f3e2052cfa3f99780436522625513383d86431c4..acedd55219e164fc6ad5f59020d93485e78104e2 100644
--- official optimism/op-chain-ops/genesis/config.go
+++ SWC optimism/op-chain-ops/genesis/config.go
@@ -377,6 +377,10 @@ // When Cancun activates. Relative to L1 genesis.
L1CancunTimeOffset *hexutil.Uint64 `json:"l1CancunTimeOffset,omitempty"`
// When Prague activates. Relative to L1 genesis.
L1PragueTimeOffset *hexutil.Uint64 `json:"l1PragueTimeOffset,omitempty"`
+
+ // L2GenesisBlobTimeOffset is the number of seconds after genesis block that the L2Blob hard fork activates.
+ // Set it to 0 to activate at genesis. Nil to disable L2Blob.
+ L2GenesisBlobTimeOffset *hexutil.Uint64 `json:"l2GenesisBlobTimeOffset,omitempty"`
}
var _ ConfigChecker = (*UpgradeScheduleDeployConfig)(nil)
@@ -518,6 +522,10 @@ }
func (d *UpgradeScheduleDeployConfig) InteropTime(genesisTime uint64) *uint64 {
return offsetToUpgradeTime(d.L2GenesisInteropTimeOffset, genesisTime)
+}
+
+func (d *UpgradeScheduleDeployConfig) L2BlobTime(genesisTime uint64) *uint64 {
+ return offsetToUpgradeTime(d.L2GenesisBlobTimeOffset, genesisTime)
}
func (d *UpgradeScheduleDeployConfig) AllocMode(genesisTime uint64) L2AllocsMode {
@@ -718,6 +726,9 @@ EIP1559DeployConfig
UpgradeScheduleDeployConfig
L2CoreDeployConfig
AltDADeployConfig
+ SoulGasTokenConfig
+ InboxContractConfig
+ L1ScalarMultiplierConfig
}
func (d *L2InitializationConfig) Check(log log.Logger) error {
@@ -890,6 +901,33 @@
ProtocolVersionsProxy common.Address `json:"protocolVersionsProxy"`
}
+// SoulGasTokenConfig configures the SoulGasToken deployment to L2.
+type SoulGasTokenConfig struct {
+ // DeploySoulGasToken is a flag that indicates if the SGT contract will be deploy at genesis.
+ DeploySoulGasToken bool `json:"deploySoulGasToken,omitempty"`
+ // The time offset of the block at which the SoulGasToken is activated.
+ SoulGasTokenTimeOffset *hexutil.Uint64 `json:"soulGasTokenTimeOffset,omitempty"`
+ // IsSoulBackedByNative is a flag that indicates if the SoulGasToken is backed by native.
+ // Only effective when DeploySoulGasToken is true.
+ IsSoulBackedByNative bool `json:"isSoulBackedByNative,omitempty"`
+}
+
+func (c *SoulGasTokenConfig) SoulGasTokenTime(genesisTime uint64) *uint64 {
+ return offsetToUpgradeTime(c.SoulGasTokenTimeOffset, genesisTime)
+}
+
+// InboxContractConfig configures whether inbox contract is enabled.
+// If enabled, the batcher tx will be further filtered by tx status.
+type InboxContractConfig struct {
+ UseInboxContract bool `json:"useInboxContract,omitempty"`
+}
+
+// L1ScalarMultiplierConfig configures the scalar multipliers for L1 base fee and blob base fee.
+type L1ScalarMultiplierConfig struct {
+ L1BaseFeeScalarMultiplier uint64 `json:"l1BaseFeeScalarMultiplier,omitempty"`
+ L1BlobBaseFeeScalarMultiplier uint64 `json:"l1BlobBaseFeeScalarMultiplier,omitempty"`
+}
+
// DependencyContext is the contextual configuration needed to verify the L1 dependencies,
// used by DeployConfig.CheckAddresses.
type DependencyContext struct {
@@ -1044,10 +1082,22 @@ if d.SystemConfigProxy == (common.Address{}) {
return nil, errors.New("SystemConfigProxy cannot be address(0)")
}
+ l1StartTime := l1StartBlock.Time
+
+ soulGasTokenTime := d.SoulGasTokenTime(l1StartTime)
+ // The SGT contract will only be deployed if DeploySoulGasToken is true.
+ if !d.DeploySoulGasToken && soulGasTokenTime != nil {
+ return nil, fmt.Errorf("soulGasTokenTimeOffset is set, but DeploySoulGasToken is false")
+ }
chainOpConfig := ¶ms.OptimismConfig{
- EIP1559Elasticity: d.EIP1559Elasticity,
- EIP1559Denominator: d.EIP1559Denominator,
- EIP1559DenominatorCanyon: &d.EIP1559DenominatorCanyon,
+ EIP1559Elasticity: d.EIP1559Elasticity,
+ EIP1559Denominator: d.EIP1559Denominator,
+ EIP1559DenominatorCanyon: &d.EIP1559DenominatorCanyon,
+ L2BlobTime: d.L2BlobTime(l1StartTime),
+ SoulGasTokenTime: soulGasTokenTime,
+ IsSoulBackedByNative: d.IsSoulBackedByNative,
+ L1BaseFeeScalarMultiplier: d.L1BaseFeeScalarMultiplier,
+ L1BlobBaseFeeScalarMultiplier: d.L1BlobBaseFeeScalarMultiplier,
}
var altDA *rollup.AltDAConfig
@@ -1060,7 +1110,10 @@ DAResolveWindow: d.DAResolveWindow,
}
}
- l1StartTime := l1StartBlock.Time
+ var inboxContractConfig *rollup.InboxContractConfig
+ if d.UseInboxContract {
+ inboxContractConfig = &rollup.InboxContractConfig{UseInboxContract: true}
+ }
return &rollup.Config{
Genesis: rollup.Genesis{
@@ -1097,6 +1150,7 @@ JovianTime: d.JovianTime(l1StartTime),
InteropTime: d.InteropTime(l1StartTime),
ProtocolVersionsAddress: d.ProtocolVersionsProxy,
AltDAConfig: altDA,
+ InboxContractConfig: inboxContractConfig,
ChainOpConfig: chainOpConfig,
}, nil
}
diff --git official optimism/op-chain-ops/genesis/genesis.go SWC optimism/op-chain-ops/genesis/genesis.go
index fa55eda6cf21a742bbda8e7aba7d18f5d63a72f4..622f98926278cc6faf23f7f316a1d6fa1ca4d4db 100644
--- official optimism/op-chain-ops/genesis/genesis.go
+++ SWC optimism/op-chain-ops/genesis/genesis.go
@@ -43,6 +43,12 @@ }
l1StartTime := l1StartHeader.Time
+ soulGasTokenTime := config.SoulGasTokenTime(l1StartTime)
+ // The SGT contract will only be deployed if DeploySoulGasToken is true.
+ if !config.DeploySoulGasToken && soulGasTokenTime != nil {
+ return nil, fmt.Errorf("soulGasTokenTimeOffset is set, but DeploySoulGasToken is false")
+ }
+
optimismChainConfig := params.ChainConfig{
ChainID: new(big.Int).SetUint64(config.L2ChainID),
HomesteadBlock: big.NewInt(0),
@@ -76,9 +82,14 @@ JovianTime: config.JovianTime(l1StartTime),
PragueTime: config.IsthmusTime(l1StartTime),
InteropTime: config.InteropTime(l1StartTime),
Optimism: ¶ms.OptimismConfig{
- EIP1559Denominator: eip1559Denom,
- EIP1559Elasticity: eip1559Elasticity,
- EIP1559DenominatorCanyon: &eip1559DenomCanyon,
+ EIP1559Denominator: eip1559Denom,
+ EIP1559Elasticity: eip1559Elasticity,
+ EIP1559DenominatorCanyon: &eip1559DenomCanyon,
+ L2BlobTime: config.L2BlobTime(l1StartTime),
+ IsSoulBackedByNative: config.IsSoulBackedByNative,
+ SoulGasTokenTime: soulGasTokenTime,
+ L1BaseFeeScalarMultiplier: config.L1BaseFeeScalarMultiplier,
+ L1BlobBaseFeeScalarMultiplier: config.L1BlobBaseFeeScalarMultiplier,
},
}
diff --git official optimism/op-deployer/pkg/deployer/opcm/l2genesis.go SWC optimism/op-deployer/pkg/deployer/opcm/l2genesis.go
index 3f91196cc85fca54a81f0c670b275255be5b33b2..1ea2e41cb0a6a63c3b6462b81cd135977ecf8f33 100644
--- official optimism/op-deployer/pkg/deployer/opcm/l2genesis.go
+++ SWC optimism/op-deployer/pkg/deployer/opcm/l2genesis.go
@@ -28,6 +28,8 @@ Fork *big.Int
DeployCrossL2Inbox bool
EnableGovernance bool
FundDevAccounts bool
+ DeploySoulGasToken bool
+ IsSoulBackedByNative bool
}
type L2GenesisScript script.DeployScriptWithoutOutput[L2GenesisInput]
diff --git official optimism/op-deployer/pkg/deployer/pipeline/l2genesis.go SWC optimism/op-deployer/pkg/deployer/pipeline/l2genesis.go
index bb3f514358bcef96f3613a093120bc0936aa8a79..c977d0a903354654c90e3b68ff4088785e528cb0 100644
--- official optimism/op-deployer/pkg/deployer/pipeline/l2genesis.go
+++ SWC optimism/op-deployer/pkg/deployer/pipeline/l2genesis.go
@@ -31,6 +31,8 @@ L1FeeVaultWithdrawalNetwork genesis.WithdrawalNetwork `json:"l1FeeVaultWithdrawalNetwork"`
SequencerFeeVaultWithdrawalNetwork genesis.WithdrawalNetwork `json:"sequencerFeeVaultWithdrawalNetwork"`
EnableGovernance bool `json:"enableGovernance"`
GovernanceTokenOwner common.Address `json:"governanceTokenOwner"`
+ DeploySoulGasToken bool `json:"deploySoulGasToken"`
+ IsSoulBackedByNative bool `json:"isSoulBackedByNative"`
}
func GenerateL2Genesis(pEnv *Env, intent *state.Intent, bundle ArtifactsBundle, st *state.State, chainID common.Hash) error {
@@ -94,6 +96,8 @@ Fork: big.NewInt(schedule.SolidityForkNumber(1)),
DeployCrossL2Inbox: len(intent.Chains) > 1,
EnableGovernance: overrides.EnableGovernance,
FundDevAccounts: overrides.FundDevAccounts,
+ DeploySoulGasToken: overrides.DeploySoulGasToken,
+ IsSoulBackedByNative: overrides.IsSoulBackedByNative,
}); err != nil {
return fmt.Errorf("failed to call L2Genesis script: %w", err)
}
diff --git official optimism/op-e2e/actions/helpers/l2_sequencer.go SWC optimism/op-e2e/actions/helpers/l2_sequencer.go
index 23be8eaf8c940ca0cd64c6d6102ae0473b48c8e0..f097e9bf1d6aed3ee2e4067300babf7cd15a5b9a 100644
--- official optimism/op-e2e/actions/helpers/l2_sequencer.go
+++ SWC optimism/op-e2e/actions/helpers/l2_sequencer.go
@@ -70,7 +70,7 @@ seqStateListener := config.DisabledConfigPersistence{}
conduc := &conductor.NoOpConductor{}
asyncGossip := async.NoOpGossiper{}
seq := sequencing.NewSequencer(t.Ctx(), log, cfg, attrBuilder, l1OriginSelector,
- seqStateListener, conduc, asyncGossip, metr, ver.engine)
+ seqStateListener, conduc, asyncGossip, metr, ver.engine, nil)
opts := event.WithEmitLimiter(
// TestSyncBatchType/DerivationWithFlakyL1RPC does *a lot* of quick retries
// TestL2BatcherBatchType/ExtendedTimeWithoutL1Batches as well.
diff --git official optimism/op-e2e/actions/proofs/isthmus_setcode_tx_test.go SWC optimism/op-e2e/actions/proofs/isthmus_setcode_tx_test.go
index d05694ec8cd243ccb8791366086c6e9e2ae37ea6..9af8566aed5ebd90a2dbd5b7f30578a126670e36 100644
--- official optimism/op-e2e/actions/proofs/isthmus_setcode_tx_test.go
+++ SWC optimism/op-e2e/actions/proofs/isthmus_setcode_tx_test.go
@@ -98,7 +98,7 @@ GasFeeCap: uint256.NewInt(5000000000),
GasTipCap: uint256.NewInt(2),
AuthList: []types.SetCodeAuthorization{auth1, auth2},
}
- signer := types.NewIsthmusSigner(chainID)
+ signer := types.NewIsthmusSigner(chainID, false)
tx := types.MustSignNewTx(aliceSecret, signer, txdata)
err = cl.SendTransaction(t.Ctx(), tx)
@@ -244,7 +244,7 @@ u1 := sequencer.L2Unsafe()
sequencer.ActL2EmptyBlock(t) // we'll inject the setcode tx in this block's batch
- signer := types.NewIsthmusSigner(chainID)
+ signer := types.NewIsthmusSigner(chainID, false)
rng := rand.New(rand.NewSource(0))
tx := testutils.RandomSetCodeTx(rng, signer)
diff --git official optimism/op-e2e/actions/proofs/operator_fee_test.go SWC optimism/op-e2e/actions/proofs/operator_fee_test.go
index 157f55929ba1d8c141446c15c0b06a01be6f9fa0..7dab53da19f63c6e7151e2d28e1915e8508003a5 100644
--- official optimism/op-e2e/actions/proofs/operator_fee_test.go
+++ SWC optimism/op-e2e/actions/proofs/operator_fee_test.go
@@ -212,7 +212,7 @@
l1BlockInfo, err := derive.L1BlockInfoFromBytes(env.Sd.RollupCfg, unsafeHeader.Time, unsafeBlock.Transactions()[0].Data())
require.NoError(t, err)
- daCost := fjordL1Cost(l1BlockInfo, types.NewRollupCostData(rlp))
+ daCost := fjordL1Cost(l1BlockInfo, types.NewRollupCostData(rlp, len(tx.BlobHashes())))
expectedFeePreIsthmus := nextBaseFee.Mul(nextBaseFee, big.NewInt(int64(params.TxGas)))
expectedFeePreIsthmus.Add(expectedFeePreIsthmus, daCost)
@@ -361,7 +361,9 @@
// Ensure that the logs contain a mention of the block being replaced _due to the signer not having enough
// balance_.
require.NotNil(t, env.Logs.FindLog(testlog.NewAttributesContainsFilter("err", "insufficient funds for gas * price + value")))
- require.NotNil(t, env.Logs.FindLog(testlog.NewAttributesContainsFilter("err", "have 1400000021000 want 1400000086535")))
+ // log diff is caused by sgt, which is enabled by default
+ require.NotNil(t, env.Logs.FindLog(testlog.NewAttributesContainsFilter("err", "have total balance 1400000021000 want 1400000086535")))
+ // require.NotNil(t, env.Logs.FindLog(testlog.NewAttributesContainsFilter("err", "have 1400000021000 want 1400000086535")))
} else {
require.Equal(t, len(safeHeadBlock.Transactions()), 2)
}
@@ -386,7 +388,10 @@ costFunc := types.NewL1CostFuncFjord(
l1BlockInfo.BaseFee,
l1BlockInfo.BlobBaseFee,
new(big.Int).SetUint64(uint64(l1BlockInfo.BaseFeeScalar)),
- new(big.Int).SetUint64(uint64(l1BlockInfo.BlobBaseFeeScalar)))
+ new(big.Int).SetUint64(uint64(l1BlockInfo.BlobBaseFeeScalar)),
+ new(big.Int).SetUint64(1),
+ new(big.Int).SetUint64(1),
+ )
fee, _ := costFunc(rollupCostData)
return fee
diff --git official optimism/op-e2e/actions/sgt/sgt_test.go SWC optimism/op-e2e/actions/sgt/sgt_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..aaae0d3ce7e983adf3a88a9b34c090932ddbe6fa
--- /dev/null
+++ SWC optimism/op-e2e/actions/sgt/sgt_test.go
@@ -0,0 +1,114 @@
+package sgt
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
+ "github.com/ethereum-optimism/optimism/op-e2e/bindings"
+ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
+ "github.com/ethereum-optimism/optimism/op-service/predeploys"
+ "github.com/ethereum-optimism/optimism/op-service/testlog"
+ "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/core/types"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/stretchr/testify/require"
+)
+
+func TestDynamicSGT(gt *testing.T) {
+ t := helpers.NewDefaultTesting(gt)
+ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams())
+ dp.DeployConfig.DeploySoulGasToken = true
+ timeOffset := new(hexutil.Uint64)
+ *timeOffset = 100
+ dp.DeployConfig.SoulGasTokenTimeOffset = timeOffset
+ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc)
+ log := testlog.Logger(t, log.LevelDebug)
+ miner, engine, sequencer := helpers.SetupSequencerTest(t, sd, log)
+
+ cl := engine.EthClient()
+ depositSGT(gt, engine, sd, dp, dp.Addresses.Alice, e2eutils.Ether(2))
+
+ sequencer.ActL2PipelineFull(t)
+
+ genesisTime := sequencer.L2Unsafe().Time
+
+ // Make L2 block
+ sequencer.ActL2StartBlock(t)
+ engine.ActL2IncludeTx(dp.Addresses.Alice)(t)
+ sequencer.ActL2EndBlock(t)
+
+ // Alice makes a L2 tx
+
+ balance1, err := cl.BalanceAt(t.Ctx(), dp.Addresses.Alice, nil)
+ require.NoError(t, err)
+ n, err := cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice)
+ require.NoError(t, err)
+ signer := types.LatestSigner(sd.L2Cfg.Config)
+ tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{
+ ChainID: sd.L2Cfg.Config.ChainID,
+ Nonce: n,
+ GasTipCap: big.NewInt(2 * params.GWei),
+ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)),
+ Gas: params.TxGas,
+ To: &dp.Addresses.Bob,
+ })
+ require.NoError(t, cl.SendTransaction(t.Ctx(), tx))
+
+ // Make L2 block
+ sequencer.ActL2StartBlock(t)
+ engine.ActL2IncludeTx(dp.Addresses.Alice)(t)
+ sequencer.ActL2EndBlock(t)
+
+ balance2, err := cl.BalanceAt(t.Ctx(), dp.Addresses.Alice, nil)
+ require.NoError(t, err)
+ // Check that the balance is different
+ // because the SGT is not active yet
+ require.True(t, balance2.Cmp(balance1) < 0)
+
+ // advance to the block where the SGT is active
+ sequencer.ActBuildL2ToTime(t, genesisTime+(uint64)(*dp.DeployConfig.SoulGasTokenTimeOffset))
+
+ // Alice makes a L2 tx
+ n, err = cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice)
+ require.NoError(t, err)
+ tx = types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{
+ ChainID: sd.L2Cfg.Config.ChainID,
+ Nonce: n,
+ GasTipCap: big.NewInt(2 * params.GWei),
+ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)),
+ Gas: params.TxGas,
+ To: &dp.Addresses.Bob,
+ })
+ require.NoError(t, cl.SendTransaction(t.Ctx(), tx))
+
+ // Make L2 block
+ sequencer.ActL2StartBlock(t)
+ engine.ActL2IncludeTx(dp.Addresses.Alice)(t)
+ sequencer.ActL2EndBlock(t)
+
+ balance3, err := cl.BalanceAt(t.Ctx(), dp.Addresses.Alice, nil)
+ require.NoError(t, err)
+
+ // Check that the balance is the same as before
+ // because the SGT is active
+ require.True(t, balance3.Cmp(balance2) == 0)
+}
+
+func depositSGT(t *testing.T, engine *helpers.L2Engine, sd *e2eutils.SetupData, dp *e2eutils.DeployParams, target common.Address, depositSgtValue *big.Int) {
+
+ sgtAddr := predeploys.SoulGasTokenAddr
+ sgtContract, err := bindings.NewSoulGasToken(sgtAddr, engine.EthClient())
+ require.NoError(t, err)
+
+ txOpts, err := bind.NewKeyedTransactorWithChainID(dp.Secrets.Alice, sd.L2Cfg.Config.ChainID)
+ require.NoError(t, err)
+ txOpts.Value = depositSgtValue
+
+ _, err = sgtContract.BatchDepositForAll(txOpts, []common.Address{target}, depositSgtValue)
+ require.NoError(t, err)
+
+}
diff --git official optimism/op-e2e/actions/upgrades/fjord_fork_test.go SWC optimism/op-e2e/actions/upgrades/fjord_fork_test.go
index ae0dbfb0b2b6dbf5514e06ee369ea6f6c4fb8b73..bb15e76134c0cf3b1f030b6335c8dab87d6c19c5 100644
--- official optimism/op-e2e/actions/upgrades/fjord_fork_test.go
+++ SWC optimism/op-e2e/actions/upgrades/fjord_fork_test.go
@@ -142,7 +142,10 @@ costFunc := types.NewL1CostFuncFjord(
l1BaseFee,
blobBaseFee,
new(big.Int).SetUint64(uint64(baseFeeScalar)),
- new(big.Int).SetUint64(uint64(blobBaseFeeScalar)))
+ new(big.Int).SetUint64(uint64(blobBaseFeeScalar)),
+ new(big.Int).SetUint64(1),
+ new(big.Int).SetUint64(1),
+ )
fee, _ := costFunc(rollupCostData)
return fee
diff --git official optimism/op-e2e/bindings/batchinbox.go SWC optimism/op-e2e/bindings/batchinbox.go
new file mode 100644
index 0000000000000000000000000000000000000000..24f67a1efa2d7b378c4817c191e2daa4cd5b3a29
--- /dev/null
+++ SWC optimism/op-e2e/bindings/batchinbox.go
@@ -0,0 +1,351 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+// The contract is located at https://github.com/ethstorage/es-op-batchinbox/blob/main/src/BatchInbox.sol
+
+package bindings
+
+import (
+ "errors"
+ "math/big"
+ "strings"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+ _ = errors.New
+ _ = big.NewInt
+ _ = strings.NewReader
+ _ = ethereum.NotFound
+ _ = bind.Bind
+ _ = common.Big1
+ _ = types.BloomLookup
+ _ = event.NewSubscription
+ _ = abi.ConvertType
+)
+
+// BatchInboxMetaData contains all meta data concerning the BatchInbox contract.
+var BatchInboxMetaData = &bind.MetaData{
+ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_esStorageContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BalanceNotEnough\",\"type\":\"error\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"esStorageContract\",\"outputs\":[{\"internalType\":\"contractStorageContract\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]",
+ Bin: "0x60a060405234801561000f575f5ffd5b50604051610984380380610984833981810160405281019061003191906100c9565b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1681525050506100f4565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100988261006f565b9050919050565b6100a88161008e565b81146100b2575f5ffd5b50565b5f815190506100c38161009f565b92915050565b5f602082840312156100de576100dd61006b565b5b5f6100eb848285016100b5565b91505092915050565b60805161086a61011a5f395f81816101990152818161022901526103b3015261086a5ff3fe608060405260043610610042575f3560e01c806322eb767d1461006f57806327e235e314610099578063f340fa01146100d5578063f3fef3a3146100f15761005b565b3661005b576100513334610119565b610059610178565b005b6100653334610119565b61006d610178565b005b34801561007a575f5ffd5b506100836103b1565b604051610090919061057f565b60405180910390f35b3480156100a4575f5ffd5b506100bf60048036038101906100ba91906105d7565b6103d5565b6040516100cc919061061a565b60405180910390f35b6100ef60048036038101906100ea91906105d7565b6103e9565b005b3480156100fc575f5ffd5b506101176004803603810190610112919061065d565b6103f6565b005b5f81031561017457805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461016c91906106c8565b925050819055505b5050565b5f5f90505f5f90505f5b824990505f5f1b8103156102c5575f8203610227577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631ccbc6da6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610200573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610224919061070f565b91505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634581a920838386620200006040518563ffffffff1660e01b81526004016102889392919061078b565b5f604051808303818588803b15801561029f575f5ffd5b505af11580156102b1573d5f5f3e3d5ffd5b505050505082806001019350506001610182575b5f83036102d4575050506103af565b5f83836102e191906107c0565b90505f5f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561035d576040517f9882883500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816103699190610801565b5f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555050505050505b565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f602052805f5260405f205f915090505481565b6103f38134610119565b50565b5f5f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015610470576040517f9882883500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818161047c9190610801565b5f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff166108fc8390811502906040515f60405180830381858888f193505050501580156104ff573d5f5f3e3d5ffd5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f61054761054261053d84610505565b610524565b610505565b9050919050565b5f6105588261052d565b9050919050565b5f6105698261054e565b9050919050565b6105798161055f565b82525050565b5f6020820190506105925f830184610570565b92915050565b5f5ffd5b5f6105a682610505565b9050919050565b6105b68161059c565b81146105c0575f5ffd5b50565b5f813590506105d1816105ad565b92915050565b5f602082840312156105ec576105eb610598565b5b5f6105f9848285016105c3565b91505092915050565b5f819050919050565b61061481610602565b82525050565b5f60208201905061062d5f83018461060b565b92915050565b61063c81610602565b8114610646575f5ffd5b50565b5f8135905061065781610633565b92915050565b5f5f6040838503121561067357610672610598565b5b5f610680858286016105c3565b925050602061069185828601610649565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6106d282610602565b91506106dd83610602565b92508282019050808211156106f5576106f461069b565b5b92915050565b5f8151905061070981610633565b92915050565b5f6020828403121561072457610723610598565b5b5f610731848285016106fb565b91505092915050565b5f819050919050565b61074c8161073a565b82525050565b5f819050919050565b5f61077561077061076b84610752565b610524565b610602565b9050919050565b6107858161075b565b82525050565b5f60608201905061079e5f830186610743565b6107ab602083018561060b565b6107b8604083018461077c565b949350505050565b5f6107ca82610602565b91506107d583610602565b92508282026107e381610602565b915082820484148315176107fa576107f961069b565b5b5092915050565b5f61080b82610602565b915061081683610602565b925082820390508181111561082e5761082d61069b565b5b9291505056fea2646970667358221220ad769cb754fdad1ddf58c9c13e0a15d938b6139b499ebc6a85cd815b50b05f8b64736f6c634300081c0033",
+}
+
+// BatchInboxABI is the input ABI used to generate the binding from.
+// Deprecated: Use BatchInboxMetaData.ABI instead.
+var BatchInboxABI = BatchInboxMetaData.ABI
+
+// BatchInboxBin is the compiled bytecode used for deploying new contracts.
+// Deprecated: Use BatchInboxMetaData.Bin instead.
+var BatchInboxBin = BatchInboxMetaData.Bin
+
+// DeployBatchInbox deploys a new Ethereum contract, binding an instance of BatchInbox to it.
+func DeployBatchInbox(auth *bind.TransactOpts, backend bind.ContractBackend, _esStorageContract common.Address) (common.Address, *types.Transaction, *BatchInbox, error) {
+ parsed, err := BatchInboxMetaData.GetAbi()
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ if parsed == nil {
+ return common.Address{}, nil, nil, errors.New("GetABI returned nil")
+ }
+
+ address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BatchInboxBin), backend, _esStorageContract)
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ return address, tx, &BatchInbox{BatchInboxCaller: BatchInboxCaller{contract: contract}, BatchInboxTransactor: BatchInboxTransactor{contract: contract}, BatchInboxFilterer: BatchInboxFilterer{contract: contract}}, nil
+}
+
+// BatchInbox is an auto generated Go binding around an Ethereum contract.
+type BatchInbox struct {
+ BatchInboxCaller // Read-only binding to the contract
+ BatchInboxTransactor // Write-only binding to the contract
+ BatchInboxFilterer // Log filterer for contract events
+}
+
+// BatchInboxCaller is an auto generated read-only Go binding around an Ethereum contract.
+type BatchInboxCaller struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// BatchInboxTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type BatchInboxTransactor struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// BatchInboxFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type BatchInboxFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// BatchInboxSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type BatchInboxSession struct {
+ Contract *BatchInbox // Generic contract binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// BatchInboxCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type BatchInboxCallerSession struct {
+ Contract *BatchInboxCaller // Generic contract caller binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+}
+
+// BatchInboxTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type BatchInboxTransactorSession struct {
+ Contract *BatchInboxTransactor // Generic contract transactor binding to set the session for
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// BatchInboxRaw is an auto generated low-level Go binding around an Ethereum contract.
+type BatchInboxRaw struct {
+ Contract *BatchInbox // Generic contract binding to access the raw methods on
+}
+
+// BatchInboxCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type BatchInboxCallerRaw struct {
+ Contract *BatchInboxCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// BatchInboxTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type BatchInboxTransactorRaw struct {
+ Contract *BatchInboxTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewBatchInbox creates a new instance of BatchInbox, bound to a specific deployed contract.
+func NewBatchInbox(address common.Address, backend bind.ContractBackend) (*BatchInbox, error) {
+ contract, err := bindBatchInbox(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &BatchInbox{BatchInboxCaller: BatchInboxCaller{contract: contract}, BatchInboxTransactor: BatchInboxTransactor{contract: contract}, BatchInboxFilterer: BatchInboxFilterer{contract: contract}}, nil
+}
+
+// NewBatchInboxCaller creates a new read-only instance of BatchInbox, bound to a specific deployed contract.
+func NewBatchInboxCaller(address common.Address, caller bind.ContractCaller) (*BatchInboxCaller, error) {
+ contract, err := bindBatchInbox(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &BatchInboxCaller{contract: contract}, nil
+}
+
+// NewBatchInboxTransactor creates a new write-only instance of BatchInbox, bound to a specific deployed contract.
+func NewBatchInboxTransactor(address common.Address, transactor bind.ContractTransactor) (*BatchInboxTransactor, error) {
+ contract, err := bindBatchInbox(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &BatchInboxTransactor{contract: contract}, nil
+}
+
+// NewBatchInboxFilterer creates a new log filterer instance of BatchInbox, bound to a specific deployed contract.
+func NewBatchInboxFilterer(address common.Address, filterer bind.ContractFilterer) (*BatchInboxFilterer, error) {
+ contract, err := bindBatchInbox(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &BatchInboxFilterer{contract: contract}, nil
+}
+
+// bindBatchInbox binds a generic wrapper to an already deployed contract.
+func bindBatchInbox(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := BatchInboxMetaData.GetAbi()
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_BatchInbox *BatchInboxRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _BatchInbox.Contract.BatchInboxCaller.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_BatchInbox *BatchInboxRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _BatchInbox.Contract.BatchInboxTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_BatchInbox *BatchInboxRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _BatchInbox.Contract.BatchInboxTransactor.contract.Transact(opts, method, params...)
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_BatchInbox *BatchInboxCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _BatchInbox.Contract.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_BatchInbox *BatchInboxTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _BatchInbox.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_BatchInbox *BatchInboxTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _BatchInbox.Contract.contract.Transact(opts, method, params...)
+}
+
+// Balances is a free data retrieval call binding the contract method 0x27e235e3.
+//
+// Solidity: function balances(address ) view returns(uint256)
+func (_BatchInbox *BatchInboxCaller) Balances(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) {
+ var out []interface{}
+ err := _BatchInbox.contract.Call(opts, &out, "balances", arg0)
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Balances is a free data retrieval call binding the contract method 0x27e235e3.
+//
+// Solidity: function balances(address ) view returns(uint256)
+func (_BatchInbox *BatchInboxSession) Balances(arg0 common.Address) (*big.Int, error) {
+ return _BatchInbox.Contract.Balances(&_BatchInbox.CallOpts, arg0)
+}
+
+// Balances is a free data retrieval call binding the contract method 0x27e235e3.
+//
+// Solidity: function balances(address ) view returns(uint256)
+func (_BatchInbox *BatchInboxCallerSession) Balances(arg0 common.Address) (*big.Int, error) {
+ return _BatchInbox.Contract.Balances(&_BatchInbox.CallOpts, arg0)
+}
+
+// EsStorageContract is a free data retrieval call binding the contract method 0x22eb767d.
+//
+// Solidity: function esStorageContract() view returns(address)
+func (_BatchInbox *BatchInboxCaller) EsStorageContract(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _BatchInbox.contract.Call(opts, &out, "esStorageContract")
+
+ if err != nil {
+ return *new(common.Address), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
+
+ return out0, err
+
+}
+
+// EsStorageContract is a free data retrieval call binding the contract method 0x22eb767d.
+//
+// Solidity: function esStorageContract() view returns(address)
+func (_BatchInbox *BatchInboxSession) EsStorageContract() (common.Address, error) {
+ return _BatchInbox.Contract.EsStorageContract(&_BatchInbox.CallOpts)
+}
+
+// EsStorageContract is a free data retrieval call binding the contract method 0x22eb767d.
+//
+// Solidity: function esStorageContract() view returns(address)
+func (_BatchInbox *BatchInboxCallerSession) EsStorageContract() (common.Address, error) {
+ return _BatchInbox.Contract.EsStorageContract(&_BatchInbox.CallOpts)
+}
+
+// Deposit is a paid mutator transaction binding the contract method 0xf340fa01.
+//
+// Solidity: function deposit(address _to) payable returns()
+func (_BatchInbox *BatchInboxTransactor) Deposit(opts *bind.TransactOpts, _to common.Address) (*types.Transaction, error) {
+ return _BatchInbox.contract.Transact(opts, "deposit", _to)
+}
+
+// Deposit is a paid mutator transaction binding the contract method 0xf340fa01.
+//
+// Solidity: function deposit(address _to) payable returns()
+func (_BatchInbox *BatchInboxSession) Deposit(_to common.Address) (*types.Transaction, error) {
+ return _BatchInbox.Contract.Deposit(&_BatchInbox.TransactOpts, _to)
+}
+
+// Deposit is a paid mutator transaction binding the contract method 0xf340fa01.
+//
+// Solidity: function deposit(address _to) payable returns()
+func (_BatchInbox *BatchInboxTransactorSession) Deposit(_to common.Address) (*types.Transaction, error) {
+ return _BatchInbox.Contract.Deposit(&_BatchInbox.TransactOpts, _to)
+}
+
+// Withdraw is a paid mutator transaction binding the contract method 0xf3fef3a3.
+//
+// Solidity: function withdraw(address _to, uint256 _amount) returns()
+func (_BatchInbox *BatchInboxTransactor) Withdraw(opts *bind.TransactOpts, _to common.Address, _amount *big.Int) (*types.Transaction, error) {
+ return _BatchInbox.contract.Transact(opts, "withdraw", _to, _amount)
+}
+
+// Withdraw is a paid mutator transaction binding the contract method 0xf3fef3a3.
+//
+// Solidity: function withdraw(address _to, uint256 _amount) returns()
+func (_BatchInbox *BatchInboxSession) Withdraw(_to common.Address, _amount *big.Int) (*types.Transaction, error) {
+ return _BatchInbox.Contract.Withdraw(&_BatchInbox.TransactOpts, _to, _amount)
+}
+
+// Withdraw is a paid mutator transaction binding the contract method 0xf3fef3a3.
+//
+// Solidity: function withdraw(address _to, uint256 _amount) returns()
+func (_BatchInbox *BatchInboxTransactorSession) Withdraw(_to common.Address, _amount *big.Int) (*types.Transaction, error) {
+ return _BatchInbox.Contract.Withdraw(&_BatchInbox.TransactOpts, _to, _amount)
+}
+
+// Fallback is a paid mutator transaction binding the contract fallback function.
+//
+// Solidity: fallback() payable returns()
+func (_BatchInbox *BatchInboxTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) {
+ return _BatchInbox.contract.RawTransact(opts, calldata)
+}
+
+// Fallback is a paid mutator transaction binding the contract fallback function.
+//
+// Solidity: fallback() payable returns()
+func (_BatchInbox *BatchInboxSession) Fallback(calldata []byte) (*types.Transaction, error) {
+ return _BatchInbox.Contract.Fallback(&_BatchInbox.TransactOpts, calldata)
+}
+
+// Fallback is a paid mutator transaction binding the contract fallback function.
+//
+// Solidity: fallback() payable returns()
+func (_BatchInbox *BatchInboxTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
+ return _BatchInbox.Contract.Fallback(&_BatchInbox.TransactOpts, calldata)
+}
+
+// Receive is a paid mutator transaction binding the contract receive function.
+//
+// Solidity: receive() payable returns()
+func (_BatchInbox *BatchInboxTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _BatchInbox.contract.RawTransact(opts, nil) // calldata is disallowed for receive function
+}
+
+// Receive is a paid mutator transaction binding the contract receive function.
+//
+// Solidity: receive() payable returns()
+func (_BatchInbox *BatchInboxSession) Receive() (*types.Transaction, error) {
+ return _BatchInbox.Contract.Receive(&_BatchInbox.TransactOpts)
+}
+
+// Receive is a paid mutator transaction binding the contract receive function.
+//
+// Solidity: receive() payable returns()
+func (_BatchInbox *BatchInboxTransactorSession) Receive() (*types.Transaction, error) {
+ return _BatchInbox.Contract.Receive(&_BatchInbox.TransactOpts)
+}
diff --git official optimism/op-e2e/bindings/mockstorage.go SWC optimism/op-e2e/bindings/mockstorage.go
new file mode 100644
index 0000000000000000000000000000000000000000..2fd02f79fb217ad7689ce957ebb45e2860b79d2b
--- /dev/null
+++ SWC optimism/op-e2e/bindings/mockstorage.go
@@ -0,0 +1,450 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+// The contract is located at ./op-e2e/inbox/testcontract/mockstorage.sol
+
+package bindings
+
+import (
+ "errors"
+ "math/big"
+ "strings"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+ _ = errors.New
+ _ = big.NewInt
+ _ = strings.NewReader
+ _ = ethereum.NotFound
+ _ = bind.Bind
+ _ = common.Big1
+ _ = types.BloomLookup
+ _ = event.NewSubscription
+ _ = abi.ConvertType
+)
+
+// MockEthStorageMetaData contains all meta data concerning the MockEthStorage contract.
+var MockEthStorageMetaData = &bind.MetaData{
+ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_cost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"kvIdx\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"kvSize\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"}],\"name\":\"PutBlob\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"kvEntryCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_blobIdx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_length\",\"type\":\"uint256\"}],\"name\":\"putBlob\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upfrontPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
+ Bin: "0x60a0604052348015600e575f5ffd5b506040516105d43803806105d48339818101604052810190602e9190606d565b8060808181525050506093565b5f5ffd5b5f819050919050565b604f81603f565b81146058575f5ffd5b50565b5f815190506067816048565b92915050565b5f60208284031215607f57607e603b565b5b5f608a84828501605b565b91505092915050565b60805161052a6100aa5f395f60aa015261052a5ff3fe608060405260043610610033575f3560e01c80631ccbc6da146100375780634581a92014610061578063638ba9e91461007d575b5f5ffd5b348015610042575f5ffd5b5061004b6100a7565b6040516100589190610210565b60405180910390f35b61007b6004803603810190610076919061028a565b6100ce565b005b348015610088575f5ffd5b506100916101f3565b60405161009e9190610210565b60405180910390f35b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f824990505f5f1b8103610117576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161010e9061035a565b60405180910390fd5b5f5f1b840361015b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610152906103e8565b60405180910390fd5b6101636100a7565b3410156101a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161019c90610476565b60405180910390fd5b5f5f54905060015f546101b891906104c1565b5f819055508183827f8b7a21215282409938287ae262331bfe6411d35d3d46aa7e505ef02000524ac260405160405180910390a45050505050565b5f5481565b5f819050919050565b61020a816101f8565b82525050565b5f6020820190506102235f830184610201565b92915050565b5f5ffd5b5f819050919050565b61023f8161022d565b8114610249575f5ffd5b50565b5f8135905061025a81610236565b92915050565b610269816101f8565b8114610273575f5ffd5b50565b5f8135905061028481610260565b92915050565b5f5f5f606084860312156102a1576102a0610229565b5b5f6102ae8682870161024c565b93505060206102bf86828701610276565b92505060406102d086828701610276565b9150509250925092565b5f82825260208201905092915050565b7f45746853746f72616765436f6e74726163743a206661696c656420746f2067655f8201527f7420626c6f622068617368000000000000000000000000000000000000000000602082015250565b5f610344602b836102da565b915061034f826102ea565b604082019050919050565b5f6020820190508181035f83015261037181610338565b9050919050565b7f45746853746f72616765436f6e74726163743a206661696c656420746f2067655f8201527f7420626c6f62206b657900000000000000000000000000000000000000000000602082015250565b5f6103d2602a836102da565b91506103dd82610378565b604082019050919050565b5f6020820190508181035f8301526103ff816103c6565b9050919050565b7f446563656e7472616c697a65644b563a206e6f7420656e6f75676820626174635f8201527f68207061796d656e740000000000000000000000000000000000000000000000602082015250565b5f6104606029836102da565b915061046b82610406565b604082019050919050565b5f6020820190508181035f83015261048d81610454565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6104cb826101f8565b91506104d6836101f8565b92508282019050808211156104ee576104ed610494565b5b9291505056fea2646970667358221220d4d1a376c0d170d3fa44c75c4fba21e612513babbea0199bfa331bc05827b17464736f6c634300081c0033",
+}
+
+// MockEthStorageABI is the input ABI used to generate the binding from.
+// Deprecated: Use MockEthStorageMetaData.ABI instead.
+var MockEthStorageABI = MockEthStorageMetaData.ABI
+
+// MockEthStorageBin is the compiled bytecode used for deploying new contracts.
+// Deprecated: Use MockEthStorageMetaData.Bin instead.
+var MockEthStorageBin = MockEthStorageMetaData.Bin
+
+// DeployMockEthStorage deploys a new Ethereum contract, binding an instance of MockEthStorage to it.
+func DeployMockEthStorage(auth *bind.TransactOpts, backend bind.ContractBackend, _cost *big.Int) (common.Address, *types.Transaction, *MockEthStorage, error) {
+ parsed, err := MockEthStorageMetaData.GetAbi()
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ if parsed == nil {
+ return common.Address{}, nil, nil, errors.New("GetABI returned nil")
+ }
+
+ address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MockEthStorageBin), backend, _cost)
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ return address, tx, &MockEthStorage{MockEthStorageCaller: MockEthStorageCaller{contract: contract}, MockEthStorageTransactor: MockEthStorageTransactor{contract: contract}, MockEthStorageFilterer: MockEthStorageFilterer{contract: contract}}, nil
+}
+
+// MockEthStorage is an auto generated Go binding around an Ethereum contract.
+type MockEthStorage struct {
+ MockEthStorageCaller // Read-only binding to the contract
+ MockEthStorageTransactor // Write-only binding to the contract
+ MockEthStorageFilterer // Log filterer for contract events
+}
+
+// MockEthStorageCaller is an auto generated read-only Go binding around an Ethereum contract.
+type MockEthStorageCaller struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// MockEthStorageTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type MockEthStorageTransactor struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// MockEthStorageFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type MockEthStorageFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// MockEthStorageSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type MockEthStorageSession struct {
+ Contract *MockEthStorage // Generic contract binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// MockEthStorageCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type MockEthStorageCallerSession struct {
+ Contract *MockEthStorageCaller // Generic contract caller binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+}
+
+// MockEthStorageTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type MockEthStorageTransactorSession struct {
+ Contract *MockEthStorageTransactor // Generic contract transactor binding to set the session for
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// MockEthStorageRaw is an auto generated low-level Go binding around an Ethereum contract.
+type MockEthStorageRaw struct {
+ Contract *MockEthStorage // Generic contract binding to access the raw methods on
+}
+
+// MockEthStorageCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type MockEthStorageCallerRaw struct {
+ Contract *MockEthStorageCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// MockEthStorageTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type MockEthStorageTransactorRaw struct {
+ Contract *MockEthStorageTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewMockEthStorage creates a new instance of MockEthStorage, bound to a specific deployed contract.
+func NewMockEthStorage(address common.Address, backend bind.ContractBackend) (*MockEthStorage, error) {
+ contract, err := bindMockEthStorage(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &MockEthStorage{MockEthStorageCaller: MockEthStorageCaller{contract: contract}, MockEthStorageTransactor: MockEthStorageTransactor{contract: contract}, MockEthStorageFilterer: MockEthStorageFilterer{contract: contract}}, nil
+}
+
+// NewMockEthStorageCaller creates a new read-only instance of MockEthStorage, bound to a specific deployed contract.
+func NewMockEthStorageCaller(address common.Address, caller bind.ContractCaller) (*MockEthStorageCaller, error) {
+ contract, err := bindMockEthStorage(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &MockEthStorageCaller{contract: contract}, nil
+}
+
+// NewMockEthStorageTransactor creates a new write-only instance of MockEthStorage, bound to a specific deployed contract.
+func NewMockEthStorageTransactor(address common.Address, transactor bind.ContractTransactor) (*MockEthStorageTransactor, error) {
+ contract, err := bindMockEthStorage(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &MockEthStorageTransactor{contract: contract}, nil
+}
+
+// NewMockEthStorageFilterer creates a new log filterer instance of MockEthStorage, bound to a specific deployed contract.
+func NewMockEthStorageFilterer(address common.Address, filterer bind.ContractFilterer) (*MockEthStorageFilterer, error) {
+ contract, err := bindMockEthStorage(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &MockEthStorageFilterer{contract: contract}, nil
+}
+
+// bindMockEthStorage binds a generic wrapper to an already deployed contract.
+func bindMockEthStorage(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := MockEthStorageMetaData.GetAbi()
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_MockEthStorage *MockEthStorageRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _MockEthStorage.Contract.MockEthStorageCaller.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_MockEthStorage *MockEthStorageRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _MockEthStorage.Contract.MockEthStorageTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_MockEthStorage *MockEthStorageRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _MockEthStorage.Contract.MockEthStorageTransactor.contract.Transact(opts, method, params...)
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_MockEthStorage *MockEthStorageCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _MockEthStorage.Contract.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_MockEthStorage *MockEthStorageTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _MockEthStorage.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_MockEthStorage *MockEthStorageTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _MockEthStorage.Contract.contract.Transact(opts, method, params...)
+}
+
+// KvEntryCount is a free data retrieval call binding the contract method 0x638ba9e9.
+//
+// Solidity: function kvEntryCount() view returns(uint256)
+func (_MockEthStorage *MockEthStorageCaller) KvEntryCount(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _MockEthStorage.contract.Call(opts, &out, "kvEntryCount")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// KvEntryCount is a free data retrieval call binding the contract method 0x638ba9e9.
+//
+// Solidity: function kvEntryCount() view returns(uint256)
+func (_MockEthStorage *MockEthStorageSession) KvEntryCount() (*big.Int, error) {
+ return _MockEthStorage.Contract.KvEntryCount(&_MockEthStorage.CallOpts)
+}
+
+// KvEntryCount is a free data retrieval call binding the contract method 0x638ba9e9.
+//
+// Solidity: function kvEntryCount() view returns(uint256)
+func (_MockEthStorage *MockEthStorageCallerSession) KvEntryCount() (*big.Int, error) {
+ return _MockEthStorage.Contract.KvEntryCount(&_MockEthStorage.CallOpts)
+}
+
+// UpfrontPayment is a free data retrieval call binding the contract method 0x1ccbc6da.
+//
+// Solidity: function upfrontPayment() view returns(uint256)
+func (_MockEthStorage *MockEthStorageCaller) UpfrontPayment(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _MockEthStorage.contract.Call(opts, &out, "upfrontPayment")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// UpfrontPayment is a free data retrieval call binding the contract method 0x1ccbc6da.
+//
+// Solidity: function upfrontPayment() view returns(uint256)
+func (_MockEthStorage *MockEthStorageSession) UpfrontPayment() (*big.Int, error) {
+ return _MockEthStorage.Contract.UpfrontPayment(&_MockEthStorage.CallOpts)
+}
+
+// UpfrontPayment is a free data retrieval call binding the contract method 0x1ccbc6da.
+//
+// Solidity: function upfrontPayment() view returns(uint256)
+func (_MockEthStorage *MockEthStorageCallerSession) UpfrontPayment() (*big.Int, error) {
+ return _MockEthStorage.Contract.UpfrontPayment(&_MockEthStorage.CallOpts)
+}
+
+// PutBlob is a paid mutator transaction binding the contract method 0x4581a920.
+//
+// Solidity: function putBlob(bytes32 _key, uint256 _blobIdx, uint256 _length) payable returns()
+func (_MockEthStorage *MockEthStorageTransactor) PutBlob(opts *bind.TransactOpts, _key [32]byte, _blobIdx *big.Int, _length *big.Int) (*types.Transaction, error) {
+ return _MockEthStorage.contract.Transact(opts, "putBlob", _key, _blobIdx, _length)
+}
+
+// PutBlob is a paid mutator transaction binding the contract method 0x4581a920.
+//
+// Solidity: function putBlob(bytes32 _key, uint256 _blobIdx, uint256 _length) payable returns()
+func (_MockEthStorage *MockEthStorageSession) PutBlob(_key [32]byte, _blobIdx *big.Int, _length *big.Int) (*types.Transaction, error) {
+ return _MockEthStorage.Contract.PutBlob(&_MockEthStorage.TransactOpts, _key, _blobIdx, _length)
+}
+
+// PutBlob is a paid mutator transaction binding the contract method 0x4581a920.
+//
+// Solidity: function putBlob(bytes32 _key, uint256 _blobIdx, uint256 _length) payable returns()
+func (_MockEthStorage *MockEthStorageTransactorSession) PutBlob(_key [32]byte, _blobIdx *big.Int, _length *big.Int) (*types.Transaction, error) {
+ return _MockEthStorage.Contract.PutBlob(&_MockEthStorage.TransactOpts, _key, _blobIdx, _length)
+}
+
+// MockEthStoragePutBlobIterator is returned from FilterPutBlob and is used to iterate over the raw logs and unpacked data for PutBlob events raised by the MockEthStorage contract.
+type MockEthStoragePutBlobIterator struct {
+ Event *MockEthStoragePutBlob // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *MockEthStoragePutBlobIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(MockEthStoragePutBlob)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(MockEthStoragePutBlob)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error returns any retrieval or parsing error occurred during filtering.
+func (it *MockEthStoragePutBlobIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *MockEthStoragePutBlobIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// MockEthStoragePutBlob represents a PutBlob event raised by the MockEthStorage contract.
+type MockEthStoragePutBlob struct {
+ KvIdx *big.Int
+ KvSize *big.Int
+ DataHash [32]byte
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterPutBlob is a free log retrieval operation binding the contract event 0x8b7a21215282409938287ae262331bfe6411d35d3d46aa7e505ef02000524ac2.
+//
+// Solidity: event PutBlob(uint256 indexed kvIdx, uint256 indexed kvSize, bytes32 indexed dataHash)
+func (_MockEthStorage *MockEthStorageFilterer) FilterPutBlob(opts *bind.FilterOpts, kvIdx []*big.Int, kvSize []*big.Int, dataHash [][32]byte) (*MockEthStoragePutBlobIterator, error) {
+
+ var kvIdxRule []interface{}
+ for _, kvIdxItem := range kvIdx {
+ kvIdxRule = append(kvIdxRule, kvIdxItem)
+ }
+ var kvSizeRule []interface{}
+ for _, kvSizeItem := range kvSize {
+ kvSizeRule = append(kvSizeRule, kvSizeItem)
+ }
+ var dataHashRule []interface{}
+ for _, dataHashItem := range dataHash {
+ dataHashRule = append(dataHashRule, dataHashItem)
+ }
+
+ logs, sub, err := _MockEthStorage.contract.FilterLogs(opts, "PutBlob", kvIdxRule, kvSizeRule, dataHashRule)
+ if err != nil {
+ return nil, err
+ }
+ return &MockEthStoragePutBlobIterator{contract: _MockEthStorage.contract, event: "PutBlob", logs: logs, sub: sub}, nil
+}
+
+// WatchPutBlob is a free log subscription operation binding the contract event 0x8b7a21215282409938287ae262331bfe6411d35d3d46aa7e505ef02000524ac2.
+//
+// Solidity: event PutBlob(uint256 indexed kvIdx, uint256 indexed kvSize, bytes32 indexed dataHash)
+func (_MockEthStorage *MockEthStorageFilterer) WatchPutBlob(opts *bind.WatchOpts, sink chan<- *MockEthStoragePutBlob, kvIdx []*big.Int, kvSize []*big.Int, dataHash [][32]byte) (event.Subscription, error) {
+
+ var kvIdxRule []interface{}
+ for _, kvIdxItem := range kvIdx {
+ kvIdxRule = append(kvIdxRule, kvIdxItem)
+ }
+ var kvSizeRule []interface{}
+ for _, kvSizeItem := range kvSize {
+ kvSizeRule = append(kvSizeRule, kvSizeItem)
+ }
+ var dataHashRule []interface{}
+ for _, dataHashItem := range dataHash {
+ dataHashRule = append(dataHashRule, dataHashItem)
+ }
+
+ logs, sub, err := _MockEthStorage.contract.WatchLogs(opts, "PutBlob", kvIdxRule, kvSizeRule, dataHashRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(MockEthStoragePutBlob)
+ if err := _MockEthStorage.contract.UnpackLog(event, "PutBlob", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ParsePutBlob is a log parse operation binding the contract event 0x8b7a21215282409938287ae262331bfe6411d35d3d46aa7e505ef02000524ac2.
+//
+// Solidity: event PutBlob(uint256 indexed kvIdx, uint256 indexed kvSize, bytes32 indexed dataHash)
+func (_MockEthStorage *MockEthStorageFilterer) ParsePutBlob(log types.Log) (*MockEthStoragePutBlob, error) {
+ event := new(MockEthStoragePutBlob)
+ if err := _MockEthStorage.contract.UnpackLog(event, "PutBlob", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
diff --git official optimism/op-e2e/bindings/soulgastoken.go SWC optimism/op-e2e/bindings/soulgastoken.go
new file mode 100644
index 0000000000000000000000000000000000000000..4930a2bba88c0a3d625b47ba0069aa0764f49194
--- /dev/null
+++ SWC optimism/op-e2e/bindings/soulgastoken.go
@@ -0,0 +1,1795 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package bindings
+
+import (
+ "errors"
+ "math/big"
+ "strings"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+ _ = errors.New
+ _ = big.NewInt
+ _ = strings.NewReader
+ _ = ethereum.NotFound
+ _ = bind.Bind
+ _ = common.Big1
+ _ = types.BloomLookup
+ _ = event.NewSubscription
+ _ = abi.ConvertType
+)
+
+// SoulGasTokenMetaData contains all meta data concerning the SoulGasToken contract.
+var SoulGasTokenMetaData = &bind.MetaData{
+ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_isBackedByNative\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addBurners\",\"inputs\":[{\"name\":\"_burners\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addMinters\",\"inputs\":[{\"name\":\"_minters\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowSgtValue\",\"inputs\":[{\"name\":\"_contracts\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"batchBurnFrom\",\"inputs\":[{\"name\":\"_accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"_values\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"batchDepositFor\",\"inputs\":[{\"name\":\"_accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"_values\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"batchDepositForAll\",\"inputs\":[{\"name\":\"_accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"_value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"batchMint\",\"inputs\":[{\"name\":\"_accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"_values\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"batchWithdrawFrom\",\"inputs\":[{\"name\":\"_accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"_values\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"burnFrom\",\"inputs\":[{\"name\":\"_account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"chargeFromOrigin\",\"inputs\":[{\"name\":\"_amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"amountCharged_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decreaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"subtractedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"delBurners\",\"inputs\":[{\"name\":\"_burners\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"delMinters\",\"inputs\":[{\"name\":\"_minters\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"disallowSgtValue\",\"inputs\":[{\"name\":\"_contracts\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"increaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"addedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_name\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_symbol\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isBackedByNative\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFrom\",\"inputs\":[{\"name\":\"_account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AllowSgtValue\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DisallowSgtValue\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]",
+}
+
+// SoulGasTokenABI is the input ABI used to generate the binding from.
+// Deprecated: Use SoulGasTokenMetaData.ABI instead.
+var SoulGasTokenABI = SoulGasTokenMetaData.ABI
+
+// SoulGasToken is an auto generated Go binding around an Ethereum contract.
+type SoulGasToken struct {
+ SoulGasTokenCaller // Read-only binding to the contract
+ SoulGasTokenTransactor // Write-only binding to the contract
+ SoulGasTokenFilterer // Log filterer for contract events
+}
+
+// SoulGasTokenCaller is an auto generated read-only Go binding around an Ethereum contract.
+type SoulGasTokenCaller struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// SoulGasTokenTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type SoulGasTokenTransactor struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// SoulGasTokenFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type SoulGasTokenFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// SoulGasTokenSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type SoulGasTokenSession struct {
+ Contract *SoulGasToken // Generic contract binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// SoulGasTokenCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type SoulGasTokenCallerSession struct {
+ Contract *SoulGasTokenCaller // Generic contract caller binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+}
+
+// SoulGasTokenTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type SoulGasTokenTransactorSession struct {
+ Contract *SoulGasTokenTransactor // Generic contract transactor binding to set the session for
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// SoulGasTokenRaw is an auto generated low-level Go binding around an Ethereum contract.
+type SoulGasTokenRaw struct {
+ Contract *SoulGasToken // Generic contract binding to access the raw methods on
+}
+
+// SoulGasTokenCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type SoulGasTokenCallerRaw struct {
+ Contract *SoulGasTokenCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// SoulGasTokenTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type SoulGasTokenTransactorRaw struct {
+ Contract *SoulGasTokenTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewSoulGasToken creates a new instance of SoulGasToken, bound to a specific deployed contract.
+func NewSoulGasToken(address common.Address, backend bind.ContractBackend) (*SoulGasToken, error) {
+ contract, err := bindSoulGasToken(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasToken{SoulGasTokenCaller: SoulGasTokenCaller{contract: contract}, SoulGasTokenTransactor: SoulGasTokenTransactor{contract: contract}, SoulGasTokenFilterer: SoulGasTokenFilterer{contract: contract}}, nil
+}
+
+// NewSoulGasTokenCaller creates a new read-only instance of SoulGasToken, bound to a specific deployed contract.
+func NewSoulGasTokenCaller(address common.Address, caller bind.ContractCaller) (*SoulGasTokenCaller, error) {
+ contract, err := bindSoulGasToken(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasTokenCaller{contract: contract}, nil
+}
+
+// NewSoulGasTokenTransactor creates a new write-only instance of SoulGasToken, bound to a specific deployed contract.
+func NewSoulGasTokenTransactor(address common.Address, transactor bind.ContractTransactor) (*SoulGasTokenTransactor, error) {
+ contract, err := bindSoulGasToken(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasTokenTransactor{contract: contract}, nil
+}
+
+// NewSoulGasTokenFilterer creates a new log filterer instance of SoulGasToken, bound to a specific deployed contract.
+func NewSoulGasTokenFilterer(address common.Address, filterer bind.ContractFilterer) (*SoulGasTokenFilterer, error) {
+ contract, err := bindSoulGasToken(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasTokenFilterer{contract: contract}, nil
+}
+
+// bindSoulGasToken binds a generic wrapper to an already deployed contract.
+func bindSoulGasToken(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := SoulGasTokenMetaData.GetAbi()
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_SoulGasToken *SoulGasTokenRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _SoulGasToken.Contract.SoulGasTokenCaller.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_SoulGasToken *SoulGasTokenRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.SoulGasTokenTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_SoulGasToken *SoulGasTokenRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.SoulGasTokenTransactor.contract.Transact(opts, method, params...)
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_SoulGasToken *SoulGasTokenCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _SoulGasToken.Contract.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_SoulGasToken *SoulGasTokenTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_SoulGasToken *SoulGasTokenTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.contract.Transact(opts, method, params...)
+}
+
+// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e.
+//
+// Solidity: function allowance(address owner, address spender) view returns(uint256)
+func (_SoulGasToken *SoulGasTokenCaller) Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) {
+ var out []interface{}
+ err := _SoulGasToken.contract.Call(opts, &out, "allowance", owner, spender)
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e.
+//
+// Solidity: function allowance(address owner, address spender) view returns(uint256)
+func (_SoulGasToken *SoulGasTokenSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) {
+ return _SoulGasToken.Contract.Allowance(&_SoulGasToken.CallOpts, owner, spender)
+}
+
+// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e.
+//
+// Solidity: function allowance(address owner, address spender) view returns(uint256)
+func (_SoulGasToken *SoulGasTokenCallerSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) {
+ return _SoulGasToken.Contract.Allowance(&_SoulGasToken.CallOpts, owner, spender)
+}
+
+// BalanceOf is a free data retrieval call binding the contract method 0x70a08231.
+//
+// Solidity: function balanceOf(address account) view returns(uint256)
+func (_SoulGasToken *SoulGasTokenCaller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) {
+ var out []interface{}
+ err := _SoulGasToken.contract.Call(opts, &out, "balanceOf", account)
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// BalanceOf is a free data retrieval call binding the contract method 0x70a08231.
+//
+// Solidity: function balanceOf(address account) view returns(uint256)
+func (_SoulGasToken *SoulGasTokenSession) BalanceOf(account common.Address) (*big.Int, error) {
+ return _SoulGasToken.Contract.BalanceOf(&_SoulGasToken.CallOpts, account)
+}
+
+// BalanceOf is a free data retrieval call binding the contract method 0x70a08231.
+//
+// Solidity: function balanceOf(address account) view returns(uint256)
+func (_SoulGasToken *SoulGasTokenCallerSession) BalanceOf(account common.Address) (*big.Int, error) {
+ return _SoulGasToken.Contract.BalanceOf(&_SoulGasToken.CallOpts, account)
+}
+
+// Decimals is a free data retrieval call binding the contract method 0x313ce567.
+//
+// Solidity: function decimals() view returns(uint8)
+func (_SoulGasToken *SoulGasTokenCaller) Decimals(opts *bind.CallOpts) (uint8, error) {
+ var out []interface{}
+ err := _SoulGasToken.contract.Call(opts, &out, "decimals")
+
+ if err != nil {
+ return *new(uint8), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8)
+
+ return out0, err
+
+}
+
+// Decimals is a free data retrieval call binding the contract method 0x313ce567.
+//
+// Solidity: function decimals() view returns(uint8)
+func (_SoulGasToken *SoulGasTokenSession) Decimals() (uint8, error) {
+ return _SoulGasToken.Contract.Decimals(&_SoulGasToken.CallOpts)
+}
+
+// Decimals is a free data retrieval call binding the contract method 0x313ce567.
+//
+// Solidity: function decimals() view returns(uint8)
+func (_SoulGasToken *SoulGasTokenCallerSession) Decimals() (uint8, error) {
+ return _SoulGasToken.Contract.Decimals(&_SoulGasToken.CallOpts)
+}
+
+// IsBackedByNative is a free data retrieval call binding the contract method 0xbbd10120.
+//
+// Solidity: function isBackedByNative() view returns(bool)
+func (_SoulGasToken *SoulGasTokenCaller) IsBackedByNative(opts *bind.CallOpts) (bool, error) {
+ var out []interface{}
+ err := _SoulGasToken.contract.Call(opts, &out, "isBackedByNative")
+
+ if err != nil {
+ return *new(bool), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
+
+ return out0, err
+
+}
+
+// IsBackedByNative is a free data retrieval call binding the contract method 0xbbd10120.
+//
+// Solidity: function isBackedByNative() view returns(bool)
+func (_SoulGasToken *SoulGasTokenSession) IsBackedByNative() (bool, error) {
+ return _SoulGasToken.Contract.IsBackedByNative(&_SoulGasToken.CallOpts)
+}
+
+// IsBackedByNative is a free data retrieval call binding the contract method 0xbbd10120.
+//
+// Solidity: function isBackedByNative() view returns(bool)
+func (_SoulGasToken *SoulGasTokenCallerSession) IsBackedByNative() (bool, error) {
+ return _SoulGasToken.Contract.IsBackedByNative(&_SoulGasToken.CallOpts)
+}
+
+// Name is a free data retrieval call binding the contract method 0x06fdde03.
+//
+// Solidity: function name() view returns(string)
+func (_SoulGasToken *SoulGasTokenCaller) Name(opts *bind.CallOpts) (string, error) {
+ var out []interface{}
+ err := _SoulGasToken.contract.Call(opts, &out, "name")
+
+ if err != nil {
+ return *new(string), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(string)).(*string)
+
+ return out0, err
+
+}
+
+// Name is a free data retrieval call binding the contract method 0x06fdde03.
+//
+// Solidity: function name() view returns(string)
+func (_SoulGasToken *SoulGasTokenSession) Name() (string, error) {
+ return _SoulGasToken.Contract.Name(&_SoulGasToken.CallOpts)
+}
+
+// Name is a free data retrieval call binding the contract method 0x06fdde03.
+//
+// Solidity: function name() view returns(string)
+func (_SoulGasToken *SoulGasTokenCallerSession) Name() (string, error) {
+ return _SoulGasToken.Contract.Name(&_SoulGasToken.CallOpts)
+}
+
+// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
+//
+// Solidity: function owner() view returns(address)
+func (_SoulGasToken *SoulGasTokenCaller) Owner(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _SoulGasToken.contract.Call(opts, &out, "owner")
+
+ if err != nil {
+ return *new(common.Address), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
+
+ return out0, err
+
+}
+
+// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
+//
+// Solidity: function owner() view returns(address)
+func (_SoulGasToken *SoulGasTokenSession) Owner() (common.Address, error) {
+ return _SoulGasToken.Contract.Owner(&_SoulGasToken.CallOpts)
+}
+
+// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
+//
+// Solidity: function owner() view returns(address)
+func (_SoulGasToken *SoulGasTokenCallerSession) Owner() (common.Address, error) {
+ return _SoulGasToken.Contract.Owner(&_SoulGasToken.CallOpts)
+}
+
+// Symbol is a free data retrieval call binding the contract method 0x95d89b41.
+//
+// Solidity: function symbol() view returns(string)
+func (_SoulGasToken *SoulGasTokenCaller) Symbol(opts *bind.CallOpts) (string, error) {
+ var out []interface{}
+ err := _SoulGasToken.contract.Call(opts, &out, "symbol")
+
+ if err != nil {
+ return *new(string), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(string)).(*string)
+
+ return out0, err
+
+}
+
+// Symbol is a free data retrieval call binding the contract method 0x95d89b41.
+//
+// Solidity: function symbol() view returns(string)
+func (_SoulGasToken *SoulGasTokenSession) Symbol() (string, error) {
+ return _SoulGasToken.Contract.Symbol(&_SoulGasToken.CallOpts)
+}
+
+// Symbol is a free data retrieval call binding the contract method 0x95d89b41.
+//
+// Solidity: function symbol() view returns(string)
+func (_SoulGasToken *SoulGasTokenCallerSession) Symbol() (string, error) {
+ return _SoulGasToken.Contract.Symbol(&_SoulGasToken.CallOpts)
+}
+
+// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd.
+//
+// Solidity: function totalSupply() view returns(uint256)
+func (_SoulGasToken *SoulGasTokenCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _SoulGasToken.contract.Call(opts, &out, "totalSupply")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd.
+//
+// Solidity: function totalSupply() view returns(uint256)
+func (_SoulGasToken *SoulGasTokenSession) TotalSupply() (*big.Int, error) {
+ return _SoulGasToken.Contract.TotalSupply(&_SoulGasToken.CallOpts)
+}
+
+// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd.
+//
+// Solidity: function totalSupply() view returns(uint256)
+func (_SoulGasToken *SoulGasTokenCallerSession) TotalSupply() (*big.Int, error) {
+ return _SoulGasToken.Contract.TotalSupply(&_SoulGasToken.CallOpts)
+}
+
+// AddBurners is a paid mutator transaction binding the contract method 0x3ab84dd9.
+//
+// Solidity: function addBurners(address[] _burners) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) AddBurners(opts *bind.TransactOpts, _burners []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "addBurners", _burners)
+}
+
+// AddBurners is a paid mutator transaction binding the contract method 0x3ab84dd9.
+//
+// Solidity: function addBurners(address[] _burners) returns()
+func (_SoulGasToken *SoulGasTokenSession) AddBurners(_burners []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.AddBurners(&_SoulGasToken.TransactOpts, _burners)
+}
+
+// AddBurners is a paid mutator transaction binding the contract method 0x3ab84dd9.
+//
+// Solidity: function addBurners(address[] _burners) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) AddBurners(_burners []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.AddBurners(&_SoulGasToken.TransactOpts, _burners)
+}
+
+// AddMinters is a paid mutator transaction binding the contract method 0x71e2a657.
+//
+// Solidity: function addMinters(address[] _minters) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) AddMinters(opts *bind.TransactOpts, _minters []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "addMinters", _minters)
+}
+
+// AddMinters is a paid mutator transaction binding the contract method 0x71e2a657.
+//
+// Solidity: function addMinters(address[] _minters) returns()
+func (_SoulGasToken *SoulGasTokenSession) AddMinters(_minters []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.AddMinters(&_SoulGasToken.TransactOpts, _minters)
+}
+
+// AddMinters is a paid mutator transaction binding the contract method 0x71e2a657.
+//
+// Solidity: function addMinters(address[] _minters) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) AddMinters(_minters []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.AddMinters(&_SoulGasToken.TransactOpts, _minters)
+}
+
+// AllowSgtValue is a paid mutator transaction binding the contract method 0x674e29ea.
+//
+// Solidity: function allowSgtValue(address[] _contracts) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) AllowSgtValue(opts *bind.TransactOpts, _contracts []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "allowSgtValue", _contracts)
+}
+
+// AllowSgtValue is a paid mutator transaction binding the contract method 0x674e29ea.
+//
+// Solidity: function allowSgtValue(address[] _contracts) returns()
+func (_SoulGasToken *SoulGasTokenSession) AllowSgtValue(_contracts []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.AllowSgtValue(&_SoulGasToken.TransactOpts, _contracts)
+}
+
+// AllowSgtValue is a paid mutator transaction binding the contract method 0x674e29ea.
+//
+// Solidity: function allowSgtValue(address[] _contracts) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) AllowSgtValue(_contracts []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.AllowSgtValue(&_SoulGasToken.TransactOpts, _contracts)
+}
+
+// Approve is a paid mutator transaction binding the contract method 0x095ea7b3.
+//
+// Solidity: function approve(address , uint256 ) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactor) Approve(opts *bind.TransactOpts, arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "approve", arg0, arg1)
+}
+
+// Approve is a paid mutator transaction binding the contract method 0x095ea7b3.
+//
+// Solidity: function approve(address , uint256 ) returns(bool)
+func (_SoulGasToken *SoulGasTokenSession) Approve(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.Approve(&_SoulGasToken.TransactOpts, arg0, arg1)
+}
+
+// Approve is a paid mutator transaction binding the contract method 0x095ea7b3.
+//
+// Solidity: function approve(address , uint256 ) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactorSession) Approve(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.Approve(&_SoulGasToken.TransactOpts, arg0, arg1)
+}
+
+// BatchBurnFrom is a paid mutator transaction binding the contract method 0x1b9a7529.
+//
+// Solidity: function batchBurnFrom(address[] _accounts, uint256[] _values) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) BatchBurnFrom(opts *bind.TransactOpts, _accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "batchBurnFrom", _accounts, _values)
+}
+
+// BatchBurnFrom is a paid mutator transaction binding the contract method 0x1b9a7529.
+//
+// Solidity: function batchBurnFrom(address[] _accounts, uint256[] _values) returns()
+func (_SoulGasToken *SoulGasTokenSession) BatchBurnFrom(_accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchBurnFrom(&_SoulGasToken.TransactOpts, _accounts, _values)
+}
+
+// BatchBurnFrom is a paid mutator transaction binding the contract method 0x1b9a7529.
+//
+// Solidity: function batchBurnFrom(address[] _accounts, uint256[] _values) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) BatchBurnFrom(_accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchBurnFrom(&_SoulGasToken.TransactOpts, _accounts, _values)
+}
+
+// BatchDepositFor is a paid mutator transaction binding the contract method 0x299f8170.
+//
+// Solidity: function batchDepositFor(address[] _accounts, uint256[] _values) payable returns()
+func (_SoulGasToken *SoulGasTokenTransactor) BatchDepositFor(opts *bind.TransactOpts, _accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "batchDepositFor", _accounts, _values)
+}
+
+// BatchDepositFor is a paid mutator transaction binding the contract method 0x299f8170.
+//
+// Solidity: function batchDepositFor(address[] _accounts, uint256[] _values) payable returns()
+func (_SoulGasToken *SoulGasTokenSession) BatchDepositFor(_accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchDepositFor(&_SoulGasToken.TransactOpts, _accounts, _values)
+}
+
+// BatchDepositFor is a paid mutator transaction binding the contract method 0x299f8170.
+//
+// Solidity: function batchDepositFor(address[] _accounts, uint256[] _values) payable returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) BatchDepositFor(_accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchDepositFor(&_SoulGasToken.TransactOpts, _accounts, _values)
+}
+
+// BatchDepositForAll is a paid mutator transaction binding the contract method 0x84e08810.
+//
+// Solidity: function batchDepositForAll(address[] _accounts, uint256 _value) payable returns()
+func (_SoulGasToken *SoulGasTokenTransactor) BatchDepositForAll(opts *bind.TransactOpts, _accounts []common.Address, _value *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "batchDepositForAll", _accounts, _value)
+}
+
+// BatchDepositForAll is a paid mutator transaction binding the contract method 0x84e08810.
+//
+// Solidity: function batchDepositForAll(address[] _accounts, uint256 _value) payable returns()
+func (_SoulGasToken *SoulGasTokenSession) BatchDepositForAll(_accounts []common.Address, _value *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchDepositForAll(&_SoulGasToken.TransactOpts, _accounts, _value)
+}
+
+// BatchDepositForAll is a paid mutator transaction binding the contract method 0x84e08810.
+//
+// Solidity: function batchDepositForAll(address[] _accounts, uint256 _value) payable returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) BatchDepositForAll(_accounts []common.Address, _value *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchDepositForAll(&_SoulGasToken.TransactOpts, _accounts, _value)
+}
+
+// BatchMint is a paid mutator transaction binding the contract method 0x68573107.
+//
+// Solidity: function batchMint(address[] _accounts, uint256[] _values) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) BatchMint(opts *bind.TransactOpts, _accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "batchMint", _accounts, _values)
+}
+
+// BatchMint is a paid mutator transaction binding the contract method 0x68573107.
+//
+// Solidity: function batchMint(address[] _accounts, uint256[] _values) returns()
+func (_SoulGasToken *SoulGasTokenSession) BatchMint(_accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchMint(&_SoulGasToken.TransactOpts, _accounts, _values)
+}
+
+// BatchMint is a paid mutator transaction binding the contract method 0x68573107.
+//
+// Solidity: function batchMint(address[] _accounts, uint256[] _values) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) BatchMint(_accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchMint(&_SoulGasToken.TransactOpts, _accounts, _values)
+}
+
+// BatchWithdrawFrom is a paid mutator transaction binding the contract method 0xb3e2a832.
+//
+// Solidity: function batchWithdrawFrom(address[] _accounts, uint256[] _values) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) BatchWithdrawFrom(opts *bind.TransactOpts, _accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "batchWithdrawFrom", _accounts, _values)
+}
+
+// BatchWithdrawFrom is a paid mutator transaction binding the contract method 0xb3e2a832.
+//
+// Solidity: function batchWithdrawFrom(address[] _accounts, uint256[] _values) returns()
+func (_SoulGasToken *SoulGasTokenSession) BatchWithdrawFrom(_accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchWithdrawFrom(&_SoulGasToken.TransactOpts, _accounts, _values)
+}
+
+// BatchWithdrawFrom is a paid mutator transaction binding the contract method 0xb3e2a832.
+//
+// Solidity: function batchWithdrawFrom(address[] _accounts, uint256[] _values) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) BatchWithdrawFrom(_accounts []common.Address, _values []*big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BatchWithdrawFrom(&_SoulGasToken.TransactOpts, _accounts, _values)
+}
+
+// BurnFrom is a paid mutator transaction binding the contract method 0x79cc6790.
+//
+// Solidity: function burnFrom(address _account, uint256 _value) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) BurnFrom(opts *bind.TransactOpts, _account common.Address, _value *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "burnFrom", _account, _value)
+}
+
+// BurnFrom is a paid mutator transaction binding the contract method 0x79cc6790.
+//
+// Solidity: function burnFrom(address _account, uint256 _value) returns()
+func (_SoulGasToken *SoulGasTokenSession) BurnFrom(_account common.Address, _value *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BurnFrom(&_SoulGasToken.TransactOpts, _account, _value)
+}
+
+// BurnFrom is a paid mutator transaction binding the contract method 0x79cc6790.
+//
+// Solidity: function burnFrom(address _account, uint256 _value) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) BurnFrom(_account common.Address, _value *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.BurnFrom(&_SoulGasToken.TransactOpts, _account, _value)
+}
+
+// ChargeFromOrigin is a paid mutator transaction binding the contract method 0xce25c861.
+//
+// Solidity: function chargeFromOrigin(uint256 _amount) returns(uint256 amountCharged_)
+func (_SoulGasToken *SoulGasTokenTransactor) ChargeFromOrigin(opts *bind.TransactOpts, _amount *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "chargeFromOrigin", _amount)
+}
+
+// ChargeFromOrigin is a paid mutator transaction binding the contract method 0xce25c861.
+//
+// Solidity: function chargeFromOrigin(uint256 _amount) returns(uint256 amountCharged_)
+func (_SoulGasToken *SoulGasTokenSession) ChargeFromOrigin(_amount *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.ChargeFromOrigin(&_SoulGasToken.TransactOpts, _amount)
+}
+
+// ChargeFromOrigin is a paid mutator transaction binding the contract method 0xce25c861.
+//
+// Solidity: function chargeFromOrigin(uint256 _amount) returns(uint256 amountCharged_)
+func (_SoulGasToken *SoulGasTokenTransactorSession) ChargeFromOrigin(_amount *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.ChargeFromOrigin(&_SoulGasToken.TransactOpts, _amount)
+}
+
+// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7.
+//
+// Solidity: function decreaseAllowance(address spender, uint256 subtractedValue) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactor) DecreaseAllowance(opts *bind.TransactOpts, spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "decreaseAllowance", spender, subtractedValue)
+}
+
+// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7.
+//
+// Solidity: function decreaseAllowance(address spender, uint256 subtractedValue) returns(bool)
+func (_SoulGasToken *SoulGasTokenSession) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.DecreaseAllowance(&_SoulGasToken.TransactOpts, spender, subtractedValue)
+}
+
+// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7.
+//
+// Solidity: function decreaseAllowance(address spender, uint256 subtractedValue) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactorSession) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.DecreaseAllowance(&_SoulGasToken.TransactOpts, spender, subtractedValue)
+}
+
+// DelBurners is a paid mutator transaction binding the contract method 0xb8de86b4.
+//
+// Solidity: function delBurners(address[] _burners) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) DelBurners(opts *bind.TransactOpts, _burners []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "delBurners", _burners)
+}
+
+// DelBurners is a paid mutator transaction binding the contract method 0xb8de86b4.
+//
+// Solidity: function delBurners(address[] _burners) returns()
+func (_SoulGasToken *SoulGasTokenSession) DelBurners(_burners []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.DelBurners(&_SoulGasToken.TransactOpts, _burners)
+}
+
+// DelBurners is a paid mutator transaction binding the contract method 0xb8de86b4.
+//
+// Solidity: function delBurners(address[] _burners) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) DelBurners(_burners []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.DelBurners(&_SoulGasToken.TransactOpts, _burners)
+}
+
+// DelMinters is a paid mutator transaction binding the contract method 0xe04b8180.
+//
+// Solidity: function delMinters(address[] _minters) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) DelMinters(opts *bind.TransactOpts, _minters []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "delMinters", _minters)
+}
+
+// DelMinters is a paid mutator transaction binding the contract method 0xe04b8180.
+//
+// Solidity: function delMinters(address[] _minters) returns()
+func (_SoulGasToken *SoulGasTokenSession) DelMinters(_minters []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.DelMinters(&_SoulGasToken.TransactOpts, _minters)
+}
+
+// DelMinters is a paid mutator transaction binding the contract method 0xe04b8180.
+//
+// Solidity: function delMinters(address[] _minters) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) DelMinters(_minters []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.DelMinters(&_SoulGasToken.TransactOpts, _minters)
+}
+
+// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0.
+//
+// Solidity: function deposit() payable returns()
+func (_SoulGasToken *SoulGasTokenTransactor) Deposit(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "deposit")
+}
+
+// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0.
+//
+// Solidity: function deposit() payable returns()
+func (_SoulGasToken *SoulGasTokenSession) Deposit() (*types.Transaction, error) {
+ return _SoulGasToken.Contract.Deposit(&_SoulGasToken.TransactOpts)
+}
+
+// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0.
+//
+// Solidity: function deposit() payable returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) Deposit() (*types.Transaction, error) {
+ return _SoulGasToken.Contract.Deposit(&_SoulGasToken.TransactOpts)
+}
+
+// DisallowSgtValue is a paid mutator transaction binding the contract method 0xdc270eb8.
+//
+// Solidity: function disallowSgtValue(address[] _contracts) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) DisallowSgtValue(opts *bind.TransactOpts, _contracts []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "disallowSgtValue", _contracts)
+}
+
+// DisallowSgtValue is a paid mutator transaction binding the contract method 0xdc270eb8.
+//
+// Solidity: function disallowSgtValue(address[] _contracts) returns()
+func (_SoulGasToken *SoulGasTokenSession) DisallowSgtValue(_contracts []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.DisallowSgtValue(&_SoulGasToken.TransactOpts, _contracts)
+}
+
+// DisallowSgtValue is a paid mutator transaction binding the contract method 0xdc270eb8.
+//
+// Solidity: function disallowSgtValue(address[] _contracts) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) DisallowSgtValue(_contracts []common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.DisallowSgtValue(&_SoulGasToken.TransactOpts, _contracts)
+}
+
+// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351.
+//
+// Solidity: function increaseAllowance(address spender, uint256 addedValue) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactor) IncreaseAllowance(opts *bind.TransactOpts, spender common.Address, addedValue *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "increaseAllowance", spender, addedValue)
+}
+
+// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351.
+//
+// Solidity: function increaseAllowance(address spender, uint256 addedValue) returns(bool)
+func (_SoulGasToken *SoulGasTokenSession) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.IncreaseAllowance(&_SoulGasToken.TransactOpts, spender, addedValue)
+}
+
+// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351.
+//
+// Solidity: function increaseAllowance(address spender, uint256 addedValue) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactorSession) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.IncreaseAllowance(&_SoulGasToken.TransactOpts, spender, addedValue)
+}
+
+// Initialize is a paid mutator transaction binding the contract method 0x077f224a.
+//
+// Solidity: function initialize(string _name, string _symbol, address _owner) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) Initialize(opts *bind.TransactOpts, _name string, _symbol string, _owner common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "initialize", _name, _symbol, _owner)
+}
+
+// Initialize is a paid mutator transaction binding the contract method 0x077f224a.
+//
+// Solidity: function initialize(string _name, string _symbol, address _owner) returns()
+func (_SoulGasToken *SoulGasTokenSession) Initialize(_name string, _symbol string, _owner common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.Initialize(&_SoulGasToken.TransactOpts, _name, _symbol, _owner)
+}
+
+// Initialize is a paid mutator transaction binding the contract method 0x077f224a.
+//
+// Solidity: function initialize(string _name, string _symbol, address _owner) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) Initialize(_name string, _symbol string, _owner common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.Initialize(&_SoulGasToken.TransactOpts, _name, _symbol, _owner)
+}
+
+// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.
+//
+// Solidity: function renounceOwnership() returns()
+func (_SoulGasToken *SoulGasTokenTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "renounceOwnership")
+}
+
+// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.
+//
+// Solidity: function renounceOwnership() returns()
+func (_SoulGasToken *SoulGasTokenSession) RenounceOwnership() (*types.Transaction, error) {
+ return _SoulGasToken.Contract.RenounceOwnership(&_SoulGasToken.TransactOpts)
+}
+
+// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.
+//
+// Solidity: function renounceOwnership() returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) RenounceOwnership() (*types.Transaction, error) {
+ return _SoulGasToken.Contract.RenounceOwnership(&_SoulGasToken.TransactOpts)
+}
+
+// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb.
+//
+// Solidity: function transfer(address , uint256 ) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactor) Transfer(opts *bind.TransactOpts, arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "transfer", arg0, arg1)
+}
+
+// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb.
+//
+// Solidity: function transfer(address , uint256 ) returns(bool)
+func (_SoulGasToken *SoulGasTokenSession) Transfer(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.Transfer(&_SoulGasToken.TransactOpts, arg0, arg1)
+}
+
+// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb.
+//
+// Solidity: function transfer(address , uint256 ) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactorSession) Transfer(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.Transfer(&_SoulGasToken.TransactOpts, arg0, arg1)
+}
+
+// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd.
+//
+// Solidity: function transferFrom(address , address , uint256 ) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactor) TransferFrom(opts *bind.TransactOpts, arg0 common.Address, arg1 common.Address, arg2 *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "transferFrom", arg0, arg1, arg2)
+}
+
+// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd.
+//
+// Solidity: function transferFrom(address , address , uint256 ) returns(bool)
+func (_SoulGasToken *SoulGasTokenSession) TransferFrom(arg0 common.Address, arg1 common.Address, arg2 *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.TransferFrom(&_SoulGasToken.TransactOpts, arg0, arg1, arg2)
+}
+
+// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd.
+//
+// Solidity: function transferFrom(address , address , uint256 ) returns(bool)
+func (_SoulGasToken *SoulGasTokenTransactorSession) TransferFrom(arg0 common.Address, arg1 common.Address, arg2 *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.TransferFrom(&_SoulGasToken.TransactOpts, arg0, arg1, arg2)
+}
+
+// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b.
+//
+// Solidity: function transferOwnership(address newOwner) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "transferOwnership", newOwner)
+}
+
+// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b.
+//
+// Solidity: function transferOwnership(address newOwner) returns()
+func (_SoulGasToken *SoulGasTokenSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.TransferOwnership(&_SoulGasToken.TransactOpts, newOwner)
+}
+
+// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b.
+//
+// Solidity: function transferOwnership(address newOwner) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.TransferOwnership(&_SoulGasToken.TransactOpts, newOwner)
+}
+
+// WithdrawFrom is a paid mutator transaction binding the contract method 0x9470b0bd.
+//
+// Solidity: function withdrawFrom(address _account, uint256 _value) returns()
+func (_SoulGasToken *SoulGasTokenTransactor) WithdrawFrom(opts *bind.TransactOpts, _account common.Address, _value *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.contract.Transact(opts, "withdrawFrom", _account, _value)
+}
+
+// WithdrawFrom is a paid mutator transaction binding the contract method 0x9470b0bd.
+//
+// Solidity: function withdrawFrom(address _account, uint256 _value) returns()
+func (_SoulGasToken *SoulGasTokenSession) WithdrawFrom(_account common.Address, _value *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.WithdrawFrom(&_SoulGasToken.TransactOpts, _account, _value)
+}
+
+// WithdrawFrom is a paid mutator transaction binding the contract method 0x9470b0bd.
+//
+// Solidity: function withdrawFrom(address _account, uint256 _value) returns()
+func (_SoulGasToken *SoulGasTokenTransactorSession) WithdrawFrom(_account common.Address, _value *big.Int) (*types.Transaction, error) {
+ return _SoulGasToken.Contract.WithdrawFrom(&_SoulGasToken.TransactOpts, _account, _value)
+}
+
+// SoulGasTokenAllowSgtValueIterator is returned from FilterAllowSgtValue and is used to iterate over the raw logs and unpacked data for AllowSgtValue events raised by the SoulGasToken contract.
+type SoulGasTokenAllowSgtValueIterator struct {
+ Event *SoulGasTokenAllowSgtValue // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *SoulGasTokenAllowSgtValueIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenAllowSgtValue)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenAllowSgtValue)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error returns any retrieval or parsing error occurred during filtering.
+func (it *SoulGasTokenAllowSgtValueIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *SoulGasTokenAllowSgtValueIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// SoulGasTokenAllowSgtValue represents a AllowSgtValue event raised by the SoulGasToken contract.
+type SoulGasTokenAllowSgtValue struct {
+ From common.Address
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterAllowSgtValue is a free log retrieval operation binding the contract event 0xf135aca2ee4483470b8f44f38ab676fc36fc67437777f3c520e5fbeb3706009f.
+//
+// Solidity: event AllowSgtValue(address indexed from)
+func (_SoulGasToken *SoulGasTokenFilterer) FilterAllowSgtValue(opts *bind.FilterOpts, from []common.Address) (*SoulGasTokenAllowSgtValueIterator, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.FilterLogs(opts, "AllowSgtValue", fromRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasTokenAllowSgtValueIterator{contract: _SoulGasToken.contract, event: "AllowSgtValue", logs: logs, sub: sub}, nil
+}
+
+// WatchAllowSgtValue is a free log subscription operation binding the contract event 0xf135aca2ee4483470b8f44f38ab676fc36fc67437777f3c520e5fbeb3706009f.
+//
+// Solidity: event AllowSgtValue(address indexed from)
+func (_SoulGasToken *SoulGasTokenFilterer) WatchAllowSgtValue(opts *bind.WatchOpts, sink chan<- *SoulGasTokenAllowSgtValue, from []common.Address) (event.Subscription, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.WatchLogs(opts, "AllowSgtValue", fromRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(SoulGasTokenAllowSgtValue)
+ if err := _SoulGasToken.contract.UnpackLog(event, "AllowSgtValue", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ParseAllowSgtValue is a log parse operation binding the contract event 0xf135aca2ee4483470b8f44f38ab676fc36fc67437777f3c520e5fbeb3706009f.
+//
+// Solidity: event AllowSgtValue(address indexed from)
+func (_SoulGasToken *SoulGasTokenFilterer) ParseAllowSgtValue(log types.Log) (*SoulGasTokenAllowSgtValue, error) {
+ event := new(SoulGasTokenAllowSgtValue)
+ if err := _SoulGasToken.contract.UnpackLog(event, "AllowSgtValue", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+// SoulGasTokenApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the SoulGasToken contract.
+type SoulGasTokenApprovalIterator struct {
+ Event *SoulGasTokenApproval // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *SoulGasTokenApprovalIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenApproval)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenApproval)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error returns any retrieval or parsing error occurred during filtering.
+func (it *SoulGasTokenApprovalIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *SoulGasTokenApprovalIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// SoulGasTokenApproval represents a Approval event raised by the SoulGasToken contract.
+type SoulGasTokenApproval struct {
+ Owner common.Address
+ Spender common.Address
+ Value *big.Int
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925.
+//
+// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value)
+func (_SoulGasToken *SoulGasTokenFilterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*SoulGasTokenApprovalIterator, error) {
+
+ var ownerRule []interface{}
+ for _, ownerItem := range owner {
+ ownerRule = append(ownerRule, ownerItem)
+ }
+ var spenderRule []interface{}
+ for _, spenderItem := range spender {
+ spenderRule = append(spenderRule, spenderItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasTokenApprovalIterator{contract: _SoulGasToken.contract, event: "Approval", logs: logs, sub: sub}, nil
+}
+
+// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925.
+//
+// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value)
+func (_SoulGasToken *SoulGasTokenFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *SoulGasTokenApproval, owner []common.Address, spender []common.Address) (event.Subscription, error) {
+
+ var ownerRule []interface{}
+ for _, ownerItem := range owner {
+ ownerRule = append(ownerRule, ownerItem)
+ }
+ var spenderRule []interface{}
+ for _, spenderItem := range spender {
+ spenderRule = append(spenderRule, spenderItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.WatchLogs(opts, "Approval", ownerRule, spenderRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(SoulGasTokenApproval)
+ if err := _SoulGasToken.contract.UnpackLog(event, "Approval", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925.
+//
+// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value)
+func (_SoulGasToken *SoulGasTokenFilterer) ParseApproval(log types.Log) (*SoulGasTokenApproval, error) {
+ event := new(SoulGasTokenApproval)
+ if err := _SoulGasToken.contract.UnpackLog(event, "Approval", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+// SoulGasTokenDisallowSgtValueIterator is returned from FilterDisallowSgtValue and is used to iterate over the raw logs and unpacked data for DisallowSgtValue events raised by the SoulGasToken contract.
+type SoulGasTokenDisallowSgtValueIterator struct {
+ Event *SoulGasTokenDisallowSgtValue // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *SoulGasTokenDisallowSgtValueIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenDisallowSgtValue)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenDisallowSgtValue)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error returns any retrieval or parsing error occurred during filtering.
+func (it *SoulGasTokenDisallowSgtValueIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *SoulGasTokenDisallowSgtValueIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// SoulGasTokenDisallowSgtValue represents a DisallowSgtValue event raised by the SoulGasToken contract.
+type SoulGasTokenDisallowSgtValue struct {
+ From common.Address
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterDisallowSgtValue is a free log retrieval operation binding the contract event 0x42d3350598a4a2ec6e60463e0bffa1aab494a9e8d4484b017270dde628b4edb1.
+//
+// Solidity: event DisallowSgtValue(address indexed from)
+func (_SoulGasToken *SoulGasTokenFilterer) FilterDisallowSgtValue(opts *bind.FilterOpts, from []common.Address) (*SoulGasTokenDisallowSgtValueIterator, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.FilterLogs(opts, "DisallowSgtValue", fromRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasTokenDisallowSgtValueIterator{contract: _SoulGasToken.contract, event: "DisallowSgtValue", logs: logs, sub: sub}, nil
+}
+
+// WatchDisallowSgtValue is a free log subscription operation binding the contract event 0x42d3350598a4a2ec6e60463e0bffa1aab494a9e8d4484b017270dde628b4edb1.
+//
+// Solidity: event DisallowSgtValue(address indexed from)
+func (_SoulGasToken *SoulGasTokenFilterer) WatchDisallowSgtValue(opts *bind.WatchOpts, sink chan<- *SoulGasTokenDisallowSgtValue, from []common.Address) (event.Subscription, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.WatchLogs(opts, "DisallowSgtValue", fromRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(SoulGasTokenDisallowSgtValue)
+ if err := _SoulGasToken.contract.UnpackLog(event, "DisallowSgtValue", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ParseDisallowSgtValue is a log parse operation binding the contract event 0x42d3350598a4a2ec6e60463e0bffa1aab494a9e8d4484b017270dde628b4edb1.
+//
+// Solidity: event DisallowSgtValue(address indexed from)
+func (_SoulGasToken *SoulGasTokenFilterer) ParseDisallowSgtValue(log types.Log) (*SoulGasTokenDisallowSgtValue, error) {
+ event := new(SoulGasTokenDisallowSgtValue)
+ if err := _SoulGasToken.contract.UnpackLog(event, "DisallowSgtValue", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+// SoulGasTokenInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the SoulGasToken contract.
+type SoulGasTokenInitializedIterator struct {
+ Event *SoulGasTokenInitialized // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *SoulGasTokenInitializedIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenInitialized)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenInitialized)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error returns any retrieval or parsing error occurred during filtering.
+func (it *SoulGasTokenInitializedIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *SoulGasTokenInitializedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// SoulGasTokenInitialized represents a Initialized event raised by the SoulGasToken contract.
+type SoulGasTokenInitialized struct {
+ Version uint8
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498.
+//
+// Solidity: event Initialized(uint8 version)
+func (_SoulGasToken *SoulGasTokenFilterer) FilterInitialized(opts *bind.FilterOpts) (*SoulGasTokenInitializedIterator, error) {
+
+ logs, sub, err := _SoulGasToken.contract.FilterLogs(opts, "Initialized")
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasTokenInitializedIterator{contract: _SoulGasToken.contract, event: "Initialized", logs: logs, sub: sub}, nil
+}
+
+// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498.
+//
+// Solidity: event Initialized(uint8 version)
+func (_SoulGasToken *SoulGasTokenFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *SoulGasTokenInitialized) (event.Subscription, error) {
+
+ logs, sub, err := _SoulGasToken.contract.WatchLogs(opts, "Initialized")
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(SoulGasTokenInitialized)
+ if err := _SoulGasToken.contract.UnpackLog(event, "Initialized", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498.
+//
+// Solidity: event Initialized(uint8 version)
+func (_SoulGasToken *SoulGasTokenFilterer) ParseInitialized(log types.Log) (*SoulGasTokenInitialized, error) {
+ event := new(SoulGasTokenInitialized)
+ if err := _SoulGasToken.contract.UnpackLog(event, "Initialized", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+// SoulGasTokenOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the SoulGasToken contract.
+type SoulGasTokenOwnershipTransferredIterator struct {
+ Event *SoulGasTokenOwnershipTransferred // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *SoulGasTokenOwnershipTransferredIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenOwnershipTransferred)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenOwnershipTransferred)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error returns any retrieval or parsing error occurred during filtering.
+func (it *SoulGasTokenOwnershipTransferredIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *SoulGasTokenOwnershipTransferredIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// SoulGasTokenOwnershipTransferred represents a OwnershipTransferred event raised by the SoulGasToken contract.
+type SoulGasTokenOwnershipTransferred struct {
+ PreviousOwner common.Address
+ NewOwner common.Address
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
+//
+// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
+func (_SoulGasToken *SoulGasTokenFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*SoulGasTokenOwnershipTransferredIterator, error) {
+
+ var previousOwnerRule []interface{}
+ for _, previousOwnerItem := range previousOwner {
+ previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
+ }
+ var newOwnerRule []interface{}
+ for _, newOwnerItem := range newOwner {
+ newOwnerRule = append(newOwnerRule, newOwnerItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasTokenOwnershipTransferredIterator{contract: _SoulGasToken.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil
+}
+
+// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
+//
+// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
+func (_SoulGasToken *SoulGasTokenFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *SoulGasTokenOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) {
+
+ var previousOwnerRule []interface{}
+ for _, previousOwnerItem := range previousOwner {
+ previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
+ }
+ var newOwnerRule []interface{}
+ for _, newOwnerItem := range newOwner {
+ newOwnerRule = append(newOwnerRule, newOwnerItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(SoulGasTokenOwnershipTransferred)
+ if err := _SoulGasToken.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
+//
+// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
+func (_SoulGasToken *SoulGasTokenFilterer) ParseOwnershipTransferred(log types.Log) (*SoulGasTokenOwnershipTransferred, error) {
+ event := new(SoulGasTokenOwnershipTransferred)
+ if err := _SoulGasToken.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+// SoulGasTokenTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the SoulGasToken contract.
+type SoulGasTokenTransferIterator struct {
+ Event *SoulGasTokenTransfer // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *SoulGasTokenTransferIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenTransfer)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(SoulGasTokenTransfer)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error returns any retrieval or parsing error occurred during filtering.
+func (it *SoulGasTokenTransferIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *SoulGasTokenTransferIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// SoulGasTokenTransfer represents a Transfer event raised by the SoulGasToken contract.
+type SoulGasTokenTransfer struct {
+ From common.Address
+ To common.Address
+ Value *big.Int
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef.
+//
+// Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
+func (_SoulGasToken *SoulGasTokenFilterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*SoulGasTokenTransferIterator, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+ var toRule []interface{}
+ for _, toItem := range to {
+ toRule = append(toRule, toItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.FilterLogs(opts, "Transfer", fromRule, toRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SoulGasTokenTransferIterator{contract: _SoulGasToken.contract, event: "Transfer", logs: logs, sub: sub}, nil
+}
+
+// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef.
+//
+// Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
+func (_SoulGasToken *SoulGasTokenFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *SoulGasTokenTransfer, from []common.Address, to []common.Address) (event.Subscription, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+ var toRule []interface{}
+ for _, toItem := range to {
+ toRule = append(toRule, toItem)
+ }
+
+ logs, sub, err := _SoulGasToken.contract.WatchLogs(opts, "Transfer", fromRule, toRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(SoulGasTokenTransfer)
+ if err := _SoulGasToken.contract.UnpackLog(event, "Transfer", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef.
+//
+// Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
+func (_SoulGasToken *SoulGasTokenFilterer) ParseTransfer(log types.Log) (*SoulGasTokenTransfer, error) {
+ event := new(SoulGasTokenTransfer)
+ if err := _SoulGasToken.contract.UnpackLog(event, "Transfer", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
diff --git official optimism/op-e2e/config/init.go SWC optimism/op-e2e/config/init.go
index 04aa0fd6209255e73448ed50431e546060c61ada..77a4dd855ddc7d03c393b356ced5ec3f9f0585ce 100644
--- official optimism/op-e2e/config/init.go
+++ SWC optimism/op-e2e/config/init.go
@@ -250,6 +250,10 @@ "l2GenesisFjordTimeOffset": nil,
"l2GenesisGraniteTimeOffset": nil,
"l2GenesisHoloceneTimeOffset": nil,
"l2GenesisIsthmusTimeOffset": nil,
+ // SWC changes
+ "deploySoulGasToken": true,
+ "isSoulBackedByNative": true,
+ "soulGasTokenTimeOffset": "0x0",
}
upgradeSchedule := new(genesis.UpgradeScheduleDeployConfig)
@@ -306,6 +310,9 @@ dc.FundDevAccounts = true
// Speed up the in memory tests
dc.L1BlockTime = 2
dc.L2BlockTime = 1
+ if !(dc.DeploySoulGasToken && dc.IsSoulBackedByNative) {
+ panic("Soul gas token must be deployed and backed by native")
+ }
dc.SetContracts(l1Contracts)
mtx.Lock()
deployConfigsByType[allocType] = dc
diff --git official optimism/op-e2e/inbox/inbox_test.go SWC optimism/op-e2e/inbox/inbox_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..f391043878b726104d13da324b7a6746cd01d828
--- /dev/null
+++ SWC optimism/op-e2e/inbox/inbox_test.go
@@ -0,0 +1,148 @@
+package inbox
+
+import (
+ "context"
+ "math/big"
+ "testing"
+ "time"
+
+ batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
+ op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
+ "github.com/ethereum-optimism/optimism/op-e2e/bindings"
+ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
+ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/ethclient"
+ "github.com/stretchr/testify/require"
+)
+
+var (
+ ctx, _ = context.WithTimeout(context.Background(), 20*time.Second)
+ cost = big.NewInt(1500000000000000)
+)
+
+func TestBatchInboxFunctionSuccess(t *testing.T) {
+ op_e2e.InitParallel(t)
+
+ sys, l1Client := startSystemWithBatchInboxContract(t)
+ t.Cleanup(sys.Close)
+
+ // Wait for batch submitted and check event
+ requireEventualBatcherTx(t, &sys.Cfg, l1Client, 8*time.Second)
+}
+
+func startSystemWithBatchInboxContract(t *testing.T) (*e2esys.System, *ethclient.Client) {
+ cfg := e2esys.DefaultSystemConfig(t)
+ cfg.DataAvailabilityType = batcherFlags.BlobsType
+ cfg.BatcherTargetNumFrames = 6
+ cfg.DeployConfig.UseInboxContract = true
+ c, ok := cfg.Nodes["sequencer"]
+ require.True(t, ok, "sequencer is required")
+ c.Driver.SequencerEnabled = true
+
+ sys, err := cfg.Start(t, e2esys.StartOption{
+ Key: "afterL1Start",
+ Action: func(cfg *e2esys.SystemConfig, s *e2esys.System) {
+ l1Client := s.NodeClient(e2esys.RoleL1)
+ // Deploy mock storage contract
+ mockStorageAddr := deployContract(t, cfg, l1Client, bindings.MockEthStorageMetaData, cost)
+ // Deploy BatchInbox.sol contract
+ batchInboxAddr := deployContract(t, cfg, l1Client, bindings.BatchInboxMetaData, mockStorageAddr)
+ t.Logf("mock storage %s, batchInbox %s", mockStorageAddr.Hex(), batchInboxAddr.Hex())
+ // Set BatchInboxAddress
+ cfg.DeployConfig.BatchInboxAddress = batchInboxAddr
+ // Deposit token
+ transferNativeTokenToBatchInboxAddress(t, cfg, l1Client, new(big.Int).Mul(cost, big.NewInt(1000)))
+ },
+ })
+ require.Nil(t, err, "Error starting up system")
+ return sys, sys.NodeClient(e2esys.RoleL1)
+}
+
+func requireEventualBatcherTx(t *testing.T, cfg *e2esys.SystemConfig, l1Client *ethclient.Client, timeout time.Duration) {
+ require.Eventually(t, func() bool {
+ b, err := l1Client.BlockByNumber(ctx, nil)
+ require.NoError(t, err)
+ for _, tx := range b.Transactions() {
+ if tx.To() == nil || tx.To().Cmp(cfg.DeployConfig.BatchInboxAddress) != 0 {
+ continue
+ }
+ receipt, err := l1Client.TransactionReceipt(ctx, tx.Hash())
+ require.NoError(t, err)
+ if len(receipt.Logs) == 0 {
+ continue
+ }
+ balanceBefore, err := l1Client.BalanceAt(ctx, receipt.Logs[0].Address, new(big.Int).Add(receipt.BlockNumber, big.NewInt(-1)))
+ require.NoError(t, err)
+ balanceAfter, err := l1Client.BalanceAt(ctx, receipt.Logs[0].Address, receipt.BlockNumber)
+ require.NoError(t, err)
+ require.True(t, balanceAfter.Uint64()-balanceBefore.Uint64() == cost.Uint64()*uint64(len(receipt.Logs)), "Cost is mismatch")
+ return true
+ }
+ return false
+ }, timeout, time.Second, "expected batcher tx type didn't arrive")
+}
+
+func deployContract(t *testing.T, cfg *e2esys.SystemConfig, client *ethclient.Client, meta *bind.MetaData,
+ params ...interface{}) common.Address {
+ ethPrivKey := cfg.Secrets.Batcher
+ fromAddr := cfg.Secrets.Addresses().Batcher
+
+ nonce, err := client.PendingNonceAt(context.Background(), fromAddr)
+ require.NoError(t, err)
+ gasPrice, err := client.SuggestGasPrice(context.Background())
+ require.NoError(t, err)
+
+ auth, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig())
+ require.NoError(t, err)
+ auth.Nonce = big.NewInt(int64(nonce))
+ auth.Value = big.NewInt(0)
+ auth.GasLimit = uint64(3000000)
+ auth.GasPrice = gasPrice
+
+ parsed, err := meta.GetAbi()
+ require.NoError(t, err)
+
+ address, tx, _, err := bind.DeployContract(auth, *parsed, common.FromHex(meta.Bin), client, params...)
+ require.NoError(t, err)
+
+ _, err = wait.ForReceiptOK(ctx, client, tx.Hash())
+ require.NoError(t, err)
+ return address
+}
+
+func transferNativeTokenToBatchInboxAddress(t *testing.T, cfg *e2esys.SystemConfig, client *ethclient.Client, amount *big.Int) {
+ ethPrivKey := cfg.Secrets.Batcher
+ fromAddr := cfg.Secrets.Addresses().Batcher
+
+ gasTipCap, err := client.SuggestGasTipCap(ctx)
+ require.NoError(t, err)
+ head, err := client.HeaderByNumber(ctx, nil)
+ require.NoError(t, err)
+ gasFeeCap := new(big.Int).Add(
+ gasTipCap,
+ new(big.Int).Mul(head.BaseFee, big.NewInt(2)),
+ )
+
+ nonce, err := client.NonceAt(ctx, fromAddr, nil)
+ require.NoError(t, err)
+ tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L1ChainIDBig()), &types.DynamicFeeTx{
+ ChainID: cfg.L1ChainIDBig(),
+ Nonce: nonce,
+ To: &cfg.DeployConfig.BatchInboxAddress,
+ Value: amount,
+ GasTipCap: gasTipCap,
+ GasFeeCap: gasFeeCap,
+ Gas: 1000000,
+ })
+ err = client.SendTransaction(ctx, tx)
+ require.NoError(t, err)
+ _, err = wait.ForReceiptOK(context.Background(), client, tx.Hash())
+ require.NoError(t, err)
+
+ balance, err := client.BalanceAt(ctx, cfg.DeployConfig.BatchInboxAddress, nil)
+ require.NoError(t, err)
+ require.True(t, balance.Uint64() == amount.Uint64(), "balance no match")
+}
diff --git official optimism/op-e2e/inbox/testcontract/mockstorage.sol SWC optimism/op-e2e/inbox/testcontract/mockstorage.sol
new file mode 100644
index 0000000000000000000000000000000000000000..f3316089c47a51ed4f10b8648cdf6a495f4358b8
--- /dev/null
+++ SWC optimism/op-e2e/inbox/testcontract/mockstorage.sol
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.24;
+
+contract EthStorageContract {
+ uint256 internal immutable COST;
+ uint256 public kvEntryCount;
+
+ /// @notice Emitted when a BLOB is appended.
+ /// @param kvIdx The index of the KV pair
+ /// @param kvSize The size of the KV pair
+ /// @param dataHash The hash of the data
+ event PutBlob(uint256 indexed kvIdx, uint256 indexed kvSize, bytes32 indexed dataHash);
+
+ constructor(uint256 _cost) {
+ COST = _cost;
+ }
+
+ /// @notice Write a large value to KV store. If the KV pair exists, overrides it.
+ /// Otherwise, will append the KV to the KV array.
+ /// @param _key The key of the KV pair
+ /// @param _blobIdx The index of the blob
+ /// @param _length The length of the blob
+ function putBlob(bytes32 _key, uint256 _blobIdx, uint256 _length) public payable virtual {
+ bytes32 dataHash = blobhash(_blobIdx);
+ require(dataHash != 0, "EthStorageContract: failed to get blob hash");
+ require(_key != 0, "EthStorageContract: failed to get blob key");
+ require(msg.value >= upfrontPayment(), "DecentralizedKV: not enough batch payment");
+
+ uint256 kvIndex = kvEntryCount;
+ kvEntryCount = kvEntryCount + 1;
+
+ emit PutBlob(kvIndex, _length, dataHash);
+ }
+
+ /// @notice Evaluate the storage cost of a single put().
+ function upfrontPayment() public view virtual returns (uint256) {
+ return COST ;
+ }
+}
diff --git official optimism/op-e2e/l2blob/l2blob_test.go SWC optimism/op-e2e/l2blob/l2blob_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..3ac21abf112b3b39f06dce54c90e4e3623b69aab
--- /dev/null
+++ SWC optimism/op-e2e/l2blob/l2blob_test.go
@@ -0,0 +1,175 @@
+package l2blob
+
+import (
+ "bytes"
+ "context"
+ "crypto/ecdsa"
+ "errors"
+ "fmt"
+ "math/big"
+ mrand "math/rand"
+ "testing"
+ "time"
+
+ op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
+ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
+ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys"
+ "github.com/ethereum-optimism/optimism/op-node/config"
+ "github.com/ethereum-optimism/optimism/op-service/eth"
+ "github.com/ethereum-optimism/optimism/op-service/testutils"
+ "github.com/ethereum-optimism/optimism/op-service/txmgr"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethclient"
+ "github.com/ethstorage/da-server/pkg/da"
+ "github.com/ethstorage/da-server/pkg/da/client"
+ "github.com/holiman/uint256"
+ "github.com/stretchr/testify/require"
+)
+
+const (
+ dacPort = 37777
+)
+
+var (
+ ctx, _ = context.WithTimeout(context.Background(), 10*time.Second)
+ dacUrl = fmt.Sprintf("http://127.0.0.1:%d", dacPort)
+)
+
+func TestSubmitTXWithBlobsFunctionSuccess(t *testing.T) {
+ op_e2e.InitParallel(t)
+ dacServer := startDACServer(t)
+ defer func() {
+ if err := dacServer.Stop(ctx); err != nil {
+ t.Errorf("Failed to stop DAC server: %v", err)
+ }
+ }()
+
+ sys, l2Client := startSystemWithDAC(t)
+ t.Cleanup(sys.Close)
+
+ var (
+ toAddress = testutils.RandomAddress(mrand.New(mrand.NewSource(dacPort)))
+ blobs = make([]*eth.Blob, 3)
+ )
+ for i := range blobs {
+ b := getRandBlob(t, int64(i))
+ blobs[i] = &b
+ }
+
+ tx, err := sendTransactionWithBlobs(t, ctx, l2Client, sys.TestAccount(0), toAddress, blobs)
+ require.NoError(t, err)
+ _, err = wait.ForReceiptOK(ctx, l2Client, tx.Hash())
+ require.NoError(t, err)
+
+ dblobs, err := downloadBlobs(dacUrl, tx.BlobHashes())
+ require.NoError(t, err)
+ require.True(t, len(dblobs) == len(tx.BlobHashes()), "blobs downloaded is not equal to blob hashes")
+
+ for i, blob := range dblobs {
+ require.True(t, len(blob) == eth.BlobSize, fmt.Sprintf("invalid downloaded blob, index %d; len %d", i, len(blob)))
+ require.True(t, bytes.Equal(blob, blobs[i][:]), fmt.Sprintf("blob content diff: %s vs %s",
+ common.Bytes2Hex(blob[:32]), common.Bytes2Hex(blobs[i][:32])))
+ }
+}
+
+func startSystemWithDAC(t *testing.T) (*e2esys.System, *ethclient.Client) {
+ cfg := e2esys.IsthmusSystemConfig(t, new(hexutil.Uint64))
+ delete(cfg.Nodes, "verifier")
+ c, ok := cfg.Nodes["sequencer"]
+ require.True(t, ok, "sequencer is required")
+ c.DACConfig = &config.DACConfig{URLS: []string{dacUrl}}
+ c.Driver.SequencerEnabled = true
+ cfg.DeployConfig.L2GenesisBlobTimeOffset = new(hexutil.Uint64)
+ // Disable proposer creating fast games automatically - required games are manually created
+ cfg.DisableProposer = true
+ sys, err := cfg.Start(t)
+ require.Nil(t, err, "Error starting up system")
+ return sys, sys.NodeClient(e2esys.RoleSeq)
+}
+
+func sendTransactionWithBlobs(t *testing.T, ctx context.Context, l2Client *ethclient.Client, sender *ecdsa.PrivateKey,
+ toAddr common.Address, blobs []*eth.Blob) (*types.Transaction, error) {
+ chainID, err := l2Client.ChainID(ctx)
+ require.NoError(t, err)
+ gasTipCap, gasFeeCap, blobFeeCap, err := gasPriceEstimator(ctx, l2Client)
+ require.NoError(t, err)
+ nonce, err := l2Client.NonceAt(ctx, crypto.PubkeyToAddress(sender.PublicKey), nil)
+ require.NoError(t, err)
+ sidecar, blobHashes, err := txmgr.MakeSidecar(blobs)
+ require.NoError(t, err)
+ tx := types.MustSignNewTx(sender, types.LatestSignerForChainID(chainID), &types.BlobTx{
+ ChainID: uint256.NewInt(chainID.Uint64()),
+ Nonce: nonce,
+ GasFeeCap: uint256.NewInt(gasFeeCap.Uint64()),
+ GasTipCap: uint256.NewInt(gasTipCap.Uint64()),
+ Gas: uint64(22000),
+ To: toAddr,
+ Value: uint256.NewInt(0),
+ BlobFeeCap: uint256.NewInt(blobFeeCap.Uint64()),
+ BlobHashes: blobHashes,
+ Sidecar: sidecar,
+ })
+ ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
+ defer cancel()
+ err = l2Client.SendTransaction(ctx, tx)
+ return tx, err
+}
+
+func gasPriceEstimator(ctx context.Context, client *ethclient.Client) (*big.Int, *big.Int, *big.Int, error) {
+ tip, err := client.SuggestGasTipCap(ctx)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ head, err := client.HeaderByNumber(ctx, nil)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ if head.BaseFee == nil {
+ return nil, nil, nil, errors.New("head BaseFee is nil")
+ }
+
+ var blobFee *big.Int
+ if head.ExcessBlobGas != nil {
+ blobFee = eth.CalcBlobFeeDefault(head)
+ }
+
+ gasFeeCap := new(big.Int).Add(
+ tip,
+ new(big.Int).Mul(head.BaseFee, big.NewInt(2)),
+ )
+ return tip, gasFeeCap, blobFee, nil
+}
+
+func getRandBlob(t *testing.T, seed int64) eth.Blob {
+ r := mrand.New(mrand.NewSource(seed))
+ bigData := eth.Data(make([]byte, eth.MaxBlobDataSize))
+ _, err := r.Read(bigData)
+ require.NoError(t, err)
+ var b eth.Blob
+ err = b.FromData(bigData)
+ require.NoError(t, err)
+ return b
+}
+
+func startDACServer(t *testing.T) *da.Server {
+ config := da.Config{
+ SequencerIP: "127.0.0.1",
+ ListenAddr: fmt.Sprintf("0.0.0.0:%d", dacPort),
+ StorePath: t.TempDir(),
+ }
+ server := da.NewServer(&config)
+ err := server.Start(ctx)
+ require.NoError(t, err)
+
+ return server
+}
+
+func downloadBlobs(dacUrl string, blobHashes []common.Hash) (blobs []hexutil.Bytes, err error) {
+ client := client.New([]string{dacUrl})
+ blobs, err = client.GetBlobs(ctx, blobHashes)
+ return
+}
diff --git official optimism/op-e2e/opgeth/fastlz_test.go SWC optimism/op-e2e/opgeth/fastlz_test.go
index 5b03ca38eca3c1fa3356e12d5213ff5c185bcc82..3b910d41f816df5f3a223cfa4e03563b4636244c 100644
--- official optimism/op-e2e/opgeth/fastlz_test.go
+++ SWC optimism/op-e2e/opgeth/fastlz_test.go
@@ -173,7 +173,7 @@
l1FeeSolidity.Mul(l1FeeSolidity, feeScaled)
l1FeeSolidity.Div(l1FeeSolidity, big.NewInt(1e12))
- costData := types.NewRollupCostData(fuzzedData)
+ costData := types.NewRollupCostData(fuzzedData, 0)
l1FeeGeth := costFunc(costData, zeroTime)
diff --git official optimism/op-e2e/sgt/helper.go SWC optimism/op-e2e/sgt/helper.go
new file mode 100644
index 0000000000000000000000000000000000000000..d39dd4e436202c5afb2c8206379a03e58e3ce140
--- /dev/null
+++ SWC optimism/op-e2e/sgt/helper.go
@@ -0,0 +1,92 @@
+package sgt
+
+import (
+ "context"
+ "crypto/ecdsa"
+ "math/big"
+ "testing"
+ "time"
+
+ "github.com/ethereum-optimism/optimism/op-e2e/bindings"
+ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
+ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys"
+ "github.com/ethereum-optimism/optimism/op-service/predeploys"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethclient"
+ "github.com/stretchr/testify/require"
+)
+
+type SgtHelper struct {
+ T *testing.T
+ L2Client *ethclient.Client
+ SysCfg e2esys.SystemConfig
+ SgtContract *bindings.SoulGasToken
+ ChainID *big.Int
+ sys *e2esys.System
+}
+
+func NewSgtHelper(t *testing.T, ctx context.Context, sys *e2esys.System) *SgtHelper {
+ // use sequencer's L2 client
+ client := sys.NodeClient(e2esys.RoleSeq)
+ chainID, err := client.ChainID(ctx)
+ require.NoError(t, err)
+
+ sgtAddr := predeploys.SoulGasTokenAddr
+ sgtContract, err := bindings.NewSoulGasToken(sgtAddr, client)
+ require.NoError(t, err)
+
+ return &SgtHelper{
+ T: t,
+ L2Client: client,
+ SysCfg: sys.Cfg,
+ SgtContract: sgtContract,
+ ChainID: chainID,
+ sys: sys,
+ }
+}
+
+func (s *SgtHelper) GetTestAccount(idx int) *ecdsa.PrivateKey {
+ return s.sys.TestAccount(idx)
+}
+
+func (s *SgtHelper) depositSgtAndNativeFromGenesisAccountToAccount(t *testing.T, ctx context.Context, toAddr common.Address, sgtValue *big.Int, l2Value *big.Int) {
+ privKey := s.GetTestAccount(0) // Genesis Account with lots of native balances
+ // deposit some sgt and native tokens first
+ txOpts, err := bind.NewKeyedTransactorWithChainID(privKey, s.ChainID)
+ require.NoError(t, err)
+ txOpts.Value = sgtValue
+ sgtTx, err := s.SgtContract.BatchDepositForAll(txOpts, []common.Address{toAddr}, sgtValue)
+ require.NoError(t, err)
+ _, err = wait.ForReceiptOK(ctx, s.L2Client, sgtTx.Hash())
+ require.NoError(t, err)
+ nativeTx, err := s.transferNativeToken(t, ctx, privKey, toAddr, l2Value)
+ require.NoError(t, err)
+ _, err = wait.ForReceiptOK(ctx, s.L2Client, nativeTx.Hash())
+ require.NoError(t, err)
+}
+
+func (s *SgtHelper) transferNativeToken(t *testing.T, ctx context.Context, sender *ecdsa.PrivateKey, toAddr common.Address, amount *big.Int) (*types.Transaction, error) {
+ chainID, err := s.L2Client.ChainID(ctx)
+ require.NoError(t, err)
+ gasFeeCap := big.NewInt(200)
+ gasTipCap := big.NewInt(10)
+
+ nonce, err := s.L2Client.NonceAt(ctx, crypto.PubkeyToAddress(sender.PublicKey), nil)
+ require.NoError(t, err)
+ tx := types.MustSignNewTx(sender, types.LatestSignerForChainID(chainID), &types.DynamicFeeTx{
+ ChainID: chainID,
+ Nonce: nonce,
+ To: &toAddr,
+ Value: amount,
+ GasTipCap: gasTipCap,
+ GasFeeCap: gasFeeCap,
+ Gas: 21000,
+ })
+ ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
+ defer cancel()
+ err = s.L2Client.SendTransaction(ctx, tx)
+ return tx, err
+}
diff --git official optimism/op-e2e/sgt/sgt_test.go SWC optimism/op-e2e/sgt/sgt_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..93fd2372f3cd594443dbd26d95ee724cc0ba21c1
--- /dev/null
+++ SWC optimism/op-e2e/sgt/sgt_test.go
@@ -0,0 +1,396 @@
+package sgt
+
+import (
+ "context"
+ "crypto/ecdsa"
+ "math/big"
+ "math/rand"
+ "testing"
+
+ op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
+ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
+ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys"
+ "github.com/ethereum-optimism/optimism/op-service/predeploys"
+ "github.com/ethereum-optimism/optimism/op-service/testutils"
+
+ "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/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/stretchr/testify/require"
+)
+
+var (
+ seqVault = predeploys.SequencerFeeVaultAddr
+ baseVault = predeploys.BaseFeeVaultAddr
+ l1Vault = predeploys.L1FeeVaultAddr
+ dummyAddr = common.Address{0xff, 0xff}
+)
+
+func TestSGTDepositFunctionSuccess(t *testing.T) {
+ op_e2e.InitParallel(t)
+ sgtTimeOffset := uint64(0)
+ sys := startSystemWithSGT(&sgtTimeOffset, t)
+ t.Cleanup(sys.Close)
+ ctx := context.Background()
+
+ sgt := NewSgtHelper(t, ctx, sys)
+ depositSgtValue := big.NewInt(10000)
+ _, _, _ = setUpTestAccount(t, ctx, 0, sgt, depositSgtValue, big.NewInt(0))
+}
+
+func startSystemWithSGT(sgtTimeOffset *uint64, t *testing.T) *e2esys.System {
+ cfg := e2esys.DefaultSystemConfig(t)
+ delete(cfg.Nodes, "verifier")
+ _, ok := cfg.Nodes["sequencer"]
+ require.True(t, ok, "sequencer is required")
+
+ if sgtTimeOffset != nil {
+ cfg.DeployConfig.DeploySoulGasToken = true
+ cfg.DeployConfig.SoulGasTokenTimeOffset = (*hexutil.Uint64)(sgtTimeOffset)
+ } else {
+ cfg.DeployConfig.DeploySoulGasToken = false
+ }
+ // Disable proposer creating fast games automatically - required games are manually created
+ cfg.DisableProposer = true
+ sys, err := cfg.Start(t)
+ require.Nil(t, err, "Error starting up system")
+ return sys
+}
+
+// Diverse test scenarios to verify that the SoulGasToken(sgt) is utilized for gas payment firstly,
+// unless there is insufficient sgt balance, in which case the native balance will be used instead.
+func TestSGTAsGasPayment(t *testing.T) {
+ op_e2e.InitParallel(t)
+ sgtTimeOffset := uint64(0)
+ sys := startSystemWithSGT(&sgtTimeOffset, t)
+ t.Cleanup(sys.Close)
+ ctx := context.Background()
+
+ sgt := NewSgtHelper(t, ctx, sys)
+ // 1. setup a test account and deposit specified amount of sgt tokens (`depositSgtValue`) and native tokens (`depositL2Value`) into it.
+ // 2. execute a token transfer tx with `txValue` to `dummyAddr` and validate that the gas payment behavior using sgt is as anticipated.
+ tests := []struct {
+ name string
+ action func(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper)
+ }{
+ {
+ name: "NativaGasPaymentWithoutSGTSuccess",
+ action: nativaGasPaymentWithoutSGTSuccess,
+ },
+ {
+ name: "FullSGTGasPaymentWithoutNativeBalanceSuccess",
+ action: fullSGTGasPaymentWithoutNativeBalanceSuccess,
+ },
+ {
+ name: "FullSGTGasPaymentWithNativeBalanceSuccess",
+ action: fullSGTGasPaymentWithNativeBalanceSuccess,
+ },
+ {
+ name: "PartialSGTGasPaymentSuccess",
+ action: partialSGTGasPaymentSuccess,
+ },
+ {
+ name: "FullSGTGasPaymentAndNonZeroTxValueWithSufficientNativeBalanceSuccess",
+ action: fullSGTGasPaymentAndNonZeroTxValueWithSufficientNativeBalanceSuccess,
+ },
+ {
+ name: "PartialSGTGasPaymentAndNonZeroTxValueWithSufficientNativeBalanceSuccess",
+ action: partialSGTGasPaymentAndNonZeroTxValueWithSufficientNativeBalanceSuccess,
+ },
+ {
+ name: "FullSGTInsufficientGasPaymentFail",
+ action: fullSGTInsufficientGasPaymentFail,
+ },
+ {
+ name: "FullNativeInsufficientGasPaymentFail",
+ action: fullNativeInsufficientGasPaymentFail,
+ },
+ {
+ name: "PartialSGTInsufficientGasPaymentFail",
+ action: partialSGTInsufficientGasPaymentFail,
+ },
+ {
+ name: "FullSGTGasPaymentAndNonZeroTxValueWithInsufficientNativeBalanceFail",
+ action: fullSGTGasPaymentAndNonZeroTxValueWithInsufficientNativeBalanceFail,
+ },
+ {
+ name: "PartialSGTGasPaymentAndNonZeroTxValueWithInsufficientNativeBalanceFail",
+ action: partialSGTGasPaymentAndNonZeroTxValueWithInsufficientNativeBalanceFail,
+ },
+ }
+
+ for index, tCase := range tests {
+ t.Run(tCase.name, func(t *testing.T) {
+ tCase.action(t, ctx, int64(index), sgt)
+ })
+ }
+}
+
+func setUpTestAccount(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper, depositSgtValue *big.Int, depositL2Value *big.Int) (*ecdsa.PrivateKey, common.Address, *big.Int) {
+ opts := &bind.CallOpts{Context: ctx}
+ rng := rand.New(rand.NewSource(index))
+ testPrivKey := testutils.InsecureRandomKey(rng)
+ testAddr := crypto.PubkeyToAddress(testPrivKey.PublicKey)
+
+ // check it's a fresh account
+ sgtBalance, err := sgt.SgtContract.BalanceOf(opts, testAddr)
+ require.NoError(t, err)
+ require.Equal(t, int64(0), sgtBalance.Int64())
+ l2Balance, err := sgt.L2Client.BalanceAt(ctx, testAddr, nil)
+ require.NoError(t, err)
+ require.Equal(t, int64(0), l2Balance.Int64())
+
+ // deposit initial sgt and native(L2) balance to the test account
+ sgt.depositSgtAndNativeFromGenesisAccountToAccount(t, ctx, testAddr, depositSgtValue, depositL2Value)
+ // ensure that sgt and native balance of testAccount are correctly initialized
+ preSgtBalance, err := sgt.SgtContract.BalanceOf(opts, testAddr)
+ require.NoError(t, err)
+ require.Equal(t, depositSgtValue.Cmp(preSgtBalance), 0)
+ preL2Balance, err := sgt.L2Client.BalanceAt(ctx, testAddr, nil)
+ require.NoError(t, err)
+ require.Equal(t, depositL2Value.Cmp(preL2Balance), 0)
+
+ return testPrivKey, testAddr, calcVaultBalance(t, ctx, sgt)
+}
+
+// balance invariant check: preTotalBalance = postTotalBalance + gasCost + txValue
+func invariantBalanceCheck(t *testing.T, ctx context.Context, sgt *SgtHelper, addr common.Address, gasCost *big.Int, txValue *big.Int, preSgtBalance *big.Int, preL2Balance *big.Int, postSgtBalance *big.Int, sgtShouldChange bool) {
+ if sgtShouldChange {
+ require.True(t, preSgtBalance.Cmp(postSgtBalance) != 0)
+ } else {
+ require.True(t, preSgtBalance.Cmp(postSgtBalance) == 0)
+ }
+ postL2Balance, err := sgt.L2Client.BalanceAt(ctx, addr, nil)
+ require.NoError(t, err)
+ preBalance := new(big.Int).Add(preSgtBalance, preL2Balance)
+ postBalance := new(big.Int).Add(postSgtBalance, gasCost)
+ postBalance = postBalance.Add(postBalance, txValue)
+ postBalance = postBalance.Add(postBalance, postL2Balance)
+ require.Equal(t, 0, preBalance.Cmp(postBalance))
+}
+
+func nativaGasPaymentWithoutSGTSuccess(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(0)
+ // 10000000000000 is a random chosen value that is far bigger than the gas cos (~1225000231000) of the following `transferNativeToken` tx
+ depositL2Value := big.NewInt(10000000000000)
+ txValue := big.NewInt(0)
+ testAccount, testAddr, vaultBalanceBefore := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ tx, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.NoError(t, err)
+ receipt, err := wait.ForReceiptOK(ctx, sgt.L2Client, tx.Hash())
+ require.NoError(t, err)
+ gasCost := calcGasFee(receipt)
+ vaultBalanceAfter := calcVaultBalance(t, ctx, sgt)
+
+ // gasCost == vaultBalanceDiff check
+ require.Equal(t, new(big.Int).Sub(vaultBalanceAfter, vaultBalanceBefore).Cmp(gasCost), 0)
+ // post sgt balance check: it should be 0
+ opts := &bind.CallOpts{Context: ctx}
+ postSgtBalance, err := sgt.SgtContract.BalanceOf(opts, testAddr)
+ require.NoError(t, err)
+ require.Equal(t, common.Big0.Cmp(postSgtBalance), 0)
+ // balance invariant check
+ invariantBalanceCheck(t, ctx, sgt, testAddr, gasCost, txValue, depositSgtValue, depositL2Value, postSgtBalance, false)
+}
+
+func fullSGTGasPaymentWithoutNativeBalanceSuccess(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(10000000000000)
+ depositL2Value := big.NewInt(0)
+ txValue := big.NewInt(0)
+ testAccount, testAddr, vaultBalanceBefore := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ tx, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.NoError(t, err)
+ receipt, err := wait.ForReceiptOK(ctx, sgt.L2Client, tx.Hash())
+ require.NoError(t, err)
+ gasCost := calcGasFee(receipt)
+ vaultBalanceAfter := calcVaultBalance(t, ctx, sgt)
+
+ // gasCost == vaultBalanceDiff check
+ require.Equal(t, new(big.Int).Sub(vaultBalanceAfter, vaultBalanceBefore).Cmp(gasCost), 0)
+ // post sgt balance check: sgt should be used as gas first
+ opts := &bind.CallOpts{Context: ctx}
+ postSgtBalance, err := sgt.SgtContract.BalanceOf(opts, testAddr)
+ require.NoError(t, err)
+ require.Equal(t, new(big.Int).Add(postSgtBalance, gasCost).Cmp(depositSgtValue), 0)
+ // balance invariant check
+ invariantBalanceCheck(t, ctx, sgt, testAddr, gasCost, txValue, depositSgtValue, depositL2Value, postSgtBalance, true)
+}
+
+func fullSGTGasPaymentWithNativeBalanceSuccess(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(10000000000000)
+ depositL2Value := big.NewInt(10000000000000)
+ txValue := big.NewInt(0)
+ testAccount, testAddr, vaultBalanceBefore := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ tx, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.NoError(t, err)
+ receipt, err := wait.ForReceiptOK(ctx, sgt.L2Client, tx.Hash())
+ require.NoError(t, err)
+ gasCost := calcGasFee(receipt)
+ vaultBalanceAfter := calcVaultBalance(t, ctx, sgt)
+
+ // gasCost == vaultBalanceDiff check
+ require.Equal(t, new(big.Int).Sub(vaultBalanceAfter, vaultBalanceBefore).Cmp(gasCost), 0)
+ // post sgt balance check: sgt should be used as gas first
+ opts := &bind.CallOpts{Context: ctx}
+ postSgtBalance, err := sgt.SgtContract.BalanceOf(opts, testAddr)
+ require.NoError(t, err)
+ require.Equal(t, new(big.Int).Add(postSgtBalance, gasCost).Cmp(depositSgtValue), 0)
+ // balance invariant check
+ invariantBalanceCheck(t, ctx, sgt, testAddr, gasCost, txValue, depositSgtValue, depositL2Value, postSgtBalance, true)
+}
+
+func partialSGTGasPaymentSuccess(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ // 1000 is a random chosen value that is far less than the gas cos (~1225000231000) of the following `transferNativeToken` tx
+ depositSgtValue := big.NewInt(1000)
+ depositL2Value := big.NewInt(10000000000000)
+ txValue := big.NewInt(0)
+ testAccount, testAddr, vaultBalanceBefore := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ tx, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.NoError(t, err)
+ receipt, err := wait.ForReceiptOK(ctx, sgt.L2Client, tx.Hash())
+ require.NoError(t, err)
+ gasCost := calcGasFee(receipt)
+ vaultBalanceAfter := calcVaultBalance(t, ctx, sgt)
+
+ // gasCost == vaultBalanceDiff check
+ require.Equal(t, new(big.Int).Sub(vaultBalanceAfter, vaultBalanceBefore).Cmp(gasCost), 0)
+ // post sgt balance check: sgt should be used as gas first and should be spent all
+ opts := &bind.CallOpts{Context: ctx}
+ postSgtBalance, err := sgt.SgtContract.BalanceOf(opts, testAddr)
+ require.NoError(t, err)
+ require.Equal(t, common.Big0.Cmp(postSgtBalance), 0)
+ // balance invariant check
+ invariantBalanceCheck(t, ctx, sgt, testAddr, gasCost, txValue, depositSgtValue, depositL2Value, postSgtBalance, true)
+}
+
+func fullSGTGasPaymentAndNonZeroTxValueWithSufficientNativeBalanceSuccess(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(10000000000000)
+ depositL2Value := big.NewInt(10000000000000)
+ txValue := big.NewInt(10000)
+ testAccount, testAddr, vaultBalanceBefore := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ tx, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.NoError(t, err)
+ receipt, err := wait.ForReceiptOK(ctx, sgt.L2Client, tx.Hash())
+ require.NoError(t, err)
+ gasCost := calcGasFee(receipt)
+ vaultBalanceAfter := calcVaultBalance(t, ctx, sgt)
+
+ // gasCost == vaultBalanceDiff check
+ require.Equal(t, new(big.Int).Sub(vaultBalanceAfter, vaultBalanceBefore).Cmp(gasCost), 0)
+ // post sgt balance check: sgt should be used as gas first
+ opts := &bind.CallOpts{Context: ctx}
+ postSgtBalance, err := sgt.SgtContract.BalanceOf(opts, testAddr)
+ require.NoError(t, err)
+ require.Equal(t, new(big.Int).Add(postSgtBalance, gasCost).Cmp(depositSgtValue), 0)
+ // balance invariant check
+ invariantBalanceCheck(t, ctx, sgt, testAddr, gasCost, txValue, depositSgtValue, depositL2Value, postSgtBalance, true)
+}
+
+func partialSGTGasPaymentAndNonZeroTxValueWithSufficientNativeBalanceSuccess(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(1000)
+ depositL2Value := big.NewInt(10000000000000)
+ txValue := big.NewInt(10000)
+ testAccount, testAddr, vaultBalanceBefore := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ tx, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.NoError(t, err)
+ receipt, err := wait.ForReceiptOK(ctx, sgt.L2Client, tx.Hash())
+ require.NoError(t, err)
+ gasCost := calcGasFee(receipt)
+ vaultBalanceAfter := calcVaultBalance(t, ctx, sgt)
+
+ // gasCost == vaultBalanceDiff check
+ require.Equal(t, new(big.Int).Sub(vaultBalanceAfter, vaultBalanceBefore).Cmp(gasCost), 0)
+ // post sgt balance check: sgt should be used as gas first and should be spent all
+ opts := &bind.CallOpts{Context: ctx}
+ postSgtBalance, err := sgt.SgtContract.BalanceOf(opts, testAddr)
+ require.NoError(t, err)
+ require.Equal(t, common.Big0.Cmp(postSgtBalance), 0)
+ // balance invariant check
+ invariantBalanceCheck(t, ctx, sgt, testAddr, gasCost, txValue, depositSgtValue, depositL2Value, postSgtBalance, true)
+}
+
+func fullSGTInsufficientGasPaymentFail(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(10000)
+ depositL2Value := big.NewInt(0)
+ txValue := big.NewInt(0)
+ testAccount, _, _ := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ _, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.Error(t, err)
+}
+
+func fullNativeInsufficientGasPaymentFail(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(0)
+ depositL2Value := big.NewInt(10000)
+ txValue := big.NewInt(0)
+ testAccount, _, _ := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ _, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.Error(t, err)
+}
+
+func partialSGTInsufficientGasPaymentFail(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(10000)
+ depositL2Value := big.NewInt(10000)
+ txValue := big.NewInt(0)
+ testAccount, _, _ := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ _, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.Error(t, err)
+}
+
+func fullSGTGasPaymentAndNonZeroTxValueWithInsufficientNativeBalanceFail(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(10000000000000)
+ depositL2Value := big.NewInt(10000)
+ txValue := big.NewInt(10001)
+ testAccount, _, _ := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ _, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.Error(t, err)
+}
+
+func partialSGTGasPaymentAndNonZeroTxValueWithInsufficientNativeBalanceFail(t *testing.T, ctx context.Context, index int64, sgt *SgtHelper) {
+ depositSgtValue := big.NewInt(10000)
+ depositL2Value := big.NewInt(10000000000000)
+ txValue := new(big.Int).Sub(depositL2Value, depositSgtValue)
+ testAccount, _, _ := setUpTestAccount(t, ctx, index, sgt, depositSgtValue, depositL2Value)
+
+ // make a simple tx with the testAccount: transfer txValue from testAccount to dummyAddr
+ _, err := sgt.transferNativeToken(t, ctx, testAccount, dummyAddr, txValue)
+ require.Error(t, err)
+}
+
+func calcGasFee(receipt *types.Receipt) *big.Int {
+ // OPStackTxFee = L2ExecutionGasFee + L1DataFee
+ fees := new(big.Int).Mul(receipt.EffectiveGasPrice, big.NewInt(int64(receipt.GasUsed)))
+ fees = fees.Add(fees, receipt.L1Fee)
+ return fees
+}
+
+func calcVaultBalance(t *testing.T, ctx context.Context, sgt *SgtHelper) *big.Int {
+ sequencerFee, err := sgt.L2Client.BalanceAt(ctx, seqVault, nil)
+ require.NoError(t, err)
+ baseFee, err := sgt.L2Client.BalanceAt(ctx, baseVault, nil)
+ require.NoError(t, err)
+ l1Fee, err := sgt.L2Client.BalanceAt(ctx, l1Vault, nil)
+ require.NoError(t, err)
+ return sequencerFee.Add(sequencerFee, baseFee.Add(baseFee, l1Fee))
+}
diff --git official optimism/op-e2e/system/bridge/deposit_test.go SWC optimism/op-e2e/system/bridge/deposit_test.go
index a79147cee16bf03f239a3a1eb909f09134ab604f..e38da0a252fb5aae56c5e93d27fd09a26feb9a3f 100644
--- official optimism/op-e2e/system/bridge/deposit_test.go
+++ SWC optimism/op-e2e/system/bridge/deposit_test.go
@@ -143,7 +143,7 @@
// Simple constructor that is prefixed to the actual contract code
// Results in the contract code being returned as the code for the new contract
deployData := append(deployPrefix, sstoreContract...)
- signer := types.NewIsthmusSigner(cfg.L2ChainIDBig())
+ signer := types.NewIsthmusSigner(cfg.L2ChainIDBig(), false)
tx := types.MustSignNewTx(cfg.Secrets.Alice, signer, &types.DynamicFeeTx{
ChainID: cfg.L2ChainIDBig(),
diff --git official optimism/op-e2e/system/e2esys/setup.go SWC optimism/op-e2e/system/e2esys/setup.go
index 3b4588065b3e649b5b47b7536b2e92e5c176eea6..27ef348d11f549450a029b989743c0ad332ea656 100644
--- official optimism/op-e2e/system/e2esys/setup.go
+++ SWC optimism/op-e2e/system/e2esys/setup.go
@@ -117,6 +117,7 @@ secrets := secrets.DefaultSecrets
deployConfig := config.DeployConfig(sco.AllocType)
require.Nil(t, deployConfig.L2GenesisJovianTimeOffset, "jovian not supported yet")
deployConfig.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix())
+ deployConfig.L2GenesisBlobTimeOffset = nil
e2eutils.ApplyDeployConfigForks(deployConfig)
require.NoError(t, deployConfig.Check(testlog.Logger(t, log.LevelInfo)),
"Deploy config is invalid, do you need to run make devnet-allocs?")
@@ -681,6 +682,11 @@ CommitmentType: altda.GenericCommitmentString,
}
}
+ var inboxContractConfig *rollup.InboxContractConfig
+ if cfg.DeployConfig.UseInboxContract {
+ inboxContractConfig = &rollup.InboxContractConfig{UseInboxContract: true}
+ }
+
makeRollupConfig := func() rollup.Config {
return rollup.Config{
Genesis: rollup.Genesis{
@@ -717,10 +723,16 @@ JovianTime: cfg.DeployConfig.JovianTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
InteropTime: cfg.DeployConfig.InteropTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
ProtocolVersionsAddress: cfg.L1Deployments.ProtocolVersionsProxy,
AltDAConfig: rollupAltDAConfig,
+ InboxContractConfig: inboxContractConfig,
ChainOpConfig: ¶ms.OptimismConfig{
- EIP1559Elasticity: cfg.DeployConfig.EIP1559Elasticity,
- EIP1559Denominator: cfg.DeployConfig.EIP1559Denominator,
- EIP1559DenominatorCanyon: &cfg.DeployConfig.EIP1559DenominatorCanyon,
+ EIP1559Elasticity: cfg.DeployConfig.EIP1559Elasticity,
+ EIP1559Denominator: cfg.DeployConfig.EIP1559Denominator,
+ EIP1559DenominatorCanyon: &cfg.DeployConfig.EIP1559DenominatorCanyon,
+ L2BlobTime: cfg.DeployConfig.L2BlobTime(l1Block.Time()),
+ SoulGasTokenTime: cfg.DeployConfig.SoulGasTokenTime(l1Block.Time()),
+ IsSoulBackedByNative: cfg.DeployConfig.IsSoulBackedByNative,
+ L1BaseFeeScalarMultiplier: cfg.DeployConfig.L1BaseFeeScalarMultiplier,
+ L1BlobBaseFeeScalarMultiplier: cfg.DeployConfig.L1BlobBaseFeeScalarMultiplier,
},
}
}
@@ -806,6 +818,11 @@ l1Client := sys.NodeClient(RoleL1)
_, err = geth.WaitForBlock(big.NewInt(2), l1Client)
if err != nil {
return nil, fmt.Errorf("waiting for blocks: %w", err)
+ }
+
+ // exec func which needs to run after L1 node starts and before L2 nodes start.
+ if action, ok := parsedStartOpts.Get("afterL1Start", ""); ok {
+ action(&cfg, sys)
}
sys.Mocknet = mocknet.New()
diff --git official optimism/op-e2e/system/runcfg/protocol_versions_test.go SWC optimism/op-e2e/system/runcfg/protocol_versions_test.go
index 85daeff6c43657ae3a51ee500d1b638e92ecebdc..e91ae90cd16da72ec008ae077a26990085df8066 100644
--- official optimism/op-e2e/system/runcfg/protocol_versions_test.go
+++ SWC optimism/op-e2e/system/runcfg/protocol_versions_test.go
@@ -128,7 +128,13 @@ t.Log("verified that op-node closed!")
// Checking if the engine is down is not trivial in op-e2e.
// In op-geth we have halting tests covering the Engine API, in op-e2e we instead check if the API stops.
_, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) {
- available := client.IsURLAvailable(context.Background(), sys.NodeEndpoint("verifier").(endpoint.HttpRPC).HttpRPC(), 5*time.Second)
+ url := sys.NodeEndpoint("verifier").(endpoint.HttpRPC).HttpRPC()
+ // The URL of the verifier op-geth becomes empty after it is stopped.
+ // In this case, IsURLAvailable() returns an incorrect value when port 80 happens to be occupied by another process.
+ if url == "http://" {
+ return struct{}{}, nil
+ }
+ available := client.IsURLAvailable(context.Background(), url, 5*time.Second)
if !available { // waiting for client to stop responding to RPC requests (slow dials with timeout don't count)
return struct{}{}, nil
}
diff --git official optimism/op-node/bindings/l1block.go SWC optimism/op-node/bindings/l1block.go
index 41a24ec38878128d02ced08b4b14abca2aa378e6..5793ce341edb0a499c698b9fbe84f3669ff9d499 100644
--- official optimism/op-node/bindings/l1block.go
+++ SWC optimism/op-node/bindings/l1block.go
@@ -30,8 +30,8 @@ )
// L1BlockMetaData contains all meta data concerning the L1Block contract.
var L1BlockMetaData = &bind.MetaData{
- ABI: "[{\"type\":\"function\",\"name\":\"DEPOSITOR_ACCOUNT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"baseFeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"basefee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"batcherHash\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blobBaseFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blobBaseFeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hash\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"l1FeeOverhead\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"l1FeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"number\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"sequenceNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setL1BlockValues\",\"inputs\":[{\"name\":\"_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_basefee\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_hash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_batcherHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_l1FeeOverhead\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_l1FeeScalar\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setL1BlockValuesEcotone\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"timestamp\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"}]",
- Bin: "0x608060405234801561001057600080fd5b5061053e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80638381f58a11610097578063c598591811610066578063c598591814610229578063e591b28214610249578063e81b2c6d14610289578063f82061401461029257600080fd5b80638381f58a146101e35780638b239f73146101f75780639e8c496614610200578063b80777ea1461020957600080fd5b806354fd4d50116100d357806354fd4d50146101335780635cf249691461017c57806364ca23ef1461018557806368d5dca6146101b257600080fd5b8063015d8eb9146100fa57806309bd5a601461010f578063440a5e201461012b575b600080fd5b61010d61010836600461044c565b61029b565b005b61011860025481565b6040519081526020015b60405180910390f35b61010d6103da565b61016f6040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161012291906104be565b61011860015481565b6003546101999067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610122565b6003546101ce9068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610122565b6000546101999067ffffffffffffffff1681565b61011860055481565b61011860065481565b6000546101999068010000000000000000900467ffffffffffffffff1681565b6003546101ce906c01000000000000000000000000900463ffffffff1681565b61026473deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610122565b61011860045481565b61011860075481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b3373deaddeaddeaddeaddeaddeaddeaddeaddead00011461040357633cc50b456000526004601cfd5b60043560801c60035560143560801c600055602435600155604435600755606435600255608435600455565b803567ffffffffffffffff8116811461044757600080fd5b919050565b600080600080600080600080610100898b03121561046957600080fd5b6104728961042f565b975061048060208a0161042f565b9650604089013595506060890135945061049c60808a0161042f565b979a969950949793969560a0850135955060c08501359460e001359350915050565b600060208083528351808285015260005b818110156104eb578581018301518582016040015282016104cf565b818111156104fd576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201604001939250505056fea164736f6c634300080f000a",
+ ABI: "[{\"type\":\"function\",\"name\":\"DEPOSITOR_ACCOUNT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"HISTORY_SIZE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"baseFeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"basefee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"batcherHash\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blobBaseFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blobBaseFeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blockHash\",\"inputs\":[{\"name\":\"_historyNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hash\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"historyHashes\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"l1FeeOverhead\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"l1FeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"number\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"sequenceNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setL1BlockValues\",\"inputs\":[{\"name\":\"_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_basefee\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_hash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_batcherHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_l1FeeOverhead\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_l1FeeScalar\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setL1BlockValuesEcotone\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"timestamp\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"}]",
+ Bin: "0x608060405234801561001057600080fd5b5061075e806100206000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806385df51fd116100b2578063b80777ea11610081578063e591b28211610066578063e591b282146102b9578063e81b2c6d146102f9578063f82061401461030257600080fd5b8063b80777ea14610279578063c59859181461029957600080fd5b806385df51fd146102415780638b239f731461025457806392abaa421461025d5780639e8c49661461027057600080fd5b80635cf2496911610109578063652c462e116100ee578063652c462e146101f357806368d5dca6146101fc5780638381f58a1461022d57600080fd5b80635cf24969146101bd57806364ca23ef146101c657600080fd5b8063015d8eb91461013b57806309bd5a6014610150578063440a5e201461016c57806354fd4d5014610174575b600080fd5b61014e61014936600461058b565b61030b565b005b61015960025481565b6040519081526020015b60405180910390f35b61014e61044a565b6101b06040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161016391906105fd565b61015960015481565b6003546101da9067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610163565b61015961200081565b6003546102189068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610163565b6000546101da9067ffffffffffffffff1681565b61015961024f366004610670565b6104d2565b61015960055481565b61015961026b366004610670565b610556565b61015960065481565b6000546101da9068010000000000000000900467ffffffffffffffff1681565b600354610218906c01000000000000000000000000900463ffffffff1681565b6102d473deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610163565b61015960045481565b61015960075481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146103b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b3373deaddeaddeaddeaddeaddeaddeaddeaddead00011461047357633cc50b456000526004601cfd5b60048035608090811c600355601435901c600081905560243560015560443560075560643560028190556084359092556008906104bd906120009067ffffffffffffffff16610689565b61200081106104ce576104ce6106c4565b0155565b60008054819067ffffffffffffffff166120008110156104f5576000915061050f565b61050161200082610722565b61050c906001610739565b91505b81841015801561051e57508084105b1561054c57600861053161200086610689565b6120008110610542576105426106c4565b0154949350505050565b5060009392505050565b600881612000811061056757600080fd5b0154905081565b803567ffffffffffffffff8116811461058657600080fd5b919050565b600080600080600080600080610100898b0312156105a857600080fd5b6105b18961056e565b97506105bf60208a0161056e565b965060408901359550606089013594506105db60808a0161056e565b979a969950949793969560a0850135955060c08501359460e001359350915050565b600060208083528351808285015260005b8181101561062a5785810183015185820160400152820161060e565b8181111561063c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561068257600080fd5b5035919050565b6000826106bf577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610734576107346106f3565b500390565b6000821982111561074c5761074c6106f3565b50019056fea164736f6c634300080f000a",
}
// L1BlockABI is the input ABI used to generate the binding from.
@@ -232,6 +232,37 @@ func (_L1Block *L1BlockCallerSession) DEPOSITORACCOUNT() (common.Address, error) {
return _L1Block.Contract.DEPOSITORACCOUNT(&_L1Block.CallOpts)
}
+// HISTORYSIZE is a free data retrieval call binding the contract method 0x652c462e.
+//
+// Solidity: function HISTORY_SIZE() view returns(uint256)
+func (_L1Block *L1BlockCaller) HISTORYSIZE(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _L1Block.contract.Call(opts, &out, "HISTORY_SIZE")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// HISTORYSIZE is a free data retrieval call binding the contract method 0x652c462e.
+//
+// Solidity: function HISTORY_SIZE() view returns(uint256)
+func (_L1Block *L1BlockSession) HISTORYSIZE() (*big.Int, error) {
+ return _L1Block.Contract.HISTORYSIZE(&_L1Block.CallOpts)
+}
+
+// HISTORYSIZE is a free data retrieval call binding the contract method 0x652c462e.
+//
+// Solidity: function HISTORY_SIZE() view returns(uint256)
+func (_L1Block *L1BlockCallerSession) HISTORYSIZE() (*big.Int, error) {
+ return _L1Block.Contract.HISTORYSIZE(&_L1Block.CallOpts)
+}
+
// BaseFeeScalar is a free data retrieval call binding the contract method 0xc5985918.
//
// Solidity: function baseFeeScalar() view returns(uint32)
@@ -387,6 +418,37 @@ func (_L1Block *L1BlockCallerSession) BlobBaseFeeScalar() (uint32, error) {
return _L1Block.Contract.BlobBaseFeeScalar(&_L1Block.CallOpts)
}
+// BlockHash is a free data retrieval call binding the contract method 0x85df51fd.
+//
+// Solidity: function blockHash(uint256 _historyNumber) view returns(bytes32)
+func (_L1Block *L1BlockCaller) BlockHash(opts *bind.CallOpts, _historyNumber *big.Int) ([32]byte, error) {
+ var out []interface{}
+ err := _L1Block.contract.Call(opts, &out, "blockHash", _historyNumber)
+
+ if err != nil {
+ return *new([32]byte), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
+
+ return out0, err
+
+}
+
+// BlockHash is a free data retrieval call binding the contract method 0x85df51fd.
+//
+// Solidity: function blockHash(uint256 _historyNumber) view returns(bytes32)
+func (_L1Block *L1BlockSession) BlockHash(_historyNumber *big.Int) ([32]byte, error) {
+ return _L1Block.Contract.BlockHash(&_L1Block.CallOpts, _historyNumber)
+}
+
+// BlockHash is a free data retrieval call binding the contract method 0x85df51fd.
+//
+// Solidity: function blockHash(uint256 _historyNumber) view returns(bytes32)
+func (_L1Block *L1BlockCallerSession) BlockHash(_historyNumber *big.Int) ([32]byte, error) {
+ return _L1Block.Contract.BlockHash(&_L1Block.CallOpts, _historyNumber)
+}
+
// Hash is a free data retrieval call binding the contract method 0x09bd5a60.
//
// Solidity: function hash() view returns(bytes32)
@@ -416,6 +478,37 @@ //
// Solidity: function hash() view returns(bytes32)
func (_L1Block *L1BlockCallerSession) Hash() ([32]byte, error) {
return _L1Block.Contract.Hash(&_L1Block.CallOpts)
+}
+
+// HistoryHashes is a free data retrieval call binding the contract method 0x92abaa42.
+//
+// Solidity: function historyHashes(uint256 ) view returns(bytes32)
+func (_L1Block *L1BlockCaller) HistoryHashes(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) {
+ var out []interface{}
+ err := _L1Block.contract.Call(opts, &out, "historyHashes", arg0)
+
+ if err != nil {
+ return *new([32]byte), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
+
+ return out0, err
+
+}
+
+// HistoryHashes is a free data retrieval call binding the contract method 0x92abaa42.
+//
+// Solidity: function historyHashes(uint256 ) view returns(bytes32)
+func (_L1Block *L1BlockSession) HistoryHashes(arg0 *big.Int) ([32]byte, error) {
+ return _L1Block.Contract.HistoryHashes(&_L1Block.CallOpts, arg0)
+}
+
+// HistoryHashes is a free data retrieval call binding the contract method 0x92abaa42.
+//
+// Solidity: function historyHashes(uint256 ) view returns(bytes32)
+func (_L1Block *L1BlockCallerSession) HistoryHashes(arg0 *big.Int) ([32]byte, error) {
+ return _L1Block.Contract.HistoryHashes(&_L1Block.CallOpts, arg0)
}
// L1FeeOverhead is a free data retrieval call binding the contract method 0x8b239f73.
diff --git official optimism/op-node/config/config.go SWC optimism/op-node/config/config.go
index 80a438c18834a3c51c44fb546376212e4893b800..5e5f2e61fb954db547b25145c3a2f22f7c9eb171 100644
--- official optimism/op-node/config/config.go
+++ SWC optimism/op-node/config/config.go
@@ -4,6 +4,9 @@ import (
"context"
"errors"
"fmt"
+
+ "strings"
+
"time"
"github.com/ethereum/go-ethereum/log"
@@ -14,12 +17,15 @@ "github.com/ethereum-optimism/optimism/op-node/node/tracer"
"github.com/ethereum-optimism/optimism/op-node/p2p"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/driver"
+ "github.com/ethereum-optimism/optimism/op-node/rollup/engine"
"github.com/ethereum-optimism/optimism/op-node/rollup/interop"
"github.com/ethereum-optimism/optimism/op-node/rollup/sync"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum-optimism/optimism/op-service/oppprof"
oprpc "github.com/ethereum-optimism/optimism/op-service/rpc"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/depset"
+ "github.com/ethstorage/da-server/pkg/da/client"
+ "github.com/urfave/cli/v2"
)
type Config struct {
@@ -81,6 +87,8 @@ ConductorRpcTimeout time.Duration
// AltDA config
AltDA altda.CLIConfig
+ // DACConfig for sequencer when l2 blob is enabled
+ DACConfig *DACConfig
IgnoreMissingPectraBlobSchedule bool
FetchWithdrawalRootFromState bool
@@ -89,6 +97,27 @@ // Experimental. Enables new opstack RPC namespace. Used by op-test-sequencer.
ExperimentalOPStackAPI bool
}
+func ReadDACConfigFromCLI(c *cli.Context) *DACConfig {
+ urls := c.String(flags.DACUrlsFlag.Name)
+ if urls == "" {
+ return nil
+ }
+ return &DACConfig{
+ URLS: strings.Split(urls, ","),
+ }
+}
+
+type DACConfig struct {
+ URLS []string
+}
+
+func (dacConfig *DACConfig) Client() engine.DACClient {
+ if dacConfig == nil || len(dacConfig.URLS) == 0 {
+ return nil
+ }
+ return client.New(dacConfig.URLS)
+}
+
// ConductorRPCFunc retrieves the endpoint. The RPC may not immediately be available.
type ConductorRPCFunc func(ctx context.Context) (string, error)
@@ -174,6 +203,12 @@ return fmt.Errorf("altDA config error: %w", err)
}
if cfg.AltDA.Enabled {
log.Warn("Alt-DA Mode is a Beta feature of the MIT licensed OP Stack. While it has received initial review from core contributors, it is still undergoing testing, and may have bugs or other issues.")
+ }
+ if cfg.Driver.SequencerEnabled && cfg.Rollup.IsL2BlobTimeSet() && cfg.DACConfig == nil {
+ return fmt.Errorf("dac.urls must be set for sequencer when l2 blob time is set")
+ }
+ if (!cfg.Driver.SequencerEnabled || !cfg.Rollup.IsL2BlobTimeSet()) && cfg.DACConfig != nil {
+ return fmt.Errorf("dac.urls can only be set for sequencer when l2 blob time is set")
}
return nil
}
diff --git official optimism/op-node/flags/flags.go SWC optimism/op-node/flags/flags.go
index d7b8ece67a13e458440478a7016505a9a7926685..f43a4115a39b456e9e99a4794975ce2623cc3962 100644
--- official optimism/op-node/flags/flags.go
+++ SWC optimism/op-node/flags/flags.go
@@ -361,6 +361,12 @@ EnvVars: prefixEnvVars("CONDUCTOR_RPC_TIMEOUT"),
Value: time.Second * 1,
Category: SequencerCategory,
}
+ DACUrlsFlag = &cli.StringFlag{
+ Name: "dac.urls",
+ Usage: "dac urls for sequencer when l2 blob is enabled",
+ EnvVars: prefixEnvVars("DAC_URLS"),
+ Category: SequencerCategory,
+ }
/* Interop flags, experimental. */
InteropRPCAddr = &cli.StringFlag{
Name: "interop.rpc.addr",
@@ -457,6 +463,7 @@ ConductorRpcFlag,
ConductorRpcTimeoutFlag,
SafeDBPath,
L2EngineKind,
+ DACUrlsFlag,
L2EngineRpcTimeout,
InteropRPCAddr,
InteropRPCPort,
diff --git official optimism/op-node/node/node.go SWC optimism/op-node/node/node.go
index 5d7caadfa62dfef4acab51cc4d567e72d9fb8ce8..f4843da6e9a6035fe5d5e4bb84a6b67f7b08e417 100644
--- official optimism/op-node/node/node.go
+++ SWC optimism/op-node/node/node.go
@@ -456,12 +456,13 @@ } else {
n.safeDB = safedb.Disabled
}
+ dacClient := cfg.DACConfig.Client()
if cfg.Rollup.ChainOpConfig == nil {
return fmt.Errorf("cfg.Rollup.ChainOpConfig is nil. Please see https://github.com/ethereum-optimism/optimism/releases/tag/op-node/v1.11.0: %w", err)
}
n.l2Driver = driver.NewDriver(n.eventSys, n.eventDrain, &cfg.Driver, &cfg.Rollup, cfg.DependencySet, n.l2Source, n.l1Source,
- n.beacon, n, n, n.log, n.metrics, cfg.ConfigPersistence, n.safeDB, &cfg.Sync, sequencerConductor, altDA, indexingMode)
+ n.beacon, n, n, n.log, n.metrics, cfg.ConfigPersistence, n.safeDB, &cfg.Sync, sequencerConductor, altDA, indexingMode, dacClient)
// Wire up IndexingMode to engine controller for direct force reset notifications
if n.interopSys != nil {
diff --git official optimism/op-node/p2p/gossip.go SWC optimism/op-node/p2p/gossip.go
index a8871a7364f68e896d810338c6205a741d137d91..f212d5290dc75a52ccc5a14d986a21b57acf9367 100644
--- official optimism/op-node/p2p/gossip.go
+++ SWC optimism/op-node/p2p/gossip.go
@@ -332,7 +332,7 @@ now := uint64(time.Now().Unix())
// [REJECT] if the `payload.timestamp` is older than the configured threshold
threshold := uint64(gossipConf.GetGossipTimestampThreshold().Seconds())
- if uint64(payload.Timestamp) < now-threshold {
+ if uint64(payload.Timestamp) < now-threshold || uint64(payload.Timestamp) < cfg.BlockTime /* ensure timestamp>=BlockTime since we'll do subtraction below */ {
log.Warn("payload is too old", "timestamp", uint64(payload.Timestamp), "threshold_seconds", threshold)
return pubsub.ValidationReject
}
@@ -381,13 +381,13 @@ }
if blockVersion.HasBlobProperties() {
// [REJECT] if the block is on a topic >= V3 and has a blob gas used value that is not zero
- if payload.BlobGasUsed == nil || *payload.BlobGasUsed != 0 {
+ if payload.BlobGasUsed == nil || (!cfg.IsL2Blob(uint64(payload.Timestamp)-cfg.BlockTime) && *payload.BlobGasUsed != 0) {
log.Warn("payload is on v3 topic, but has non-zero blob gas used", "bad_hash", payload.BlockHash.String(), "blob_gas_used", payload.BlobGasUsed)
return pubsub.ValidationReject
}
// [REJECT] if the block is on a topic >= V3 and has an excess blob gas value that is not zero
- if payload.ExcessBlobGas == nil || *payload.ExcessBlobGas != 0 {
+ if payload.ExcessBlobGas == nil || (!cfg.IsL2Blob(uint64(payload.Timestamp)-cfg.BlockTime) && *payload.ExcessBlobGas != 0) {
log.Warn("payload is on v3 topic, but has non-zero excess blob gas", "bad_hash", payload.BlockHash.String(), "excess_blob_gas", payload.ExcessBlobGas)
return pubsub.ValidationReject
}
diff --git official optimism/op-node/rollup/derive/batch_test.go SWC optimism/op-node/rollup/derive/batch_test.go
index c206739c979aeb9a9e92536d137266a7a0d7bf6f..4f67ef2e30e515554e720f29edaecf5adc213b7a 100644
--- official optimism/op-node/rollup/derive/batch_test.go
+++ SWC optimism/op-node/rollup/derive/batch_test.go
@@ -34,7 +34,7 @@ blockTxCount := 1 + uint64(rng.Intn(16))
blockTxCounts = append(blockTxCounts, blockTxCount)
totalblockTxCounts += blockTxCount
}
- signer := types.NewIsthmusSigner(chainId)
+ signer := types.NewIsthmusSigner(chainId, false)
var txs [][]byte
for i := 0; i < int(totalblockTxCounts); i++ {
var tx *types.Transaction
diff --git official optimism/op-node/rollup/derive/batch_test_utils.go SWC optimism/op-node/rollup/derive/batch_test_utils.go
index bf28c1e00e656fb3afc5a2d2ad455bde71ce325b..a1007af5b62fc61edfb4e3b21d566bdc28f16545 100644
--- official optimism/op-node/rollup/derive/batch_test_utils.go
+++ SWC optimism/op-node/rollup/derive/batch_test_utils.go
@@ -11,7 +11,7 @@ "github.com/ethereum/go-ethereum/core/types"
)
func RandomSingularBatch(rng *rand.Rand, txCount int, chainID *big.Int) *SingularBatch {
- signer := types.NewIsthmusSigner(chainID)
+ signer := types.NewIsthmusSigner(chainID, false)
baseFee := big.NewInt(rng.Int63n(300_000_000_000))
txsEncoded := make([]hexutil.Bytes, 0, txCount)
// force each tx to have equal chainID
diff --git official optimism/op-node/rollup/derive/batches.go SWC optimism/op-node/rollup/derive/batches.go
index 861a8be953cf42d7f727d09701cfde53e1d15ebc..620910c04161db4864c8f31a28a15f3108136a26 100644
--- official optimism/op-node/rollup/derive/batches.go
+++ SWC optimism/op-node/rollup/derive/batches.go
@@ -168,6 +168,7 @@ }
}
isIsthmus := cfg.IsIsthmus(batch.Timestamp)
+ isL2Blob := cfg.IsL2Blob(batch.Timestamp)
// We can do this check earlier, but it's a more intensive one, so we do this last.
for i, txBytes := range batch.Transactions {
@@ -181,6 +182,10 @@ return BatchDrop
}
if !isIsthmus && txBytes[0] == types.SetCodeTxType {
log.Warn("sequencers may not embed any SetCode transactions before Isthmus", "tx_index", i)
+ return BatchDrop
+ }
+ if !isL2Blob && txBytes[0] == types.BlobTxType {
+ log.Warn("sequencers may not embed any Blob transactions before L2Blob", "tx_index", i)
return BatchDrop
}
}
diff --git official optimism/op-node/rollup/derive/batches_test.go SWC optimism/op-node/rollup/derive/batches_test.go
index 19397fc415b637ad9139bb7ee024a16573b47c0e..388dd6ffa4c19c0be311f406d96138e570e90aef 100644
--- official optimism/op-node/rollup/derive/batches_test.go
+++ SWC optimism/op-node/rollup/derive/batches_test.go
@@ -73,7 +73,7 @@
rng := rand.New(rand.NewSource(1234))
chainId := new(big.Int).SetUint64(rng.Uint64())
- signer := types.NewIsthmusSigner(chainId)
+ signer := types.NewIsthmusSigner(chainId, false)
randTx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer)
randTxData, _ := randTx.MarshalBinary()
diff --git official optimism/op-node/rollup/derive/blob_data_source.go SWC optimism/op-node/rollup/derive/blob_data_source.go
index 2c4626941b8b51cb9477c9c08dd9f6e3fb01208a..fd2f7cef1236ea9e8e7c886bf7e78a934ae4b98a 100644
--- official optimism/op-node/rollup/derive/blob_data_source.go
+++ SWC optimism/op-node/rollup/derive/blob_data_source.go
@@ -27,13 +27,13 @@ data []blobOrCalldata
ref eth.L1BlockRef
batcherAddr common.Address
dsCfg DataSourceConfig
- fetcher L1TransactionFetcher
+ fetcher L1Fetcher
blobsFetcher L1BlobsFetcher
log log.Logger
}
// NewBlobDataSource creates a new blob data source.
-func NewBlobDataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1TransactionFetcher, blobsFetcher L1BlobsFetcher, ref eth.L1BlockRef, batcherAddr common.Address) DataIter {
+func NewBlobDataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1Fetcher, blobsFetcher L1BlobsFetcher, ref eth.L1BlockRef, batcherAddr common.Address) DataIter {
return &BlobDataSource{
ref: ref,
dsCfg: dsCfg,
@@ -73,6 +73,51 @@ }
return data, nil
}
+// getTxSucceedMap returns a map indicating whether tx status is successful if useInboxContract;
+// if !useInboxContract, nil map is returned to indicate that no status check is needed.
+func getTxSucceedMap(ctx context.Context, useInboxContract bool, fetcher L1Fetcher, hash common.Hash) (txSucceeded map[common.Hash]bool, err error) {
+ if !useInboxContract {
+ return
+ }
+ _, receipts, err := fetcher.FetchReceipts(ctx, hash)
+ if err != nil {
+ return nil, NewTemporaryError(fmt.Errorf("failed to fetch L1 block info and receipts: %w", err))
+ }
+ txSucceeded = make(map[common.Hash]bool)
+ for _, receipt := range receipts {
+ if receipt.Status == types.ReceiptStatusSuccessful {
+ txSucceeded[receipt.TxHash] = true
+ }
+ }
+ return
+}
+
+// getTxSucceed returns all successful txs
+func getTxSucceed(ctx context.Context, useInboxContract bool, fetcher L1Fetcher, hash common.Hash, txs types.Transactions) (successTxs types.Transactions, err error) {
+ if !useInboxContract {
+ // if !useInboxContract, all txs are considered successful
+ return txs, nil
+ }
+ _, receipts, err := fetcher.FetchReceipts(ctx, hash)
+ if err != nil {
+ return nil, NewTemporaryError(fmt.Errorf("failed to fetch L1 block info and receipts: %w", err))
+ }
+
+ txSucceeded := make(map[common.Hash]bool)
+ for _, receipt := range receipts {
+ if receipt.Status == types.ReceiptStatusSuccessful {
+ txSucceeded[receipt.TxHash] = true
+ }
+ }
+ successTxs = make(types.Transactions, 0)
+ for _, tx := range txs {
+ if _, ok := txSucceeded[tx.Hash()]; ok {
+ successTxs = append(successTxs, tx)
+ }
+ }
+ return successTxs, nil
+}
+
// open fetches and returns the blob or calldata (as appropriate) from all valid batcher
// transactions in the referenced block. Returns an empty (non-nil) array if no batcher
// transactions are found. It returns ResetError if it cannot find the referenced block or a
@@ -85,8 +130,12 @@ return nil, NewResetError(fmt.Errorf("failed to open blob data source: %w", err))
}
return nil, NewTemporaryError(fmt.Errorf("failed to open blob data source: %w", err))
}
+ txSucceedMap, err := getTxSucceedMap(ctx, ds.dsCfg.useInboxContract, ds.fetcher, ds.ref.Hash)
+ if err != nil {
+ return nil, err
+ }
- data, hashes := dataAndHashesFromTxs(txs, &ds.dsCfg, ds.batcherAddr, ds.log)
+ data, hashes := dataAndHashesFromTxs(txs, &ds.dsCfg, ds.batcherAddr, ds.log, txSucceedMap)
if len(hashes) == 0 {
// there are no blobs to fetch so we can return immediately
@@ -115,13 +164,15 @@
// dataAndHashesFromTxs extracts calldata and datahashes from the input transactions and returns them. It
// creates a placeholder blobOrCalldata element for each returned blob hash that must be populated
// by fillBlobPointers after blob bodies are retrieved.
-func dataAndHashesFromTxs(txs types.Transactions, config *DataSourceConfig, batcherAddr common.Address, logger log.Logger) ([]blobOrCalldata, []eth.IndexedBlobHash) {
+func dataAndHashesFromTxs(txs types.Transactions, config *DataSourceConfig, batcherAddr common.Address, logger log.Logger, txSucceedMap map[common.Hash]bool) ([]blobOrCalldata, []eth.IndexedBlobHash) {
data := []blobOrCalldata{}
var hashes []eth.IndexedBlobHash
blobIndex := 0 // index of each blob in the block's blob sidecar
for _, tx := range txs {
- // skip any non-batcher transactions
- if !isValidBatchTx(tx, config.l1Signer, config.batchInboxAddress, batcherAddr, logger) {
+ // skip any non-batcher transactions or failed transactions
+ // blobIndex needs to be incremented for both invalid batch tx and failed tx
+ // if txSucceedMap is nil, it means no status check is needed.
+ if (!isValidBatchTx(tx, config.l1Signer, config.batchInboxAddress, batcherAddr, logger)) || (txSucceedMap != nil && !txSucceedMap[tx.Hash()]) {
blobIndex += len(tx.BlobHashes())
continue
}
diff --git official optimism/op-node/rollup/derive/blob_data_source_test.go SWC optimism/op-node/rollup/derive/blob_data_source_test.go
index a20205544c478c35fe088d9bb782f504f5c6bf18..beb2aeadc5550b4f322c4b8418d1b8cbfec49591 100644
--- official optimism/op-node/rollup/derive/blob_data_source_test.go
+++ SWC optimism/op-node/rollup/derive/blob_data_source_test.go
@@ -45,7 +45,7 @@ Data: testutils.RandomData(rng, rng.Intn(1000)),
}
calldataTx, _ := types.SignNewTx(privateKey, signer, txData)
txs := types.Transactions{calldataTx}
- data, blobHashes := dataAndHashesFromTxs(txs, &config, batcherAddr, logger)
+ data, blobHashes := dataAndHashesFromTxs(txs, &config, batcherAddr, logger, nil)
require.Equal(t, 1, len(data))
require.Equal(t, 0, len(blobHashes))
@@ -60,14 +60,14 @@ BlobHashes: []common.Hash{blobHash},
}
blobTx, _ := types.SignNewTx(privateKey, signer, blobTxData)
txs = types.Transactions{blobTx}
- data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger)
+ data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger, nil)
require.Equal(t, 1, len(data))
require.Equal(t, 1, len(blobHashes))
require.Nil(t, data[0].calldata)
// try again with both the blob & calldata transactions and make sure both are picked up
txs = types.Transactions{blobTx, calldataTx}
- data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger)
+ data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger, nil)
require.Equal(t, 2, len(data))
require.Equal(t, 1, len(blobHashes))
require.NotNil(t, data[1].calldata)
@@ -75,7 +75,7 @@
// make sure blob tx to the batch inbox is ignored if not signed by the batcher
blobTx, _ = types.SignNewTx(testutils.RandomKey(), signer, blobTxData)
txs = types.Transactions{blobTx}
- data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger)
+ data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger, nil)
require.Equal(t, 0, len(data))
require.Equal(t, 0, len(blobHashes))
@@ -84,7 +84,7 @@ // signature is valid.
blobTxData.To = testutils.RandomAddress(rng)
blobTx, _ = types.SignNewTx(privateKey, signer, blobTxData)
txs = types.Transactions{blobTx}
- data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger)
+ data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger, nil)
require.Equal(t, 0, len(data))
require.Equal(t, 0, len(blobHashes))
@@ -98,9 +98,47 @@ }
setCodeTx, err := types.SignNewTx(privateKey, signer, setCodeTxData)
require.NoError(t, err)
txs = types.Transactions{setCodeTx}
- data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger)
+ data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger, nil)
require.Equal(t, 0, len(data))
require.Equal(t, 0, len(blobHashes))
+}
+
+func TestBlockWithFailedBlobTx(t *testing.T) {
+ // test setup
+ rng := rand.New(rand.NewSource(12345))
+ privateKey := testutils.InsecureRandomKey(rng)
+ publicKey, _ := privateKey.Public().(*ecdsa.PublicKey)
+ batcherAddr := crypto.PubkeyToAddress(*publicKey)
+ batchInboxAddr := testutils.RandomAddress(rng)
+ logger := testlog.Logger(t, log.LvlInfo)
+
+ chainId := new(big.Int).SetUint64(rng.Uint64())
+ signer := types.NewCancunSigner(chainId)
+ config := DataSourceConfig{
+ l1Signer: signer,
+ batchInboxAddress: batchInboxAddr,
+ }
+
+ // create two valid blob batcher txs
+ var txs types.Transactions
+ for i := 0; i < 2; i++ {
+ blobHash := testutils.RandomHash(rng)
+ blobTxData := &types.BlobTx{
+ Nonce: rng.Uint64(),
+ Gas: 2_000_000,
+ To: batchInboxAddr,
+ Data: testutils.RandomData(rng, rng.Intn(1000)),
+ BlobHashes: []common.Hash{blobHash},
+ }
+ blobTx, _ := types.SignNewTx(privateKey, signer, blobTxData)
+ txs = append(txs, blobTx)
+ }
+
+ // mark the first blob tx as failed
+ txSucceedMap := map[common.Hash]bool{txs[1].Hash(): true}
+ _, blobHashes := dataAndHashesFromTxs(txs, &config, batcherAddr, logger, txSucceedMap)
+ // check the returned blob index is 1
+ require.True(t, len(blobHashes) == 1 && blobHashes[0].Index == 1)
}
func TestFillBlobPointers(t *testing.T) {
diff --git official optimism/op-node/rollup/derive/calldata_source.go SWC optimism/op-node/rollup/derive/calldata_source.go
index 0e8147261e93e4235c33b93f1d56be2285d96297..776428dce37b8a9099177efb526185a60e1272c0 100644
--- official optimism/op-node/rollup/derive/calldata_source.go
+++ SWC optimism/op-node/rollup/derive/calldata_source.go
@@ -24,7 +24,7 @@ data []eth.Data
// Required to re-attempt fetching
ref eth.L1BlockRef
dsCfg DataSourceConfig
- fetcher L1TransactionFetcher
+ fetcher L1Fetcher
log log.Logger
batcherAddr common.Address
@@ -32,7 +32,7 @@ }
// NewCalldataSource creates a new calldata source. It suppresses errors in fetching the L1 block if they occur.
// If there is an error, it will attempt to fetch the result on the next call to `Next`.
-func NewCalldataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1TransactionFetcher, ref eth.L1BlockRef, batcherAddr common.Address) DataIter {
+func NewCalldataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1Fetcher, ref eth.L1BlockRef, batcherAddr common.Address) DataIter {
_, txs, err := fetcher.InfoAndTxsByHash(ctx, ref.Hash)
if err != nil {
return &CalldataSource{
@@ -44,6 +44,17 @@ log: log,
batcherAddr: batcherAddr,
}
}
+ txs, err = getTxSucceed(ctx, dsCfg.useInboxContract, fetcher, ref.Hash, txs)
+ if err != nil {
+ return &CalldataSource{
+ open: false,
+ ref: ref,
+ dsCfg: dsCfg,
+ fetcher: fetcher,
+ log: log,
+ batcherAddr: batcherAddr,
+ }
+ }
return &CalldataSource{
open: true,
data: DataFromEVMTransactions(dsCfg, batcherAddr, txs, log.New("origin", ref)),
@@ -56,6 +67,10 @@ // otherwise it returns a temporary error if fetching the block returns an error.
func (ds *CalldataSource) Next(ctx context.Context) (eth.Data, error) {
if !ds.open {
if _, txs, err := ds.fetcher.InfoAndTxsByHash(ctx, ds.ref.Hash); err == nil {
+ txs, err := getTxSucceed(ctx, ds.dsCfg.useInboxContract, ds.fetcher, ds.ref.Hash, txs)
+ if err != nil {
+ return nil, err
+ }
ds.open = true
ds.data = DataFromEVMTransactions(ds.dsCfg, ds.batcherAddr, txs, ds.log)
} else if errors.Is(err, ethereum.NotFound) {
diff --git official optimism/op-node/rollup/derive/calldata_source_test.go SWC optimism/op-node/rollup/derive/calldata_source_test.go
index 01b2616cca3fa66be0beeff9b4e9de814f492120..31555996ddbe354a81ba2982585c18be1344c654 100644
--- official optimism/op-node/rollup/derive/calldata_source_test.go
+++ SWC optimism/op-node/rollup/derive/calldata_source_test.go
@@ -121,7 +121,7 @@ expectedData = append(expectedData, txs[i].Data())
}
}
- out := DataFromEVMTransactions(DataSourceConfig{cfg.L1Signer(), cfg.BatchInboxAddress, false}, batcherAddr, txs, testlog.Logger(t, log.LevelCrit))
+ out := DataFromEVMTransactions(DataSourceConfig{cfg.L1Signer(), cfg.BatchInboxAddress, false, false}, batcherAddr, txs, testlog.Logger(t, log.LevelCrit))
require.ElementsMatch(t, expectedData, out)
}
diff --git official optimism/op-node/rollup/derive/data_source.go SWC optimism/op-node/rollup/derive/data_source.go
index dfeda599501a1970dca6a52a15f99e867d0fb992..a86e0de4b98eafcb68f6bd883f2c21f5d8b2b46f 100644
--- official optimism/op-node/rollup/derive/data_source.go
+++ SWC optimism/op-node/rollup/derive/data_source.go
@@ -52,6 +52,7 @@ config := DataSourceConfig{
l1Signer: cfg.L1Signer(),
batchInboxAddress: cfg.BatchInboxAddress,
altDAEnabled: cfg.AltDAEnabled(),
+ useInboxContract: cfg.UseInboxContract(),
}
return &DataSourceFactory{
log: log,
@@ -88,6 +89,7 @@ type DataSourceConfig struct {
l1Signer types.Signer
batchInboxAddress common.Address
altDAEnabled bool
+ useInboxContract bool
}
// isValidBatchTx returns true if:
diff --git official optimism/op-node/rollup/derive/span_batch_test.go SWC optimism/op-node/rollup/derive/span_batch_test.go
index 96628c92c10ba213a1fe16524be4cf532ee94efc..e691fa58059966032a7f3cb3d300139fd38fb1be 100644
--- official optimism/op-node/rollup/derive/span_batch_test.go
+++ SWC optimism/op-node/rollup/derive/span_batch_test.go
@@ -485,7 +485,7 @@ for i, testCase := range cases {
t.Run(testCase.name, func(t *testing.T) {
rng := rand.New(rand.NewSource(int64(0x109550 + i)))
chainID := new(big.Int).SetUint64(rng.Uint64())
- signer := types.NewIsthmusSigner(chainID)
+ signer := types.NewIsthmusSigner(chainID, false)
if !testCase.protected {
signer = types.HomesteadSigner{}
}
diff --git official optimism/op-node/rollup/derive/span_batch_tx.go SWC optimism/op-node/rollup/derive/span_batch_tx.go
index 876fbd9347f27566b571b3f0d09e1f600f6ba0ec..3d8e5a01962120470eff853522b23838ee287f3c 100644
--- official optimism/op-node/rollup/derive/span_batch_tx.go
+++ SWC optimism/op-node/rollup/derive/span_batch_tx.go
@@ -46,6 +46,18 @@ }
func (txData *spanBatchDynamicFeeTxData) txType() byte { return types.DynamicFeeTxType }
+type spanBatchBlobTxData struct {
+ Value *uint256.Int
+ GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas
+ GasFeeCap *uint256.Int // a.k.a. maxFeePerGas
+ Data []byte
+ AccessList types.AccessList
+ BlobFeeCap *uint256.Int // a.k.a. maxFeePerBlobGas
+ BlobHashes []common.Hash
+}
+
+func (txData *spanBatchBlobTxData) txType() byte { return types.BlobTxType }
+
type spanBatchSetCodeTxData struct {
Value *uint256.Int
GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas
@@ -103,6 +115,13 @@ var inner spanBatchDynamicFeeTxData
err := rlp.DecodeBytes(b[1:], &inner)
if err != nil {
return nil, fmt.Errorf("failed to decode spanBatchDynamicFeeTxData: %w", err)
+ }
+ return &inner, nil
+ case types.BlobTxType:
+ var inner spanBatchBlobTxData
+ err := rlp.DecodeBytes(b[1:], &inner)
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode spanBatchBlobTxData: %w", err)
}
return &inner, nil
case types.SetCodeTxType:
@@ -187,6 +206,39 @@ V: V,
R: R,
S: S,
}
+ case types.BlobTxType:
+ if to == nil {
+ return nil, fmt.Errorf("invalid blob tx: to can't be nil")
+ }
+ VU256, overflow := uint256.FromBig(V)
+ if overflow {
+ return nil, fmt.Errorf("invalid blob tx: V overflow:%v", V)
+ }
+ RU256, overflow := uint256.FromBig(R)
+ if overflow {
+ return nil, fmt.Errorf("invalid blob tx: R overflow:%v", R)
+ }
+ SU256, overflow := uint256.FromBig(S)
+ if overflow {
+ return nil, fmt.Errorf("invalid blob tx: S overflow:%v", R)
+ }
+ batchTxInner := tx.inner.(*spanBatchBlobTxData)
+ inner = &types.BlobTx{
+ ChainID: uint256.MustFromBig(chainID),
+ Nonce: nonce,
+ GasTipCap: batchTxInner.GasTipCap,
+ GasFeeCap: batchTxInner.GasFeeCap,
+ Gas: gas,
+ To: *to,
+ Value: batchTxInner.Value,
+ Data: batchTxInner.Data,
+ AccessList: batchTxInner.AccessList,
+ BlobFeeCap: batchTxInner.BlobFeeCap,
+ BlobHashes: batchTxInner.BlobHashes,
+ V: VU256,
+ R: RU256,
+ S: SU256,
+ }
case types.SetCodeTxType:
if to == nil {
return nil, fmt.Errorf("to address is required for SetCodeTx")
@@ -238,6 +290,32 @@ GasFeeCap: tx.GasFeeCap(),
Value: tx.Value(),
Data: tx.Data(),
AccessList: tx.AccessList(),
+ }
+ case types.BlobTxType:
+ gasTipCap, overflow := uint256.FromBig(tx.GasTipCap())
+ if overflow {
+ return nil, fmt.Errorf("tx.GasTipCap() overflow: %v", tx.GasTipCap())
+ }
+ gasFeeCap, overflow := uint256.FromBig(tx.GasFeeCap())
+ if overflow {
+ return nil, fmt.Errorf("tx.GasFeeCap() overflow: %v", tx.GasFeeCap())
+ }
+ value, overflow := uint256.FromBig(tx.Value())
+ if overflow {
+ return nil, fmt.Errorf("tx.Value() overflow: %v", tx.Value())
+ }
+ blobFeeCap, overflow := uint256.FromBig(tx.BlobGasFeeCap())
+ if overflow {
+ return nil, fmt.Errorf("tx.BlobGasFeeCap() overflow: %v", tx.BlobGasFeeCap())
+ }
+ inner = &spanBatchBlobTxData{
+ Value: value,
+ GasTipCap: gasTipCap,
+ GasFeeCap: gasFeeCap,
+ Data: tx.Data(),
+ AccessList: tx.AccessList(),
+ BlobFeeCap: blobFeeCap,
+ BlobHashes: tx.BlobHashes(),
}
case types.SetCodeTxType:
inner = &spanBatchSetCodeTxData{
diff --git official optimism/op-node/rollup/derive/span_batch_tx_test.go SWC optimism/op-node/rollup/derive/span_batch_tx_test.go
index d215a0f2c6be01a30b3421e44c3d34b768941687..d39278856869f6385426f4c5fc99dbffe6642798 100644
--- official optimism/op-node/rollup/derive/span_batch_tx_test.go
+++ SWC optimism/op-node/rollup/derive/span_batch_tx_test.go
@@ -31,7 +31,7 @@ for i, testCase := range cases {
t.Run(testCase.name, func(t *testing.T) {
rng := rand.New(rand.NewSource(int64(0x1331 + i)))
chainID := big.NewInt(rng.Int63n(1000))
- signer := types.NewIsthmusSigner(chainID)
+ signer := types.NewIsthmusSigner(chainID, false)
if !testCase.protected {
signer = types.HomesteadSigner{}
}
@@ -71,7 +71,7 @@ for i, testCase := range cases {
t.Run(testCase.name, func(t *testing.T) {
rng := rand.New(rand.NewSource(int64(0x1332 + i)))
chainID := big.NewInt(rng.Int63n(1000))
- signer := types.NewIsthmusSigner(chainID)
+ signer := types.NewIsthmusSigner(chainID, false)
if !testCase.protected {
signer = types.HomesteadSigner{}
}
diff --git official optimism/op-node/rollup/derive/span_batch_txs.go SWC optimism/op-node/rollup/derive/span_batch_txs.go
index 7c354430fc30e5a61f2fbbdcb36df607f311e677..159a9eb14506010fbc23980912d5bea288af0e15 100644
--- official optimism/op-node/rollup/derive/span_batch_txs.go
+++ SWC optimism/op-node/rollup/derive/span_batch_txs.go
@@ -271,6 +271,8 @@ case types.AccessListTxType:
v = bit
case types.DynamicFeeTxType:
v = bit
+ case types.BlobTxType:
+ v = bit
case types.SetCodeTxType:
v = bit
default:
@@ -387,6 +389,8 @@ }
case types.AccessListTxType:
yParityBit = uint(v)
case types.DynamicFeeTxType:
+ yParityBit = uint(v)
+ case types.BlobTxType:
yParityBit = uint(v)
case types.SetCodeTxType:
yParityBit = uint(v)
diff --git official optimism/op-node/rollup/derive/span_batch_txs_test.go SWC optimism/op-node/rollup/derive/span_batch_txs_test.go
index 1a752f75f47baab50442081154e40b49b048729f..7ccd1b2761a60a00ee5c533d837591d9c2f060e6 100644
--- official optimism/op-node/rollup/derive/span_batch_txs_test.go
+++ SWC optimism/op-node/rollup/derive/span_batch_txs_test.go
@@ -333,7 +333,8 @@ func TestSpanBatchTxsRecoverV(t *testing.T) {
rng := rand.New(rand.NewSource(0x123))
chainID := big.NewInt(rng.Int63n(1000))
- isthmusSigner := types.NewIsthmusSigner(chainID)
+ isthmusSigner := types.NewIsthmusSigner(chainID, false)
+ cancunSigner := types.NewCancunSigner(chainID)
totalblockTxCount := 20 + rng.Intn(100)
cases := []txTypeTest{
@@ -342,6 +343,7 @@ {"legacy tx", testutils.RandomLegacyTx, isthmusSigner},
{"access list tx", testutils.RandomAccessListTx, isthmusSigner},
{"dynamic fee tx", testutils.RandomDynamicFeeTx, isthmusSigner},
{"setcode tx", testutils.RandomSetCodeTx, isthmusSigner},
+ {"blob tx", testutils.RandomBlobTx, cancunSigner},
}
for _, testCase := range cases {
@@ -425,7 +427,7 @@
func TestSpanBatchTxsRoundTripFullTxs(t *testing.T) {
rng := rand.New(rand.NewSource(0x13377331))
chainID := big.NewInt(rng.Int63n(1000))
- isthmusSigner := types.NewIsthmusSigner(chainID)
+ isthmusSigner := types.NewIsthmusSigner(chainID, false)
cases := []txTypeTest{
{"unprotected legacy tx", testutils.RandomLegacyTx, types.HomesteadSigner{}},
@@ -476,7 +478,7 @@
func TestSpanBatchTxsFullTxNotEnoughTxTos(t *testing.T) {
rng := rand.New(rand.NewSource(0x13572468))
chainID := big.NewInt(rng.Int63n(1000))
- isthmusSigner := types.NewIsthmusSigner(chainID)
+ isthmusSigner := types.NewIsthmusSigner(chainID, false)
cases := []txTypeTest{
{"unprotected legacy tx", testutils.RandomLegacyTx, types.HomesteadSigner{}},
diff --git official optimism/op-node/rollup/derive/test/random.go SWC optimism/op-node/rollup/derive/test/random.go
index 8502855d014637d50599db1256ee849602c7eac3..9f4febcb354ca24ec8e88fac2403664364cf38ba 100644
--- official optimism/op-node/rollup/derive/test/random.go
+++ SWC optimism/op-node/rollup/derive/test/random.go
@@ -40,7 +40,7 @@ return RandomL2BlockWithChainIdAndTime(rng, txCount, chainId, time.Time{})
}
func RandomL2BlockWithChainIdAndTime(rng *rand.Rand, txCount int, chainId *big.Int, t time.Time) *types.Block {
- signer := types.NewIsthmusSigner(chainId)
+ signer := types.NewIsthmusSigner(chainId, false)
block, _ := RandomL2Block(rng, 0, t)
txs := []*types.Transaction{block.Transactions()[0]} // L1 info deposit TX
for i := 0; i < txCount; i++ {
diff --git official optimism/op-node/rollup/driver/driver.go SWC optimism/op-node/rollup/driver/driver.go
index 8d77bb3fec4eb6aa41d7541d609dacdd6cd9d285..ffcde0d1a5cd21393f3b1c07defca7853bc9c3d0 100644
--- official optimism/op-node/rollup/driver/driver.go
+++ SWC optimism/op-node/rollup/driver/driver.go
@@ -179,6 +179,7 @@ syncCfg *sync.Config,
sequencerConductor conductor.SequencerConductor,
altDA AltDAIface,
indexingMode bool,
+ dacClient engine.DACClient,
) *Driver {
driverCtx, driverCancel := context.WithCancel(context.Background())
@@ -258,7 +259,7 @@ // Connect origin selector to the engine controller for force reset notifications
ec.SetOriginSelectorResetter(findL1Origin)
sequencer = sequencing.NewSequencer(driverCtx, log, cfg, attrBuilder, findL1Origin,
- sequencerStateListener, sequencerConductor, asyncGossiper, metrics, ec)
+ sequencerStateListener, sequencerConductor, asyncGossiper, metrics, ec, dacClient)
sys.Register("sequencer", sequencer)
} else {
sequencer = sequencing.DisabledSequencer{}
diff --git official optimism/op-node/rollup/engine/engine_controller.go SWC optimism/op-node/rollup/engine/engine_controller.go
index aa7185655260c7e4171aa7387cb38261f0c34ff9..b8db71ed2c586925e9b52202908cda6f562c451b 100644
--- official optimism/op-node/rollup/engine/engine_controller.go
+++ SWC optimism/op-node/rollup/engine/engine_controller.go
@@ -69,6 +69,10 @@ OnCrossUnsafeUpdate(ctx context.Context, crossUnsafe eth.L2BlockRef, localUnsafe eth.L2BlockRef)
OnCrossSafeUpdate(ctx context.Context, crossSafe eth.L2BlockRef, localSafe eth.L2BlockRef)
}
+type DACClient interface {
+ UploadBlobs(context.Context, *eth.ExecutionPayloadEnvelope) error
+}
+
type EngineController struct {
engine ExecEngine // Underlying execution engine RPC
log log.Logger
diff --git official optimism/op-node/rollup/sequencing/sequencer.go SWC optimism/op-node/rollup/sequencing/sequencer.go
index ca32311094700aaade4c7bc8ed4f7a5f3412dc41..4a5d358d8cafd4009ec4b5bb747436803f2ba2bd 100644
--- official optimism/op-node/rollup/sequencing/sequencer.go
+++ SWC optimism/op-node/rollup/sequencing/sequencer.go
@@ -126,6 +126,8 @@ latestHeadSet chan struct{}
// toBlockRef converts a payload to a block-ref, and is only configurable for test-purposes
toBlockRef func(rollupCfg *rollup.Config, payload *eth.ExecutionPayload) (eth.L2BlockRef, error)
+
+ dacClient engine.DACClient
}
var _ SequencerIface = (*Sequencer)(nil)
@@ -138,6 +140,7 @@ conductor conductor.SequencerConductor,
asyncGossip AsyncGossiper,
metrics Metrics,
eng attributes.EngineController,
+ dacClient engine.DACClient,
) *Sequencer {
return &Sequencer{
ctx: driverCtx,
@@ -153,6 +156,7 @@ metrics: metrics,
eng: eng,
timeNow: time.Now,
toBlockRef: derive.PayloadToBlockRef,
+ dacClient: dacClient,
}
}
@@ -274,6 +278,28 @@ "block", x.Envelope.ExecutionPayload.ID(),
"parent", x.Envelope.ExecutionPayload.ParentID(),
"txs", len(x.Envelope.ExecutionPayload.Transactions),
"time", uint64(x.Envelope.ExecutionPayload.Timestamp))
+
+ {
+ envelope := x.Envelope
+ if envelope.BlobsBundle != nil && len(envelope.BlobsBundle.Blobs) > 0 {
+ // Deriving is based on onchain-data which doesn't contain L2 blob.
+ if x.DerivedFrom != (eth.L1BlockRef{}) {
+ d.emitter.Emit(d.ctx, rollup.EngineTemporaryErrorEvent{
+ Err: fmt.Errorf("got blobs when deriving")})
+ return
+ }
+ if d.dacClient != nil {
+ ctx, cancel := context.WithTimeout(d.ctx, time.Second*5)
+ defer cancel()
+ err := d.dacClient.UploadBlobs(ctx, envelope)
+ if err != nil {
+ d.emitter.Emit(d.ctx, rollup.EngineTemporaryErrorEvent{
+ Err: fmt.Errorf("UploadBlobs failed: %w", err)})
+ return
+ }
+ }
+ }
+ }
// generous timeout, the conductor is important
ctx, cancel := context.WithTimeout(d.ctx, time.Second*30)
diff --git official optimism/op-node/rollup/sequencing/sequencer_test.go SWC optimism/op-node/rollup/sequencing/sequencer_test.go
index 353388a9a6c9847d0eb966b2669414e4ccda64b5..c2479bdd3c17f213157f5534dba9b2769a89c2ca 100644
--- official optimism/op-node/rollup/sequencing/sequencer_test.go
+++ SWC optimism/op-node/rollup/sequencing/sequencer_test.go
@@ -729,7 +729,7 @@ asyncGossip: &FakeAsyncGossip{},
}
seq := NewSequencer(context.Background(), log, cfg, deps.attribBuilder,
deps.l1OriginSelector, deps.seqState, deps.conductor,
- deps.asyncGossip, metrics.NoopMetrics, fakeEngController{})
+ deps.asyncGossip, metrics.NoopMetrics, fakeEngController{}, nil)
// We create mock payloads, with the epoch-id as tx[0], rather than proper L1Block-info deposit tx.
seq.toBlockRef = func(rollupCfg *rollup.Config, payload *eth.ExecutionPayload) (eth.L2BlockRef, error) {
return eth.L2BlockRef{
diff --git official optimism/op-node/rollup/superchain.go SWC optimism/op-node/rollup/superchain.go
index ec3da88143097204db2a705e192fa9c19d6bb844..e8d46ab93df2b211e0b2ab5c7ec5e167ea629ebb 100644
--- official optimism/op-node/rollup/superchain.go
+++ SWC optimism/op-node/rollup/superchain.go
@@ -12,6 +12,14 @@ )
var OPStackSupport = params.ProtocolVersionV0{Build: [8]byte{}, Major: 9, Minor: 0, Patch: 0, PreRelease: 0}.Encode()
+func copyuint64ptr(ptr *uint64) *uint64 {
+ if ptr == nil {
+ return nil
+ }
+ val := *ptr
+ return &val
+}
+
// LoadOPStackRollupConfig loads the rollup configuration of the requested chain ID from the superchain-registry.
// Some chains may require a SystemConfigProvider to retrieve any values not part of the registry.
func LoadOPStackRollupConfig(chainID uint64) (*Config, error) {
@@ -25,9 +33,14 @@ if err != nil {
return nil, fmt.Errorf("unable to retrieve chain %d config: %w", chainID, err)
}
chOpConfig := ¶ms.OptimismConfig{
- EIP1559Elasticity: chConfig.Optimism.EIP1559Elasticity,
- EIP1559Denominator: chConfig.Optimism.EIP1559Denominator,
- EIP1559DenominatorCanyon: chConfig.Optimism.EIP1559DenominatorCanyon,
+ EIP1559Elasticity: chConfig.Optimism.EIP1559Elasticity,
+ EIP1559Denominator: chConfig.Optimism.EIP1559Denominator,
+ EIP1559DenominatorCanyon: chConfig.Optimism.EIP1559DenominatorCanyon,
+ L2BlobTime: copyuint64ptr(chConfig.Optimism.L2BlobTime),
+ SoulGasTokenTime: copyuint64ptr(chConfig.Optimism.SoulGasTokenTime),
+ IsSoulBackedByNative: chConfig.Optimism.IsSoulBackedByNative,
+ L1BaseFeeScalarMultiplier: chConfig.Optimism.L1BaseFeeScalarMultiplier,
+ L1BlobBaseFeeScalarMultiplier: chConfig.Optimism.L1BlobBaseFeeScalarMultiplier,
}
superConfig, err := superchain.GetSuperchain(chain.Network)
diff --git official optimism/op-node/rollup/types.go SWC optimism/op-node/rollup/types.go
index 28f9e195644451257ecb6dbe86b9b38273548a91..725084a0f2eb9ce77e1a74956edd939cc8c6044c 100644
--- official optimism/op-node/rollup/types.go
+++ SWC optimism/op-node/rollup/types.go
@@ -150,6 +150,8 @@ // parameters to the protocol values, like the execution layer does.
// If missing, it is loaded by the op-node from the embedded superchain config at startup.
ChainOpConfig *params.OptimismConfig `json:"chain_op_config,omitempty"`
+ InboxContractConfig *InboxContractConfig `json:"inbox_contract_config,omitempty"`
+
// Optional Features
// AltDAConfig. We are in the process of migrating to the AltDAConfig from these legacy top level values
@@ -162,6 +164,29 @@ // blob parameters for the first L1 Prague block, as was intended.
// This feature (de)activates by L1 origin timestamp, to keep a consistent L1 block info per L2
// epoch.
PectraBlobScheduleTime *uint64 `json:"pectra_blob_schedule_time,omitempty"`
+}
+
+type L2BlobConfig struct {
+ L2BlobTime *uint64 `json:"l2BlobTime,omitempty"`
+}
+
+type InboxContractConfig struct {
+ UseInboxContract bool `json:"use_inbox_contract,omitempty"`
+}
+
+// IsL2Blob returns whether l2 blob is enabled
+func (cfg *Config) IsL2Blob(timestamp uint64) bool {
+ return cfg.IsL2BlobTimeSet() && *cfg.ChainOpConfig.L2BlobTime <= timestamp
+}
+
+// UseInboxContract returns whether inbox contract is enabled
+func (cfg *Config) UseInboxContract() bool {
+ return cfg.InboxContractConfig != nil && cfg.InboxContractConfig.UseInboxContract
+}
+
+// IsL2BlobTimeSet returns whether l2 blob activation time is set
+func (cfg *Config) IsL2BlobTimeSet() bool {
+ return cfg.ChainOpConfig != nil && cfg.ChainOpConfig.L2BlobTime != nil
}
// ValidateL1Config checks L1 config variables for errors.
@@ -734,6 +759,12 @@ banner += "Post-Bedrock Network Upgrades (timestamp based):\n"
c.forEachFork(func(name string, _ string, time *uint64) {
banner += fmt.Sprintf(" - %v: %s\n", name, fmtForkTimeOrUnset(time))
})
+ var l2BlobTime *uint64
+ if c.ChainOpConfig != nil {
+ l2BlobTime = c.ChainOpConfig.L2BlobTime
+ }
+ banner += fmt.Sprintf(" - L2Blob: %s\n", fmtForkTimeOrUnset(l2BlobTime))
+ banner += fmt.Sprintf(" - Use inbox contract: %v\n", c.UseInboxContract())
// Report the protocol version
banner += fmt.Sprintf("Node supports up to OP-Stack Protocol Version: %s\n", OPStackSupport)
if c.AltDAConfig != nil {
@@ -776,6 +807,13 @@ })
if c.AltDAConfig != nil {
ctx = append(ctx, "alt_da", *c.AltDAConfig)
}
+
+ var l2BlobTime *uint64
+ if c.ChainOpConfig != nil {
+ l2BlobTime = c.ChainOpConfig.L2BlobTime
+ }
+ ctx = append(ctx, "l2_blob_config", fmtForkTimeOrUnset(l2BlobTime))
+ ctx = append(ctx, "use_inbox_contract", c.UseInboxContract())
log.Info("Rollup Config", ctx...)
}
diff --git official optimism/op-node/service.go SWC optimism/op-node/service.go
index 78216daa44508f1fda830cbf70a3042f098cf6d4..1eec481158ccecc42b4a36f1c9a75ae64f434d68 100644
--- official optimism/op-node/service.go
+++ SWC optimism/op-node/service.go
@@ -115,7 +115,8 @@ return conductorRPCEndpoint, nil
},
ConductorRpcTimeout: ctx.Duration(flags.ConductorRpcTimeoutFlag.Name),
- AltDA: altda.ReadCLIConfig(ctx),
+ AltDA: altda.ReadCLIConfig(ctx),
+ DACConfig: config.ReadDACConfigFromCLI(ctx),
IgnoreMissingPectraBlobSchedule: ctx.Bool(flags.IgnoreMissingPectraBlobSchedule.Name),
FetchWithdrawalRootFromState: ctx.Bool(flags.FetchWithdrawalRootFromState.Name),
diff --git official optimism/op-program/Makefile SWC optimism/op-program/Makefile
index 48c9f13ad443d2fdaa6488eed84d99e7723ad800..4f0008a2a8788e2be6bfb00392d4d4ecf5bf92da 100644
--- official optimism/op-program/Makefile
+++ SWC optimism/op-program/Makefile
@@ -74,6 +74,10 @@
test:
go test -v ./...
+
+verify-beta-testnet: op-program-host op-program-client
+ env GO111MODULE=on go run ./verify/beta-testnet/cmd/beta-testnet.go --l1 $$SEPOLIA_L1URL --l1.beacon $$SEPOLIA_BEACON_URL --l2 $$SEPOLIA_L2URL --datadir /tmp/test-beta-testnet
+
capture-mainnet-genesis: op-program-host op-program-client
rm -rf "$(COMPAT_DIR)/mainnet-genesis" "$(COMPAT_DIR)/mainnet-genesis.tar.bz"
env GO111MODULE=on go run ./verify/mainnet/cmd/mainnet.go --l1 $$MAINNET_L1URL --l1.beacon $$MAINNET_BEACON_URL --l2 $$MAINNET_L2URL --datadir "$(COMPAT_DIR)/mainnet-genesis" --l1.head "0x4903424f6cc2cfba7c2bf8c8f48ca46721c963fa64b411cfee3697b781e3e5f1" --l2.start "105235063" --l2.end "105235064"
diff --git official optimism/op-program/client/l2/engineapi/block_processor.go SWC optimism/op-program/client/l2/engineapi/block_processor.go
index 953b6d526d890222ff3ff41671b371b6ec32bdd9..5110ca453a703f2f48e09aabbfb10636b60e4261 100644
--- official optimism/op-program/client/l2/engineapi/block_processor.go
+++ SWC optimism/op-program/client/l2/engineapi/block_processor.go
@@ -10,6 +10,7 @@ "github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@@ -103,7 +104,8 @@ if provider.Config().IsCancun(header.Number, header.Time) {
// Blob tx not supported on optimism chains but fields must be set when Cancun is active.
zero := uint64(0)
header.BlobGasUsed = &zero
- header.ExcessBlobGas = &zero
+ excessBlobGas := eip4844.CalcExcessBlobGas(provider.Config(), parentHeader, header.Time)
+ header.ExcessBlobGas = &excessBlobGas
}
// core.NewEVMBlockContext need to be called after the blob gas fields are set
vmenv = mkEVM()
@@ -151,6 +153,9 @@ return nil, fmt.Errorf("failed to apply transaction to L2 block (tx %d): %w", txIndex, err)
}
b.receipts = append(b.receipts, receipt)
b.transactions = append(b.transactions, tx)
+ if b.header.BlobGasUsed != nil {
+ *b.header.BlobGasUsed += receipt.BlobGasUsed
+ }
return receipt, nil
}
diff --git official optimism/op-program/scripts/build-prestates.sh SWC optimism/op-program/scripts/build-prestates.sh
index 3c3ddff0bb2793b6ffbc0a73818a35786c352725..7cf3309c7ce138b5d57e7d51351ce9b7e6930b73 100755
--- official optimism/op-program/scripts/build-prestates.sh
+++ SWC optimism/op-program/scripts/build-prestates.sh
@@ -12,7 +12,7 @@ cd "${TMP_DIR}"
# Need to check out a fresh copy of the monorepo so we can switch to specific tags without it also affecting the
# contents of this script (which is checked into the repo).
-git clone https://github.com/ethereum-optimism/optimism --recurse-submodules
+git clone https://github.com/ethstorage/optimism --recurse-submodules
STATES_DIR="${SCRIPTS_DIR}/../temp/states"
LOGS_DIR="${SCRIPTS_DIR}/../temp/logs"
diff --git official optimism/op-program/verify/beta-testnet/cmd/beta-testnet.go SWC optimism/op-program/verify/beta-testnet/cmd/beta-testnet.go
new file mode 100644
index 0000000000000000000000000000000000000000..79fdda66394c34e8a8650ee11b10f10937de6fac
--- /dev/null
+++ SWC optimism/op-program/verify/beta-testnet/cmd/beta-testnet.go
@@ -0,0 +1,68 @@
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+
+ "github.com/ethereum-optimism/optimism/op-program/verify"
+ "github.com/ethereum-optimism/optimism/op-service/eth"
+ "github.com/ethereum/go-ethereum/common"
+)
+
+func main() {
+ var l1RpcUrl string
+ var l1RpcKind string
+ var l1BeaconUrl string
+ var l2RpcUrl string
+ var dataDir string
+ var l1HashStr string
+ var l2Start uint64
+ var l2End uint64
+ flag.StringVar(&l1RpcUrl, "l1", "", "L1 RPC URL to use")
+ flag.StringVar(&l1BeaconUrl, "l1.beacon", "", "L1 Beacon URL to use")
+ flag.StringVar(&l1RpcKind, "l1-rpckind", "", "L1 RPC kind")
+ flag.StringVar(&l2RpcUrl, "l2", "", "L2 RPC URL to use")
+ flag.StringVar(&dataDir, "datadir", "",
+ "Directory to use for storing pre-images. If not set a temporary directory will be used.")
+ flag.StringVar(&l1HashStr, "l1.head", "", "Hash of L1 block to use")
+ flag.Uint64Var(&l2Start, "l2.start", 0, "Block number of agreed L2 block")
+ flag.Uint64Var(&l2End, "l2.end", 0, "Block number of claimed L2 block")
+ flag.Parse()
+
+ if l1RpcUrl == "" {
+ _, _ = fmt.Fprintln(os.Stderr, "Must specify --l1 RPC URL")
+ os.Exit(2)
+ }
+ if l1BeaconUrl == "" {
+ _, _ = fmt.Fprintln(os.Stderr, "Must specify --l1.beacon URL")
+ os.Exit(2)
+ }
+ if l2RpcUrl == "" {
+ _, _ = fmt.Fprintln(os.Stderr, "Must specify --l2 RPC URL")
+ os.Exit(2)
+ }
+
+ // Apply the custom configs by running op-program
+ runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "3335", eth.ChainIDFromUInt64(3335), false)
+ if err != nil {
+ _, _ = fmt.Fprintf(os.Stderr, "Failed to create runner: %v\n", err.Error())
+ os.Exit(1)
+ }
+
+ if l1HashStr == "" && l2Start == 0 && l2End == 0 {
+ err = runner.RunToFinalized(context.Background())
+ } else {
+ l1Hash := common.HexToHash(l1HashStr)
+ if l1Hash == (common.Hash{}) {
+ _, _ = fmt.Fprintf(os.Stderr, "Invalid --l1.head: %v\n", l1HashStr)
+ os.Exit(2)
+ }
+ err = runner.RunBetweenBlocks(context.Background(), l1Hash, l2Start, l2End)
+ }
+ if err != nil {
+ _, _ = fmt.Fprintf(os.Stderr, "Failed: %v\n", err.Error())
+ os.Exit(1)
+ }
+}
diff --git official optimism/op-service/eth/types.go SWC optimism/op-service/eth/types.go
index f10a1cc32431268f6bf3a40847fc70bfbe1f91e2..98d6ff4a5c98f9daa219ccbee8c21f029ca6b66f 100644
--- official optimism/op-service/eth/types.go
+++ SWC optimism/op-service/eth/types.go
@@ -231,8 +231,9 @@ Timestamp uint64 `json:"timestamp"`
}
type ExecutionPayloadEnvelope struct {
- ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot,omitempty"`
- ExecutionPayload *ExecutionPayload `json:"executionPayload"`
+ ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot,omitempty"`
+ ExecutionPayload *ExecutionPayload `json:"executionPayload"`
+ BlobsBundle *engine.BlobsBundleV1 `json:"blobsBundle"`
}
func (env *ExecutionPayloadEnvelope) ID() BlockID {
diff --git official optimism/op-service/predeploys/addresses.go SWC optimism/op-service/predeploys/addresses.go
index e461f0c86faaf596bbd3ec9914e8b5ee6dd21b93..de20083e3d0aa4c675d82936e82525baab74e15d 100644
--- official optimism/op-service/predeploys/addresses.go
+++ SWC optimism/op-service/predeploys/addresses.go
@@ -26,6 +26,7 @@ L1FeeVault = "0x420000000000000000000000000000000000001a"
OperatorFeeVault = "0x420000000000000000000000000000000000001b"
SchemaRegistry = "0x4200000000000000000000000000000000000020"
EAS = "0x4200000000000000000000000000000000000021"
+ SoulGasToken = "0x4200000000000000000000000000000000000800"
CrossL2Inbox = "0x4200000000000000000000000000000000000022"
L2toL2CrossDomainMessenger = "0x4200000000000000000000000000000000000023"
SuperchainETHBridge = "0x4200000000000000000000000000000000000024"
@@ -67,6 +68,7 @@ L1FeeVaultAddr = common.HexToAddress(L1FeeVault)
OperatorFeeVaultAddr = common.HexToAddress(OperatorFeeVault)
SchemaRegistryAddr = common.HexToAddress(SchemaRegistry)
EASAddr = common.HexToAddress(EAS)
+ SoulGasTokenAddr = common.HexToAddress(SoulGasToken)
CrossL2InboxAddr = common.HexToAddress(CrossL2Inbox)
L2toL2CrossDomainMessengerAddr = common.HexToAddress(L2toL2CrossDomainMessenger)
SuperchainETHBridgeAddr = common.HexToAddress(SuperchainETHBridge)
@@ -122,6 +124,7 @@ Predeploys["L1FeeVault"] = &Predeploy{Address: L1FeeVaultAddr}
Predeploys["OperatorFeeVault"] = &Predeploy{Address: OperatorFeeVaultAddr}
Predeploys["SchemaRegistry"] = &Predeploy{Address: SchemaRegistryAddr}
Predeploys["EAS"] = &Predeploy{Address: EASAddr}
+ Predeploys["SoulGasToken"] = &Predeploy{Address: SoulGasTokenAddr}
Predeploys["Create2Deployer"] = &Predeploy{
Address: Create2DeployerAddr,
ProxyDisabled: true,
diff --git official optimism/op-service/sources/engine_client.go SWC optimism/op-service/sources/engine_client.go
index c16629b77d2bbd040188d1b4f6cd6747b6bacbec..755bcf5a0070061d856c0c7e42af4e22f3d6adf9 100644
--- official optimism/op-service/sources/engine_client.go
+++ SWC optimism/op-service/sources/engine_client.go
@@ -107,6 +107,8 @@ switch method := s.evp.NewPayloadVersion(uint64(payload.Timestamp)); method {
case eth.NewPayloadV4:
err = s.RPC.CallContext(ctx, &result, string(method), payload, []common.Hash{}, parentBeaconBlockRoot, []hexutil.Bytes{})
case eth.NewPayloadV3:
+ // now we pass empty array to skip checking versionedHashes
+ // TODO: sync with OP upstream once they support L2 blob tx
err = s.RPC.CallContext(ctx, &result, string(method), payload, []common.Hash{}, parentBeaconBlockRoot)
case eth.NewPayloadV2:
err = s.RPC.CallContext(ctx, &result, string(method), payload)
diff --git official optimism/op-service/testutils/devnet/proxy.go SWC optimism/op-service/testutils/devnet/proxy.go
index 0f1ab2c89ee131a7de303f8bcc429f660d41a28a..6d494389c855e6050fb2aaa3698a80dfea82e982 100644
--- official optimism/op-service/testutils/devnet/proxy.go
+++ SWC optimism/op-service/testutils/devnet/proxy.go
@@ -162,6 +162,7 @@ req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.upstream, bytes.NewReader(body))
if err != nil {
panic(fmt.Errorf("failed to create request: %w", err))
}
+ req.Header.Set("Content-Type", "application/json")
res, err := p.client.Do(req)
if err != nil {
p.lgr.Warn("failed to proxy request", "err", err)
diff --git official optimism/op-service/testutils/random.go SWC optimism/op-service/testutils/random.go
index e685b97c11b3947d73a25a3b714371e9e40ca6fe..87f50f666699c98931b575233d1373f56be453a9 100644
--- official optimism/op-service/testutils/random.go
+++ SWC optimism/op-service/testutils/random.go
@@ -144,7 +144,7 @@ return &to
}
func isIsthmusSigner(signer types.Signer) bool {
- isthusSigner := types.NewIsthmusSigner(signer.ChainID())
+ isthusSigner := types.NewIsthmusSigner(signer.ChainID(), false)
return signer.Equal(isthusSigner)
}
@@ -253,6 +253,30 @@ baseFee := new(big.Int).SetUint64(rng.Uint64())
return RandomDynamicFeeTxWithBaseFee(rng, baseFee, signer)
}
+func RandomBlobTx(rng *rand.Rand, signer types.Signer) *types.Transaction {
+ baseFee := new(big.Int).SetUint64(rng.Uint64())
+ key := InsecureRandomKey(rng)
+ tip := big.NewInt(rng.Int63n(10 * params.GWei))
+ txData := &types.BlobTx{
+ ChainID: uint256.MustFromBig(signer.ChainID()),
+ Nonce: rng.Uint64(),
+ GasTipCap: uint256.MustFromBig(tip),
+ GasFeeCap: uint256.MustFromBig(new(big.Int).Add(baseFee, tip)),
+ Gas: params.TxGas + uint64(rng.Int63n(2_000_000)),
+ To: RandomAddress(rng),
+ Value: uint256.MustFromBig(RandomETH(rng, 10)),
+ Data: RandomData(rng, rng.Intn(1000)),
+ AccessList: nil,
+ BlobFeeCap: uint256.MustFromBig(baseFee),
+ BlobHashes: []common.Hash{RandomHash(rng)},
+ }
+ tx, err := types.SignNewTx(key, signer, txData)
+ if err != nil {
+ panic(err)
+ }
+ return tx
+}
+
func RandomSetCodeAuth(rng *rand.Rand) types.SetCodeAuthorization {
key := InsecureRandomKey(rng)
@@ -360,7 +384,7 @@ if chainIDInt == 0 { // Zero chainID is invalid.
chainIDInt++
}
chainID := big.NewInt(chainIDInt)
- signer := types.NewIsthmusSigner(chainID)
+ signer := types.NewIsthmusSigner(chainID, false)
txs := make([]*types.Transaction, 0, txCount+len(ptxs))
txs = append(txs, ptxs...)
for i := 0; i < txCount; i++ {
diff --git official optimism/op-service/txinclude/isthmus_cost_oracle.go SWC optimism/op-service/txinclude/isthmus_cost_oracle.go
index 4083b87328c38af80a135ae4c76a1c06339d1f18..cdaba0155024a6995806b0d875d5f4ecb2b791e6 100644
--- official optimism/op-service/txinclude/isthmus_cost_oracle.go
+++ SWC optimism/op-service/txinclude/isthmus_cost_oracle.go
@@ -86,7 +86,7 @@
func (i *IsthmusCostOracle) OPCost(tx *types.Transaction) *big.Int {
params := i.costParams.Load()
- l1CostFunc := types.NewL1CostFuncFjord(params.L1BaseFee, params.L1BlobBaseFee, params.L1BaseFeeScalar, params.L1BlobBaseFeeScalar)
+ l1CostFunc := types.NewL1CostFuncFjord(params.L1BaseFee, params.L1BlobBaseFee, params.L1BaseFeeScalar, params.L1BlobBaseFeeScalar, big.NewInt(1), big.NewInt(1))
l1Cost, _ := l1CostFunc(tx.RollupCostData())
operatorCost := new(big.Int).SetUint64(tx.Gas())
diff --git official optimism/op-service/txinclude/isthmus_cost_oracle_test.go SWC optimism/op-service/txinclude/isthmus_cost_oracle_test.go
index a6dafba52a5660c884d404dc79fb52b86a1a6622..7993cbcdca6ba2d51fab60f544e97a4df5895520 100644
--- official optimism/op-service/txinclude/isthmus_cost_oracle_test.go
+++ SWC optimism/op-service/txinclude/isthmus_cost_oracle_test.go
@@ -100,7 +100,7 @@ oracle := txinclude.NewIsthmusCostOracle(mock, time.Millisecond)
require.NoError(t, oracle.SetParams(context.Background()))
tx := types.NewTx(&types.DynamicFeeTx{})
got := oracle.OPCost(tx)
- want, _ := types.NewL1CostFuncFjord(big.NewInt(102), big.NewInt(104), big.NewInt(103), big.NewInt(105))(tx.RollupCostData())
+ want, _ := types.NewL1CostFuncFjord(big.NewInt(102), big.NewInt(104), big.NewInt(103), big.NewInt(105), big.NewInt(1), big.NewInt(1))(tx.RollupCostData())
require.Equal(t, want, got)
})
}
diff --git official optimism/op-service/txinclude/txbudget.go SWC optimism/op-service/txinclude/txbudget.go
index 50f11900fbc190c69168c04646a86833f923fc19..24f19b8e389ff784992f5a261410d4c20ad8b7af 100644
--- official optimism/op-service/txinclude/txbudget.go
+++ SWC optimism/op-service/txinclude/txbudget.go
@@ -88,7 +88,7 @@ // l1Cost
if receipt.L1BaseFeeScalar != nil {
l1BaseFeeScalar := new(big.Int).SetUint64(*receipt.L1BaseFeeScalar)
l1BlobBaseFeeScalar := new(big.Int).SetUint64(*receipt.L1BlobBaseFeeScalar)
- costFunc := types.NewL1CostFuncFjord(receipt.L1GasPrice, receipt.L1BlobBaseFee, l1BaseFeeScalar, l1BlobBaseFeeScalar)
+ costFunc := types.NewL1CostFuncFjord(receipt.L1GasPrice, receipt.L1BlobBaseFee, l1BaseFeeScalar, l1BlobBaseFeeScalar, big.NewInt(1), big.NewInt(1))
l1Cost, _ := costFunc(tx.Transaction.RollupCostData())
actualCost.Add(actualCost, l1Cost)
}
diff --git official optimism/op-service/txinclude/txbudget_test.go SWC optimism/op-service/txinclude/txbudget_test.go
index a658fc8085258148bc7ac2da4d35d493e388d8a6..600a18186bb852a8006eadbb1124f712166582b4 100644
--- official optimism/op-service/txinclude/txbudget_test.go
+++ SWC optimism/op-service/txinclude/txbudget_test.go
@@ -91,8 +91,7 @@ BlobFeeCap: uint256.NewInt(1),
BlobHashes: []common.Hash{{}},
})
- l1Cost, _ := types.NewL1CostFuncFjord(big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1))(tx.RollupCostData())
- l1Cost.Add(l1Cost, big.NewInt(1)) // operator fee
+ l1Cost, _ := types.NewL1CostFuncFjord(big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1))(tx.RollupCostData())
oracle := mockOPCostOracle{
cost: l1Cost,
}
@@ -104,7 +103,7 @@ budgetedCost := eth.WeiBig(cost)
receipt := &types.Receipt{
EffectiveGasPrice: eth.WeiU64(1).ToBig(),
- GasUsed: budgetedCost.ToBig().Uint64(),
+ GasUsed: budgetedCost.ToBig().Uint64() - l1Cost.Uint64(),
Type: types.DynamicFeeTxType,
L1GasPrice: big.NewInt(1),
diff --git official optimism/ops/docker/op-stack-go/Dockerfile SWC optimism/ops/docker/op-stack-go/Dockerfile
index c077852bb17834355b11be5da6db6e8d2dd2bd47..5f40aaff949677936718b460ba4568e16e212f81 100644
--- official optimism/ops/docker/op-stack-go/Dockerfile
+++ SWC optimism/ops/docker/op-stack-go/Dockerfile
@@ -14,7 +14,7 @@ ARG UBUNTU_TARGET_BASE_IMAGE=ubuntu:22.04
# The version of kona to use.
# The only build that uses this is `op-challenger-target`.
-ARG KONA_VERSION=none
+ARG KONA_VERSION=kona-client-v0.1.0-beta.5
# The version of asterisc to use.
# The only build that uses this is `op-challenger-target`.
@@ -149,6 +149,15 @@ ARG OP_DEPLOYER_VERSION=v0.0.0
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-chain-ops && make op-deployer \
GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_DEPLOYER_VERSION"
+
+FROM --platform=$BUILDPLATFORM builder AS dac-server-builder
+ARG OP_NODE_VERSION=v0.0.0
+RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd da-server && go build -o da-server main.go
+
+FROM --platform=$BUILDPLATFORM builder AS op-geth-builder
+ARG OP_NODE_VERSION=v0.0.0
+RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-geth && CGO_ENABLED=0 make geth
+
FROM --platform=$BUILDPLATFORM builder AS op-dripper-builder
ARG OP_DRIPPER_VERSION=v0.0.0
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-dripper && make op-dripper \
@@ -181,6 +190,9 @@ CMD ["op-wheel"]
FROM $TARGET_BASE_IMAGE AS op-node-target
COPY --from=op-node-builder /app/op-node/bin/op-node /usr/local/bin/
+COPY --from=dac-server-builder /app/da-server/da-server /usr/local/bin/
+COPY --from=dac-server-builder /app/da-server/default.json /usr/local/bin/
+COPY --from=op-geth-builder /app/op-geth/build/bin/geth /usr/local/bin/
CMD ["op-node"]
# Make the kona docker image published by upstream available as a source to copy kona from.
diff --git official optimism/ops/docker/op-stack-go/Dockerfile.dockerignore SWC optimism/ops/docker/op-stack-go/Dockerfile.dockerignore
index 882c17c846c0c6cfbf17d61e57613eaff6012d0b..5e98b81312ccfc83d0c6f062e2056dce32345726 100644
--- official optimism/ops/docker/op-stack-go/Dockerfile.dockerignore
+++ SWC optimism/ops/docker/op-stack-go/Dockerfile.dockerignore
@@ -23,6 +23,8 @@ !/op-wheel
!/op-alt-da
!/op-faucet
!/op-interop-mon
+!/da-server
+!/op-geth
!/go.mod
!/go.sum
!/justfiles
diff --git official optimism/packages/contracts-bedrock/snapshots/abi/L1Block.json SWC optimism/packages/contracts-bedrock/snapshots/abi/L1Block.json
index 153d2676cf5bb3c9bdbb4da3e5253b16cec67f06..15c0616cc23c2ed637898198cdde077c64bee2df 100644
--- official optimism/packages/contracts-bedrock/snapshots/abi/L1Block.json
+++ SWC optimism/packages/contracts-bedrock/snapshots/abi/L1Block.json
@@ -78,6 +78,25 @@ "stateMutability": "view",
"type": "function"
},
{
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_historyNumber",
+ "type": "uint256"
+ }
+ ],
+ "name": "blockHash",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"inputs": [],
"name": "gasPayingToken",
"outputs": [
@@ -132,6 +151,19 @@ "type": "bytes32"
}
],
"stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "historySize",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "pure",
"type": "function"
},
{
diff --git official optimism/packages/contracts-bedrock/snapshots/abi/SoulGasToken.json SWC optimism/packages/contracts-bedrock/snapshots/abi/SoulGasToken.json
new file mode 100644
index 0000000000000000000000000000000000000000..be5f31855e48a036da9c07800d3a73b405d41229
--- /dev/null
+++ SWC optimism/packages/contracts-bedrock/snapshots/abi/SoulGasToken.json
@@ -0,0 +1,640 @@
+[
+ {
+ "inputs": [
+ {
+ "internalType": "bool",
+ "name": "_isBackedByNative",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_burners",
+ "type": "address[]"
+ }
+ ],
+ "name": "addBurners",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_minters",
+ "type": "address[]"
+ }
+ ],
+ "name": "addMinters",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_contracts",
+ "type": "address[]"
+ }
+ ],
+ "name": "allowSgtValue",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_accounts",
+ "type": "address[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "_values",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "batchBurnFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_accounts",
+ "type": "address[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "_values",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "batchDepositFor",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_accounts",
+ "type": "address[]"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "batchDepositForAll",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_accounts",
+ "type": "address[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "_values",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "batchMint",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_accounts",
+ "type": "address[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "_values",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "batchWithdrawFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_account",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "burnFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "chargeFromOrigin",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amountCharged_",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "decimals",
+ "outputs": [
+ {
+ "internalType": "uint8",
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "subtractedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "decreaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_burners",
+ "type": "address[]"
+ }
+ ],
+ "name": "delBurners",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_minters",
+ "type": "address[]"
+ }
+ ],
+ "name": "delMinters",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "deposit",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "_contracts",
+ "type": "address[]"
+ }
+ ],
+ "name": "disallowSgtValue",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "addedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "increaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "_name",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "_symbol",
+ "type": "string"
+ },
+ {
+ "internalType": "address",
+ "name": "_owner",
+ "type": "address"
+ }
+ ],
+ "name": "initialize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "isBackedByNative",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "renounceOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_account",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ }
+ ],
+ "name": "AllowSgtValue",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ }
+ ],
+ "name": "DisallowSgtValue",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint8",
+ "name": "version",
+ "type": "uint8"
+ }
+ ],
+ "name": "Initialized",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "previousOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "OwnershipTransferred",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ }
+]
\ No newline at end of file
diff --git official optimism/packages/contracts-bedrock/snapshots/abi_loader.go SWC optimism/packages/contracts-bedrock/snapshots/abi_loader.go
index d014c6604e05051df13a8b14d8d8c088260c93bb..4783bbd4c6a3a544b4f847aeed2f3c290f1eb4f5 100644
--- official optimism/packages/contracts-bedrock/snapshots/abi_loader.go
+++ SWC optimism/packages/contracts-bedrock/snapshots/abi_loader.go
@@ -31,6 +31,9 @@
//go:embed abi/CrossL2Inbox.json
var crossL2Inbox []byte
+//go:embed abi/SoulGasToken.json
+var solGasToken []byte
+
func LoadDisputeGameFactoryABI() *abi.ABI {
return loadABI(disputeGameFactory)
}
@@ -56,6 +59,10 @@ }
func LoadCrossL2InboxABI() *abi.ABI {
return loadABI(crossL2Inbox)
+}
+
+func LoadSoulGasTokenABI() *abi.ABI {
+ return loadABI(solGasToken)
}
func loadABI(json []byte) *abi.ABI {
diff --git official optimism/packages/contracts-bedrock/snapshots/abi_loader_test.go SWC optimism/packages/contracts-bedrock/snapshots/abi_loader_test.go
index dc9d0884cb094f1960e944086a3f787ee110a532..ef27d28838cace1dd76bedede464c7dc8c4105d5 100644
--- official optimism/packages/contracts-bedrock/snapshots/abi_loader_test.go
+++ SWC optimism/packages/contracts-bedrock/snapshots/abi_loader_test.go
@@ -18,6 +18,7 @@ {"SuperFaultDisputeGame", LoadSuperFaultDisputeGameABI},
{"PreimageOracle", LoadPreimageOracleABI},
{"MIPS", LoadMIPSABI},
{"DelayedWETH", LoadDelayedWETHABI},
+ {"SoulGasToken", LoadSoulGasTokenABI},
}
for _, test := range tests {
test := test
diff --git official optimism/packages/contracts-bedrock/snapshots/semver-lock.json SWC optimism/packages/contracts-bedrock/snapshots/semver-lock.json
index 14601517909bbf850d7d2202bad0d4ad9fa46729..ab5894d1bdb415e9d7b7346f1c42157a4690f220 100644
--- official optimism/packages/contracts-bedrock/snapshots/semver-lock.json
+++ SWC optimism/packages/contracts-bedrock/snapshots/semver-lock.json
@@ -28,8 +28,8 @@ "initCodeHash": "0x00544069c2122703f3234e5f315f5849c139d34d0e2f864c28d15ac210fe132b",
"sourceCodeHash": "0xc9647bf7895870cbbcdba8daae470c9f266388ca1e4cc9d421c676736cbe8220"
},
"src/L1/OptimismPortal2.sol:OptimismPortal2": {
- "initCodeHash": "0x0bd9360663627aab37a548aca16e26b1a8017766445b3969e16bc6cca6ec801a",
- "sourceCodeHash": "0xe2cc287f8c3caebc3a7e9c849155c9a4820c26ebe231b9959987bb4fb455c2d7"
+ "initCodeHash": "0x5d2ce1fffce653e225e611516405600e212f1d533a3e9c061d5644c509ff6170",
+ "sourceCodeHash": "0x920e96784b34d34da0135716c64064f01859b777c024c3a1416d6e85afaa303a"
},
"src/L1/OptimismPortalInterop.sol:OptimismPortalInterop": {
"initCodeHash": "0x7911f37dc9614291a3dfd76c5434d70ae573bb84f213f1c28baec078a2f4b559",
@@ -64,8 +64,8 @@ "initCodeHash": "0x38ef70b2783dd45ad807afcf57972c7df4abaaeb5d16d17cdb451b9e931a9cbb",
"sourceCodeHash": "0x4351fe2ac1106c8c220b8cfe7839bc107c24d8084deb21259ac954f5a362725d"
},
"src/L2/L1Block.sol:L1Block": {
- "initCodeHash": "0xc35734387887a95f611888f3944546c6bcf82fd4c05dcdaa1e019779b628ad68",
- "sourceCodeHash": "0x6e5349fd781d5f0127ff29ccea4d86a80240550cfa322364183a0f629abcb43e"
+ "initCodeHash": "0x78993662229a5e928fab86ed51d16f9bef03878e221a05715b58edeab35ac76f",
+ "sourceCodeHash": "0xed0be52dc505279a206d4dba74481fb5a3c3767f4246e5df842d65dac7f6ed59"
},
"src/L2/L1FeeVault.sol:L1FeeVault": {
"initCodeHash": "0x9b664e3d84ad510091337b4aacaa494b142512e2f6f7fbcdb6210ed62ca9b885",
@@ -88,8 +88,8 @@ "initCodeHash": "0xa7a2e7efe8116ebb21f47ee06c1e62d3b2f5a046478094611a2ab4b714154030",
"sourceCodeHash": "0xde724da82ecf3c96b330c2876a7285b6e2b933ac599241eaa3174c443ebbe33a"
},
"src/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser": {
- "initCodeHash": "0x88f7b25f956eceeab9ad84c17e66cded6a1acbb933054ac2c8b336641f70f875",
- "sourceCodeHash": "0x83396cbd12a0c5c02e09a4d99c4b62ab4e9d9eb762745e63283e2e818a78a39c"
+ "initCodeHash": "0x7169999087d4dfca3dac4993c7452fa56bb2a8986ca62f09c91523bb9e6bd2e1",
+ "sourceCodeHash": "0x242bf5fc497c9da521c0be0fa4046fae86587ccb6aecb37fa2681a44c4f4a39e"
},
"src/L2/L2ToL2CrossDomainMessenger.sol:L2ToL2CrossDomainMessenger": {
"initCodeHash": "0x975fd33a3a386310d54dbb01b56f3a6a8350f55a3b6bd7781e5ccc2166ddf2e6",
diff --git official optimism/packages/contracts-bedrock/snapshots/storageLayout/SoulGasToken.json SWC optimism/packages/contracts-bedrock/snapshots/storageLayout/SoulGasToken.json
new file mode 100644
index 0000000000000000000000000000000000000000..ce8662ad00f0554231a033169dbb984b0a4c150b
--- /dev/null
+++ SWC optimism/packages/contracts-bedrock/snapshots/storageLayout/SoulGasToken.json
@@ -0,0 +1,79 @@
+[
+ {
+ "bytes": "1",
+ "label": "_initialized",
+ "offset": 0,
+ "slot": "0",
+ "type": "uint8"
+ },
+ {
+ "bytes": "1",
+ "label": "_initializing",
+ "offset": 1,
+ "slot": "0",
+ "type": "bool"
+ },
+ {
+ "bytes": "1600",
+ "label": "__gap",
+ "offset": 0,
+ "slot": "1",
+ "type": "uint256[50]"
+ },
+ {
+ "bytes": "32",
+ "label": "_balances",
+ "offset": 0,
+ "slot": "51",
+ "type": "mapping(address => uint256)"
+ },
+ {
+ "bytes": "32",
+ "label": "_allowances",
+ "offset": 0,
+ "slot": "52",
+ "type": "mapping(address => mapping(address => uint256))"
+ },
+ {
+ "bytes": "32",
+ "label": "_totalSupply",
+ "offset": 0,
+ "slot": "53",
+ "type": "uint256"
+ },
+ {
+ "bytes": "32",
+ "label": "_name",
+ "offset": 0,
+ "slot": "54",
+ "type": "string"
+ },
+ {
+ "bytes": "32",
+ "label": "_symbol",
+ "offset": 0,
+ "slot": "55",
+ "type": "string"
+ },
+ {
+ "bytes": "1440",
+ "label": "__gap",
+ "offset": 0,
+ "slot": "56",
+ "type": "uint256[45]"
+ },
+ {
+ "bytes": "20",
+ "label": "_owner",
+ "offset": 0,
+ "slot": "101",
+ "type": "address"
+ },
+ {
+ "bytes": "1568",
+ "label": "__gap",
+ "offset": 0,
+ "slot": "102",
+ "type": "uint256[49]"
+ }
+]
\ No newline at end of file
diff --git official optimism/qkc-fork.yaml SWC optimism/qkc-fork.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..67f84f0714b9dee01cbfc79ed29cc272e14138fd
--- /dev/null
+++ SWC optimism/qkc-fork.yaml
@@ -0,0 +1,178 @@
+title: "SWC-optimism - official-optimism fork diff overview"
+footer: |
+ Fork-diff overview of [`SWC optimism`](https://github.com/Quarkchain/optimism), a fork of [`official optimism`](https://github.com/ethereum-optimism/optimism).
+ and consensus layer of the `SWC OP-stack`.
+base:
+ name: official optimism
+ url: https://github.com/ethereum-optimism/optimism
+ hash: c8b9f62736a7dad7e569719a84c406605f4472e6
+fork:
+ name: SWC optimism
+ url: https://github.com/Quarkchain/optimism
+ ref: refs/heads/op-es
+def:
+ title: "optimism"
+ description: |
+ This is an overview of the changes in [`SWC optimism`](https://github.com/Quarkchain/optimism),
+ a fork of [`official optimism`](https://github.com/ethereum-optimism/optimism), part of the `SWC OP-stack`.
+ sub:
+ - title: "Inbox contract modifications"
+ description: |
+ The OP-stack is extended to to allow the batch inbox to be a contract, enabling customized batch submission conditions such as:
+
+ - Requiring the batch transaction to be signed by a quorum of sequencers in a decentralized sequencing network; or
+
+ - Mandating that the batch transaction call a BLOB storage contract (e.g., EthStorage) with a long-term storage fee, which is then distributed to data nodes that prove BLOB storage over time.
+ globs:
+ - "op-batcher/batcher/driver.go"
+ - "op-chain-ops/genesis/config.go"
+ - "op-node/rollup/derive/blob_data_source.go"
+ - "op-node/rollup/derive/calldata_source.go"
+ - "op-node/rollup/derive/calldata_source_test.go"
+ - "op-node/rollup/derive/blob_data_source_test.go"
+ - "op-node/rollup/derive/data_source.go"
+ - "op-node/rollup/types.go"
+ - title: "Soul Gas Token modifications"
+ description: |
+ To bridge the gap between traditional web users and the growing world of Web3,
+ we propose a **non-transferable gas token** named Soul Gas Token (SGT), where the gas token is the native token of a Rollup.
+
+ The concept revolves around facilitating Web2 users' entry into Web3 by airdropping them with SGT.
+
+ This token will enable users to pay for transaction gas fees without the immediate selling pressure of the airdropped token.
+
+ This initiative is particularly aimed at those new to Web3, providing a seamless transition without the upfront cost of acquiring a gas token.
+ globs:
+ - "op-chain-ops/genesis/genesis.go"
+ - "op-service/predeploys/addresses.go"
+ - "packages/contracts-bedrock/scripts/Artifacts.s.sol"
+ - "packages/contracts-bedrock/scripts/L2Genesis.s.sol"
+ - "packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol"
+ - "packages/contracts-bedrock/src/L2/SoulGasToken.sol"
+ - "packages/contracts-bedrock/src/libraries/Predeploys.sol"
+ - "packages/contracts-bedrock/interfaces/L2/ISoulGasToken.sol"
+ - "packages/contracts-bedrock/deploy-config/devnetL1-template.json"
+ - title: "L2 Blob modifications"
+ description: |
+ The Ethereum Cancun upgrade has significantly reduced Layer 2 (L2) data uploading costs by introducing BLOB
+ transactions to Layer 1 (L1). This innovation has also enabled a variety of additional applications based on
+ the BLOBs due to their low cost, such as [blob.fm](https://blob.fm/), [EthStorage](https://ethstorage.io), and
+ [Ethscriptions](https://ethscriptions.com/). However, while the data upload costs have decreased, the execution
+ costs on L1 remain high compared to L2, leading to high costs for L2 state proposals and non-financial applications
+ that rely on BLOBs.
+
+ To address these challenges, the L2 BLOB feature introduces support for BLOB transactions on L2. enabling L3 solutions that settle on L2 to use an enshrined 4844-compatible DA layer without needing to
+ integrate third-party DA providers or deal with the security risks associated with DA bridges. Additionally, the
+ applications mentioned above could migrate to L2 with minimal costs.
+ globs:
+ - "op-node/flags/flags.go"
+ - "op-node/node/config.go"
+ - "op-node/node/node.go"
+ - "op-node/p2p/gossip.go"
+ - "op-node/rollup/derive/span_batch_tx.go"
+ - "op-node/rollup/derive/span_batch_txs.go"
+ - "op-node/rollup/derive/span_batch_txs_test.go"
+ - "op-node/rollup/driver/driver.go"
+ - "op-node/rollup/engine/engine_controller.go"
+ - "op-node/rollup/sequencing/sequencer.go"
+ - "op-node/rollup/sequencing/sequencer_test.go"
+ - "op-node/rollup/types.go"
+ - "op-node/service.go"
+ - "op-service/eth/types.go"
+ - "op-service/sources/engine_client.go"
+ - "op-service/testutils/random.go"
+ - "op-program/client/l2/engineapi/block_processor.go"
+ - "packages/contracts-bedrock/deploy-config/devnetL1-template.json"
+ - title: "L1 Header Hash History modifications"
+ description: |
+ In order to simplify the integration with EthStorage as L3, The `L1Block` contract is extended to allow
+ fetching 8191 history L1 blockhash not including the current one.
+ globs:
+ - "packages/contracts-bedrock/src/L2/L1Block.sol"
+ - "packages/contracts-bedrock/interfaces/L2/IL1Block.sol"
+ - "packages/contracts-bedrock/interfaces/L2/IL1BlockInterop.sol"
+ - "op-node/bindings/l1block.go"
+ - "packages/contracts-bedrock/test/L2/L1Block.t.sol"
+ - title: "Disable native deposit & enable minting"
+ description: |
+ In order to facilitate token migration of existing L1 token to L2 native token, we disable the native deposit
+ and enable minting L2 native token on L1. Refer to this [PR](https://github.com/QuarkChain/optimism/pull/49) for details.
+ globs:
+ - "packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol"
+ - "packages/contracts-bedrock/interfaces/L2/IL2ToL1MessagePasser.sol"
+ - "packages/contracts-bedrock/src/L1/OptimismPortal2.sol"
+ - "packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol"
+ - "packages/contracts-bedrock/src/libraries/Constants.sol"
+ - title: "Fault Proof for beta testnet"
+ description: |
+ Based on these PRs to enable fault proof for custom chains:
+
+ - https://github.com/ethereum-optimism/optimism/pull/12503
+ - https://github.com/ethereum-optimism/optimism/pull/12310
+
+ We enabled fault proof for the beta testnet.
+ globs:
+ - "op-program/chainconfig/configs/3335-genesis-l2.json"
+ - "op-program/chainconfig/configs/3335-rollup.json"
+ - "op-program/client/l2/engineapi/block_processor.go"
+ - "op-program/verify/beta-testnet/cmd/beta-testnet.go"
+ - "op-program/Makefile"
+ - "op-program/scripts/build-prestates.sh"
+ - "op-program/prestates/releases.json"
+ - title: "Testing"
+ sub:
+ - title: "Inbox contract e2e test"
+ description: ""
+ globs:
+ - "op-e2e/inbox/inbox_test.go"
+ - "op-e2e/bindings/batchinbox.go"
+ - "op-e2e/bindings/mockstorage.go"
+ - "op-e2e/inbox/testcontract/mockstorage.sol"
+ - "op-e2e/system/e2esys/setup.go"
+ - title: "Soul Gas Token e2e test"
+ description: ""
+ globs:
+ - "op-e2e/bindings/soulgastoken.go"
+ - "op-e2e/sgt/sgt_test.go"
+ - "op-e2e/sgt/helper.go"
+ - "op-e2e/actions/sgt/sgt_test.go"
+ - "op-e2e/config/init.go"
+ - title: "L2 Blob e2e test"
+ description: ""
+ globs:
+ - "op-e2e/l2blob/l2blob_test.go"
+ - title: "Script to run overall local test"
+ description: |
+ This script is used to run the overall local test for the OP-stack.
+ For details, please refer to [here](https://github.com/ethstorage/optimism/pull/161).
+ globs:
+ - ".mise-tasks/dev-test.sh"
+ - title: "Tools"
+ sub:
+ - title: "Script to upgrade SoulGasToken"
+ description: |
+ This script is used to upgrade the SoulGasToken contract on L2.
+ It allows for the deployment of a new version of the contract, ensuring that
+ users can benefit from the latest features and improvements.
+ globs:
+ - "packages/contracts-bedrock/scripts/deploy/UpgradeSoulGasToken.s.sol"
+ - title: "Script to update the AnchorStateRegistry"
+ description: |
+ This script is used to update the AnchorStateRegistry with a new anchor state when
+ switching from permissioned FDG to permissionless FDG on L1.
+ Fore details, please refer to [here](https://github.com/ethstorage/pm/blob/main/L2/beta_testnet_fdg_upgrade.md).
+ globs:
+ - "packages/contracts-bedrock/scripts/deploy/UpgradeAnchorStateRegistry.s.sol"
+
+
+# ignored globally, does not count towards line count
+ignore:
+ - ".circleci/*"
+ - "*.sum"
+ - "go.mod"
+ - "qkc-fork.yaml"
+ - ".github/**"
+ - "**/*.gob" # data asset, not code
+ - "core/vm/testdata/precompiles/p256Verify.json" # data asset, not code
+ - "eth/tracers/internal/tracetest/testdata/**/*.json"
+ - "packages/contracts-bedrock/snapshots/**"