Commit 7318b5e1 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into refcell/fix-contributors-label-section

parents 1329ad51 e6742f45
...@@ -745,8 +745,7 @@ jobs: ...@@ -745,8 +745,7 @@ jobs:
- checkout - checkout
- run: - run:
name: run lint name: run lint
command: | command: make lint
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
working_directory: <<parameters.module>> working_directory: <<parameters.module>>
go-test: go-test:
...@@ -842,7 +841,7 @@ jobs: ...@@ -842,7 +841,7 @@ jobs:
patterns: <<parameters.working_directory>>,<<parameters.dependencies>> patterns: <<parameters.working_directory>>,<<parameters.dependencies>>
- run: - run:
name: Lint name: Lint
command: golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 2m -e "errors.As" -e "errors.Is" ./... command: make lint
working_directory: <<parameters.working_directory>> working_directory: <<parameters.working_directory>>
- store_test_results: - store_test_results:
path: /test-results path: /test-results
...@@ -892,7 +891,7 @@ jobs: ...@@ -892,7 +891,7 @@ jobs:
name: Test name: Test
command: | command: |
mkdir -p /test-results mkdir -p /test-results
DB_USER=postgres gotestsum --junitfile /test-results/tests.xml -- -parallel=4 ./... DB_USER=postgres gotestsum --format=standard-verbose --junitfile /test-results/tests.xml -- -parallel=4 ./...
working_directory: indexer working_directory: indexer
- run: - run:
name: Build name: Build
......
...@@ -74,7 +74,7 @@ pull_request_rules: ...@@ -74,7 +74,7 @@ pull_request_rules:
More details can be found on the `Queue: Embarked in merge train` More details can be found on the `Queue: Embarked in merge train`
check-run. check-run.
- name: Add indexer tag and ecopod reviewers - name: Add A-indexer label and ecopod reviewers
conditions: conditions:
- 'files~=^indexer/' - 'files~=^indexer/'
actions: actions:
...@@ -84,7 +84,7 @@ pull_request_rules: ...@@ -84,7 +84,7 @@ pull_request_rules:
request_reviews: request_reviews:
users: users:
- roninjin10 - roninjin10
- name: Add sdk tag and ecopod reviewers - name: Add A-pkg-sdk label and ecopod reviewers
conditions: conditions:
- 'files~=^packages/sdk/' - 'files~=^packages/sdk/'
actions: actions:
...@@ -94,7 +94,7 @@ pull_request_rules: ...@@ -94,7 +94,7 @@ pull_request_rules:
request_reviews: request_reviews:
users: users:
- roninjin10 - roninjin10
- name: Add common-ts tag and ecopod reviewers - name: Add A-pkg-common-ts label and ecopod reviewers
conditions: conditions:
- 'files~=^packages/common-ts/' - 'files~=^packages/common-ts/'
actions: actions:
...@@ -104,3 +104,69 @@ pull_request_rules: ...@@ -104,3 +104,69 @@ pull_request_rules:
request_reviews: request_reviews:
users: users:
- roninjin10 - roninjin10
- name: Add A-op-node label
conditions:
- 'files~=^op-node/'
actions:
label:
add:
- A-op-node
- name: Add A-op-batcher label
conditions:
- 'files~=^op-batcher/'
actions:
label:
add:
- A-op-batcher
- name: Add A-cannon label
conditions:
- 'files~=^cannon/'
actions:
label:
add:
- A-cannon
- name: Add A-op-program label
conditions:
- 'files~=^op-program/'
actions:
label:
add:
- A-op-program
- name: Add A-op-challenger label
conditions:
- 'files~=^op-challenger/'
actions:
label:
add:
- A-op-challenger
- name: Add A-pkg-contracts-bedrock label
conditions:
- 'files~=^packages/contracts-bedrock/'
actions:
label:
add:
- A-pkg-contracts-bedrock
- name: Add M-docs label
conditions:
- 'files~=^technical-documents/'
- 'files~=^specs/'
actions:
label:
add:
- A-pkg-contracts-bedrock
- name: Add M-deletion label when files are removed
conditions:
- 'removed-files~=^/'
actions:
label:
add:
- M-deletion
- name: Add M-ci label when ci files are modified
conditions:
- 'files~=^.github/'
- 'files~=^.circleci/'
- 'files~=^.husky/'
actions:
label:
add:
- M-ci
...@@ -10,8 +10,9 @@ jobs: ...@@ -10,8 +10,9 @@ jobs:
- uses: actions/stale@v4 - uses: actions/stale@v4
with: with:
stale-pr-message: 'This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days.' stale-pr-message: 'This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
stale-issue-label: 'S-stale'
exempt-pr-labels: exempt-stale exempt-pr-labels: exempt-stale
days-before-issue-stale: 999 days-before-issue-stale: 999
days-before-pr-stale: 14 days-before-pr-stale: 14
days-before-close: 5 days-before-close: 5
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
...@@ -2,6 +2,15 @@ ...@@ -2,6 +2,15 @@
## Getting started ## Getting started
### Setup env
The `indexer.toml` stores a set of preset environmental variables that can be used to run the indexer with the exception of the network specific `l1-rpc` and `l2-rpc` variables. The `indexer.toml` file can be ran as a default config, otherwise a custom `.toml` config can provided via the `--config` flag when running the application. Additionally, L1 system contract addresses must provided for the specific OP Stack network actively being indexed. Currently the indexer has no way to infer L1 system config addresses provided a L2 chain ID or network enum.
### Testing
All tests can be ran by running `make test` from the `/indexer` directory. This will run all unit and e2e tests.
**NOTE:** Successfully running the E2E tests requires spinning up a local L1 geth node and pre-populating it with necessary bedrock genesis state. This can be done by calling `make devnet-allocs` from the root of the optimism monorepo before running the indexer tests. More information on this can be found in the [op-e2e README](../op-e2e/README.md).
### Run indexer vs goerli ### Run indexer vs goerli
- install docker - install docker
......
...@@ -46,15 +46,6 @@ func (mbv *MockBridgeTransfersView) L1BridgeDepositWithFilter(filter database.Br ...@@ -46,15 +46,6 @@ func (mbv *MockBridgeTransfersView) L1BridgeDepositWithFilter(filter database.Br
return &deposit, nil return &deposit, nil
} }
func (mbv *MockBridgeTransfersView) L1BridgeDepositsByAddress(address common.Address) ([]*database.L1BridgeDepositWithTransactionHashes, error) {
return []*database.L1BridgeDepositWithTransactionHashes{
{
L1BridgeDeposit: deposit,
L1TransactionHash: common.HexToHash("0x123"),
},
}, nil
}
func (mbv *MockBridgeTransfersView) L2BridgeWithdrawal(address common.Hash) (*database.L2BridgeWithdrawal, error) { func (mbv *MockBridgeTransfersView) L2BridgeWithdrawal(address common.Hash) (*database.L2BridgeWithdrawal, error) {
return &withdrawal, nil return &withdrawal, nil
} }
...@@ -63,15 +54,27 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalWithFilter(filter database ...@@ -63,15 +54,27 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalWithFilter(filter database
return &withdrawal, nil return &withdrawal, nil
} }
func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common.Address) ([]*database.L2BridgeWithdrawalWithTransactionHashes, error) { func (mbv *MockBridgeTransfersView) L1BridgeDepositsByAddress(address common.Address, cursor string, limit int) (*database.L1BridgeDepositsResponse, error) {
return []*database.L2BridgeWithdrawalWithTransactionHashes{ return &database.L1BridgeDepositsResponse{
{ Deposits: []*database.L1BridgeDepositWithTransactionHashes{
L2BridgeWithdrawal: withdrawal, {
L2TransactionHash: common.HexToHash("0x789"), L1BridgeDeposit: deposit,
L1TransactionHash: common.HexToHash("0x123"),
},
}, },
}, nil }, nil
} }
func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common.Address, cursor string, limit int) (*database.L2BridgeWithdrawalsResponse, error) {
return &database.L2BridgeWithdrawalsResponse{
Withdrawals: []*database.L2BridgeWithdrawalWithTransactionHashes{
{
L2BridgeWithdrawal: withdrawal,
L2TransactionHash: common.HexToHash("0x789"),
},
},
}, nil
}
func TestHealthz(t *testing.T) { func TestHealthz(t *testing.T) {
logger := testlog.Logger(t, log.LvlInfo) logger := testlog.Logger(t, log.LvlInfo)
api := NewApi(&MockBridgeTransfersView{}, logger) api := NewApi(&MockBridgeTransfersView{}, logger)
......
...@@ -2,6 +2,7 @@ package routes ...@@ -2,6 +2,7 @@ package routes
import ( import (
"net/http" "net/http"
"strconv"
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -29,9 +30,9 @@ type DepositResponse struct { ...@@ -29,9 +30,9 @@ type DepositResponse struct {
// TODO this is original spec but maybe include the l2 block info too for the relayed tx // TODO this is original spec but maybe include the l2 block info too for the relayed tx
// FIXME make a pure function that returns a struct instead of newWithdrawalResponse // FIXME make a pure function that returns a struct instead of newWithdrawalResponse
func newDepositResponse(deposits []*database.L1BridgeDepositWithTransactionHashes) DepositResponse { func newDepositResponse(deposits *database.L1BridgeDepositsResponse) DepositResponse {
items := make([]DepositItem, len(deposits)) items := make([]DepositItem, len(deposits.Deposits))
for _, deposit := range deposits { for _, deposit := range deposits.Deposits {
item := DepositItem{ item := DepositItem{
Guid: deposit.L1BridgeDeposit.TransactionSourceHash.String(), Guid: deposit.L1BridgeDeposit.TransactionSourceHash.String(),
Block: Block{ Block: Block{
...@@ -71,16 +72,30 @@ func newDepositResponse(deposits []*database.L1BridgeDepositWithTransactionHashe ...@@ -71,16 +72,30 @@ func newDepositResponse(deposits []*database.L1BridgeDepositWithTransactionHashe
} }
return DepositResponse{ return DepositResponse{
Cursor: "42042042-4204-4204-4204-420420420420", // TODO Cursor: deposits.Cursor,
HasNextPage: false, // TODO HasNextPage: deposits.HasNextPage,
Items: items, Items: items,
} }
} }
func (h Routes) L1DepositsHandler(w http.ResponseWriter, r *http.Request) { func (h Routes) L1DepositsHandler(w http.ResponseWriter, r *http.Request) {
address := common.HexToAddress(chi.URLParam(r, "address")) address := common.HexToAddress(chi.URLParam(r, "address"))
cursor := r.URL.Query().Get("cursor")
limitQuery := r.URL.Query().Get("limit")
deposits, err := h.BridgeTransfersView.L1BridgeDepositsByAddress(address) defaultLimit := 100
limit := defaultLimit
if limitQuery != "" {
parsedLimit, err := strconv.Atoi(limitQuery)
if err != nil {
http.Error(w, "Limit could not be parsed into a number", http.StatusBadRequest)
h.Logger.Error("Invalid limit")
h.Logger.Error(err.Error())
}
limit = parsedLimit
}
deposits, err := h.BridgeTransfersView.L1BridgeDepositsByAddress(address, cursor, limit)
if err != nil { if err != nil {
http.Error(w, "Internal server error reading deposits", http.StatusInternalServerError) http.Error(w, "Internal server error reading deposits", http.StatusInternalServerError)
h.Logger.Error("Unable to read deposits from DB") h.Logger.Error("Unable to read deposits from DB")
......
...@@ -2,6 +2,7 @@ package routes ...@@ -2,6 +2,7 @@ package routes
import ( import (
"net/http" "net/http"
"strconv"
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -42,9 +43,9 @@ type WithdrawalResponse struct { ...@@ -42,9 +43,9 @@ type WithdrawalResponse struct {
} }
// FIXME make a pure function that returns a struct instead of newWithdrawalResponse // FIXME make a pure function that returns a struct instead of newWithdrawalResponse
func newWithdrawalResponse(withdrawals []*database.L2BridgeWithdrawalWithTransactionHashes) WithdrawalResponse { func newWithdrawalResponse(withdrawals *database.L2BridgeWithdrawalsResponse) WithdrawalResponse {
items := make([]WithdrawalItem, len(withdrawals)) items := make([]WithdrawalItem, len(withdrawals.Withdrawals))
for _, withdrawal := range withdrawals { for _, withdrawal := range withdrawals.Withdrawals {
item := WithdrawalItem{ item := WithdrawalItem{
Guid: withdrawal.L2BridgeWithdrawal.TransactionWithdrawalHash.String(), Guid: withdrawal.L2BridgeWithdrawal.TransactionWithdrawalHash.String(),
Block: Block{ Block: Block{
...@@ -96,23 +97,34 @@ func newWithdrawalResponse(withdrawals []*database.L2BridgeWithdrawalWithTransac ...@@ -96,23 +97,34 @@ func newWithdrawalResponse(withdrawals []*database.L2BridgeWithdrawalWithTransac
} }
return WithdrawalResponse{ return WithdrawalResponse{
Cursor: "42042042-0420-4204-2042-420420420420", // TODO Cursor: withdrawals.Cursor,
HasNextPage: true, // TODO HasNextPage: withdrawals.HasNextPage,
Items: items, Items: items,
} }
} }
func (h Routes) L2WithdrawalsHandler(w http.ResponseWriter, r *http.Request) { func (h Routes) L2WithdrawalsHandler(w http.ResponseWriter, r *http.Request) {
address := common.HexToAddress(chi.URLParam(r, "address")) address := common.HexToAddress(chi.URLParam(r, "address"))
cursor := r.URL.Query().Get("cursor")
limitQuery := r.URL.Query().Get("limit")
withdrawals, err := h.BridgeTransfersView.L2BridgeWithdrawalsByAddress(address) defaultLimit := 100
limit := defaultLimit
if limitQuery != "" {
parsedLimit, err := strconv.Atoi(limitQuery)
if err != nil {
http.Error(w, "Limit could not be parsed into a number", http.StatusBadRequest)
h.Logger.Error("Invalid limit")
h.Logger.Error(err.Error())
}
limit = parsedLimit
}
withdrawals, err := h.BridgeTransfersView.L2BridgeWithdrawalsByAddress(address, cursor, limit)
if err != nil { if err != nil {
http.Error(w, "Internal server error fetching withdrawals", http.StatusInternalServerError) http.Error(w, "Internal server error reading withdrawals", http.StatusInternalServerError)
h.Logger.Error("Unable to read deposits from DB") h.Logger.Error("Unable to read withdrawals from DB")
h.Logger.Error(err.Error()) h.Logger.Error(err.Error())
return
} }
response := newWithdrawalResponse(withdrawals) response := newWithdrawalResponse(withdrawals)
jsonResponse(w, h.Logger, response, http.StatusOK) jsonResponse(w, h.Logger, response, http.StatusOK)
......
...@@ -24,11 +24,11 @@ type Config struct { ...@@ -24,11 +24,11 @@ type Config struct {
// fetch this via onchain config from RPCsConfig and remove from config in future // fetch this via onchain config from RPCsConfig and remove from config in future
type L1Contracts struct { type L1Contracts struct {
OptimismPortal common.Address OptimismPortal common.Address `toml:"optimism-portal"`
L2OutputOracle common.Address L2OutputOracle common.Address `toml:"l2-output-oracle"`
L1CrossDomainMessenger common.Address L1CrossDomainMessenger common.Address `toml:"l1-cross-domain-messenger"`
L1StandardBridge common.Address L1StandardBridge common.Address `toml:"l1-standard-bridge"`
L1ERC721Bridge common.Address L1ERC721Bridge common.Address `toml:"l1-erc721-bridge"`
// Some more contracts -- ProxyAdmin, SystemConfig, etcc // Some more contracts -- ProxyAdmin, SystemConfig, etcc
// Ignore the auxiliary contracts? // Ignore the auxiliary contracts?
...@@ -52,9 +52,12 @@ func (c L1Contracts) ToSlice() []common.Address { ...@@ -52,9 +52,12 @@ func (c L1Contracts) ToSlice() []common.Address {
// ChainConfig configures of the chain being indexed // ChainConfig configures of the chain being indexed
type ChainConfig struct { type ChainConfig struct {
// Configure known chains with the l2 chain id // Configure known chains with the l2 chain id
Preset int // NOTE - This currently performs no lookups to extract known L1 contracts by l2 chain id
// Configure custom chains via providing the L1Contract addresses Preset int
L1Contracts L1Contracts L1Contracts L1Contracts `toml:"l1-contracts"`
// L1StartingHeight is the block height to start indexing from
// NOTE - This is currently unimplemented
L1StartingHeight int
} }
// RPCsConfig configures the RPC urls // RPCsConfig configures the RPC urls
......
...@@ -80,7 +80,12 @@ func TestLoadConfig_WithoutPreset(t *testing.T) { ...@@ -80,7 +80,12 @@ func TestLoadConfig_WithoutPreset(t *testing.T) {
testData := ` testData := `
[chain] [chain]
l1contracts = { OptimismPortal = "0x4205Fc579115071764c7423A4f12eDde41f106Ed", L2OutputOracle = "0x42097868233d1aa22e815a266982f2cf17685a27", L1CrossDomainMessenger = "0x420ce71c97B33Cc4729CF772ae268934F7ab5fA1", L1StandardBridge = "0x4209fc46f92E8a1c0deC1b1747d010903E884bE1", L1ERC721Bridge ="0x420749f83b81B301cAb5f48EB8516B986DAef23D" } [chain.l1-contracts]
optimism-portal = "0x4205Fc579115071764c7423A4f12eDde41f106Ed"
l2-output-oracle = "0x42097868233d1aa22e815a266982f2cf17685a27"
l1-cross-domain-messenger = "0x420ce71c97B33Cc4729CF772ae268934F7ab5fA1"
l1-standard-bridge = "0x4209fc46f92E8a1c0deC1b1747d010903E884bE1"
l1-erc721-bridge = "0x420749f83b81B301cAb5f48EB8516B986DAef23D"
[rpcs] [rpcs]
l1-rpc = "https://l1.example.com" l1-rpc = "https://l1.example.com"
......
...@@ -2,6 +2,7 @@ package database ...@@ -2,6 +2,7 @@ package database
import ( import (
"errors" "errors"
"fmt"
"gorm.io/gorm" "gorm.io/gorm"
...@@ -59,11 +60,11 @@ type L2BridgeWithdrawalWithTransactionHashes struct { ...@@ -59,11 +60,11 @@ type L2BridgeWithdrawalWithTransactionHashes struct {
type BridgeTransfersView interface { type BridgeTransfersView interface {
L1BridgeDeposit(common.Hash) (*L1BridgeDeposit, error) L1BridgeDeposit(common.Hash) (*L1BridgeDeposit, error)
L1BridgeDepositWithFilter(BridgeTransfer) (*L1BridgeDeposit, error) L1BridgeDepositWithFilter(BridgeTransfer) (*L1BridgeDeposit, error)
L1BridgeDepositsByAddress(common.Address) ([]*L1BridgeDepositWithTransactionHashes, error) L1BridgeDepositsByAddress(common.Address, string, int) (*L1BridgeDepositsResponse, error)
L2BridgeWithdrawal(common.Hash) (*L2BridgeWithdrawal, error) L2BridgeWithdrawal(common.Hash) (*L2BridgeWithdrawal, error)
L2BridgeWithdrawalWithFilter(BridgeTransfer) (*L2BridgeWithdrawal, error) L2BridgeWithdrawalWithFilter(BridgeTransfer) (*L2BridgeWithdrawal, error)
L2BridgeWithdrawalsByAddress(common.Address) ([]*L2BridgeWithdrawalWithTransactionHashes, error) L2BridgeWithdrawalsByAddress(common.Address, string, int) (*L2BridgeWithdrawalsResponse, error)
} }
type BridgeTransfersDB interface { type BridgeTransfersDB interface {
...@@ -122,9 +123,20 @@ func (db *bridgeTransfersDB) L1BridgeDepositWithFilter(filter BridgeTransfer) (* ...@@ -122,9 +123,20 @@ func (db *bridgeTransfersDB) L1BridgeDepositWithFilter(filter BridgeTransfer) (*
return &deposit, nil return &deposit, nil
} }
type L1BridgeDepositsResponse struct {
Deposits []*L1BridgeDepositWithTransactionHashes
Cursor string
HasNextPage bool
}
// L1BridgeDepositsByAddress retrieves a list of deposits intiated by the specified address, coupled with the L1/L2 transaction // L1BridgeDepositsByAddress retrieves a list of deposits intiated by the specified address, coupled with the L1/L2 transaction
// hashes that complete the bridge transaction. // hashes that complete the bridge transaction.
func (db *bridgeTransfersDB) L1BridgeDepositsByAddress(address common.Address) ([]*L1BridgeDepositWithTransactionHashes, error) { func (db *bridgeTransfersDB) L1BridgeDepositsByAddress(address common.Address, cursor string, limit int) (*L1BridgeDepositsResponse, error) {
defaultLimit := 100
if limit <= 0 {
limit = defaultLimit
}
depositsQuery := db.gorm.Table("l1_bridge_deposits").Select(` depositsQuery := db.gorm.Table("l1_bridge_deposits").Select(`
l1_bridge_deposits.*, l1_bridge_deposits.*,
l1_contract_events.transaction_hash AS l1_transaction_hash, l1_contract_events.transaction_hash AS l1_transaction_hash,
...@@ -134,8 +146,11 @@ l1_transaction_deposits.l2_transaction_hash`) ...@@ -134,8 +146,11 @@ l1_transaction_deposits.l2_transaction_hash`)
depositsQuery = depositsQuery.Joins("INNER JOIN l1_transaction_deposits ON l1_bridge_deposits.transaction_source_hash = l1_transaction_deposits.source_hash") depositsQuery = depositsQuery.Joins("INNER JOIN l1_transaction_deposits ON l1_bridge_deposits.transaction_source_hash = l1_transaction_deposits.source_hash")
depositsQuery = depositsQuery.Joins("INNER JOIN l1_contract_events ON l1_transaction_deposits.initiated_l1_event_guid = l1_contract_events.guid") depositsQuery = depositsQuery.Joins("INNER JOIN l1_contract_events ON l1_transaction_deposits.initiated_l1_event_guid = l1_contract_events.guid")
// add in cursoring options if cursor != "" {
filteredQuery := depositsQuery.Where(&Transaction{FromAddress: address}).Order("l1_bridge_deposits.timestamp DESC").Limit(100) depositsQuery = depositsQuery.Where("l1_bridge_deposits.transaction_source_hash < ?", cursor)
}
filteredQuery := depositsQuery.Where(&Transaction{FromAddress: address}).Order("l1_bridge_deposits.transaction_source_hash DESC").Limit(limit + 1)
deposits := []*L1BridgeDepositWithTransactionHashes{} deposits := []*L1BridgeDepositWithTransactionHashes{}
result := filteredQuery.Scan(&deposits) result := filteredQuery.Scan(&deposits)
...@@ -146,7 +161,24 @@ l1_transaction_deposits.l2_transaction_hash`) ...@@ -146,7 +161,24 @@ l1_transaction_deposits.l2_transaction_hash`)
return nil, result.Error return nil, result.Error
} }
return deposits, nil hasNextPage := false
if len(deposits) > limit {
hasNextPage = true
deposits = deposits[:limit]
}
nextCursor := ""
if hasNextPage {
nextCursor = deposits[len(deposits)-1].L1TransactionHash.String()
}
response := &L1BridgeDepositsResponse{
Deposits: deposits,
Cursor: nextCursor,
HasNextPage: hasNextPage,
}
return response, nil
} }
/** /**
...@@ -186,9 +218,20 @@ func (db *bridgeTransfersDB) L2BridgeWithdrawalWithFilter(filter BridgeTransfer) ...@@ -186,9 +218,20 @@ func (db *bridgeTransfersDB) L2BridgeWithdrawalWithFilter(filter BridgeTransfer)
return &withdrawal, nil return &withdrawal, nil
} }
type L2BridgeWithdrawalsResponse struct {
Withdrawals []*L2BridgeWithdrawalWithTransactionHashes
Cursor string
HasNextPage bool
}
// L2BridgeDepositsByAddress retrieves a list of deposits intiated by the specified address, coupled with the L1/L2 transaction hashes // L2BridgeDepositsByAddress retrieves a list of deposits intiated by the specified address, coupled with the L1/L2 transaction hashes
// that complete the bridge transaction. The hashes that correspond to with the Bedrock multistep withdrawal process are also surfaced // that complete the bridge transaction. The hashes that correspond to with the Bedrock multistep withdrawal process are also surfaced
func (db *bridgeTransfersDB) L2BridgeWithdrawalsByAddress(address common.Address) ([]*L2BridgeWithdrawalWithTransactionHashes, error) { func (db *bridgeTransfersDB) L2BridgeWithdrawalsByAddress(address common.Address, cursor string, limit int) (*L2BridgeWithdrawalsResponse, error) {
defaultLimit := 100
if limit <= 0 {
limit = defaultLimit
}
withdrawalsQuery := db.gorm.Table("l2_bridge_withdrawals").Select(` withdrawalsQuery := db.gorm.Table("l2_bridge_withdrawals").Select(`
l2_bridge_withdrawals.*, l2_bridge_withdrawals.*,
l2_contract_events.transaction_hash AS l2_transaction_hash, l2_contract_events.transaction_hash AS l2_transaction_hash,
...@@ -200,8 +243,11 @@ finalized_l1_contract_events.transaction_hash AS finalized_l1_transaction_hash`) ...@@ -200,8 +243,11 @@ finalized_l1_contract_events.transaction_hash AS finalized_l1_transaction_hash`)
withdrawalsQuery = withdrawalsQuery.Joins("LEFT JOIN l1_contract_events AS proven_l1_contract_events ON l2_transaction_withdrawals.proven_l1_event_guid = proven_l1_contract_events.guid") withdrawalsQuery = withdrawalsQuery.Joins("LEFT JOIN l1_contract_events AS proven_l1_contract_events ON l2_transaction_withdrawals.proven_l1_event_guid = proven_l1_contract_events.guid")
withdrawalsQuery = withdrawalsQuery.Joins("LEFT JOIN l1_contract_events AS finalized_l1_contract_events ON l2_transaction_withdrawals.finalized_l1_event_guid = finalized_l1_contract_events.guid") withdrawalsQuery = withdrawalsQuery.Joins("LEFT JOIN l1_contract_events AS finalized_l1_contract_events ON l2_transaction_withdrawals.finalized_l1_event_guid = finalized_l1_contract_events.guid")
// add in cursoring options if cursor != "" {
filteredQuery := withdrawalsQuery.Where(&Transaction{FromAddress: address}).Order("l2_bridge_withdrawals.timestamp DESC").Limit(100) withdrawalsQuery = withdrawalsQuery.Where("l2_bridge_withdrawals.id < ?", cursor)
}
filteredQuery := withdrawalsQuery.Where(&Transaction{FromAddress: address}).Order("l2_bridge_withdrawals.timestamp DESC").Limit(limit + 1)
withdrawals := []*L2BridgeWithdrawalWithTransactionHashes{} withdrawals := []*L2BridgeWithdrawalWithTransactionHashes{}
result := filteredQuery.Scan(&withdrawals) result := filteredQuery.Scan(&withdrawals)
...@@ -212,5 +258,28 @@ finalized_l1_contract_events.transaction_hash AS finalized_l1_transaction_hash`) ...@@ -212,5 +258,28 @@ finalized_l1_contract_events.transaction_hash AS finalized_l1_transaction_hash`)
return nil, result.Error return nil, result.Error
} }
return withdrawals, nil hasNextPage := false
if len(withdrawals) > limit {
hasNextPage = true
withdrawals = withdrawals[:limit]
}
nextCursor := ""
if hasNextPage {
nextCursor = fmt.Sprintf("%d", withdrawals[len(withdrawals)-1].L2TransactionHash)
}
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
response := &L2BridgeWithdrawalsResponse{
Withdrawals: withdrawals,
Cursor: nextCursor,
HasNextPage: hasNextPage,
}
return response, nil
} }
...@@ -47,13 +47,19 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) { ...@@ -47,13 +47,19 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) {
return l1Header != nil && l1Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil return l1Header != nil && l1Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil
})) }))
aliceDeposits, err := testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr) cursor := ""
limit := 0
aliceDeposits, err := testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err) require.NoError(t, err)
require.Len(t, aliceDeposits, 1) require.Len(t, aliceDeposits.Deposits, 1)
require.Equal(t, depositTx.Hash(), aliceDeposits[0].L1TransactionHash) require.Equal(t, depositTx.Hash(), aliceDeposits.Deposits[0].L1TransactionHash)
require.Equal(t, types.NewTx(depositInfo.DepositTx).Hash(), aliceDeposits[0].L2TransactionHash) require.Equal(t, "", aliceDeposits.Cursor)
require.Equal(t, false, aliceDeposits.HasNextPage)
require.Equal(t, types.NewTx(depositInfo.DepositTx).Hash().String(), aliceDeposits.Deposits[0].L2TransactionHash.String())
deposit := aliceDeposits[0].L1BridgeDeposit deposit := aliceDeposits.Deposits[0].L1BridgeDeposit
require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash) require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.RemoteTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.RemoteTokenAddress)
...@@ -80,6 +86,118 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) { ...@@ -80,6 +86,118 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) {
require.NotNil(t, crossDomainBridgeMessage.RelayedMessageEventGUID) require.NotNil(t, crossDomainBridgeMessage.RelayedMessageEventGUID)
} }
/*
TODO make this test work:
Error Trace: /root/project/indexer/e2e_tests/bridge_transfers_e2e_test.go:116
Error: Received unexpected error:
expected status 1, but got 0
tx trace unavailable: websocket: read limit exceeded
Test: TestE2EBridgeTransfersPagination
func TestE2EBridgeTransfersPagination(t *testing.T) {
testSuite := createE2ETestSuite(t)
l1StandardBridge, err := bindings.NewL1StandardBridge(testSuite.OpCfg.L1Deployments.L1StandardBridgeProxy, testSuite.L1Client)
require.NoError(t, err)
// 1 ETH transfer
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
// (1) Test Deposit Initiation
var deposits []struct {
Tx *types.Transaction
Receipt *types.Receipt
Info *e2etest_utils.DepositInfo
}
for i := 0; i < 3; i++ {
l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err)
l1Opts.Value = big.NewInt(params.Ether)
depositTx, err := l1StandardBridge.DepositETH(l1Opts, 200_000, []byte{byte(i)})
require.NoError(t, err)
depositReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash())
require.NoError(t, err)
depositInfo, err := e2etest_utils.ParseDepositInfo(depositReceipt)
require.NoError(t, err)
// wait for processor catchup
err = wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil
})
require.NoError(t, err)
deposits = append(deposits, struct {
Tx *types.Transaction
Receipt *types.Receipt
Info *e2etest_utils.DepositInfo
}{
Tx: depositTx,
Receipt: depositReceipt,
Info: depositInfo,
})
// wait for processor catchup
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= deposits[i].Receipt.BlockNumber.Uint64(), nil
}))
}
// Test no cursor or limit
cursor := ""
limit := 0
aliceDeposits, err := testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err)
require.Len(t, aliceDeposits.Deposits, 3)
require.Equal(t, deposits[0].Tx.Hash(), aliceDeposits.Deposits[0].L1TransactionHash)
require.Equal(t, deposits[1].Tx.Hash(), aliceDeposits.Deposits[1].L1TransactionHash)
require.Equal(t, deposits[2].Tx.Hash(), aliceDeposits.Deposits[2].L1TransactionHash)
require.Equal(t, "", aliceDeposits.Cursor)
require.Equal(t, false, aliceDeposits.HasNextPage)
// test cursor with no limit
cursor = deposits[1].Tx.Hash().String()
limit = 0
aliceDeposits, err = testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err)
require.Len(t, aliceDeposits.Deposits, 2)
require.Equal(t, deposits[1].Tx.Hash().String(), aliceDeposits.Deposits[0].L1TransactionHash)
require.Equal(t, deposits[2].Tx.Hash().String(), aliceDeposits.Deposits[1].L1TransactionHash)
require.Equal(t, "", aliceDeposits.Cursor)
require.Equal(t, false, aliceDeposits.HasNextPage)
// test no cursor with limit and hasNext page is true
cursor = ""
limit = 2
aliceDeposits, err = testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err)
require.Len(t, aliceDeposits.Deposits, limit)
require.Equal(t, deposits[0].Tx.Hash().String(), aliceDeposits.Deposits[0].L1TransactionHash)
require.Equal(t, deposits[1].Tx.Hash().String(), aliceDeposits.Deposits[1].L1TransactionHash)
require.Equal(t, deposits[2].Tx.Hash().String(), aliceDeposits.Cursor)
require.Equal(t, true, aliceDeposits.HasNextPage)
// test cursor with limit and hasNext page is true
cursor = deposits[1].Tx.Hash().String()
limit = 1
aliceDeposits, err = testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err)
require.Len(t, aliceDeposits.Deposits, 1)
require.Equal(t, deposits[1].Tx.Hash().String(), aliceDeposits.Deposits[1].L1TransactionHash)
require.Equal(t, deposits[2].Tx.Hash().String(), aliceDeposits.Cursor)
require.Equal(t, true, aliceDeposits.HasNextPage)
// limit bigger than the total amount
cursor = ""
limit = 10
aliceDeposits, err = testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err)
require.Len(t, aliceDeposits.Deposits, 3)
}
*/
func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) { func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) {
testSuite := createE2ETestSuite(t) testSuite := createE2ETestSuite(t)
...@@ -107,12 +225,11 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) { ...@@ -107,12 +225,11 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) {
return l1Header != nil && l1Header.Number.Uint64() >= portalDepositReceipt.BlockNumber.Uint64(), nil return l1Header != nil && l1Header.Number.Uint64() >= portalDepositReceipt.BlockNumber.Uint64(), nil
})) }))
aliceDeposits, err := testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr) aliceDeposits, err := testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, "", 0)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, portalDepositTx.Hash(), aliceDeposits[0].L1TransactionHash) require.Equal(t, portalDepositTx.Hash(), aliceDeposits.Deposits[0].L1TransactionHash)
require.Equal(t, types.NewTx(depositInfo.DepositTx).Hash(), aliceDeposits[0].L2TransactionHash)
deposit := aliceDeposits[0].L1BridgeDeposit deposit := aliceDeposits.Deposits[0].L1BridgeDeposit
require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash) require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.RemoteTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.RemoteTokenAddress)
...@@ -133,9 +250,9 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) { ...@@ -133,9 +250,9 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) {
})) }))
// Still nil as the withdrawal did not occur through the standard bridge // Still nil as the withdrawal did not occur through the standard bridge
aliceDeposits, err = testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr) aliceDeposits, err = testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, "", 0)
require.NoError(t, err) require.NoError(t, err)
require.Nil(t, aliceDeposits[0].L1BridgeDeposit.CrossDomainMessageHash) require.Nil(t, aliceDeposits.Deposits[0].L1BridgeDeposit.CrossDomainMessageHash)
} }
func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
...@@ -173,17 +290,17 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { ...@@ -173,17 +290,17 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
return l2Header != nil && l2Header.Number.Uint64() >= withdrawReceipt.BlockNumber.Uint64(), nil return l2Header != nil && l2Header.Number.Uint64() >= withdrawReceipt.BlockNumber.Uint64(), nil
})) }))
aliceWithdrawals, err := testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr) aliceWithdrawals, err := testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, "", 0)
require.NoError(t, err) require.NoError(t, err)
require.Len(t, aliceWithdrawals, 1) require.Len(t, aliceWithdrawals.Withdrawals, 1)
require.Equal(t, withdrawTx.Hash(), aliceWithdrawals[0].L2TransactionHash) require.Equal(t, withdrawTx.Hash().String(), aliceWithdrawals.Withdrawals[0].L2TransactionHash.String())
msgPassed, err := withdrawals.ParseMessagePassed(withdrawReceipt) msgPassed, err := withdrawals.ParseMessagePassed(withdrawReceipt)
require.NoError(t, err) require.NoError(t, err)
withdrawalHash, err := withdrawals.WithdrawalHash(msgPassed) withdrawalHash, err := withdrawals.WithdrawalHash(msgPassed)
require.NoError(t, err) require.NoError(t, err)
withdrawal := aliceWithdrawals[0].L2BridgeWithdrawal withdrawal := aliceWithdrawals.Withdrawals[0].L2BridgeWithdrawal
require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash) require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.RemoteTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.RemoteTokenAddress)
...@@ -201,8 +318,8 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { ...@@ -201,8 +318,8 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
require.Nil(t, crossDomainBridgeMessage.RelayedMessageEventGUID) require.Nil(t, crossDomainBridgeMessage.RelayedMessageEventGUID)
// (2) Test Withdrawal Proven/Finalized. Test the sql join queries to populate the right transaction // (2) Test Withdrawal Proven/Finalized. Test the sql join queries to populate the right transaction
require.Empty(t, aliceWithdrawals[0].ProvenL1TransactionHash) require.Empty(t, aliceWithdrawals.Withdrawals[0].ProvenL1TransactionHash)
require.Empty(t, aliceWithdrawals[0].FinalizedL1TransactionHash) require.Empty(t, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash)
// wait for processor catchup // wait for processor catchup
proveReceipt, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, withdrawReceipt) proveReceipt, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, withdrawReceipt)
...@@ -211,10 +328,10 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { ...@@ -211,10 +328,10 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
})) }))
aliceWithdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr) aliceWithdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, "", 0)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, proveReceipt.TxHash, aliceWithdrawals[0].ProvenL1TransactionHash) require.Equal(t, proveReceipt.TxHash, aliceWithdrawals.Withdrawals[0].ProvenL1TransactionHash)
require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals[0].FinalizedL1TransactionHash) require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash)
crossDomainBridgeMessage, err = testSuite.DB.BridgeMessages.L2BridgeMessage(*withdrawal.CrossDomainMessageHash) crossDomainBridgeMessage, err = testSuite.DB.BridgeMessages.L2BridgeMessage(*withdrawal.CrossDomainMessageHash)
require.NoError(t, err) require.NoError(t, err)
...@@ -257,16 +374,16 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserReceive(t *testing.T) { ...@@ -257,16 +374,16 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserReceive(t *testing.T) {
return l2Header != nil && l2Header.Number.Uint64() >= l2ToL1WithdrawReceipt.BlockNumber.Uint64(), nil return l2Header != nil && l2Header.Number.Uint64() >= l2ToL1WithdrawReceipt.BlockNumber.Uint64(), nil
})) }))
aliceWithdrawals, err := testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr) aliceWithdrawals, err := testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, "", 0)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, l2ToL1MessagePasserWithdrawTx.Hash(), aliceWithdrawals[0].L2TransactionHash) require.Equal(t, l2ToL1MessagePasserWithdrawTx.Hash().String(), aliceWithdrawals.Withdrawals[0].L2TransactionHash.String())
msgPassed, err := withdrawals.ParseMessagePassed(l2ToL1WithdrawReceipt) msgPassed, err := withdrawals.ParseMessagePassed(l2ToL1WithdrawReceipt)
require.NoError(t, err) require.NoError(t, err)
withdrawalHash, err := withdrawals.WithdrawalHash(msgPassed) withdrawalHash, err := withdrawals.WithdrawalHash(msgPassed)
require.NoError(t, err) require.NoError(t, err)
withdrawal := aliceWithdrawals[0].L2BridgeWithdrawal withdrawal := aliceWithdrawals.Withdrawals[0].L2BridgeWithdrawal
require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash) require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.RemoteTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.RemoteTokenAddress)
...@@ -279,8 +396,8 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserReceive(t *testing.T) { ...@@ -279,8 +396,8 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserReceive(t *testing.T) {
require.Nil(t, withdrawal.CrossDomainMessageHash) require.Nil(t, withdrawal.CrossDomainMessageHash)
// (2) Test Withdrawal Proven/Finalized. Test the sql join queries to populate the right transaction // (2) Test Withdrawal Proven/Finalized. Test the sql join queries to populate the right transaction
require.Empty(t, aliceWithdrawals[0].ProvenL1TransactionHash) require.Empty(t, aliceWithdrawals.Withdrawals[0].ProvenL1TransactionHash)
require.Empty(t, aliceWithdrawals[0].FinalizedL1TransactionHash) require.Empty(t, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash)
// wait for processor catchup // wait for processor catchup
proveReceipt, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, l2ToL1WithdrawReceipt) proveReceipt, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, l2ToL1WithdrawReceipt)
...@@ -289,11 +406,96 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserReceive(t *testing.T) { ...@@ -289,11 +406,96 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserReceive(t *testing.T) {
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
})) }))
aliceWithdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr) aliceWithdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, "", 0)
require.NoError(t, err)
require.Equal(t, proveReceipt.TxHash, aliceWithdrawals.Withdrawals[0].ProvenL1TransactionHash)
require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash)
}
/**
THIS test will work after we order transactions correctly
func TestE2EBridgeTransfersPaginationWithdrawals(t *testing.T) {
testSuite := createE2ETestSuite(t)
l2StandardBridge, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, testSuite.L2Client)
require.NoError(t, err)
// 1 ETH transfer
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
l2Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err)
l2Opts.Value = big.NewInt(params.Ether)
var withdrawals []struct {
Tx *types.Transaction
Receipt *types.Receipt
}
for i := 0; i < 3; i++ {
withdrawTx, err := l2StandardBridge.Withdraw(l2Opts, predeploys.LegacyERC20ETHAddr, l2Opts.Value, 200_000, []byte{byte(i)})
require.NoError(t, err)
withdrawReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, withdrawTx.Hash())
require.NoError(t, err)
err = wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= withdrawReceipt.BlockNumber.Uint64(), nil
})
require.NoError(t, err)
withdrawals = append(withdrawals, struct {
Tx *types.Transaction
Receipt *types.Receipt
}{
Tx: withdrawTx,
Receipt: withdrawReceipt,
})
}
cursor := ""
limit := 0
aliceWithdrawals, err := testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err)
require.Len(t, aliceWithdrawals.Withdrawals, 3)
require.Equal(t, withdrawals[0].Tx.Hash().String(), aliceWithdrawals.Withdrawals[0].L2TransactionHash.String())
require.Equal(t, withdrawals[1].Tx.Hash().String(), aliceWithdrawals.Withdrawals[1].L2TransactionHash.String())
require.Equal(t, withdrawals[2].Tx.Hash().String(), aliceWithdrawals.Withdrawals[2].L2TransactionHash.String())
cursor = withdrawals[1].Tx.Hash().String()
limit = 0
aliceWithdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err)
require.Len(t, aliceWithdrawals, 2)
require.Equal(t, withdrawals[1].Tx.Hash().String(), aliceWithdrawals.Withdrawals[0].L2TransactionHash.String())
require.Equal(t, withdrawals[2].Tx.Hash().String(), aliceWithdrawals.Withdrawals[1].L2TransactionHash.String())
cursor = ""
limit = 2
aliceWithdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err)
require.Len(t, aliceWithdrawals, limit)
require.Equal(t, withdrawals[0].Tx.Hash().String(), aliceWithdrawals.Withdrawals[0].L2TransactionHash.String())
require.Equal(t, withdrawals[1].Tx.Hash().String(), aliceWithdrawals.Withdrawals[1].L2TransactionHash.String())
cursor = withdrawals[1].Tx.Hash().String()
limit = 1
aliceWithdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err)
require.Len(t, aliceWithdrawals, 1)
require.Equal(t, withdrawals[1].Tx.Hash().String(), aliceWithdrawals.Withdrawals[0].L2TransactionHash.String())
require.Equal(t, true, aliceWithdrawals.HasNextPage)
require.Equal(t, withdrawals[2].Tx.Hash().String(), aliceWithdrawals.Cursor)
cursor = ""
limit = 10
aliceWithdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, cursor, limit)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, proveReceipt.TxHash, aliceWithdrawals[0].ProvenL1TransactionHash) require.Equal(t, proveReceipt.TxHash, aliceWithdrawals.Withdrawals[0].ProvenL1TransactionHash)
require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals[0].FinalizedL1TransactionHash) require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash)
// Still nil as the withdrawal did not occur through the standard bridge // Still nil as the withdrawal did not occur through the standard bridge
require.Nil(t, aliceWithdrawals[0].L2BridgeWithdrawal.CrossDomainMessageHash) require.Nil(t, aliceWithdrawals.Withdrawals[0].L2BridgeWithdrawal.CrossDomainMessageHash)
} }
*/
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
[chain] [chain]
# OP Goerli # OP Goerli
preset = 420 preset = 420
[rpcs] [rpcs]
l1-rpc = "${INDEXER_RPC_URL_L1}" l1-rpc = "${INDEXER_RPC_URL_L1}"
l2-rpc = "${INDEXER_RPC_URL_L2}" l2-rpc = "${INDEXER_RPC_URL_L2}"
......
...@@ -28,7 +28,7 @@ CREATE TABLE IF NOT EXISTS l2_block_headers ( ...@@ -28,7 +28,7 @@ CREATE TABLE IF NOT EXISTS l2_block_headers (
rlp_bytes VARCHAR NOT NULL rlp_bytes VARCHAR NOT NULL
); );
/** /**
* EVENT DATA * EVENT DATA
*/ */
......
...@@ -17,7 +17,7 @@ test: ...@@ -17,7 +17,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
fuzz: fuzz:
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzChannelConfig_CheckTimeout ./batcher go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzChannelConfig_CheckTimeout ./batcher
......
...@@ -25,6 +25,9 @@ bindings-build: ...@@ -25,6 +25,9 @@ bindings-build:
-package $(pkg) \ -package $(pkg) \
-monorepo-base $(monorepo-base) -monorepo-base $(monorepo-base)
lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
mkdir: mkdir:
mkdir -p $(pkg) mkdir -p $(pkg)
......
...@@ -30,8 +30,8 @@ var ( ...@@ -30,8 +30,8 @@ var (
// OptimismMintableERC20FactoryMetaData contains all meta data concerning the OptimismMintableERC20Factory contract. // OptimismMintableERC20FactoryMetaData contains all meta data concerning the OptimismMintableERC20Factory contract.
var OptimismMintableERC20FactoryMetaData = &bind.MetaData{ var OptimismMintableERC20FactoryMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\"}],\"name\":\"OptimismMintableERC20Created\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"StandardL2TokenCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createOptimismMintableERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createStandardL2Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\"}],\"name\":\"OptimismMintableERC20Created\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"StandardL2TokenCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createOptimismMintableERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createStandardL2Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x61010060405234801561001157600080fd5b506040516124bb3803806124bb83398101604081905261003091610050565b6001608052600260a052600060c0526001600160a01b031660e052610080565b60006020828403121561006257600080fd5b81516001600160a01b038116811461007957600080fd5b9392505050565b60805160a05160c05160e0516123fd6100be6000396000818160d3015261029701526000610153015260006101280152600060fd01526123fd6000f3fe60806040523480156200001157600080fd5b5060043610620000525760003560e01c806354fd4d501462000057578063896f93d11462000079578063ce5ac90f14620000b6578063ee9a31a214620000cd575b600080fd5b62000061620000f5565b60405162000070919062000587565b60405180910390f35b620000906200008a36600462000685565b620001a0565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000070565b62000090620000c736600462000685565b620001b7565b620000907f000000000000000000000000000000000000000000000000000000000000000081565b6060620001227f0000000000000000000000000000000000000000000000000000000000000000620003ad565b6200014d7f0000000000000000000000000000000000000000000000000000000000000000620003ad565b620001787f0000000000000000000000000000000000000000000000000000000000000000620003ad565b6040516020016200018c939291906200071c565b604051602081830303815290604052905090565b6000620001af848484620001b7565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff841662000261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e206164647265737300606482015260840160405180910390fd5b60008484846040516020016200027a9392919062000798565b6040516020818303038152906040528051906020012090506000817f0000000000000000000000000000000000000000000000000000000000000000878787604051620002c790620004fa565b620002d69493929190620007e7565b8190604051809103906000f5905080158015620002f7573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80881691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a395945050505050565b606081600003620003f157505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115620004215780620004088162000870565b9150620004199050600a83620008da565b9150620003f5565b60008167ffffffffffffffff8111156200043f576200043f620005a3565b6040519080825280601f01601f1916602001820160405280156200046a576020820181803683370190505b5090505b8415620001af5762000482600183620008f1565b915062000491600a866200090b565b6200049e90603062000922565b60f81b818381518110620004b657620004b66200093d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620004f2600a86620008da565b94506200046e565b611a84806200096d83390190565b60005b83811015620005255781810151838201526020016200050b565b8381111562000535576000848401525b50505050565b600081518084526200055581602086016020860162000508565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006200059c60208301846200053b565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620005e457600080fd5b813567ffffffffffffffff80821115620006025762000602620005a3565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200064b576200064b620005a3565b816040528381528660208588010111156200066557600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200069b57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff81168114620006c057600080fd5b9250602084013567ffffffffffffffff80821115620006de57600080fd5b620006ec87838801620005d2565b935060408601359150808211156200070357600080fd5b506200071286828701620005d2565b9150509250925092565b600084516200073081846020890162000508565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516200076e816001850160208a0162000508565b600192019182015283516200078b81600284016020880162000508565b0160020195945050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000620007c960608301856200053b565b8281036040840152620007dd81856200053b565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250608060408301526200082260808301856200053b565b82810360608401526200083681856200053b565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620008a457620008a462000841565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082620008ec57620008ec620008ab565b500490565b60008282101562000906576200090662000841565b500390565b6000826200091d576200091d620008ab565b500690565b6000821982111562000938576200093862000841565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe6101206040523480156200001257600080fd5b5060405162001a8438038062001a8483398101604081905262000035916200016d565b6001806000848460036200004a83826200028c565b5060046200005982826200028c565b50505060809290925260a05260c05250506001600160a01b0390811660e052166101005262000358565b80516001600160a01b03811681146200009b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000c857600080fd5b81516001600160401b0380821115620000e557620000e5620000a0565b604051601f8301601f19908116603f01168101908282118183101715620001105762000110620000a0565b816040528381526020925086838588010111156200012d57600080fd5b600091505b8382101562000151578582018301518183018401529082019062000132565b83821115620001635760008385830101525b9695505050505050565b600080600080608085870312156200018457600080fd5b6200018f8562000083565b93506200019f6020860162000083565b60408601519093506001600160401b0380821115620001bd57600080fd5b620001cb88838901620000b6565b93506060870151915080821115620001e257600080fd5b50620001f187828801620000b6565b91505092959194509250565b600181811c908216806200021257607f821691505b6020821081036200023357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028757600081815260208120601f850160051c81016020861015620002625750805b601f850160051c820191505b8181101562000283578281556001016200026e565b5050505b505050565b81516001600160401b03811115620002a857620002a8620000a0565b620002c081620002b98454620001fd565b8462000239565b602080601f831160018114620002f85760008415620002df5750858301515b600019600386901b1c1916600185901b17855562000283565b600085815260208120601f198616915b82811015620003295788860151825594840194600190910190840162000308565b5085821015620003485787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610100516116cb620003b9600039600081816102f50152818161038a015281816105cf01526107a90152600081816101a9015261031b015260006107380152600061070f015260006106e601526116cb6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e1461033f578063e78cea92146102f3578063ee9a31a21461038557600080fd5b8063ae1f6aaf146102f3578063c01e1bd614610319578063d6c0b2c41461031957600080fd5b80639dc29fac116100bd5780639dc29fac146102ba578063a457c2d7146102cd578063a9059cbb146102e057600080fd5b806370a082311461027c57806395d89b41146102b257600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461024c57806340c10f191461025f57806354fd4d501461027457600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611307565b6103ac565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f861049d565b60405161019b919061137c565b61018f6102133660046113f6565b61052f565b6002545b60405190815260200161019b565b61018f610238366004611420565b610547565b6040516012815260200161019b565b61018f61025a3660046113f6565b61056b565b61027261026d3660046113f6565b6105b7565b005b6101f86106df565b61021c61028a36600461145c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610782565b6102726102c83660046113f6565b610791565b61018f6102db3660046113f6565b6108a8565b61018f6102ee3660046113f6565b610979565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61034d366004611477565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061046557507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b8061049457507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ac906114aa565b80601f01602080910402602001604051908101604052809291908181526020018280546104d8906114aa565b80156105255780601f106104fa57610100808354040283529160200191610525565b820191906000526020600020905b81548152906001019060200180831161050857829003601f168201915b5050505050905090565b60003361053d818585610987565b5060019392505050565b600033610555858285610b3b565b610560858585610c12565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061053d90829086906105b290879061152c565b610987565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b61068b8282610ec5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106d391815260200190565b60405180910390a25050565b606061070a7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b6107337f0000000000000000000000000000000000000000000000000000000000000000610fe5565b61075c7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b60405160200161076e93929190611544565b604051602081830303815290604052905090565b6060600480546104ac906114aa565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e0000000000000000000000006064820152608401610678565b6108608282611122565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106d391815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561096c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610678565b6105608286868403610987565b60003361053d818585610c12565b73ffffffffffffffffffffffffffffffffffffffff8316610a29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c0c5781811015610bff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610678565b610c0c8484848403610987565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e5290849061152c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eb891815260200190565b60405180910390a3610c0c565b73ffffffffffffffffffffffffffffffffffffffff8216610f42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610678565b8060026000828254610f54919061152c565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f8e90849061152c565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361102857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611052578061103c816115ba565b915061104b9050600a83611621565b915061102c565b60008167ffffffffffffffff81111561106d5761106d611635565b6040519080825280601f01601f191660200182016040528015611097576020820181803683370190505b5090505b841561111a576110ac600183611664565b91506110b9600a8661167b565b6110c490603061152c565b60f81b8183815181106110d9576110d961168f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611113600a86611621565b945061109b565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561127b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112b7908490611664565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b2e565b60006020828403121561131957600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461134957600080fd5b9392505050565b60005b8381101561136b578181015183820152602001611353565b83811115610c0c5750506000910152565b602081526000825180602084015261139b816040850160208701611350565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146113f157600080fd5b919050565b6000806040838503121561140957600080fd5b611412836113cd565b946020939093013593505050565b60008060006060848603121561143557600080fd5b61143e846113cd565b925061144c602085016113cd565b9150604084013590509250925092565b60006020828403121561146e57600080fd5b611349826113cd565b6000806040838503121561148a57600080fd5b611493836113cd565b91506114a1602084016113cd565b90509250929050565b600181811c908216806114be57607f821691505b6020821081036114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561153f5761153f6114fd565b500190565b60008451611556818460208901611350565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611592816001850160208a01611350565b600192019182015283516115ad816002840160208801611350565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115eb576115eb6114fd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611630576116306115f2565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015611676576116766114fd565b500390565b60008261168a5761168a6115f2565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", Bin: "0x60e060405234801561001057600080fd5b506001608052600360a052600060c081905261002b90610030565b610128565b600054600290610100900460ff16158015610052575060005460ff8083169116105b6100b95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805461010060ff841661ffff19909216821717610100600160b01b03191661ff0019620100006001600160a01b0387160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b60805160a05160c05161261261015760003960006101b90152600061018e0152600061016301526126126000f3fe60806040523480156200001157600080fd5b50600436106200007b5760003560e01c8063ce5ac90f1162000056578063ce5ac90f14620000f8578063e78cea92146200010f578063ee9a31a2146200013657600080fd5b806354fd4d501462000080578063896f93d114620000a2578063c4d66de814620000df575b600080fd5b6200008a6200015b565b6040516200009991906200076e565b60405180910390f35b620000b9620000b336600462000896565b62000206565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000099565b620000f6620000f036600462000913565b6200021d565b005b620000b96200010936600462000896565b6200039f565b600054620000b99062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000b9565b6060620001887f000000000000000000000000000000000000000000000000000000000000000062000594565b620001b37f000000000000000000000000000000000000000000000000000000000000000062000594565b620001de7f000000000000000000000000000000000000000000000000000000000000000062000594565b604051602001620001f29392919062000931565b604051602081830303815290604052905090565b6000620002158484846200039f565b949350505050565b600054600290610100900460ff1615801562000240575060005460ff8083169116105b620002d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b600073ffffffffffffffffffffffffffffffffffffffff841662000446576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e2061646472657373006064820152608401620002c9565b60008484846040516020016200045f93929190620009ad565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff16878787604051620004ae90620006e1565b620004bd9493929190620009fc565b8190604051809103906000f5905080158015620004de573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80881691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a395945050505050565b606081600003620005d857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115620006085780620005ef8162000a85565b9150620006009050600a8362000aef565b9150620005dc565b60008167ffffffffffffffff811115620006265762000626620007b4565b6040519080825280601f01601f19166020018201604052801562000651576020820181803683370190505b5090505b841562000215576200066960018362000b06565b915062000678600a8662000b20565b6200068590603062000b37565b60f81b8183815181106200069d576200069d62000b52565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620006d9600a8662000aef565b945062000655565b611a848062000b8283390190565b60005b838110156200070c578181015183820152602001620006f2565b838111156200071c576000848401525b50505050565b600081518084526200073c816020860160208601620006ef565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000783602083018462000722565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114620007af57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620007f557600080fd5b813567ffffffffffffffff80821115620008135762000813620007b4565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200085c576200085c620007b4565b816040528381528660208588010111156200087657600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620008ac57600080fd5b620008b7846200078a565b9250602084013567ffffffffffffffff80821115620008d557600080fd5b620008e387838801620007e3565b93506040860135915080821115620008fa57600080fd5b506200090986828701620007e3565b9150509250925092565b6000602082840312156200092657600080fd5b62000783826200078a565b6000845162000945818460208901620006ef565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855162000983816001850160208a01620006ef565b60019201918201528351620009a0816002840160208801620006ef565b0160020195945050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000620009de606083018562000722565b8281036040840152620009f2818562000722565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015262000a37608083018562000722565b828103606084015262000a4b818562000722565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362000ab95762000ab962000a56565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008262000b015762000b0162000ac0565b500490565b60008282101562000b1b5762000b1b62000a56565b500390565b60008262000b325762000b3262000ac0565b500690565b6000821982111562000b4d5762000b4d62000a56565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe6101206040523480156200001257600080fd5b5060405162001a8438038062001a8483398101604081905262000035916200016d565b6001806000848460036200004a83826200028c565b5060046200005982826200028c565b50505060809290925260a05260c05250506001600160a01b0390811660e052166101005262000358565b80516001600160a01b03811681146200009b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000c857600080fd5b81516001600160401b0380821115620000e557620000e5620000a0565b604051601f8301601f19908116603f01168101908282118183101715620001105762000110620000a0565b816040528381526020925086838588010111156200012d57600080fd5b600091505b8382101562000151578582018301518183018401529082019062000132565b83821115620001635760008385830101525b9695505050505050565b600080600080608085870312156200018457600080fd5b6200018f8562000083565b93506200019f6020860162000083565b60408601519093506001600160401b0380821115620001bd57600080fd5b620001cb88838901620000b6565b93506060870151915080821115620001e257600080fd5b50620001f187828801620000b6565b91505092959194509250565b600181811c908216806200021257607f821691505b6020821081036200023357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028757600081815260208120601f850160051c81016020861015620002625750805b601f850160051c820191505b8181101562000283578281556001016200026e565b5050505b505050565b81516001600160401b03811115620002a857620002a8620000a0565b620002c081620002b98454620001fd565b8462000239565b602080601f831160018114620002f85760008415620002df5750858301515b600019600386901b1c1916600185901b17855562000283565b600085815260208120601f198616915b82811015620003295788860151825594840194600190910190840162000308565b5085821015620003485787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610100516116cb620003b9600039600081816102f50152818161038a015281816105cf01526107a90152600081816101a9015261031b015260006107380152600061070f015260006106e601526116cb6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e1461033f578063e78cea92146102f3578063ee9a31a21461038557600080fd5b8063ae1f6aaf146102f3578063c01e1bd614610319578063d6c0b2c41461031957600080fd5b80639dc29fac116100bd5780639dc29fac146102ba578063a457c2d7146102cd578063a9059cbb146102e057600080fd5b806370a082311461027c57806395d89b41146102b257600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461024c57806340c10f191461025f57806354fd4d501461027457600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611307565b6103ac565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f861049d565b60405161019b919061137c565b61018f6102133660046113f6565b61052f565b6002545b60405190815260200161019b565b61018f610238366004611420565b610547565b6040516012815260200161019b565b61018f61025a3660046113f6565b61056b565b61027261026d3660046113f6565b6105b7565b005b6101f86106df565b61021c61028a36600461145c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610782565b6102726102c83660046113f6565b610791565b61018f6102db3660046113f6565b6108a8565b61018f6102ee3660046113f6565b610979565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61034d366004611477565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061046557507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b8061049457507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ac906114aa565b80601f01602080910402602001604051908101604052809291908181526020018280546104d8906114aa565b80156105255780601f106104fa57610100808354040283529160200191610525565b820191906000526020600020905b81548152906001019060200180831161050857829003601f168201915b5050505050905090565b60003361053d818585610987565b5060019392505050565b600033610555858285610b3b565b610560858585610c12565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061053d90829086906105b290879061152c565b610987565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b61068b8282610ec5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106d391815260200190565b60405180910390a25050565b606061070a7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b6107337f0000000000000000000000000000000000000000000000000000000000000000610fe5565b61075c7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b60405160200161076e93929190611544565b604051602081830303815290604052905090565b6060600480546104ac906114aa565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e0000000000000000000000006064820152608401610678565b6108608282611122565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106d391815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561096c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610678565b6105608286868403610987565b60003361053d818585610c12565b73ffffffffffffffffffffffffffffffffffffffff8316610a29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c0c5781811015610bff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610678565b610c0c8484848403610987565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e5290849061152c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eb891815260200190565b60405180910390a3610c0c565b73ffffffffffffffffffffffffffffffffffffffff8216610f42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610678565b8060026000828254610f54919061152c565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f8e90849061152c565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361102857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611052578061103c816115ba565b915061104b9050600a83611621565b915061102c565b60008167ffffffffffffffff81111561106d5761106d611635565b6040519080825280601f01601f191660200182016040528015611097576020820181803683370190505b5090505b841561111a576110ac600183611664565b91506110b9600a8661167b565b6110c490603061152c565b60f81b8183815181106110d9576110d961168f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611113600a86611621565b945061109b565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561127b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112b7908490611664565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b2e565b60006020828403121561131957600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461134957600080fd5b9392505050565b60005b8381101561136b578181015183820152602001611353565b83811115610c0c5750506000910152565b602081526000825180602084015261139b816040850160208701611350565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146113f157600080fd5b919050565b6000806040838503121561140957600080fd5b611412836113cd565b946020939093013593505050565b60008060006060848603121561143557600080fd5b61143e846113cd565b925061144c602085016113cd565b9150604084013590509250925092565b60006020828403121561146e57600080fd5b611349826113cd565b6000806040838503121561148a57600080fd5b611493836113cd565b91506114a1602084016113cd565b90509250929050565b600181811c908216806114be57607f821691505b6020821081036114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561153f5761153f6114fd565b500190565b60008451611556818460208901611350565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611592816001850160208a01611350565b600192019182015283516115ad816002840160208801611350565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115eb576115eb6114fd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611630576116306115f2565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015611676576116766114fd565b500390565b60008261168a5761168a6115f2565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a",
} }
// OptimismMintableERC20FactoryABI is the input ABI used to generate the binding from. // OptimismMintableERC20FactoryABI is the input ABI used to generate the binding from.
...@@ -43,7 +43,7 @@ var OptimismMintableERC20FactoryABI = OptimismMintableERC20FactoryMetaData.ABI ...@@ -43,7 +43,7 @@ var OptimismMintableERC20FactoryABI = OptimismMintableERC20FactoryMetaData.ABI
var OptimismMintableERC20FactoryBin = OptimismMintableERC20FactoryMetaData.Bin var OptimismMintableERC20FactoryBin = OptimismMintableERC20FactoryMetaData.Bin
// DeployOptimismMintableERC20Factory deploys a new Ethereum contract, binding an instance of OptimismMintableERC20Factory to it. // DeployOptimismMintableERC20Factory deploys a new Ethereum contract, binding an instance of OptimismMintableERC20Factory to it.
func DeployOptimismMintableERC20Factory(auth *bind.TransactOpts, backend bind.ContractBackend, _bridge common.Address) (common.Address, *types.Transaction, *OptimismMintableERC20Factory, error) { func DeployOptimismMintableERC20Factory(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *OptimismMintableERC20Factory, error) {
parsed, err := OptimismMintableERC20FactoryMetaData.GetAbi() parsed, err := OptimismMintableERC20FactoryMetaData.GetAbi()
if err != nil { if err != nil {
return common.Address{}, nil, nil, err return common.Address{}, nil, nil, err
...@@ -52,7 +52,7 @@ func DeployOptimismMintableERC20Factory(auth *bind.TransactOpts, backend bind.Co ...@@ -52,7 +52,7 @@ func DeployOptimismMintableERC20Factory(auth *bind.TransactOpts, backend bind.Co
return common.Address{}, nil, nil, errors.New("GetABI returned nil") return common.Address{}, nil, nil, errors.New("GetABI returned nil")
} }
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OptimismMintableERC20FactoryBin), backend, _bridge) address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OptimismMintableERC20FactoryBin), backend)
if err != nil { if err != nil {
return common.Address{}, nil, nil, err return common.Address{}, nil, nil, err
} }
...@@ -232,6 +232,37 @@ func (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryCallerSession) ...@@ -232,6 +232,37 @@ func (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryCallerSession)
return _OptimismMintableERC20Factory.Contract.BRIDGE(&_OptimismMintableERC20Factory.CallOpts) return _OptimismMintableERC20Factory.Contract.BRIDGE(&_OptimismMintableERC20Factory.CallOpts)
} }
// Bridge is a free data retrieval call binding the contract method 0xe78cea92.
//
// Solidity: function bridge() view returns(address)
func (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryCaller) Bridge(opts *bind.CallOpts) (common.Address, error) {
var out []interface{}
err := _OptimismMintableERC20Factory.contract.Call(opts, &out, "bridge")
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, err
}
// Bridge is a free data retrieval call binding the contract method 0xe78cea92.
//
// Solidity: function bridge() view returns(address)
func (_OptimismMintableERC20Factory *OptimismMintableERC20FactorySession) Bridge() (common.Address, error) {
return _OptimismMintableERC20Factory.Contract.Bridge(&_OptimismMintableERC20Factory.CallOpts)
}
// Bridge is a free data retrieval call binding the contract method 0xe78cea92.
//
// Solidity: function bridge() view returns(address)
func (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryCallerSession) Bridge() (common.Address, error) {
return _OptimismMintableERC20Factory.Contract.Bridge(&_OptimismMintableERC20Factory.CallOpts)
}
// Version is a free data retrieval call binding the contract method 0x54fd4d50. // Version is a free data retrieval call binding the contract method 0x54fd4d50.
// //
// Solidity: function version() view returns(string) // Solidity: function version() view returns(string)
...@@ -305,6 +336,161 @@ func (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryTransactorSessi ...@@ -305,6 +336,161 @@ func (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryTransactorSessi
return _OptimismMintableERC20Factory.Contract.CreateStandardL2Token(&_OptimismMintableERC20Factory.TransactOpts, _remoteToken, _name, _symbol) return _OptimismMintableERC20Factory.Contract.CreateStandardL2Token(&_OptimismMintableERC20Factory.TransactOpts, _remoteToken, _name, _symbol)
} }
// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8.
//
// Solidity: function initialize(address _bridge) returns()
func (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryTransactor) Initialize(opts *bind.TransactOpts, _bridge common.Address) (*types.Transaction, error) {
return _OptimismMintableERC20Factory.contract.Transact(opts, "initialize", _bridge)
}
// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8.
//
// Solidity: function initialize(address _bridge) returns()
func (_OptimismMintableERC20Factory *OptimismMintableERC20FactorySession) Initialize(_bridge common.Address) (*types.Transaction, error) {
return _OptimismMintableERC20Factory.Contract.Initialize(&_OptimismMintableERC20Factory.TransactOpts, _bridge)
}
// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8.
//
// Solidity: function initialize(address _bridge) returns()
func (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryTransactorSession) Initialize(_bridge common.Address) (*types.Transaction, error) {
return _OptimismMintableERC20Factory.Contract.Initialize(&_OptimismMintableERC20Factory.TransactOpts, _bridge)
}
// OptimismMintableERC20FactoryInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the OptimismMintableERC20Factory contract.
type OptimismMintableERC20FactoryInitializedIterator struct {
Event *OptimismMintableERC20FactoryInitialized // 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 *OptimismMintableERC20FactoryInitializedIterator) 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(OptimismMintableERC20FactoryInitialized)
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(OptimismMintableERC20FactoryInitialized)
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 *OptimismMintableERC20FactoryInitializedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *OptimismMintableERC20FactoryInitializedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// OptimismMintableERC20FactoryInitialized represents a Initialized event raised by the OptimismMintableERC20Factory contract.
type OptimismMintableERC20FactoryInitialized 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 (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryFilterer) FilterInitialized(opts *bind.FilterOpts) (*OptimismMintableERC20FactoryInitializedIterator, error) {
logs, sub, err := _OptimismMintableERC20Factory.contract.FilterLogs(opts, "Initialized")
if err != nil {
return nil, err
}
return &OptimismMintableERC20FactoryInitializedIterator{contract: _OptimismMintableERC20Factory.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 (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *OptimismMintableERC20FactoryInitialized) (event.Subscription, error) {
logs, sub, err := _OptimismMintableERC20Factory.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(OptimismMintableERC20FactoryInitialized)
if err := _OptimismMintableERC20Factory.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 (_OptimismMintableERC20Factory *OptimismMintableERC20FactoryFilterer) ParseInitialized(log types.Log) (*OptimismMintableERC20FactoryInitialized, error) {
event := new(OptimismMintableERC20FactoryInitialized)
if err := _OptimismMintableERC20Factory.contract.UnpackLog(event, "Initialized", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// OptimismMintableERC20FactoryOptimismMintableERC20CreatedIterator is returned from FilterOptimismMintableERC20Created and is used to iterate over the raw logs and unpacked data for OptimismMintableERC20Created events raised by the OptimismMintableERC20Factory contract. // OptimismMintableERC20FactoryOptimismMintableERC20CreatedIterator is returned from FilterOptimismMintableERC20Created and is used to iterate over the raw logs and unpacked data for OptimismMintableERC20Created events raised by the OptimismMintableERC20Factory contract.
type OptimismMintableERC20FactoryOptimismMintableERC20CreatedIterator struct { type OptimismMintableERC20FactoryOptimismMintableERC20CreatedIterator struct {
Event *OptimismMintableERC20FactoryOptimismMintableERC20Created // Event containing the contract specifics and raw log Event *OptimismMintableERC20FactoryOptimismMintableERC20Created // Event containing the contract specifics and raw log
......
...@@ -9,11 +9,11 @@ import ( ...@@ -9,11 +9,11 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const OptimismMintableERC20FactoryStorageLayoutJSON = "{\"storage\":null,\"types\":{}}" const OptimismMintableERC20FactoryStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory\",\"label\":\"bridge\",\"offset\":2,\"slot\":\"0\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
var OptimismMintableERC20FactoryStorageLayout = new(solc.StorageLayout) var OptimismMintableERC20FactoryStorageLayout = new(solc.StorageLayout)
var OptimismMintableERC20FactoryDeployedBin = "0x60806040523480156200001157600080fd5b5060043610620000525760003560e01c806354fd4d501462000057578063896f93d11462000079578063ce5ac90f14620000b6578063ee9a31a214620000cd575b600080fd5b62000061620000f5565b60405162000070919062000587565b60405180910390f35b620000906200008a36600462000685565b620001a0565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000070565b62000090620000c736600462000685565b620001b7565b620000907f000000000000000000000000000000000000000000000000000000000000000081565b6060620001227f0000000000000000000000000000000000000000000000000000000000000000620003ad565b6200014d7f0000000000000000000000000000000000000000000000000000000000000000620003ad565b620001787f0000000000000000000000000000000000000000000000000000000000000000620003ad565b6040516020016200018c939291906200071c565b604051602081830303815290604052905090565b6000620001af848484620001b7565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff841662000261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e206164647265737300606482015260840160405180910390fd5b60008484846040516020016200027a9392919062000798565b6040516020818303038152906040528051906020012090506000817f0000000000000000000000000000000000000000000000000000000000000000878787604051620002c790620004fa565b620002d69493929190620007e7565b8190604051809103906000f5905080158015620002f7573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80881691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a395945050505050565b606081600003620003f157505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115620004215780620004088162000870565b9150620004199050600a83620008da565b9150620003f5565b60008167ffffffffffffffff8111156200043f576200043f620005a3565b6040519080825280601f01601f1916602001820160405280156200046a576020820181803683370190505b5090505b8415620001af5762000482600183620008f1565b915062000491600a866200090b565b6200049e90603062000922565b60f81b818381518110620004b657620004b66200093d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620004f2600a86620008da565b94506200046e565b611a84806200096d83390190565b60005b83811015620005255781810151838201526020016200050b565b8381111562000535576000848401525b50505050565b600081518084526200055581602086016020860162000508565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006200059c60208301846200053b565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620005e457600080fd5b813567ffffffffffffffff80821115620006025762000602620005a3565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200064b576200064b620005a3565b816040528381528660208588010111156200066557600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200069b57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff81168114620006c057600080fd5b9250602084013567ffffffffffffffff80821115620006de57600080fd5b620006ec87838801620005d2565b935060408601359150808211156200070357600080fd5b506200071286828701620005d2565b9150509250925092565b600084516200073081846020890162000508565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516200076e816001850160208a0162000508565b600192019182015283516200078b81600284016020880162000508565b0160020195945050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000620007c960608301856200053b565b8281036040840152620007dd81856200053b565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250608060408301526200082260808301856200053b565b82810360608401526200083681856200053b565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620008a457620008a462000841565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082620008ec57620008ec620008ab565b500490565b60008282101562000906576200090662000841565b500390565b6000826200091d576200091d620008ab565b500690565b6000821982111562000938576200093862000841565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe6101206040523480156200001257600080fd5b5060405162001a8438038062001a8483398101604081905262000035916200016d565b6001806000848460036200004a83826200028c565b5060046200005982826200028c565b50505060809290925260a05260c05250506001600160a01b0390811660e052166101005262000358565b80516001600160a01b03811681146200009b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000c857600080fd5b81516001600160401b0380821115620000e557620000e5620000a0565b604051601f8301601f19908116603f01168101908282118183101715620001105762000110620000a0565b816040528381526020925086838588010111156200012d57600080fd5b600091505b8382101562000151578582018301518183018401529082019062000132565b83821115620001635760008385830101525b9695505050505050565b600080600080608085870312156200018457600080fd5b6200018f8562000083565b93506200019f6020860162000083565b60408601519093506001600160401b0380821115620001bd57600080fd5b620001cb88838901620000b6565b93506060870151915080821115620001e257600080fd5b50620001f187828801620000b6565b91505092959194509250565b600181811c908216806200021257607f821691505b6020821081036200023357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028757600081815260208120601f850160051c81016020861015620002625750805b601f850160051c820191505b8181101562000283578281556001016200026e565b5050505b505050565b81516001600160401b03811115620002a857620002a8620000a0565b620002c081620002b98454620001fd565b8462000239565b602080601f831160018114620002f85760008415620002df5750858301515b600019600386901b1c1916600185901b17855562000283565b600085815260208120601f198616915b82811015620003295788860151825594840194600190910190840162000308565b5085821015620003485787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610100516116cb620003b9600039600081816102f50152818161038a015281816105cf01526107a90152600081816101a9015261031b015260006107380152600061070f015260006106e601526116cb6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e1461033f578063e78cea92146102f3578063ee9a31a21461038557600080fd5b8063ae1f6aaf146102f3578063c01e1bd614610319578063d6c0b2c41461031957600080fd5b80639dc29fac116100bd5780639dc29fac146102ba578063a457c2d7146102cd578063a9059cbb146102e057600080fd5b806370a082311461027c57806395d89b41146102b257600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461024c57806340c10f191461025f57806354fd4d501461027457600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611307565b6103ac565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f861049d565b60405161019b919061137c565b61018f6102133660046113f6565b61052f565b6002545b60405190815260200161019b565b61018f610238366004611420565b610547565b6040516012815260200161019b565b61018f61025a3660046113f6565b61056b565b61027261026d3660046113f6565b6105b7565b005b6101f86106df565b61021c61028a36600461145c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610782565b6102726102c83660046113f6565b610791565b61018f6102db3660046113f6565b6108a8565b61018f6102ee3660046113f6565b610979565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61034d366004611477565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061046557507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b8061049457507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ac906114aa565b80601f01602080910402602001604051908101604052809291908181526020018280546104d8906114aa565b80156105255780601f106104fa57610100808354040283529160200191610525565b820191906000526020600020905b81548152906001019060200180831161050857829003601f168201915b5050505050905090565b60003361053d818585610987565b5060019392505050565b600033610555858285610b3b565b610560858585610c12565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061053d90829086906105b290879061152c565b610987565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b61068b8282610ec5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106d391815260200190565b60405180910390a25050565b606061070a7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b6107337f0000000000000000000000000000000000000000000000000000000000000000610fe5565b61075c7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b60405160200161076e93929190611544565b604051602081830303815290604052905090565b6060600480546104ac906114aa565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e0000000000000000000000006064820152608401610678565b6108608282611122565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106d391815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561096c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610678565b6105608286868403610987565b60003361053d818585610c12565b73ffffffffffffffffffffffffffffffffffffffff8316610a29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c0c5781811015610bff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610678565b610c0c8484848403610987565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e5290849061152c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eb891815260200190565b60405180910390a3610c0c565b73ffffffffffffffffffffffffffffffffffffffff8216610f42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610678565b8060026000828254610f54919061152c565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f8e90849061152c565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361102857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611052578061103c816115ba565b915061104b9050600a83611621565b915061102c565b60008167ffffffffffffffff81111561106d5761106d611635565b6040519080825280601f01601f191660200182016040528015611097576020820181803683370190505b5090505b841561111a576110ac600183611664565b91506110b9600a8661167b565b6110c490603061152c565b60f81b8183815181106110d9576110d961168f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611113600a86611621565b945061109b565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561127b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112b7908490611664565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b2e565b60006020828403121561131957600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461134957600080fd5b9392505050565b60005b8381101561136b578181015183820152602001611353565b83811115610c0c5750506000910152565b602081526000825180602084015261139b816040850160208701611350565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146113f157600080fd5b919050565b6000806040838503121561140957600080fd5b611412836113cd565b946020939093013593505050565b60008060006060848603121561143557600080fd5b61143e846113cd565b925061144c602085016113cd565b9150604084013590509250925092565b60006020828403121561146e57600080fd5b611349826113cd565b6000806040838503121561148a57600080fd5b611493836113cd565b91506114a1602084016113cd565b90509250929050565b600181811c908216806114be57607f821691505b6020821081036114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561153f5761153f6114fd565b500190565b60008451611556818460208901611350565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611592816001850160208a01611350565b600192019182015283516115ad816002840160208801611350565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115eb576115eb6114fd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611630576116306115f2565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015611676576116766114fd565b500390565b60008261168a5761168a6115f2565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a" var OptimismMintableERC20FactoryDeployedBin = "0x60806040523480156200001157600080fd5b50600436106200007b5760003560e01c8063ce5ac90f1162000056578063ce5ac90f14620000f8578063e78cea92146200010f578063ee9a31a2146200013657600080fd5b806354fd4d501462000080578063896f93d114620000a2578063c4d66de814620000df575b600080fd5b6200008a6200015b565b6040516200009991906200076e565b60405180910390f35b620000b9620000b336600462000896565b62000206565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000099565b620000f6620000f036600462000913565b6200021d565b005b620000b96200010936600462000896565b6200039f565b600054620000b99062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000b9565b6060620001887f000000000000000000000000000000000000000000000000000000000000000062000594565b620001b37f000000000000000000000000000000000000000000000000000000000000000062000594565b620001de7f000000000000000000000000000000000000000000000000000000000000000062000594565b604051602001620001f29392919062000931565b604051602081830303815290604052905090565b6000620002158484846200039f565b949350505050565b600054600290610100900460ff1615801562000240575060005460ff8083169116105b620002d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b600073ffffffffffffffffffffffffffffffffffffffff841662000446576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e2061646472657373006064820152608401620002c9565b60008484846040516020016200045f93929190620009ad565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff16878787604051620004ae90620006e1565b620004bd9493929190620009fc565b8190604051809103906000f5905080158015620004de573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80881691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a395945050505050565b606081600003620005d857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115620006085780620005ef8162000a85565b9150620006009050600a8362000aef565b9150620005dc565b60008167ffffffffffffffff811115620006265762000626620007b4565b6040519080825280601f01601f19166020018201604052801562000651576020820181803683370190505b5090505b841562000215576200066960018362000b06565b915062000678600a8662000b20565b6200068590603062000b37565b60f81b8183815181106200069d576200069d62000b52565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620006d9600a8662000aef565b945062000655565b611a848062000b8283390190565b60005b838110156200070c578181015183820152602001620006f2565b838111156200071c576000848401525b50505050565b600081518084526200073c816020860160208601620006ef565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000783602083018462000722565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114620007af57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620007f557600080fd5b813567ffffffffffffffff80821115620008135762000813620007b4565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200085c576200085c620007b4565b816040528381528660208588010111156200087657600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620008ac57600080fd5b620008b7846200078a565b9250602084013567ffffffffffffffff80821115620008d557600080fd5b620008e387838801620007e3565b93506040860135915080821115620008fa57600080fd5b506200090986828701620007e3565b9150509250925092565b6000602082840312156200092657600080fd5b62000783826200078a565b6000845162000945818460208901620006ef565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855162000983816001850160208a01620006ef565b60019201918201528351620009a0816002840160208801620006ef565b0160020195945050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000620009de606083018562000722565b8281036040840152620009f2818562000722565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015262000a37608083018562000722565b828103606084015262000a4b818562000722565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362000ab95762000ab962000a56565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008262000b015762000b0162000ac0565b500490565b60008282101562000b1b5762000b1b62000a56565b500390565b60008262000b325762000b3262000ac0565b500690565b6000821982111562000b4d5762000b4d62000a56565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe6101206040523480156200001257600080fd5b5060405162001a8438038062001a8483398101604081905262000035916200016d565b6001806000848460036200004a83826200028c565b5060046200005982826200028c565b50505060809290925260a05260c05250506001600160a01b0390811660e052166101005262000358565b80516001600160a01b03811681146200009b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000c857600080fd5b81516001600160401b0380821115620000e557620000e5620000a0565b604051601f8301601f19908116603f01168101908282118183101715620001105762000110620000a0565b816040528381526020925086838588010111156200012d57600080fd5b600091505b8382101562000151578582018301518183018401529082019062000132565b83821115620001635760008385830101525b9695505050505050565b600080600080608085870312156200018457600080fd5b6200018f8562000083565b93506200019f6020860162000083565b60408601519093506001600160401b0380821115620001bd57600080fd5b620001cb88838901620000b6565b93506060870151915080821115620001e257600080fd5b50620001f187828801620000b6565b91505092959194509250565b600181811c908216806200021257607f821691505b6020821081036200023357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028757600081815260208120601f850160051c81016020861015620002625750805b601f850160051c820191505b8181101562000283578281556001016200026e565b5050505b505050565b81516001600160401b03811115620002a857620002a8620000a0565b620002c081620002b98454620001fd565b8462000239565b602080601f831160018114620002f85760008415620002df5750858301515b600019600386901b1c1916600185901b17855562000283565b600085815260208120601f198616915b82811015620003295788860151825594840194600190910190840162000308565b5085821015620003485787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610100516116cb620003b9600039600081816102f50152818161038a015281816105cf01526107a90152600081816101a9015261031b015260006107380152600061070f015260006106e601526116cb6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e1461033f578063e78cea92146102f3578063ee9a31a21461038557600080fd5b8063ae1f6aaf146102f3578063c01e1bd614610319578063d6c0b2c41461031957600080fd5b80639dc29fac116100bd5780639dc29fac146102ba578063a457c2d7146102cd578063a9059cbb146102e057600080fd5b806370a082311461027c57806395d89b41146102b257600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461024c57806340c10f191461025f57806354fd4d501461027457600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611307565b6103ac565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f861049d565b60405161019b919061137c565b61018f6102133660046113f6565b61052f565b6002545b60405190815260200161019b565b61018f610238366004611420565b610547565b6040516012815260200161019b565b61018f61025a3660046113f6565b61056b565b61027261026d3660046113f6565b6105b7565b005b6101f86106df565b61021c61028a36600461145c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610782565b6102726102c83660046113f6565b610791565b61018f6102db3660046113f6565b6108a8565b61018f6102ee3660046113f6565b610979565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61034d366004611477565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061046557507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b8061049457507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ac906114aa565b80601f01602080910402602001604051908101604052809291908181526020018280546104d8906114aa565b80156105255780601f106104fa57610100808354040283529160200191610525565b820191906000526020600020905b81548152906001019060200180831161050857829003601f168201915b5050505050905090565b60003361053d818585610987565b5060019392505050565b600033610555858285610b3b565b610560858585610c12565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061053d90829086906105b290879061152c565b610987565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b61068b8282610ec5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106d391815260200190565b60405180910390a25050565b606061070a7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b6107337f0000000000000000000000000000000000000000000000000000000000000000610fe5565b61075c7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b60405160200161076e93929190611544565b604051602081830303815290604052905090565b6060600480546104ac906114aa565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e0000000000000000000000006064820152608401610678565b6108608282611122565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106d391815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561096c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610678565b6105608286868403610987565b60003361053d818585610c12565b73ffffffffffffffffffffffffffffffffffffffff8316610a29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c0c5781811015610bff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610678565b610c0c8484848403610987565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e5290849061152c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eb891815260200190565b60405180910390a3610c0c565b73ffffffffffffffffffffffffffffffffffffffff8216610f42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610678565b8060026000828254610f54919061152c565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f8e90849061152c565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361102857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611052578061103c816115ba565b915061104b9050600a83611621565b915061102c565b60008167ffffffffffffffff81111561106d5761106d611635565b6040519080825280601f01601f191660200182016040528015611097576020820181803683370190505b5090505b841561111a576110ac600183611664565b91506110b9600a8661167b565b6110c490603061152c565b60f81b8183815181106110d9576110d961168f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611113600a86611621565b945061109b565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561127b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112b7908490611664565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b2e565b60006020828403121561131957600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461134957600080fd5b9392505050565b60005b8381101561136b578181015183820152602001611353565b83811115610c0c5750506000910152565b602081526000825180602084015261139b816040850160208701611350565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146113f157600080fd5b919050565b6000806040838503121561140957600080fd5b611412836113cd565b946020939093013593505050565b60008060006060848603121561143557600080fd5b61143e846113cd565b925061144c602085016113cd565b9150604084013590509250925092565b60006020828403121561146e57600080fd5b611349826113cd565b6000806040838503121561148a57600080fd5b611493836113cd565b91506114a1602084016113cd565b90509250929050565b600181811c908216806114be57607f821691505b6020821081036114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561153f5761153f6114fd565b500190565b60008451611556818460208901611350565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611592816001850160208a01611350565b600192019182015283516115ad816002840160208801611350565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115eb576115eb6114fd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611630576116306115f2565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015611676576116766114fd565b500390565b60008261168a5761168a6115f2565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a"
func init() { func init() {
if err := json.Unmarshal([]byte(OptimismMintableERC20FactoryStorageLayoutJSON), OptimismMintableERC20FactoryStorageLayout); err != nil { if err := json.Unmarshal([]byte(OptimismMintableERC20FactoryStorageLayoutJSON), OptimismMintableERC20FactoryStorageLayout); err != nil {
......
GITCOMMIT := $(shell git rev-parse HEAD)
GITDATE := $(shell git show -s --format='%ct')
VERSION := v0.0.0
LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT)
LDFLAGSSTRING +=-X main.GitDate=$(GITDATE)
LDFLAGSSTRING +=-X main.Version=$(VERSION)
LDFLAGS := -ldflags "$(LDFLAGSSTRING)"
op-bootnode:
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/op-bootnode ./cmd
lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
...@@ -6,6 +6,9 @@ check-l2: ...@@ -6,6 +6,9 @@ check-l2:
test: test:
go test ./... go test ./...
lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
fuzz: fuzz:
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzEncodeDecodeWithdrawal ./crossdomain go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzEncodeDecodeWithdrawal ./crossdomain
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzEncodeDecodeLegacyWithdrawal ./crossdomain go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzEncodeDecodeLegacyWithdrawal ./crossdomain
......
...@@ -543,15 +543,36 @@ func checkOptimismMintableERC20Factory(addr common.Address, client *ethclient.Cl ...@@ -543,15 +543,36 @@ func checkOptimismMintableERC20Factory(addr common.Address, client *ethclient.Cl
return err return err
} }
bridge, err := contract.BRIDGE(&bind.CallOpts{}) bridgeLegacy, err := contract.BRIDGE(&bind.CallOpts{})
if err != nil { if err != nil {
return err return err
} }
log.Info("OptimismMintableERC20Factory", "BRIDGE", bridge.Hex()) log.Info("OptimismMintableERC20Factory", "BRIDGE", bridgeLegacy.Hex())
if bridge == (common.Address{}) { if bridgeLegacy == (common.Address{}) {
return errors.New("OptimismMintableERC20Factory.BRIDGE is zero address") return errors.New("OptimismMintableERC20Factory.BRIDGE is zero address")
} }
bridge, err := contract.Bridge(&bind.CallOpts{})
if err != nil {
return err
}
if bridge == (common.Address{}) {
return errors.New("OptimismMintableERC20Factory.bridge is zero address")
}
log.Info("OptimismMintableERC20Factory", "bridge", bridge.Hex())
initialized, err := getInitialized("OptimismMintableERC20Factory", addr, client)
if err != nil {
return err
}
log.Info("OptimismMintableERC20Factory", "_initialized", initialized)
initializing, err := getInitializing("OptimismMintableERC20Factory", addr, client)
if err != nil {
return err
}
log.Info("OptimismMintableERC20Factory", "_initializing", initializing)
version, err := contract.Version(&bind.CallOpts{}) version, err := contract.Version(&bind.CallOpts{})
if err != nil { if err != nil {
return err return err
......
...@@ -695,6 +695,11 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage ...@@ -695,6 +695,11 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
"_initialized": 2, "_initialized": 2,
"_initializing": false, "_initializing": false,
} }
storage["OptimismMintableERC20Factory"] = state.StorageValues{
"bridge": predeploys.L2StandardBridgeAddr,
"_initialized": 2,
"_initializing": false,
}
return storage, nil return storage, nil
} }
......
...@@ -216,7 +216,7 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep ...@@ -216,7 +216,7 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep
} }
_, tx, _, err = bindings.DeployL1FeeVault(opts, backend, recipient, minimumWithdrawalAmount, withdrawalNetwork) _, tx, _, err = bindings.DeployL1FeeVault(opts, backend, recipient, minimumWithdrawalAmount, withdrawalNetwork)
case "OptimismMintableERC20Factory": case "OptimismMintableERC20Factory":
_, tx, _, err = bindings.DeployOptimismMintableERC20Factory(opts, backend, predeploys.L2StandardBridgeAddr) _, tx, _, err = bindings.DeployOptimismMintableERC20Factory(opts, backend)
case "DeployerWhitelist": case "DeployerWhitelist":
_, tx, _, err = bindings.DeployDeployerWhitelist(opts, backend) _, tx, _, err = bindings.DeployDeployerWhitelist(opts, backend)
case "LegacyMessagePasser": case "LegacyMessagePasser":
......
...@@ -17,7 +17,7 @@ test: ...@@ -17,7 +17,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
visualize: visualize:
./scripts/visualize.sh ./scripts/visualize.sh
......
...@@ -32,7 +32,7 @@ type Executor struct { ...@@ -32,7 +32,7 @@ type Executor struct {
logger log.Logger logger log.Logger
l1 string l1 string
l2 string l2 string
inputs localGameInputs inputs LocalGameInputs
cannon string cannon string
server string server string
network string network string
...@@ -45,7 +45,7 @@ type Executor struct { ...@@ -45,7 +45,7 @@ type Executor struct {
cmdExecutor cmdExecutor cmdExecutor cmdExecutor
} }
func NewExecutor(logger log.Logger, cfg *config.Config, inputs localGameInputs) *Executor { func NewExecutor(logger log.Logger, cfg *config.Config, inputs LocalGameInputs) *Executor {
return &Executor{ return &Executor{
logger: logger, logger: logger,
l1: cfg.L1EthRpc, l1: cfg.L1EthRpc,
...@@ -92,11 +92,11 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro ...@@ -92,11 +92,11 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro
"--l1", e.l1, "--l1", e.l1,
"--l2", e.l2, "--l2", e.l2,
"--datadir", dataDir, "--datadir", dataDir,
"--l1.head", e.inputs.l1Head.Hex(), "--l1.head", e.inputs.L1Head.Hex(),
"--l2.head", e.inputs.l2Head.Hex(), "--l2.head", e.inputs.L2Head.Hex(),
"--l2.outputroot", e.inputs.l2OutputRoot.Hex(), "--l2.outputroot", e.inputs.L2OutputRoot.Hex(),
"--l2.claim", e.inputs.l2Claim.Hex(), "--l2.claim", e.inputs.L2Claim.Hex(),
"--l2.blocknumber", e.inputs.l2BlockNumber.Text(10), "--l2.blocknumber", e.inputs.L2BlockNumber.Text(10),
) )
if e.network != "" { if e.network != "" {
args = append(args, "--network", e.network) args = append(args, "--network", e.network)
......
...@@ -29,12 +29,12 @@ func TestGenerateProof(t *testing.T) { ...@@ -29,12 +29,12 @@ func TestGenerateProof(t *testing.T) {
cfg.CannonL2 = "http://localhost:9999" cfg.CannonL2 = "http://localhost:9999"
cfg.CannonSnapshotFreq = 500 cfg.CannonSnapshotFreq = 500
inputs := localGameInputs{ inputs := LocalGameInputs{
l1Head: common.Hash{0x11}, L1Head: common.Hash{0x11},
l2Head: common.Hash{0x22}, L2Head: common.Hash{0x22},
l2OutputRoot: common.Hash{0x33}, L2OutputRoot: common.Hash{0x33},
l2Claim: common.Hash{0x44}, L2Claim: common.Hash{0x44},
l2BlockNumber: big.NewInt(3333), L2BlockNumber: big.NewInt(3333),
} }
captureExec := func(t *testing.T, cfg config.Config, proofAt uint64) (string, string, map[string]string) { captureExec := func(t *testing.T, cfg config.Config, proofAt uint64) (string, string, map[string]string) {
executor := NewExecutor(testlog.Logger(t, log.LvlInfo), &cfg, inputs) executor := NewExecutor(testlog.Logger(t, log.LvlInfo), &cfg, inputs)
...@@ -94,10 +94,10 @@ func TestGenerateProof(t *testing.T) { ...@@ -94,10 +94,10 @@ func TestGenerateProof(t *testing.T) {
require.NotContains(t, args, "--l2.genesis") require.NotContains(t, args, "--l2.genesis")
// Local game inputs // Local game inputs
require.Equal(t, inputs.l1Head.Hex(), args["--l1.head"]) require.Equal(t, inputs.L1Head.Hex(), args["--l1.head"])
require.Equal(t, inputs.l2Head.Hex(), args["--l2.head"]) require.Equal(t, inputs.L2Head.Hex(), args["--l2.head"])
require.Equal(t, inputs.l2OutputRoot.Hex(), args["--l2.outputroot"]) require.Equal(t, inputs.L2OutputRoot.Hex(), args["--l2.outputroot"])
require.Equal(t, inputs.l2Claim.Hex(), args["--l2.claim"]) require.Equal(t, inputs.L2Claim.Hex(), args["--l2.claim"])
require.Equal(t, "3333", args["--l2.blocknumber"]) require.Equal(t, "3333", args["--l2.blocknumber"])
}) })
......
...@@ -11,12 +11,12 @@ import ( ...@@ -11,12 +11,12 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
) )
type localGameInputs struct { type LocalGameInputs struct {
l1Head common.Hash L1Head common.Hash
l2Head common.Hash L2Head common.Hash
l2OutputRoot common.Hash L2OutputRoot common.Hash
l2Claim common.Hash L2Claim common.Hash
l2BlockNumber *big.Int L2BlockNumber *big.Int
} }
type L2DataSource interface { type L2DataSource interface {
...@@ -32,30 +32,30 @@ type GameInputsSource interface { ...@@ -32,30 +32,30 @@ type GameInputsSource interface {
}, error) }, error)
} }
func fetchLocalInputs(ctx context.Context, gameAddr common.Address, caller GameInputsSource, l2Client L2DataSource) (localGameInputs, error) { func fetchLocalInputs(ctx context.Context, gameAddr common.Address, caller GameInputsSource, l2Client L2DataSource) (LocalGameInputs, error) {
opts := &bind.CallOpts{Context: ctx} opts := &bind.CallOpts{Context: ctx}
l1Head, err := caller.L1Head(opts) l1Head, err := caller.L1Head(opts)
if err != nil { if err != nil {
return localGameInputs{}, fmt.Errorf("fetch L1 head for game %v: %w", gameAddr, err) return LocalGameInputs{}, fmt.Errorf("fetch L1 head for game %v: %w", gameAddr, err)
} }
proposals, err := caller.Proposals(opts) proposals, err := caller.Proposals(opts)
if err != nil { if err != nil {
return localGameInputs{}, fmt.Errorf("fetch proposals: %w", err) return LocalGameInputs{}, fmt.Errorf("fetch proposals: %w", err)
} }
claimedOutput := proposals.Disputed claimedOutput := proposals.Disputed
agreedOutput := proposals.Starting agreedOutput := proposals.Starting
agreedHeader, err := l2Client.HeaderByNumber(ctx, agreedOutput.L2BlockNumber) agreedHeader, err := l2Client.HeaderByNumber(ctx, agreedOutput.L2BlockNumber)
if err != nil { if err != nil {
return localGameInputs{}, fmt.Errorf("fetch L2 block header %v: %w", agreedOutput.L2BlockNumber, err) return LocalGameInputs{}, fmt.Errorf("fetch L2 block header %v: %w", agreedOutput.L2BlockNumber, err)
} }
l2Head := agreedHeader.Hash() l2Head := agreedHeader.Hash()
return localGameInputs{ return LocalGameInputs{
l1Head: l1Head, L1Head: l1Head,
l2Head: l2Head, L2Head: l2Head,
l2OutputRoot: agreedOutput.OutputRoot, L2OutputRoot: agreedOutput.OutputRoot,
l2Claim: claimedOutput.OutputRoot, L2Claim: claimedOutput.OutputRoot,
l2BlockNumber: claimedOutput.L2BlockNumber, L2BlockNumber: claimedOutput.L2BlockNumber,
}, nil }, nil
} }
...@@ -39,11 +39,11 @@ func TestFetchLocalInputs(t *testing.T) { ...@@ -39,11 +39,11 @@ func TestFetchLocalInputs(t *testing.T) {
inputs, err := fetchLocalInputs(ctx, gameAddr, l1Client, l2Client) inputs, err := fetchLocalInputs(ctx, gameAddr, l1Client, l2Client)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, l1Client.l1Head, inputs.l1Head) require.Equal(t, l1Client.l1Head, inputs.L1Head)
require.Equal(t, l2Client.header.Hash(), inputs.l2Head) require.Equal(t, l2Client.header.Hash(), inputs.L2Head)
require.EqualValues(t, l1Client.starting.OutputRoot, inputs.l2OutputRoot) require.EqualValues(t, l1Client.starting.OutputRoot, inputs.L2OutputRoot)
require.EqualValues(t, l1Client.disputed.OutputRoot, inputs.l2Claim) require.EqualValues(t, l1Client.disputed.OutputRoot, inputs.L2Claim)
require.Equal(t, l1Client.disputed.L2BlockNumber, inputs.l2BlockNumber) require.Equal(t, l1Client.disputed.L2BlockNumber, inputs.L2BlockNumber)
} }
type mockGameInputsSource struct { type mockGameInputsSource struct {
......
...@@ -60,16 +60,20 @@ func NewTraceProvider(ctx context.Context, logger log.Logger, cfg *config.Config ...@@ -60,16 +60,20 @@ func NewTraceProvider(ctx context.Context, logger log.Logger, cfg *config.Config
if err != nil { if err != nil {
return nil, fmt.Errorf("create caller for game %v: %w", cfg.GameAddress, err) return nil, fmt.Errorf("create caller for game %v: %w", cfg.GameAddress, err)
} }
l1Head, err := fetchLocalInputs(ctx, cfg.GameAddress, gameCaller, l2Client) localInputs, err := fetchLocalInputs(ctx, cfg.GameAddress, gameCaller, l2Client)
if err != nil { if err != nil {
return nil, fmt.Errorf("fetch local game inputs: %w", err) return nil, fmt.Errorf("fetch local game inputs: %w", err)
} }
return NewTraceProviderFromInputs(logger, cfg, localInputs), nil
}
func NewTraceProviderFromInputs(logger log.Logger, cfg *config.Config, localInputs LocalGameInputs) *CannonTraceProvider {
return &CannonTraceProvider{ return &CannonTraceProvider{
logger: logger, logger: logger,
dir: cfg.CannonDatadir, dir: cfg.CannonDatadir,
prestate: cfg.CannonAbsolutePreState, prestate: cfg.CannonAbsolutePreState,
generator: NewExecutor(logger, cfg, l1Head), generator: NewExecutor(logger, cfg, localInputs),
}, nil }
} }
func (p *CannonTraceProvider) Get(ctx context.Context, i uint64) (common.Hash, error) { func (p *CannonTraceProvider) Get(ctx context.Context, i uint64) (common.Hash, error) {
......
...@@ -26,7 +26,7 @@ clean: ...@@ -26,7 +26,7 @@ clean:
rm -r ../op-program/bin rm -r ../op-program/bin
lint: lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
.PHONY: \ .PHONY: \
test \ test \
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"os" "os"
"path/filepath" "path/filepath"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon" "github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
...@@ -12,8 +13,10 @@ import ( ...@@ -12,8 +13,10 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
) )
type CannonGameHelper struct { type CannonGameHelper struct {
...@@ -21,7 +24,7 @@ type CannonGameHelper struct { ...@@ -21,7 +24,7 @@ type CannonGameHelper struct {
} }
func (g *CannonGameHelper) StartChallenger(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Endpoint string, l2Endpoint string, name string, options ...challenger.Option) *challenger.Helper { func (g *CannonGameHelper) StartChallenger(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Endpoint string, l2Endpoint string, name string, options ...challenger.Option) *challenger.Helper {
opts := []challenger.Option{g.createConfigOption(rollupCfg, l2Genesis, l2Endpoint)} opts := []challenger.Option{createConfigOption(g.t, rollupCfg, l2Genesis, g.addr, l2Endpoint)}
opts = append(opts, options...) opts = append(opts, options...)
c := challenger.NewChallenger(g.t, ctx, l1Endpoint, name, opts...) c := challenger.NewChallenger(g.t, ctx, l1Endpoint, name, opts...)
g.t.Cleanup(func() { g.t.Cleanup(func() {
...@@ -31,10 +34,10 @@ func (g *CannonGameHelper) StartChallenger(ctx context.Context, rollupCfg *rollu ...@@ -31,10 +34,10 @@ func (g *CannonGameHelper) StartChallenger(ctx context.Context, rollupCfg *rollu
} }
func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Client bind.ContractCaller, l1Endpoint string, l2Endpoint string, options ...challenger.Option) *HonestHelper { func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Client bind.ContractCaller, l1Endpoint string, l2Endpoint string, options ...challenger.Option) *HonestHelper {
opts := []challenger.Option{g.createConfigOption(rollupCfg, l2Genesis, l2Endpoint)} opts := []challenger.Option{createConfigOption(g.t, rollupCfg, l2Genesis, g.addr, l2Endpoint)}
opts = append(opts, options...) opts = append(opts, options...)
cfg := challenger.NewChallengerConfig(g.t, l1Endpoint, opts...) cfg := challenger.NewChallengerConfig(g.t, l1Endpoint, opts...)
provider, err := cannon.NewTraceProvider(ctx, testlog.Logger(g.t, log.LvlTrace).New("role", "CorrectTrace"), cfg, l1Client) provider, err := cannon.NewTraceProvider(ctx, testlog.Logger(g.t, log.LvlInfo).New("role", "CorrectTrace"), cfg, l1Client)
g.require.NoError(err, "create cannon trace provider") g.require.NoError(err, "create cannon trace provider")
return &HonestHelper{ return &HonestHelper{
...@@ -45,28 +48,29 @@ func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rol ...@@ -45,28 +48,29 @@ func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rol
} }
} }
func (g *CannonGameHelper) createConfigOption(rollupCfg *rollup.Config, l2Genesis *core.Genesis, l2Endpoint string) challenger.Option { func createConfigOption(t *testing.T, rollupCfg *rollup.Config, l2Genesis *core.Genesis, gameAddr common.Address, l2Endpoint string) challenger.Option {
return func(c *config.Config) { return func(c *config.Config) {
c.GameAddress = g.addr require := require.New(t)
c.GameAddress = gameAddr
c.TraceType = config.TraceTypeCannon c.TraceType = config.TraceTypeCannon
c.AgreeWithProposedOutput = false c.AgreeWithProposedOutput = false
c.CannonL2 = l2Endpoint c.CannonL2 = l2Endpoint
c.CannonBin = "../cannon/bin/cannon" c.CannonBin = "../cannon/bin/cannon"
c.CannonDatadir = g.t.TempDir() c.CannonDatadir = t.TempDir()
c.CannonServer = "../op-program/bin/op-program" c.CannonServer = "../op-program/bin/op-program"
c.CannonAbsolutePreState = "../op-program/bin/prestate.json" c.CannonAbsolutePreState = "../op-program/bin/prestate.json"
c.CannonSnapshotFreq = 10_000_000 c.CannonSnapshotFreq = 10_000_000
genesisBytes, err := json.Marshal(l2Genesis) genesisBytes, err := json.Marshal(l2Genesis)
g.require.NoError(err, "marshall l2 genesis config") require.NoError(err, "marshall l2 genesis config")
genesisFile := filepath.Join(c.CannonDatadir, "l2-genesis.json") genesisFile := filepath.Join(c.CannonDatadir, "l2-genesis.json")
g.require.NoError(os.WriteFile(genesisFile, genesisBytes, 0644)) require.NoError(os.WriteFile(genesisFile, genesisBytes, 0644))
c.CannonL2GenesisPath = genesisFile c.CannonL2GenesisPath = genesisFile
rollupBytes, err := json.Marshal(rollupCfg) rollupBytes, err := json.Marshal(rollupCfg)
g.require.NoError(err, "marshall rollup config") require.NoError(err, "marshall rollup config")
rollupFile := filepath.Join(c.CannonDatadir, "rollup.json") rollupFile := filepath.Join(c.CannonDatadir, "rollup.json")
g.require.NoError(os.WriteFile(rollupFile, rollupBytes, 0644)) require.NoError(os.WriteFile(rollupFile, rollupBytes, 0644))
c.CannonRollupConfigPath = rollupFile c.CannonRollupConfigPath = rollupFile
} }
} }
...@@ -42,7 +42,7 @@ func (g *FaultGameHelper) WaitForClaimCount(ctx context.Context, count int64) { ...@@ -42,7 +42,7 @@ func (g *FaultGameHelper) WaitForClaimCount(ctx context.Context, count int64) {
g.t.Log("Waiting for claim count", "current", actual, "expected", count, "game", g.addr) g.t.Log("Waiting for claim count", "current", actual, "expected", count, "game", g.addr)
return actual.Cmp(big.NewInt(count)) == 0, nil return actual.Cmp(big.NewInt(count)) == 0, nil
}) })
g.require.NoError(err) g.require.NoErrorf(err, "Did not find expected claim count %v", count)
} }
type ContractClaim struct { type ContractClaim struct {
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math"
"math/big" "math/big"
"testing" "testing"
"time" "time"
...@@ -13,11 +14,16 @@ import ( ...@@ -13,11 +14,16 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/fault/alphabet" "github.com/ethereum-optimism/optimism/op-challenger/fault/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -125,9 +131,57 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s ...@@ -125,9 +131,57 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s
} }
func (h *FactoryHelper) StartCannonGame(ctx context.Context, rootClaim common.Hash) *CannonGameHelper { func (h *FactoryHelper) StartCannonGame(ctx context.Context, rootClaim common.Hash) *CannonGameHelper {
l2BlockNumber := h.waitForProposals(ctx) l2BlockNumber, l1Head := h.prepareCannonGame(ctx)
l1Head := h.checkpointL1Block(ctx) return h.createCannonGame(ctx, l2BlockNumber, l1Head, rootClaim)
}
func (h *FactoryHelper) StartCannonGameWithCorrectRoot(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Endpoint string, l2Endpoint string, options ...challenger.Option) (*CannonGameHelper, *HonestHelper) {
l2BlockNumber, l1Head := h.prepareCannonGame(ctx)
challengerOpts := []challenger.Option{createConfigOption(h.t, rollupCfg, l2Genesis, common.Address{0xaa}, l2Endpoint)}
challengerOpts = append(challengerOpts, options...)
cfg := challenger.NewChallengerConfig(h.t, l1Endpoint, challengerOpts...)
opts := &bind.CallOpts{Context: ctx}
outputIdx, err := h.l2oo.GetL2OutputIndexAfter(opts, new(big.Int).SetUint64(l2BlockNumber))
h.require.NoError(err, "Fetch challenged output index")
challengedOutput, err := h.l2oo.GetL2Output(opts, outputIdx)
h.require.NoError(err, "Fetch challenged output")
agreedOutput, err := h.l2oo.GetL2Output(opts, new(big.Int).Sub(outputIdx, common.Big1))
h.require.NoError(err, "Fetch agreed output")
l1BlockInfo, err := h.blockOracle.Load(opts, l1Head)
h.require.NoError(err, "Fetch L1 block info")
l2Client, err := ethclient.DialContext(ctx, cfg.CannonL2)
if err != nil {
h.require.NoErrorf(err, "Failed to dial l2 client %v", l2Endpoint)
}
defer l2Client.Close()
agreedHeader, err := l2Client.HeaderByNumber(ctx, agreedOutput.L2BlockNumber)
if err != nil {
h.require.NoErrorf(err, "Failed to fetch L2 block header %v", agreedOutput.L2BlockNumber)
}
inputs := cannon.LocalGameInputs{
L1Head: l1BlockInfo.Hash,
L2Head: agreedHeader.Hash(),
L2OutputRoot: agreedOutput.OutputRoot,
L2Claim: challengedOutput.OutputRoot,
L2BlockNumber: challengedOutput.L2BlockNumber,
}
provider := cannon.NewTraceProviderFromInputs(testlog.Logger(h.t, log.LvlInfo).New("role", "CorrectTrace"), cfg, inputs)
rootClaim, err := provider.Get(ctx, math.MaxUint64)
h.require.NoError(err, "Compute correct root hash")
game := h.createCannonGame(ctx, l2BlockNumber, l1Head, rootClaim)
honestHelper := &HonestHelper{
t: h.t,
require: h.require,
game: &game.FaultGameHelper,
correctTrace: provider,
}
return game, honestHelper
}
func (h *FactoryHelper) createCannonGame(ctx context.Context, l2BlockNumber uint64, l1Head *big.Int, rootClaim common.Hash) *CannonGameHelper {
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel() defer cancel()
...@@ -171,6 +225,12 @@ func (h *FactoryHelper) StartChallenger(ctx context.Context, l1Endpoint string, ...@@ -171,6 +225,12 @@ func (h *FactoryHelper) StartChallenger(ctx context.Context, l1Endpoint string,
return c return c
} }
func (h *FactoryHelper) prepareCannonGame(ctx context.Context) (uint64, *big.Int) {
l2BlockNumber := h.waitForProposals(ctx)
l1Head := h.checkpointL1Block(ctx)
return l2BlockNumber, l1Head
}
// waitForProposals waits until there are at least two proposals in the output oracle // waitForProposals waits until there are at least two proposals in the output oracle
// This is the minimum required for creating a game. // This is the minimum required for creating a game.
// Returns the l2 block number of the latest available proposal // Returns the l2 block number of the latest available proposal
......
...@@ -38,7 +38,8 @@ func ForReceipt(ctx context.Context, client *ethclient.Client, hash common.Hash, ...@@ -38,7 +38,8 @@ func ForReceipt(ctx context.Context, client *ethclient.Client, hash common.Hash,
return nil, fmt.Errorf("failed to get receipt: %w", err) return nil, fmt.Errorf("failed to get receipt: %w", err)
} }
if receipt.Status != status { if receipt.Status != status {
return receipt, addDebugTrace(ctx, client, hash, fmt.Errorf("expected status %d, but got %d", status, receipt.Status)) printDebugTrace(ctx, client, hash)
return receipt, fmt.Errorf("expected status %d, but got %d", status, receipt.Status)
} }
return receipt, nil return receipt, nil
} }
...@@ -52,15 +53,16 @@ func (s *jsonRawString) UnmarshalJSON(input []byte) error { ...@@ -52,15 +53,16 @@ func (s *jsonRawString) UnmarshalJSON(input []byte) error {
return nil return nil
} }
// addDebugTrace adds debug_traceTransaction output to the original error to make debugging // printDebugTrace logs debug_traceTransaction output to aid in debugging unexpected receipt statuses
func addDebugTrace(ctx context.Context, client *ethclient.Client, txHash common.Hash, origErr error) error { func printDebugTrace(ctx context.Context, client *ethclient.Client, txHash common.Hash) {
var result jsonRawString var trace jsonRawString
options := map[string]string{} options := map[string]string{}
err := client.Client().CallContext(ctx, &result, "debug_traceTransaction", hexutil.Bytes(txHash.Bytes()), options) err := client.Client().CallContext(ctx, &trace, "debug_traceTransaction", hexutil.Bytes(txHash.Bytes()), options)
if err != nil { if err != nil {
return errors.Join(origErr, fmt.Errorf("tx trace unavailable: %w", err)) fmt.Printf("TxTrace unavailable: %v\n", err)
return
} }
return fmt.Errorf("%w\nTxTrace: %v", origErr, result) fmt.Printf("TxTrace: %v\n", trace)
} }
func ForBlock(ctx context.Context, client *ethclient.Client, n uint64) error { func ForBlock(ctx context.Context, client *ethclient.Client, n uint64) error {
......
...@@ -290,6 +290,54 @@ func TestCannonDefendStep(t *testing.T) { ...@@ -290,6 +290,54 @@ func TestCannonDefendStep(t *testing.T) {
game.LogGameData(ctx) game.LogGameData(ctx)
} }
func TestCannonChallengeWithCorrectRoot(t *testing.T) {
t.Skip("Not currently handling this case as the correct approach will change when output root bisection is added")
InitParallel(t)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
l1Endpoint := sys.NodeEndpoint("l1")
l2Endpoint := sys.NodeEndpoint("sequencer")
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys.cfg.L1Deployments, l1Client)
game, correctTrace := disputeGameFactory.StartCannonGameWithCorrectRoot(ctx, sys.RollupConfig, sys.L2GenesisCfg, l1Endpoint, l2Endpoint, func(c *config.Config) {
c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Mallory)
})
require.NotNil(t, game)
game.LogGameData(ctx)
game.StartChallenger(ctx, sys.RollupConfig, sys.L2GenesisCfg, l1Endpoint, l2Endpoint, "Challenger", func(c *config.Config) {
c.AgreeWithProposedOutput = true // Agree with the proposed output, so disagree with the root claim
c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Alice)
})
maxDepth := game.MaxDepth(ctx)
for claimCount := int64(1); claimCount < maxDepth; {
game.LogGameData(ctx)
claimCount++
// Wait for the challenger to counter
game.WaitForClaimCount(ctx, claimCount)
// Defend everything because we have the same trace as the honest proposer
correctTrace.Defend(ctx, claimCount-1)
claimCount++
game.LogGameData(ctx)
game.WaitForClaimCount(ctx, claimCount)
}
game.LogGameData(ctx)
// Wait for the challenger to call step and counter our invalid claim
game.WaitForClaimAtMaxDepth(ctx, true)
sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx))
require.NoError(t, wait.ForNextBlock(ctx, l1Client))
game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins)
game.LogGameData(ctx)
}
func startFaultDisputeSystem(t *testing.T) (*System, *ethclient.Client) { func startFaultDisputeSystem(t *testing.T) (*System, *ethclient.Client) {
cfg := DefaultSystemConfig(t) cfg := DefaultSystemConfig(t)
delete(cfg.Nodes, "verifier") delete(cfg.Nodes, "verifier")
......
...@@ -23,3 +23,6 @@ all: build ...@@ -23,3 +23,6 @@ all: build
# Build binary # Build binary
build: build:
CGO_ENABLED=0 go build $(LDFLAGS) CGO_ENABLED=0 go build $(LDFLAGS)
lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
...@@ -17,7 +17,7 @@ test: ...@@ -17,7 +17,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
.PHONY: \ .PHONY: \
clean \ clean \
......
...@@ -18,7 +18,7 @@ test: ...@@ -18,7 +18,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
fuzz: fuzz:
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzL1InfoRoundTrip ./rollup/derive go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzL1InfoRoundTrip ./rollup/derive
......
...@@ -31,7 +31,7 @@ test: ...@@ -31,7 +31,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
verify-goerli: op-program-host op-program-client verify-goerli: op-program-host op-program-client
env GO111MODULE=on go run ./verify/cmd/goerli.go $$L1URL $$L2URL env GO111MODULE=on go run ./verify/cmd/goerli.go $$L1URL $$L2URL
......
...@@ -17,7 +17,7 @@ test: ...@@ -17,7 +17,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
.PHONY: \ .PHONY: \
clean \ clean \
......
...@@ -2,7 +2,7 @@ test: ...@@ -2,7 +2,7 @@ test:
go test -v ./... go test -v ./...
lint: lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" ./... golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
generate-mocks: generate-mocks:
go generate ./... go generate ./...
......
GITCOMMIT := $(shell git rev-parse HEAD)
GITDATE := $(shell git show -s --format='%ct')
VERSION := v0.0.0
LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT)
LDFLAGSSTRING +=-X main.GitDate=$(GITDATE)
LDFLAGSSTRING +=-X main.Version=$(VERSION)
LDFLAGS := -ldflags "$(LDFLAGSSTRING)"
op-wheel:
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/op-wheel ./cmd
lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
...@@ -423,10 +423,10 @@ OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11121) ...@@ -423,10 +423,10 @@ OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11121)
OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140547) OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140547)
OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9005) OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9005)
OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163441) OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163441)
OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 7646) OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 9760)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9401) OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9471)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516769032) OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516769105)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1293594) OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1295838)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 11178) OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 11178)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 16111) OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 16111)
OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 26781) OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 26781)
......
...@@ -259,8 +259,11 @@ ...@@ -259,8 +259,11 @@
➡ src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory ➡ src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory
======================= =======================
| Name | Type | Slot | Offset | Bytes | Contract | | Name | Type | Slot | Offset | Bytes | Contract |
|------|------|------|--------|-------|----------| |---------------|---------|------|--------|-------|-----------------------------------------------------------------------------|
| _initialized | uint8 | 0 | 0 | 1 | src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory |
| _initializing | bool | 0 | 1 | 1 | src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory |
| bridge | address | 0 | 2 | 20 | src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory |
======================= =======================
➡ src/dispute/DisputeGameFactory.sol:DisputeGameFactory ➡ src/dispute/DisputeGameFactory.sol:DisputeGameFactory
......
...@@ -345,10 +345,10 @@ contract Deploy is Deployer { ...@@ -345,10 +345,10 @@ contract Deploy is Deployer {
/// @notice Deploy the OptimismMintableERC20Factory /// @notice Deploy the OptimismMintableERC20Factory
function deployOptimismMintableERC20Factory() public broadcast returns (address addr_) { function deployOptimismMintableERC20Factory() public broadcast returns (address addr_) {
address l1StandardBridgeProxy = mustGetAddress("L1StandardBridgeProxy"); OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory();
OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(l1StandardBridgeProxy);
require(factory.BRIDGE() == l1StandardBridgeProxy); require(factory.BRIDGE() == address(0));
require(factory.bridge() == address(0));
save("OptimismMintableERC20Factory", address(factory)); save("OptimismMintableERC20Factory", address(factory));
console.log("OptimismMintableERC20Factory deployed at %s", address(factory)); console.log("OptimismMintableERC20Factory deployed at %s", address(factory));
...@@ -613,9 +613,10 @@ contract Deploy is Deployer { ...@@ -613,9 +613,10 @@ contract Deploy is Deployer {
address optimismMintableERC20Factory = mustGetAddress("OptimismMintableERC20Factory"); address optimismMintableERC20Factory = mustGetAddress("OptimismMintableERC20Factory");
address l1StandardBridgeProxy = mustGetAddress("L1StandardBridgeProxy"); address l1StandardBridgeProxy = mustGetAddress("L1StandardBridgeProxy");
proxyAdmin.upgrade({ proxyAdmin.upgradeAndCall({
_proxy: payable(optimismMintableERC20FactoryProxy), _proxy: payable(optimismMintableERC20FactoryProxy),
_implementation: optimismMintableERC20Factory _implementation: optimismMintableERC20Factory,
_data: abi.encodeCall(OptimismMintableERC20Factory.initialize, (l1StandardBridgeProxy))
}); });
OptimismMintableERC20Factory factory = OptimismMintableERC20Factory(optimismMintableERC20FactoryProxy); OptimismMintableERC20Factory factory = OptimismMintableERC20Factory(optimismMintableERC20FactoryProxy);
...@@ -623,6 +624,7 @@ contract Deploy is Deployer { ...@@ -623,6 +624,7 @@ contract Deploy is Deployer {
console.log("OptimismMintableERC20Factory version: %s", version); console.log("OptimismMintableERC20Factory version: %s", version);
require(factory.BRIDGE() == l1StandardBridgeProxy); require(factory.BRIDGE() == l1StandardBridgeProxy);
require(factory.bridge() == l1StandardBridgeProxy);
} }
/// @notice initializeL1CrossDomainMessenger /// @notice initializeL1CrossDomainMessenger
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
"src/periphery/op-nft/OptimistAllowlist.sol": "0x53e9a9dfecbae036fd468e8f34c80c7d9c35bd8908c8a6483db44dbc5128ad69", "src/periphery/op-nft/OptimistAllowlist.sol": "0x53e9a9dfecbae036fd468e8f34c80c7d9c35bd8908c8a6483db44dbc5128ad69",
"src/periphery/op-nft/OptimistInviter.sol": "0xfdd5b9d45205ef9372ba37f7a6394724695e676d27a47cb154ee6e4148490013", "src/periphery/op-nft/OptimistInviter.sol": "0xfdd5b9d45205ef9372ba37f7a6394724695e676d27a47cb154ee6e4148490013",
"src/universal/OptimismMintableERC20.sol": "0xa0b4f168802d0f9eca9ddc54347ca66c34ad7aa0fd84b01e0d7e99a9f86f46d6", "src/universal/OptimismMintableERC20.sol": "0xa0b4f168802d0f9eca9ddc54347ca66c34ad7aa0fd84b01e0d7e99a9f86f46d6",
"src/universal/OptimismMintableERC20Factory.sol": "0x8afb6b634f40e8ac8c60ec7e2ca3bcd610b020d09b3cae70a3d4995722cab3ce", "src/universal/OptimismMintableERC20Factory.sol": "0xf4beb7fed4defc3e70b2298831bf0024cceaa8f1cf55fd98c00f5998b8ab5589",
"src/universal/OptimismMintableERC721.sol": "0x49dc863caf3e002bf0c90b3af3873990fb282771f4c63735fd61a885b7873983", "src/universal/OptimismMintableERC721.sol": "0x49dc863caf3e002bf0c90b3af3873990fb282771f4c63735fd61a885b7873983",
"src/universal/OptimismMintableERC721Factory.sol": "0x502438b009bfaf0ab187914662468261f10446fd85d44a79b29cdaef7b4982ba" "src/universal/OptimismMintableERC721Factory.sol": "0x502438b009bfaf0ab187914662468261f10446fd85d44a79b29cdaef7b4982ba"
} }
\ No newline at end of file
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol"; import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { Semver } from "./Semver.sol"; import { Semver } from "./Semver.sol";
/// @custom:proxied /// @custom:proxied
...@@ -11,9 +12,10 @@ import { Semver } from "./Semver.sol"; ...@@ -11,9 +12,10 @@ import { Semver } from "./Semver.sol";
/// contracts on the network it's deployed to. Simplifies the deployment process for users /// contracts on the network it's deployed to. Simplifies the deployment process for users
/// who may be less familiar with deploying smart contracts. Designed to be backwards /// who may be less familiar with deploying smart contracts. Designed to be backwards
/// compatible with the older StandardL2ERC20Factory contract. /// compatible with the older StandardL2ERC20Factory contract.
contract OptimismMintableERC20Factory is Semver { contract OptimismMintableERC20Factory is Semver, Initializable {
/// @notice Address of the StandardBridge on this chain. /// @notice Address of the StandardBridge on this chain.
address public immutable BRIDGE; /// @custom:network-specific
address public bridge;
/// @custom:legacy /// @custom:legacy
/// @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer /// @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer
...@@ -28,13 +30,25 @@ contract OptimismMintableERC20Factory is Semver { ...@@ -28,13 +30,25 @@ contract OptimismMintableERC20Factory is Semver {
/// @param deployer Address of the account that deployed the token. /// @param deployer Address of the account that deployed the token.
event OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer); event OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer);
/// @custom:semver 1.2.0 /// @custom:semver 1.3.0
/// @notice The semver MUST be bumped any time that there is a change in /// @notice The semver MUST be bumped any time that there is a change in
/// the OptimismMintableERC20 token contract since this contract /// the OptimismMintableERC20 token contract since this contract
/// is responsible for deploying OptimismMintableERC20 contracts. /// is responsible for deploying OptimismMintableERC20 contracts.
constructor() Semver(1, 3, 0) {
initialize({ _bridge: address(0) });
}
/// @notice Initializer.
/// @param _bridge Address of the StandardBridge on this chain. /// @param _bridge Address of the StandardBridge on this chain.
constructor(address _bridge) Semver(1, 2, 0) { function initialize(address _bridge) public reinitializer(2) {
BRIDGE = _bridge; bridge = _bridge;
}
/// @notice Returns the address of the StandardBridge on this chain.
/// This is a legacy getter, use `bridge` instead.
/// @custom:legacy
function BRIDGE() external view returns (address) {
return bridge;
} }
/// @custom:legacy /// @custom:legacy
...@@ -71,7 +85,7 @@ contract OptimismMintableERC20Factory is Semver { ...@@ -71,7 +85,7 @@ contract OptimismMintableERC20Factory is Semver {
require(_remoteToken != address(0), "OptimismMintableERC20Factory: must provide remote token address"); require(_remoteToken != address(0), "OptimismMintableERC20Factory: must provide remote token address");
bytes32 salt = keccak256(abi.encode(_remoteToken, _name, _symbol)); bytes32 salt = keccak256(abi.encode(_remoteToken, _name, _symbol));
address localToken = address(new OptimismMintableERC20{salt: salt}(BRIDGE, _remoteToken, _name, _symbol)); address localToken = address(new OptimismMintableERC20{salt: salt}(bridge, _remoteToken, _name, _symbol));
// Emit the old event too for legacy support. // Emit the old event too for legacy support.
emit StandardL2TokenCreated(_remoteToken, localToken); emit StandardL2TokenCreated(_remoteToken, localToken);
......
...@@ -377,17 +377,17 @@ contract Bridge_Initializer is Messenger_Initializer { ...@@ -377,17 +377,17 @@ contract Bridge_Initializer is Messenger_Initializer {
vm.label(address(L1Bridge_Impl), "L1StandardBridge_Impl"); vm.label(address(L1Bridge_Impl), "L1StandardBridge_Impl");
// Deploy the L2StandardBridge, move it to the correct predeploy // Deploy the L2StandardBridge, move it to the correct predeploy
// address and then initialize it // address and then initialize it. It is safe to call initialize directly
// on the proxy because the bytecode was set in state with `etch`.
vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(new L2StandardBridge(StandardBridge(payable(proxy)))).code); vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(new L2StandardBridge(StandardBridge(payable(proxy)))).code);
L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)); L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));
L2Bridge.initialize(); L2Bridge.initialize();
// Set up the L2 mintable token factory // Set up the L2 mintable token factory
OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory( OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory();
Predeploys.L2_STANDARD_BRIDGE
);
vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code); vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);
L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY); L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);
L2TokenFactory.initialize(Predeploys.L2_STANDARD_BRIDGE);
vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code); vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);
...@@ -419,7 +419,15 @@ contract Bridge_Initializer is Messenger_Initializer { ...@@ -419,7 +419,15 @@ contract Bridge_Initializer is Messenger_Initializer {
); );
NativeL2Token = new ERC20("Native L2 Token", "L2T"); NativeL2Token = new ERC20("Native L2 Token", "L2T");
L1TokenFactory = new OptimismMintableERC20Factory(address(L1Bridge)); Proxy factoryProxy = new Proxy(multisig);
OptimismMintableERC20Factory L1TokenFactoryImpl = new OptimismMintableERC20Factory();
vm.prank(multisig);
factoryProxy.upgradeToAndCall(
address(L1TokenFactoryImpl), abi.encodeCall(OptimismMintableERC20Factory.initialize, address(L1Bridge))
);
L1TokenFactory = OptimismMintableERC20Factory(address(factoryProxy));
RemoteL1Token = OptimismMintableERC20( RemoteL1Token = OptimismMintableERC20(
L1TokenFactory.createStandardL2Token( L1TokenFactory.createStandardL2Token(
......
# @eth-optimism/web3.js-plugin
## 0.1.1
### Patch Changes
- [#6848](https://github.com/ethereum-optimism/optimism/pull/6848) [`b08fccd9e`](https://github.com/ethereum-optimism/optimism/commit/b08fccd9e21c499f9fefd4d58fb8a36bfa0d800a) Thanks [@spacesailor24](https://github.com/spacesailor24)! - Correct use of web3js-plugin to web3.js-plugin in README. Rename OptimismFeeEstimationPlugin export to OptimismPlugin
# @eth-optimism/web3js-plugin # @eth-optimism/web3.js-plugin
This web3.js plugin adds utility functions for estimating L1 and L2 gas for OP chains by wrapping the [GasPriceOracle](../contracts-bedrock/contracts/l2/GasPriceOracle.sol) contract This web3.js plugin adds utility functions for estimating L1 and L2 gas for OP chains by wrapping the [GasPriceOracle](../contracts-bedrock/contracts/l2/GasPriceOracle.sol) contract
...@@ -13,22 +13,22 @@ This plugin is intended to be [registered](https://docs.web3js.org/guides/web3_p ...@@ -13,22 +13,22 @@ This plugin is intended to be [registered](https://docs.web3js.org/guides/web3_p
### Installing the Plugin ### Installing the Plugin
```bash ```bash
pnpm install @eth-optimism/web3js-plugin pnpm install @eth-optimism/web3.js-plugin
``` ```
```bash ```bash
npm install @eth-optimism/web3js-plugin npm install @eth-optimism/web3.js-plugin
``` ```
```bash ```bash
yarn add @eth-optimism/web3js-plugin yarn add @eth-optimism/web3.js-plugin
``` ```
### Registering the Plugin ### Registering the Plugin
```typescript ```typescript
import Web3 from 'web3' import Web3 from 'web3'
import OptimismFeeEstimationPlugin from '@eth-optimism/web3js-plugin' import OptimismFeeEstimationPlugin from '@eth-optimism/web3.js-plugin'
const web3 = new Web3('http://yourProvider.com') const web3 = new Web3('http://yourProvider.com')
web3.registerPlugin(new OptimismFeeEstimationPlugin()) web3.registerPlugin(new OptimismFeeEstimationPlugin())
...@@ -65,8 +65,8 @@ async estimateFees(transaction: Transaction, returnFormat?: ReturnFormat) ...@@ -65,8 +65,8 @@ async estimateFees(transaction: Transaction, returnFormat?: ReturnFormat)
#### Parameters #### Parameters
- `transaction: Transaction` - An unsigned web3.js [transaction](https://docs.web3js.org/api/web3-types/interface/Transaction) object - `transaction: Transaction` - An unsigned web3.js [transaction](https://docs.web3js.org/api/web3-types/interface/Transaction) object
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][1] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -168,8 +168,8 @@ async getL1Fee(transaction: Transaction, returnFormat?: ReturnFormat) ...@@ -168,8 +168,8 @@ async getL1Fee(transaction: Transaction, returnFormat?: ReturnFormat)
#### Parameters #### Parameters
- `transaction: Transaction` - An unsigned web3.js [transaction](https://docs.web3js.org/api/web3-types/interface/Transaction) object - `transaction: Transaction` - An unsigned web3.js [transaction](https://docs.web3js.org/api/web3-types/interface/Transaction) object
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][1] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -235,8 +235,8 @@ async getL2Fee(transaction: Transaction, returnFormat?: ReturnFormat) ...@@ -235,8 +235,8 @@ async getL2Fee(transaction: Transaction, returnFormat?: ReturnFormat)
- A web3.js [Numbers](https://docs.web3js.org/api/web3-types#Numbers) - A web3.js [Numbers](https://docs.web3js.org/api/web3-types#Numbers)
- A web3.js [BlockTags](https://docs.web3js.org/api/web3-types/enum/BlockTags) - A web3.js [BlockTags](https://docs.web3js.org/api/web3-types/enum/BlockTags)
- If not provided, `BlockTags.LATEST` is used - If not provided, `BlockTags.LATEST` is used
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][1] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -301,8 +301,8 @@ async getBaseFee(returnFormat?: ReturnFormat) ...@@ -301,8 +301,8 @@ async getBaseFee(returnFormat?: ReturnFormat)
#### Parameters #### Parameters
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][1] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -337,8 +337,8 @@ async getDecimals(returnFormat?: ReturnFormat) ...@@ -337,8 +337,8 @@ async getDecimals(returnFormat?: ReturnFormat)
#### Parameters #### Parameters
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][3] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -373,8 +373,8 @@ async getGasPrice(returnFormat?: ReturnFormat) ...@@ -373,8 +373,8 @@ async getGasPrice(returnFormat?: ReturnFormat)
#### Parameters #### Parameters
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][3] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -410,8 +410,8 @@ async getL1GasUsed(transaction: Transaction, returnFormat?: ReturnFormat) ...@@ -410,8 +410,8 @@ async getL1GasUsed(transaction: Transaction, returnFormat?: ReturnFormat)
#### Parameters #### Parameters
- `transaction: Transaction` - An unsigned web3.js [transaction](https://docs.web3js.org/api/web3-types/interface/Transaction) object - `transaction: Transaction` - An unsigned web3.js [transaction](https://docs.web3js.org/api/web3-types/interface/Transaction) object
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][3] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -470,8 +470,8 @@ async getL1BaseFee(returnFormat?: ReturnFormat) ...@@ -470,8 +470,8 @@ async getL1BaseFee(returnFormat?: ReturnFormat)
#### Parameters #### Parameters
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][3] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -506,8 +506,8 @@ async getOverhead(returnFormat?: ReturnFormat) ...@@ -506,8 +506,8 @@ async getOverhead(returnFormat?: ReturnFormat)
#### Parameters #### Parameters
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][3] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -542,8 +542,8 @@ async getScalar(returnFormat?: ReturnFormat) ...@@ -542,8 +542,8 @@ async getScalar(returnFormat?: ReturnFormat)
#### Parameters #### Parameters
- `returnFormat?: ReturnFormat` - A web3.js [DataFormat](https://docs.web3js.org/api/web3-types#DataFormat) object that specifies how to format number and bytes values - `returnFormat?: ReturnFormat` - A web3.js [DataFormat][1] object that specifies how to format number and bytes values
- If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT](https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT) is used which will format numbers to `BigInt`s - If `returnFormat` is not provided, [DEFAULT_RETURN_FORMAT][2] is used which will format numbers to `BigInt`s
#### Returns #### Returns
...@@ -592,3 +592,7 @@ console.log(version) // 1.0.0 ...@@ -592,3 +592,7 @@ console.log(version) // 1.0.0
- As of version `4.0.3` of web3.js, both `input` and `data` parameters are automatically added to a transaction objects causing the gas estimations to be inflated. This was corrected in [this](https://github.com/web3/web3.js/pull/6294) PR, but has yet to be released - As of version `4.0.3` of web3.js, both `input` and `data` parameters are automatically added to a transaction objects causing the gas estimations to be inflated. This was corrected in [this](https://github.com/web3/web3.js/pull/6294) PR, but has yet to be released
- For the plugin function `getL2Fee`, you should be able to get the fee estimates using the state of the blockchain at a specified block, however, this doesn't seem to be working with web3.js and requires further investigation - For the plugin function `getL2Fee`, you should be able to get the fee estimates using the state of the blockchain at a specified block, however, this doesn't seem to be working with web3.js and requires further investigation
[1]: https://docs.web3js.org/api/web3-types#DataFormat
[2]: https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT
[3]: https://docs.web3js.org/api/web3-types#DataFormat
\ No newline at end of file
{ {
"name": "@eth-optimism/web3.js-plugin", "name": "@eth-optimism/web3.js-plugin",
"version": "0.1.0", "version": "0.1.1",
"description": "A Web3.js plugin for doing OP-Chain gas estimation", "description": "A Web3.js plugin for doing OP-Chain gas estimation",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
......
...@@ -8,7 +8,7 @@ import { ...@@ -8,7 +8,7 @@ import {
optimistAddress, optimistAddress,
} from '@eth-optimism/contracts-ts' } from '@eth-optimism/contracts-ts'
import { OptimismFeeEstimationPlugin } from './plugin' import { OptimismPlugin } from './plugin'
const defaultProvider = 'https://mainnet.optimism.io' const defaultProvider = 'https://mainnet.optimism.io'
const provider = z const provider = z
...@@ -21,17 +21,17 @@ if (provider === defaultProvider) ...@@ -21,17 +21,17 @@ if (provider === defaultProvider)
'Warning: Using default public provider, this could cause tests to fail due to rate limits. Set the VITE_L2_RPC_URL env to override default provider' 'Warning: Using default public provider, this could cause tests to fail due to rate limits. Set the VITE_L2_RPC_URL env to override default provider'
) )
describe('OptimismFeeEstimationPlugin', () => { describe('OptimismPlugin', () => {
let web3: Web3 let web3: Web3
beforeAll(() => { beforeAll(() => {
web3 = new Web3(provider) web3 = new Web3(provider)
web3.registerPlugin(new OptimismFeeEstimationPlugin()) web3.registerPlugin(new OptimismPlugin())
}) })
test('should be registered under .op namespace', () => test('should be registered under .op namespace', () =>
expect(web3.op).toMatchInlineSnapshot(` expect(web3.op).toMatchInlineSnapshot(`
OptimismFeeEstimationPlugin { OptimismPlugin {
"_accountProvider": { "_accountProvider": {
"create": [Function], "create": [Function],
"decrypt": [Function], "decrypt": [Function],
...@@ -62,7 +62,7 @@ describe('OptimismFeeEstimationPlugin', () => { ...@@ -62,7 +62,7 @@ describe('OptimismFeeEstimationPlugin', () => {
Symbol(kCapture): false, Symbol(kCapture): false,
}, },
"_provider": HttpProvider { "_provider": HttpProvider {
"clientUrl": "https://mainnet.optimism.io", "clientUrl": "https://opt-mainnet.g.alchemy.com/v2/OVlbpe9COlhG-ijOXGvL_phb5ns6p9-w",
"httpProviderOptions": undefined, "httpProviderOptions": undefined,
}, },
"useRpcCallSpecification": undefined, "useRpcCallSpecification": undefined,
...@@ -88,7 +88,7 @@ describe('OptimismFeeEstimationPlugin', () => { ...@@ -88,7 +88,7 @@ describe('OptimismFeeEstimationPlugin', () => {
Symbol(kCapture): false, Symbol(kCapture): false,
}, },
"_provider": HttpProvider { "_provider": HttpProvider {
"clientUrl": "https://mainnet.optimism.io", "clientUrl": "https://opt-mainnet.g.alchemy.com/v2/OVlbpe9COlhG-ijOXGvL_phb5ns6p9-w",
"httpProviderOptions": undefined, "httpProviderOptions": undefined,
}, },
"useRpcCallSpecification": undefined, "useRpcCallSpecification": undefined,
......
...@@ -17,7 +17,7 @@ import { ...@@ -17,7 +17,7 @@ import {
} from '@eth-optimism/contracts-ts' } from '@eth-optimism/contracts-ts'
import { RLP } from '@ethereumjs/rlp' import { RLP } from '@ethereumjs/rlp'
export class OptimismFeeEstimationPlugin extends Web3PluginBase { export class OptimismPlugin extends Web3PluginBase {
public pluginNamespace = 'op' public pluginNamespace = 'op'
private _gasPriceOracleContract: private _gasPriceOracleContract:
...@@ -323,6 +323,6 @@ export class OptimismFeeEstimationPlugin extends Web3PluginBase { ...@@ -323,6 +323,6 @@ export class OptimismFeeEstimationPlugin extends Web3PluginBase {
// Module Augmentation to add op namespace to root {web3} instance // Module Augmentation to add op namespace to root {web3} instance
declare module 'web3' { declare module 'web3' {
interface Web3Context { interface Web3Context {
op: OptimismFeeEstimationPlugin op: OptimismPlugin
} }
} }
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment