Commit 069f9c22 authored by Mark Tyneway's avatar Mark Tyneway Committed by Andreas Bigger

op-e2e: major refactor

Refactor op-e2e to use the same deploy script that is used in
production. There is only 1 way to deploy contracts now and
it goes through foundry. This removes the need to maintain
multiple sets of contracts deployments/devnets. It does
add a new tooling dep to the monorepo which is `geth`.
A top level `make` command is provided as well as some
docs in the `op-e2e` package on its usage.

The `devnetL1.json` deployconfig is the source of truth
for deploy configs in `op-e2e` now. In the long term,
we should delineate which config values are safe to alter
in memory and which are not. Some things are still coupled
together in weird ways, but I tried to add assertions where
I could to ensure that future people will get better error
messages.

To install geth, run the command:

`` `
make install-geth
```

To create the genesis state, run the command:

```
make devnet-allocs
```

This will run the forge deploy script against an instance of
`geth --dev` and then call `debug_dumpBlock` which will dump
the state into a format that we can inject at runtime into
the genesis of both `op-e2e` as well as the L1 of the docker
compose setup.

I tried to use `anvil` instead of `geth` but it does not
support this endpoint. It supports a different endpoint
that uses a compressed binary serialization of state,
it is easier to work with the JSON.
parent 3e60c7e1
This diff is collapsed.
...@@ -68,6 +68,7 @@ You'll need the following: ...@@ -68,6 +68,7 @@ You'll need the following:
* [Docker Compose](https://docs.docker.com/compose/install/) * [Docker Compose](https://docs.docker.com/compose/install/)
* [Go](https://go.dev/dl/) * [Go](https://go.dev/dl/)
* [Foundry](https://getfoundry.sh) * [Foundry](https://getfoundry.sh)
* [go-ethereum](https://github.com/ethereum/go-ethereum)
### Setup ### Setup
...@@ -80,7 +81,7 @@ cd optimism ...@@ -80,7 +81,7 @@ cd optimism
### Install the Correct Version of NodeJS ### Install the Correct Version of NodeJS
Install node v16.16.0 with [nvm](https://github.com/nvm-sh/nvm) Install the correct node version with [nvm](https://github.com/nvm-sh/nvm)
```bash ```bash
nvm use nvm use
...@@ -112,10 +113,11 @@ Use the above commands to recompile the packages. ...@@ -112,10 +113,11 @@ Use the above commands to recompile the packages.
### Building the rest of the system ### Building the rest of the system
If you want to run an Optimism node OR **if you want to run the integration tests**, you'll need to build the rest of the system. If you want to run an Optimism node OR **if you want to run the integration tests**, you'll need to build the rest of the system.
Note that these environment variables significantly speed up build time.
```bash ```bash
cd ops cd ops-bedrock
export COMPOSE_DOCKER_CLI_BUILD=1 # these environment variables significantly speed up build time export COMPOSE_DOCKER_CLI_BUILD=1
export DOCKER_BUILDKIT=1 export DOCKER_BUILDKIT=1
docker-compose build docker-compose build
``` ```
...@@ -124,7 +126,7 @@ Source code changes can have an impact on more than one container. ...@@ -124,7 +126,7 @@ Source code changes can have an impact on more than one container.
**If you're unsure about which containers to rebuild, just rebuild them all**: **If you're unsure about which containers to rebuild, just rebuild them all**:
```bash ```bash
cd ops cd ops-bedrock
docker-compose down docker-compose down
docker-compose build docker-compose build
docker-compose up docker-compose up
......
...@@ -77,8 +77,9 @@ devnet-up: ...@@ -77,8 +77,9 @@ devnet-up:
PYTHONPATH=./bedrock-devnet python3 ./bedrock-devnet/main.py --monorepo-dir=. PYTHONPATH=./bedrock-devnet python3 ./bedrock-devnet/main.py --monorepo-dir=.
.PHONY: devnet-up .PHONY: devnet-up
# alias for devnet-up
devnet-up-deploy: devnet-up-deploy:
PYTHONPATH=./bedrock-devnet python3 ./bedrock-devnet/main.py --monorepo-dir=. --deploy PYTHONPATH=./bedrock-devnet python3 ./bedrock-devnet/main.py --monorepo-dir=.
.PHONY: devnet-up-deploy .PHONY: devnet-up-deploy
devnet-down: devnet-down:
...@@ -93,6 +94,9 @@ devnet-clean: ...@@ -93,6 +94,9 @@ devnet-clean:
docker volume ls --filter name=ops-bedrock --format='{{.Name}}' | xargs -r docker volume rm docker volume ls --filter name=ops-bedrock --format='{{.Name}}' | xargs -r docker volume rm
.PHONY: devnet-clean .PHONY: devnet-clean
devnet-allocs:
PYTHONPATH=./bedrock-devnet python3 ./bedrock-devnet/main.py --monorepo-dir=. --allocs
devnet-logs: devnet-logs:
@(cd ./ops-bedrock && docker-compose logs -f) @(cd ./ops-bedrock && docker-compose logs -f)
.PHONY: devnet-logs .PHONY: devnet-logs
...@@ -133,3 +137,6 @@ bedrock-markdown-links: ...@@ -133,3 +137,6 @@ bedrock-markdown-links:
docker run --init -it -v `pwd`:/input lycheeverse/lychee --verbose --no-progress --exclude-loopback \ docker run --init -it -v `pwd`:/input lycheeverse/lychee --verbose --no-progress --exclude-loopback \
--exclude twitter.com --exclude explorer.optimism.io --exclude linux-mips.org \ --exclude twitter.com --exclude explorer.optimism.io --exclude linux-mips.org \
--exclude-mail /input/README.md "/input/specs/**/*.md" --exclude-mail /input/README.md "/input/specs/**/*.md"
install-geth:
go install github.com/ethereum/go-ethereum/cmd/geth@v1.12.0
This diff is collapsed.
import time
DEV_ACCOUNTS = [
'3c44cdddb6a900fa2b585dd299e03d12fa4293bc',
'70997970c51812dc3a010c7d01b50e0d17dc79c8',
'f39fd6e51aad88f6f4ce6ab8827279cfffb92266'
]
GENESIS_TMPL = {
'config': {
'chainId': 900,
"homesteadBlock": 0,
"eip150Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"muirGlacierBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"arrowGlacierBlock": 0,
"grayGlacierBlock": 0,
"shanghaiBlock": None,
"cancunBlock": None,
'clique': {
'period': 3,
'epoch': 30000
}
},
'nonce': '0x0',
'timestamp': '{:#x}'.format(int(time.time())),
'extraData': '0x0000000000000000000000000000000000000000000000000000000000000000ca062b0fd91172d89bcd4bb084ac4e21972cc4670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
'gasLimit': '0xE4E1C0',
'difficulty': '0x1',
'mixHash': '0x0000000000000000000000000000000000000000000000000000000000000000',
'coinbase': '0x0000000000000000000000000000000000000000',
'alloc': {
'{:x}'.format(i).ljust(40, '0'): {
'balance': '0x1'
} for i in range(0, 255)
},
'number': '0x0',
'gasUsed': '0x0',
'parentHash': '0x0000000000000000000000000000000000000000000000000000000000000000',
'baseFeePergas': '0x3B9ACA00'
}
GENESIS_TMPL['alloc'].update({
d: {
'balance': '0x200000000000000000000000000000000000000000000000000000000000000'
} for d in DEV_ACCOUNTS
})
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/ethereum-optimism/optimism/indexer/processor"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
...@@ -21,7 +22,8 @@ type Config struct { ...@@ -21,7 +22,8 @@ type Config struct {
// 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 Preset int
L1Contracts processor.L1Contracts
} }
// RPCsConfig configures the RPC urls // RPCsConfig configures the RPC urls
......
...@@ -7,7 +7,6 @@ import ( ...@@ -7,7 +7,6 @@ import (
"time" "time"
"github.com/ethereum-optimism/optimism/indexer/node" "github.com/ethereum-optimism/optimism/indexer/node"
"github.com/ethereum-optimism/optimism/indexer/processor"
"github.com/ethereum-optimism/optimism/op-service/client/utils" "github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
...@@ -15,6 +14,7 @@ import ( ...@@ -15,6 +14,7 @@ import (
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -25,7 +25,7 @@ func TestE2EBlockHeaders(t *testing.T) { ...@@ -25,7 +25,7 @@ func TestE2EBlockHeaders(t *testing.T) {
l1Client := testSuite.OpSys.Clients["l1"] l1Client := testSuite.OpSys.Clients["l1"]
l2Client := testSuite.OpSys.Clients["sequencer"] l2Client := testSuite.OpSys.Clients["sequencer"]
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client) l2OutputOracle, err := bindings.NewL2OutputOracleCaller(testSuite.OpCfg.L1Deployments.L2OutputOracleProxy, l1Client)
require.NoError(t, err) require.NoError(t, err)
// a minute for total setup to finish // a minute for total setup to finish
...@@ -111,7 +111,10 @@ func TestE2EBlockHeaders(t *testing.T) { ...@@ -111,7 +111,10 @@ func TestE2EBlockHeaders(t *testing.T) {
testCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) testCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
devContracts := processor.DevL1Contracts().ToSlice() devContracts := make([]common.Address, 0)
testSuite.OpCfg.L1Deployments.ForEach(func(name string, address common.Address) {
devContracts = append(devContracts, address)
})
logFilter := ethereum.FilterQuery{FromBlock: big.NewInt(0), ToBlock: big.NewInt(int64(l1Height)), Addresses: devContracts} logFilter := ethereum.FilterQuery{FromBlock: big.NewInt(0), ToBlock: big.NewInt(int64(l1Height)), Addresses: devContracts}
logs, err := l1Client.FilterLogs(testCtx, logFilter) // []types.Log logs, err := l1Client.FilterLogs(testCtx, logFilter) // []types.Log
require.NoError(t, err) require.NoError(t, err)
......
...@@ -28,7 +28,7 @@ func TestE2EBridge(t *testing.T) { ...@@ -28,7 +28,7 @@ func TestE2EBridge(t *testing.T) {
l1Client := testSuite.OpSys.Clients["l1"] l1Client := testSuite.OpSys.Clients["l1"]
l2Client := testSuite.OpSys.Clients["sequencer"] l2Client := testSuite.OpSys.Clients["sequencer"]
l1StandardBridge, err := bindings.NewL1StandardBridge(predeploys.DevL1StandardBridgeAddr, l1Client) l1StandardBridge, err := bindings.NewL1StandardBridge(testSuite.OpCfg.L1Deployments.L1StandardBridgeProxy, l1Client)
require.NoError(t, err) require.NoError(t, err)
l2StandardBridge, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, l2Client) l2StandardBridge, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, l2Client)
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"github.com/ethereum-optimism/optimism/indexer" "github.com/ethereum-optimism/optimism/indexer"
"github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/config"
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/processor"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e" op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
...@@ -44,10 +45,17 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { ...@@ -44,10 +45,17 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
// Rollup System Configuration and Start // Rollup System Configuration and Start
opCfg := op_e2e.DefaultSystemConfig(t) opCfg := op_e2e.DefaultSystemConfig(t)
opCfg.DeployConfig.FinalizationPeriodSeconds = 2
opSys, err := opCfg.Start() opSys, err := opCfg.Start()
require.NoError(t, err) require.NoError(t, err)
l1Contracts := processor.L1Contracts{
OptimismPortal: opCfg.L1Deployments.OptimismPortalProxy,
L2OutputOracle: opCfg.L1Deployments.L2OutputOracleProxy,
L1CrossDomainMessenger: opCfg.L1Deployments.L1CrossDomainMessengerProxy,
L1StandardBridge: opCfg.L1Deployments.L1StandardBridgeProxy,
L1ERC721Bridge: opCfg.L1Deployments.L1ERC721BridgeProxy,
}
// Indexer Configuration and Start // Indexer Configuration and Start
indexerCfg := config.Config{ indexerCfg := config.Config{
DB: config.DBConfig{ DB: config.DBConfig{
...@@ -61,6 +69,9 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { ...@@ -61,6 +69,9 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
L2RPC: opSys.Nodes["sequencer"].HTTPEndpoint(), L2RPC: opSys.Nodes["sequencer"].HTTPEndpoint(),
}, },
Logger: logger, Logger: logger,
Chain: config.ChainConfig{
L1Contracts: l1Contracts,
},
} }
db, err := database.NewDB(fmt.Sprintf("postgres://%s@localhost:5432/%s?sslmode=disable", dbUser, dbName)) db, err := database.NewDB(fmt.Sprintf("postgres://%s@localhost:5432/%s?sslmode=disable", dbUser, dbName))
......
...@@ -38,8 +38,7 @@ func NewIndexer(cfg config.Config) (*Indexer, error) { ...@@ -38,8 +38,7 @@ func NewIndexer(cfg config.Config) (*Indexer, error) {
return nil, err return nil, err
} }
// L1 Processor (hardhat devnet contracts). Make this configurable l1Contracts := cfg.Chain.L1Contracts
l1Contracts := processor.DevL1Contracts()
l1EthClient, err := node.DialEthClient(cfg.RPCs.L1RPC) l1EthClient, err := node.DialEthClient(cfg.RPCs.L1RPC)
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -46,7 +46,7 @@ func TestBedrockIndexer(t *testing.T) { ...@@ -46,7 +46,7 @@ func TestBedrockIndexer(t *testing.T) {
// wait a couple of blocks // wait a couple of blocks
require.NoError(t, utils.WaitBlock(e2eutils.TimeoutCtx(t, 30*time.Second), l2Client, 10)) require.NoError(t, utils.WaitBlock(e2eutils.TimeoutCtx(t, 30*time.Second), l2Client, 10))
l1SB, err := bindings.NewL1StandardBridge(predeploys.DevL1StandardBridgeAddr, l1Client) l1SB, err := bindings.NewL1StandardBridge(cfg.L1Deployments.L1StandardBridgeProxy, l1Client)
require.NoError(t, err) require.NoError(t, err)
l2SB, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, l2Client) l2SB, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, l2Client)
require.NoError(t, err) require.NoError(t, err)
...@@ -208,7 +208,7 @@ func TestBedrockIndexer(t *testing.T) { ...@@ -208,7 +208,7 @@ func TestBedrockIndexer(t *testing.T) {
require.Nil(t, wd.BedrockFinalizedTxHash) require.Nil(t, wd.BedrockFinalizedTxHash)
// Finalize withdrawal // Finalize withdrawal
err = withdrawals.WaitForFinalizationPeriod(e2eutils.TimeoutCtx(t, 30*time.Second), l1Client, predeploys.DevOptimismPortalAddr, proveReceipt.BlockNumber) err = withdrawals.WaitForFinalizationPeriod(e2eutils.TimeoutCtx(t, 30*time.Second), l1Client, cfg.L1Deployments.OptimismPortalProxy, proveReceipt.BlockNumber)
require.Nil(t, err) require.Nil(t, err)
finReceipt := op_e2e.FinalizeWithdrawal(t, cfg, l1Client, cfg.Secrets.Alice, wdReceipt, wdParams) finReceipt := op_e2e.FinalizeWithdrawal(t, cfg, l1Client, cfg.Secrets.Alice, wdReceipt, wdParams)
......
...@@ -34,16 +34,6 @@ type L1Contracts struct { ...@@ -34,16 +34,6 @@ type L1Contracts struct {
// Remove afterwards? // Remove afterwards?
} }
func DevL1Contracts() L1Contracts {
return L1Contracts{
OptimismPortal: common.HexToAddress("0x6900000000000000000000000000000000000000"),
L2OutputOracle: common.HexToAddress("0x6900000000000000000000000000000000000001"),
L1CrossDomainMessenger: common.HexToAddress("0x6900000000000000000000000000000000000002"),
L1StandardBridge: common.HexToAddress("0x6900000000000000000000000000000000000003"),
L1ERC721Bridge: common.HexToAddress("0x6900000000000000000000000000000000000004"),
}
}
func (c L1Contracts) ToSlice() []common.Address { func (c L1Contracts) ToSlice() []common.Address {
fields := reflect.VisibleFields(reflect.TypeOf(c)) fields := reflect.VisibleFields(reflect.TypeOf(c))
v := reflect.ValueOf(c) v := reflect.ValueOf(c)
......
package predeploys
import "github.com/ethereum/go-ethereum/common"
const (
DevL2OutputOracle = "0x6900000000000000000000000000000000000000"
DevOptimismPortal = "0x6900000000000000000000000000000000000001"
DevL1CrossDomainMessenger = "0x6900000000000000000000000000000000000002"
DevL1StandardBridge = "0x6900000000000000000000000000000000000003"
DevOptimismMintableERC20Factory = "0x6900000000000000000000000000000000000004"
DevAddressManager = "0x6900000000000000000000000000000000000005"
DevProxyAdmin = "0x6900000000000000000000000000000000000006"
DevWETH9 = "0x6900000000000000000000000000000000000007"
DevL1ERC721Bridge = "0x6900000000000000000000000000000000000008"
DevSystemConfig = "0x6900000000000000000000000000000000000009"
)
var (
DevL2OutputOracleAddr = common.HexToAddress(DevL2OutputOracle)
DevOptimismPortalAddr = common.HexToAddress(DevOptimismPortal)
DevL1CrossDomainMessengerAddr = common.HexToAddress(DevL1CrossDomainMessenger)
DevL1StandardBridgeAddr = common.HexToAddress(DevL1StandardBridge)
DevOptimismMintableERC20FactoryAddr = common.HexToAddress(DevOptimismMintableERC20Factory)
DevAddressManagerAddr = common.HexToAddress(DevAddressManager)
DevProxyAdminAddr = common.HexToAddress(DevProxyAdmin)
DevWETH9Addr = common.HexToAddress(DevWETH9)
DevL1ERC721BridgeAddr = common.HexToAddress(DevL1ERC721Bridge)
DevSystemConfigAddr = common.HexToAddress(DevSystemConfig)
DevPredeploys = make(map[string]*common.Address)
)
func init() {
DevPredeploys["L2OutputOracle"] = &DevL2OutputOracleAddr
DevPredeploys["OptimismPortal"] = &DevOptimismPortalAddr
DevPredeploys["L1CrossDomainMessenger"] = &DevL1CrossDomainMessengerAddr
DevPredeploys["L1StandardBridge"] = &DevL1StandardBridgeAddr
DevPredeploys["OptimismMintableERC20Factory"] = &DevOptimismMintableERC20FactoryAddr
DevPredeploys["AddressManager"] = &DevAddressManagerAddr
DevPredeploys["Admin"] = &DevProxyAdminAddr
DevPredeploys["WETH9"] = &DevWETH9Addr
DevPredeploys["L1ERC721Bridge"] = &DevL1ERC721BridgeAddr
DevPredeploys["SystemConfig"] = &DevSystemConfigAddr
}
...@@ -8,8 +8,11 @@ import ( ...@@ -8,8 +8,11 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"reflect"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
gstate "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
...@@ -74,10 +77,15 @@ type DeployConfig struct { ...@@ -74,10 +77,15 @@ type DeployConfig struct {
// L2OutputOracleChallenger is the address of the account that challenges L2 outputs. // L2OutputOracleChallenger is the address of the account that challenges L2 outputs.
L2OutputOracleChallenger common.Address `json:"l2OutputOracleChallenger"` L2OutputOracleChallenger common.Address `json:"l2OutputOracleChallenger"`
// CliqueSignerAddress represents the signer address for the clique consensus engine.
// It is used in the multi-process devnet to sign blocks.
CliqueSignerAddress common.Address `json:"cliqueSignerAddress"`
// L1UseClique represents whether or not to use the clique consensus engine.
L1UseClique bool `json:"l1UseClique"`
L1BlockTime uint64 `json:"l1BlockTime"` L1BlockTime uint64 `json:"l1BlockTime"`
L1GenesisBlockTimestamp hexutil.Uint64 `json:"l1GenesisBlockTimestamp"` L1GenesisBlockTimestamp hexutil.Uint64 `json:"l1GenesisBlockTimestamp"`
L1GenesisBlockNonce hexutil.Uint64 `json:"l1GenesisBlockNonce"` L1GenesisBlockNonce hexutil.Uint64 `json:"l1GenesisBlockNonce"`
CliqueSignerAddress common.Address `json:"cliqueSignerAddress"` // proof of stake genesis if left zeroed.
L1GenesisBlockGasLimit hexutil.Uint64 `json:"l1GenesisBlockGasLimit"` L1GenesisBlockGasLimit hexutil.Uint64 `json:"l1GenesisBlockGasLimit"`
L1GenesisBlockDifficulty *hexutil.Big `json:"l1GenesisBlockDifficulty"` L1GenesisBlockDifficulty *hexutil.Big `json:"l1GenesisBlockDifficulty"`
L1GenesisBlockMixHash common.Hash `json:"l1GenesisBlockMixHash"` L1GenesisBlockMixHash common.Hash `json:"l1GenesisBlockMixHash"`
...@@ -181,7 +189,6 @@ func (d *DeployConfig) Copy() *DeployConfig { ...@@ -181,7 +189,6 @@ func (d *DeployConfig) Copy() *DeployConfig {
if err = json.Unmarshal(raw, &cpy); err != nil { if err = json.Unmarshal(raw, &cpy); err != nil {
panic(err) panic(err)
} }
return &cpy return &cpy
} }
...@@ -311,9 +318,22 @@ func (d *DeployConfig) Check() error { ...@@ -311,9 +318,22 @@ func (d *DeployConfig) Check() error {
return fmt.Errorf("%w: GovernanceToken owner cannot be address(0)", ErrInvalidDeployConfig) return fmt.Errorf("%w: GovernanceToken owner cannot be address(0)", ErrInvalidDeployConfig)
} }
} }
// L2 block time must always be smaller than L1 block time
if d.L1BlockTime < d.L2BlockTime {
return fmt.Errorf("L2 block time (%d) is larger than L1 block time (%d)", d.L2BlockTime, d.L1BlockTime)
}
return nil return nil
} }
// SetDeployments will merge a Deployments into a DeployConfig.
func (d *DeployConfig) SetDeployments(deployments *L1Deployments) {
d.L1StandardBridgeProxy = deployments.L1StandardBridgeProxy
d.L1CrossDomainMessengerProxy = deployments.L1CrossDomainMessengerProxy
d.L1ERC721BridgeProxy = deployments.L1ERC721BridgeProxy
d.SystemConfigProxy = deployments.SystemConfigProxy
d.OptimismPortalProxy = deployments.OptimismPortalProxy
}
// GetDeployedAddresses will get the deployed addresses of deployed L1 contracts // GetDeployedAddresses will get the deployed addresses of deployed L1 contracts
// required for the L2 genesis creation. Legacy systems use the `Proxy__` prefix // required for the L2 genesis creation. Legacy systems use the `Proxy__` prefix
// while modern systems use the `Proxy` suffix. First check for the legacy // while modern systems use the `Proxy` suffix. First check for the legacy
...@@ -373,16 +393,6 @@ func (d *DeployConfig) GetDeployedAddresses(hh *hardhat.Hardhat) error { ...@@ -373,16 +393,6 @@ func (d *DeployConfig) GetDeployedAddresses(hh *hardhat.Hardhat) error {
return nil return nil
} }
// InitDeveloperDeployedAddresses will set the dev addresses on the DeployConfig
func (d *DeployConfig) InitDeveloperDeployedAddresses() error {
d.L1StandardBridgeProxy = predeploys.DevL1StandardBridgeAddr
d.L1CrossDomainMessengerProxy = predeploys.DevL1CrossDomainMessengerAddr
d.L1ERC721BridgeProxy = predeploys.DevL1ERC721BridgeAddr
d.OptimismPortalProxy = predeploys.DevOptimismPortalAddr
d.SystemConfigProxy = predeploys.DevSystemConfigAddr
return nil
}
func (d *DeployConfig) RegolithTime(genesisTime uint64) *uint64 { func (d *DeployConfig) RegolithTime(genesisTime uint64) *uint64 {
if d.L2GenesisRegolithTimeOffset == nil { if d.L2GenesisRegolithTimeOffset == nil {
return nil return nil
...@@ -479,6 +489,64 @@ type L1Deployments struct { ...@@ -479,6 +489,64 @@ type L1Deployments struct {
SystemConfigProxy common.Address `json:"SystemConfigProxy"` SystemConfigProxy common.Address `json:"SystemConfigProxy"`
} }
// GetName will return the name of the contract given an address.
func (d *L1Deployments) GetName(addr common.Address) string {
val := reflect.ValueOf(d)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
for i := 0; i < val.NumField(); i++ {
if addr == val.Field(i).Interface().(common.Address) {
return val.Type().Field(i).Name
}
}
return ""
}
// Check will ensure that the L1Deployments are sane
func (d *L1Deployments) Check() error {
val := reflect.ValueOf(d)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
for i := 0; i < val.NumField(); i++ {
name := val.Type().Field(i).Name
// Skip the non production ready contracts
if name == "DisputeGameFactory" || name == "DisputeGameFactoryProxy" {
continue
}
if val.Field(i).Interface().(common.Address) == (common.Address{}) {
return fmt.Errorf("%s is not set", name)
}
}
return nil
}
// ForEach will iterate over each contract in the L1Deployments
func (d *L1Deployments) ForEach(cb func(name string, addr common.Address)) {
val := reflect.ValueOf(d)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
for i := 0; i < val.NumField(); i++ {
name := val.Type().Field(i).Name
cb(name, val.Field(i).Interface().(common.Address))
}
}
// Copy will copy the L1Deployments struct
func (d *L1Deployments) Copy() *L1Deployments {
cpy := L1Deployments{}
data, err := json.Marshal(d)
if err != nil {
panic(err)
}
if err := json.Unmarshal(data, &cpy); err != nil {
panic(err)
}
return &cpy
}
// NewL1Deployments will create a new L1Deployments from a JSON file on disk // NewL1Deployments will create a new L1Deployments from a JSON file on disk
// at the given path. // at the given path.
func NewL1Deployments(path string) (*L1Deployments, error) { func NewL1Deployments(path string) (*L1Deployments, error) {
...@@ -495,6 +563,20 @@ func NewL1Deployments(path string) (*L1Deployments, error) { ...@@ -495,6 +563,20 @@ func NewL1Deployments(path string) (*L1Deployments, error) {
return &deployments, nil return &deployments, nil
} }
// NewStateDump will read a Dump JSON file from disk
func NewStateDump(path string) (*gstate.Dump, error) {
file, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("dump at %s not found: %w", path, err)
}
var dump gstate.Dump
if err := json.Unmarshal(file, &dump); err != nil {
return nil, fmt.Errorf("cannot unmarshal dump: %w", err)
}
return &dump, nil
}
// NewL2ImmutableConfig will create an ImmutableConfig given an instance of a // NewL2ImmutableConfig will create an ImmutableConfig given an instance of a
// DeployConfig and a block. // DeployConfig and a block.
func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (immutables.ImmutableConfig, error) { func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (immutables.ImmutableConfig, error) {
......
...@@ -89,4 +89,9 @@ func TestL1Deployments(t *testing.T) { ...@@ -89,4 +89,9 @@ func TestL1Deployments(t *testing.T) {
require.NotEqual(t, deployments.ProxyAdmin, common.Address{}) require.NotEqual(t, deployments.ProxyAdmin, common.Address{})
require.NotEqual(t, deployments.SystemConfig, common.Address{}) require.NotEqual(t, deployments.SystemConfig, common.Address{})
require.NotEqual(t, deployments.SystemConfigProxy, common.Address{}) require.NotEqual(t, deployments.SystemConfigProxy, common.Address{})
require.Equal(t, "AddressManager", deployments.GetName(deployments.AddressManager))
require.Equal(t, "OptimismPortalProxy", deployments.GetName(deployments.OptimismPortalProxy))
// One that doesn't exist returns empty string
require.Equal(t, "", deployments.GetName(common.Address{19: 0xff}))
} }
...@@ -127,20 +127,22 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) { ...@@ -127,20 +127,22 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) {
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
ShanghaiTime: u64ptr(0),
} }
if config.CliqueSignerAddress != (common.Address{}) { extraData := make([]byte, 0)
if config.L1UseClique {
// warning: clique has an overly strict block header timestamp check against the system wallclock, // warning: clique has an overly strict block header timestamp check against the system wallclock,
// causing blocks to get scheduled as "future block" and not get mined instantly when produced. // causing blocks to get scheduled as "future block" and not get mined instantly when produced.
chainConfig.Clique = &params.CliqueConfig{ chainConfig.Clique = &params.CliqueConfig{
Period: config.L1BlockTime, Period: config.L1BlockTime,
Epoch: 30000, Epoch: 30000,
} }
extraData = append(append(make([]byte, 32), config.CliqueSignerAddress[:]...), make([]byte, crypto.SignatureLength)...)
} else { } else {
chainConfig.MergeNetsplitBlock = big.NewInt(0) chainConfig.MergeNetsplitBlock = big.NewInt(0)
chainConfig.TerminalTotalDifficulty = big.NewInt(0) chainConfig.TerminalTotalDifficulty = big.NewInt(0)
chainConfig.TerminalTotalDifficultyPassed = true chainConfig.TerminalTotalDifficultyPassed = true
chainConfig.ShanghaiTime = u64ptr(0)
} }
gasLimit := config.L1GenesisBlockGasLimit gasLimit := config.L1GenesisBlockGasLimit
...@@ -160,11 +162,6 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) { ...@@ -160,11 +162,6 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) {
timestamp = hexutil.Uint64(time.Now().Unix()) timestamp = hexutil.Uint64(time.Now().Unix())
} }
extraData := make([]byte, 0)
if config.CliqueSignerAddress != (common.Address{}) {
extraData = append(append(make([]byte, 32), config.CliqueSignerAddress[:]...), make([]byte, crypto.SignatureLength)...)
}
return &core.Genesis{ return &core.Genesis{
Config: &chainConfig, Config: &chainConfig,
Nonce: uint64(config.L1GenesisBlockNonce), Nonce: uint64(config.L1GenesisBlockNonce),
......
...@@ -18,12 +18,8 @@ var ( ...@@ -18,12 +18,8 @@ var (
codeNamespace = common.HexToAddress("0xc0D3C0d3C0d3C0D3c0d3C0d3c0D3C0d3c0d30000") codeNamespace = common.HexToAddress("0xc0D3C0d3C0d3C0D3c0d3C0d3c0D3C0d3c0d30000")
// l2PredeployNamespace represents the namespace of L2 predeploys // l2PredeployNamespace represents the namespace of L2 predeploys
l2PredeployNamespace = common.HexToAddress("0x4200000000000000000000000000000000000000") l2PredeployNamespace = common.HexToAddress("0x4200000000000000000000000000000000000000")
// l1PredeployNamespace represents the namespace of L1 predeploys
l1PredeployNamespace = common.HexToAddress("0x6900000000000000000000000000000000000000")
// bigL2PredeployNamespace represents the predeploy namespace as a big.Int // bigL2PredeployNamespace represents the predeploy namespace as a big.Int
BigL2PredeployNamespace = new(big.Int).SetBytes(l2PredeployNamespace.Bytes()) BigL2PredeployNamespace = new(big.Int).SetBytes(l2PredeployNamespace.Bytes())
// bigL1PredeployNamespace represents the predeploy namespace as a big.Int
bigL1PredeployNamespace = new(big.Int).SetBytes(l1PredeployNamespace.Bytes())
// bigCodeNamespace represents the predeploy namespace as a big.Int // bigCodeNamespace represents the predeploy namespace as a big.Int
bigCodeNameSpace = new(big.Int).SetBytes(codeNamespace.Bytes()) bigCodeNameSpace = new(big.Int).SetBytes(codeNamespace.Bytes())
// implementationSlot represents the EIP 1967 implementation storage slot // implementationSlot represents the EIP 1967 implementation storage slot
...@@ -67,7 +63,7 @@ var devBalance = hexutil.MustDecodeBig("0x20000000000000000000000000000000000000 ...@@ -67,7 +63,7 @@ var devBalance = hexutil.MustDecodeBig("0x20000000000000000000000000000000000000
// AddressToCodeNamespace takes a predeploy address and computes // AddressToCodeNamespace takes a predeploy address and computes
// the implementation address that the implementation should be deployed at // the implementation address that the implementation should be deployed at
func AddressToCodeNamespace(addr common.Address) (common.Address, error) { func AddressToCodeNamespace(addr common.Address) (common.Address, error) {
if !IsL1DevPredeploy(addr) && !IsL2DevPredeploy(addr) { if !IsL2DevPredeploy(addr) {
return common.Address{}, fmt.Errorf("cannot handle non predeploy: %s", addr) return common.Address{}, fmt.Errorf("cannot handle non predeploy: %s", addr)
} }
bigAddress := new(big.Int).SetBytes(addr[18:]) bigAddress := new(big.Int).SetBytes(addr[18:])
...@@ -75,10 +71,6 @@ func AddressToCodeNamespace(addr common.Address) (common.Address, error) { ...@@ -75,10 +71,6 @@ func AddressToCodeNamespace(addr common.Address) (common.Address, error) {
return common.BigToAddress(num), nil return common.BigToAddress(num), nil
} }
func IsL1DevPredeploy(addr common.Address) bool {
return bytes.Equal(addr[0:2], []byte{0x69, 0x00})
}
func IsL2DevPredeploy(addr common.Address) bool { func IsL2DevPredeploy(addr common.Address) bool {
return bytes.Equal(addr[0:2], []byte{0x42, 0x00}) return bytes.Equal(addr[0:2], []byte{0x42, 0x00})
} }
......
This diff is collapsed.
...@@ -16,11 +16,16 @@ import ( ...@@ -16,11 +16,16 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// TestBuildL1DeveloperGenesis tests that the L1 genesis block can be built
// given a deploy config and an l1-allocs.json and a deploy.json that
// are generated from a deploy config. If new contracts are added, these
// mocks will need to be regenerated.
func TestBuildL1DeveloperGenesis(t *testing.T) { func TestBuildL1DeveloperGenesis(t *testing.T) {
b, err := os.ReadFile("testdata/test-deploy-config-full.json") b, err := os.ReadFile("testdata/test-deploy-config-full.json")
require.NoError(t, err) require.NoError(t, err)
...@@ -29,7 +34,15 @@ func TestBuildL1DeveloperGenesis(t *testing.T) { ...@@ -29,7 +34,15 @@ func TestBuildL1DeveloperGenesis(t *testing.T) {
require.NoError(t, dec.Decode(config)) require.NoError(t, dec.Decode(config))
config.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix() - 100) config.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix() - 100)
genesis, err := BuildL1DeveloperGenesis(config) c, err := os.ReadFile("testdata/allocs-l1.json")
require.NoError(t, err)
dump := new(state.Dump)
require.NoError(t, json.NewDecoder(bytes.NewReader(c)).Decode(dump))
deployments, err := NewL1Deployments("testdata/deploy.json")
require.NoError(t, err)
genesis, err := BuildL1DeveloperGenesis(config, dump, nil, false)
require.NoError(t, err) require.NoError(t, err)
sim := backends.NewSimulatedBackend( sim := backends.NewSimulatedBackend(
...@@ -38,9 +51,9 @@ func TestBuildL1DeveloperGenesis(t *testing.T) { ...@@ -38,9 +51,9 @@ func TestBuildL1DeveloperGenesis(t *testing.T) {
) )
callOpts := &bind.CallOpts{} callOpts := &bind.CallOpts{}
oracle, err := bindings.NewL2OutputOracle(predeploys.DevL2OutputOracleAddr, sim) oracle, err := bindings.NewL2OutputOracle(deployments.L2OutputOracleProxy, sim)
require.NoError(t, err) require.NoError(t, err)
portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, sim) portal, err := bindings.NewOptimismPortal(deployments.OptimismPortalProxy, sim)
require.NoError(t, err) require.NoError(t, err)
proposer, err := oracle.PROPOSER(callOpts) proposer, err := oracle.PROPOSER(callOpts)
...@@ -66,42 +79,30 @@ func TestBuildL1DeveloperGenesis(t *testing.T) { ...@@ -66,42 +79,30 @@ func TestBuildL1DeveloperGenesis(t *testing.T) {
oracleAddr, err := portal.L2ORACLE(callOpts) oracleAddr, err := portal.L2ORACLE(callOpts)
require.NoError(t, err) require.NoError(t, err)
require.EqualValues(t, predeploys.DevL2OutputOracleAddr, oracleAddr) require.EqualValues(t, deployments.L2OutputOracleProxy, oracleAddr)
msgr, err := bindings.NewL1CrossDomainMessenger(predeploys.DevL1CrossDomainMessengerAddr, sim) msgr, err := bindings.NewL1CrossDomainMessenger(deployments.L1CrossDomainMessengerProxy, sim)
require.NoError(t, err) require.NoError(t, err)
portalAddr, err := msgr.PORTAL(callOpts) portalAddr, err := msgr.PORTAL(callOpts)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, predeploys.DevOptimismPortalAddr, portalAddr) require.Equal(t, deployments.OptimismPortalProxy, portalAddr)
bridge, err := bindings.NewL1StandardBridge(predeploys.DevL1StandardBridgeAddr, sim) bridge, err := bindings.NewL1StandardBridge(deployments.L1StandardBridgeProxy, sim)
require.NoError(t, err) require.NoError(t, err)
msgrAddr, err := bridge.Messenger(callOpts) msgrAddr, err := bridge.Messenger(callOpts)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, predeploys.DevL1CrossDomainMessengerAddr, msgrAddr) require.Equal(t, deployments.L1CrossDomainMessengerProxy, msgrAddr)
otherBridge, err := bridge.OTHERBRIDGE(callOpts) otherBridge, err := bridge.OTHERBRIDGE(callOpts)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, predeploys.L2StandardBridgeAddr, otherBridge) require.Equal(t, predeploys.L2StandardBridgeAddr, otherBridge)
factory, err := bindings.NewOptimismMintableERC20(predeploys.DevOptimismMintableERC20FactoryAddr, sim) factory, err := bindings.NewOptimismMintableERC20(deployments.OptimismMintableERC20Factory, sim)
require.NoError(t, err) require.NoError(t, err)
bridgeAddr, err := factory.BRIDGE(callOpts) bridgeAddr, err := factory.BRIDGE(callOpts)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, predeploys.DevL1StandardBridgeAddr, bridgeAddr) require.Equal(t, deployments.L1StandardBridgeProxy, bridgeAddr)
weth9, err := bindings.NewWETH9(predeploys.DevWETH9Addr, sim)
require.NoError(t, err)
decimals, err := weth9.Decimals(callOpts)
require.NoError(t, err)
require.Equal(t, uint8(18), decimals)
symbol, err := weth9.Symbol(callOpts)
require.NoError(t, err)
require.Equal(t, "WETH", symbol)
name, err := weth9.Name(callOpts)
require.NoError(t, err)
require.Equal(t, "Wrapped Ether", name)
sysCfg, err := bindings.NewSystemConfig(predeploys.DevSystemConfigAddr, sim) sysCfg, err := bindings.NewSystemConfig(deployments.SystemConfigProxy, sim)
require.NoError(t, err) require.NoError(t, err)
cfg, err := sysCfg.ResourceConfig(&bind.CallOpts{}) cfg, err := sysCfg.ResourceConfig(&bind.CallOpts{})
require.NoError(t, err) require.NoError(t, err)
......
...@@ -21,6 +21,7 @@ func BuildL2Genesis(config *DeployConfig, l1StartBlock *types.Block) (*core.Gene ...@@ -21,6 +21,7 @@ func BuildL2Genesis(config *DeployConfig, l1StartBlock *types.Block) (*core.Gene
db := state.NewMemoryStateDB(genspec) db := state.NewMemoryStateDB(genspec)
if config.FundDevAccounts { if config.FundDevAccounts {
log.Info("Funding developer accounts in L2 genesis")
FundDevAccounts(db) FundDevAccounts(db)
SetPrecompileBalances(db) SetPrecompileBalances(db)
} }
......
...@@ -73,17 +73,6 @@ func testBuildL2Genesis(t *testing.T, config *genesis.DeployConfig) *core.Genesi ...@@ -73,17 +73,6 @@ func testBuildL2Genesis(t *testing.T, config *genesis.DeployConfig) *core.Genesi
return gen return gen
} }
func TestBuildL2DeveloperGenesis(t *testing.T) {
config, err := genesis.NewDeployConfig("./testdata/test-deploy-config-devnet-l1.json")
require.Nil(t, err)
config.EnableGovernance = false
config.FundDevAccounts = true
err = config.InitDeveloperDeployedAddresses()
require.NoError(t, err)
gen := testBuildL2Genesis(t, config)
require.Equal(t, 2344, len(gen.Alloc))
}
func TestBuildL2MainnetGenesis(t *testing.T) { func TestBuildL2MainnetGenesis(t *testing.T) {
config, err := genesis.NewDeployConfig("./testdata/test-deploy-config-devnet-l1.json") config, err := genesis.NewDeployConfig("./testdata/test-deploy-config-devnet-l1.json")
require.Nil(t, err) require.Nil(t, err)
......
...@@ -16,19 +16,13 @@ import ( ...@@ -16,19 +16,13 @@ import (
// FundDevAccounts will fund each of the development accounts. // FundDevAccounts will fund each of the development accounts.
func FundDevAccounts(db vm.StateDB) { func FundDevAccounts(db vm.StateDB) {
for _, account := range DevAccounts { for _, account := range DevAccounts {
db.CreateAccount(account) if !db.Exist(account) {
db.CreateAccount(account)
}
db.AddBalance(account, devBalance) db.AddBalance(account, devBalance)
} }
} }
// SetL1Proxies will set each of the proxies in the state. It requires
// a Proxy and ProxyAdmin deployment present so that the Proxy bytecode
// can be set in state and the ProxyAdmin can be set as the admin of the
// Proxy.
func SetL1Proxies(db vm.StateDB, proxyAdminAddr common.Address) error {
return setProxies(db, proxyAdminAddr, bigL1PredeployNamespace, 2048)
}
func setProxies(db vm.StateDB, proxyAdminAddr common.Address, namespace *big.Int, count uint64) error { func setProxies(db vm.StateDB, proxyAdminAddr common.Address, namespace *big.Int, count uint64) error {
depBytecode, err := bindings.GetDeployedBytecode("Proxy") depBytecode, err := bindings.GetDeployedBytecode("Proxy")
if err != nil { if err != nil {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"AddressManager": "0x7aeb97910d4070426C00e820De4137D6d2ADf0AD",
"L1CrossDomainMessenger": "0x4562938D6831437F37Dd1BF5BBb7fe7a5F080eac",
"L1CrossDomainMessengerProxy": "0xa88B2060478401a52532814eddE6819d101802E2",
"L1ERC721Bridge": "0x7eC3b539C97c98D503Fb4FeE3dd4ee885DC192cd",
"L1ERC721BridgeProxy": "0xD16dbA9f860146F08C9EE83B891c138667021eC9",
"L1StandardBridge": "0x9a7EcB1c67f88396D252725F3259e9d8027F1562",
"L1StandardBridgeProxy": "0x6fB1869D7141C97Cf28668fA0A338BDC892F53c0",
"L2OutputOracle": "0x7F325Df611b236EE3EF469Da4a74f776c787d1B3",
"L2OutputOracleProxy": "0x48204903b06a64e3c44B0260F875497EA5316A02",
"OptimismMintableERC20Factory": "0x87658463F96977Fc95a068F1A206D2C0CF2db575",
"OptimismMintableERC20FactoryProxy": "0xA051F227dA1f5F1eEcbfCdcd7316cE299A233760",
"OptimismPortal": "0xb8D5D0Fa6E413b5de72C38a0a187731171b4F341",
"OptimismPortalProxy": "0xCF1a8a7F273DA1bd3112750Cc3691B46C541e8B7",
"ProxyAdmin": "0x36F4e85652236f9EdAeba78bBE9d8C2B55Ac5809",
"SystemConfig": "0xEc466e9A46914507c484DCC5cabA1Db787e34913",
"SystemConfigProxy": "0x73317009F4FadAfcDA357F3a082C7B68F5f8732F"
}
\ No newline at end of file
...@@ -6,20 +6,21 @@ ...@@ -6,20 +6,21 @@
"maxSequencerDrift": 20, "maxSequencerDrift": 20,
"sequencerWindowSize": 100, "sequencerWindowSize": 100,
"channelTimeout": 30, "channelTimeout": 30,
"p2pSequencerAddress": "0x0000000000000000000000000000000000000000", "l1UseClique": false,
"cliqueSignerAddress": "0x0000000000000000000000000000000000000000",
"p2pSequencerAddress": "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc",
"batchInboxAddress": "0x42000000000000000000000000000000000000ff", "batchInboxAddress": "0x42000000000000000000000000000000000000ff",
"batchSenderAddress": "0x0000000000000000000000000000000000000000", "batchSenderAddress": "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc",
"l2OutputOracleSubmissionInterval": 6, "l2OutputOracleSubmissionInterval": 20,
"l2OutputOracleStartingBlockNumber": 0, "l2OutputOracleStartingBlockNumber": 0,
"l2OutputOracleStartingTimestamp": -1, "l2OutputOracleStartingTimestamp": -1,
"l2OutputOracleProposer": "0x7770000000000000000000000000000000000001", "l2OutputOracleProposer": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
"l2OutputOracleChallenger": "0x7770000000000000000000000000000000000002", "l2OutputOracleChallenger": "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65",
"l1BlockTime": 15, "l1BlockTime": 15,
"l1GenesisBlockNonce": "0x0", "l1GenesisBlockNonce": "0x0",
"cliqueSignerAddress": "0x0000000000000000000000000000000000000000",
"l1GenesisBlockGasLimit": "0x1c9c380", "l1GenesisBlockGasLimit": "0x1c9c380",
"l1GenesisBlockDifficulty": "0x1", "l1GenesisBlockDifficulty": "0x1",
"finalSystemOwner": "0x0000000000000000000000000000000000000111", "finalSystemOwner": "0xbcd4042de499d14e55001ccbb24a551f3b954096",
"portalGuardian": "0x0000000000000000000000000000000000000112", "portalGuardian": "0x0000000000000000000000000000000000000112",
"finalizationPeriodSeconds": 2, "finalizationPeriodSeconds": 2,
"l1GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "l1GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
...@@ -158,6 +159,7 @@ func BuildOptimism(immutable ImmutableConfig) (DeploymentResults, error) { ...@@ -158,6 +159,7 @@ func BuildOptimism(immutable ImmutableConfig) (DeploymentResults, error) {
// can be properly set. The bytecode returned in the results is suitable to be // can be properly set. The bytecode returned in the results is suitable to be
// inserted into the state via state surgery. // inserted into the state via state surgery.
func BuildL2(constructors []deployer.Constructor) (DeploymentResults, error) { func BuildL2(constructors []deployer.Constructor) (DeploymentResults, error) {
log.Info("Creating L2 state")
deployments, err := deployer.Deploy(deployer.NewL2Backend(), constructors, l2Deployer) deployments, err := deployer.Deploy(deployer.NewL2Backend(), constructors, l2Deployer)
if err != nil { if err != nil {
return nil, err return nil, err
......
# op-e2e
The end to end tests in this repo depend on genesis state that is
created with the `bedrock-devnet` package. To create this state,
run the following commands from the root of the repository:
```bash
make install-geth
make devnet-allocs
```
This will leave artifacts in the `.devnet` directory that will be
read into `op-e2e` at runtime. The default deploy configuration
used for starting all `op-e2e` based tests can be found in
`packages/contracts-bedrock/deploy-config/devnetL1.json`. There
are some values that are safe to change in memory in `op-e2e` at
runtime, but others cannot be changed or else it will result in
broken tests. Any changes to `devnetL1.json` should result in
rebuilding the `.devnet` artifacts before the new values will
be present in the `op-e2e` tests.
...@@ -21,6 +21,8 @@ func TestBatchInLastPossibleBlocks(gt *testing.T) { ...@@ -21,6 +21,8 @@ func TestBatchInLastPossibleBlocks(gt *testing.T) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
dp.DeployConfig.SequencerWindowSize = 4 dp.DeployConfig.SequencerWindowSize = 4
dp.DeployConfig.L2BlockTime = 2
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlDebug) log := testlog.Logger(t, log.LvlDebug)
......
...@@ -26,6 +26,7 @@ func TestBatcher(gt *testing.T) { ...@@ -26,6 +26,7 @@ func TestBatcher(gt *testing.T) {
MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12)
SequencerWindowSize: 24, SequencerWindowSize: 24,
ChannelTimeout: 20, ChannelTimeout: 20,
L1BlockTime: 12,
} }
dp := e2eutils.MakeDeployParams(t, p) dp := e2eutils.MakeDeployParams(t, p)
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
...@@ -345,6 +346,7 @@ func TestExtendedTimeWithoutL1Batches(gt *testing.T) { ...@@ -345,6 +346,7 @@ func TestExtendedTimeWithoutL1Batches(gt *testing.T) {
MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12)
SequencerWindowSize: 24, SequencerWindowSize: 24,
ChannelTimeout: 20, ChannelTimeout: 20,
L1BlockTime: 12,
} }
dp := e2eutils.MakeDeployParams(t, p) dp := e2eutils.MakeDeployParams(t, p)
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
...@@ -402,6 +404,7 @@ func TestBigL2Txs(gt *testing.T) { ...@@ -402,6 +404,7 @@ func TestBigL2Txs(gt *testing.T) {
MaxSequencerDrift: 100, MaxSequencerDrift: 100,
SequencerWindowSize: 1000, SequencerWindowSize: 1000,
ChannelTimeout: 200, // give enough space to buffer large amounts of data before submitting it ChannelTimeout: 200, // give enough space to buffer large amounts of data before submitting it
L1BlockTime: 12,
} }
dp := e2eutils.MakeDeployParams(t, p) dp := e2eutils.MakeDeployParams(t, p)
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
......
...@@ -126,6 +126,7 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) { ...@@ -126,6 +126,7 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) {
require.NoError(t, err, "need to sign tx") require.NoError(t, err, "need to sign tx")
err = p.l1.SendTransaction(t.Ctx(), tx) err = p.l1.SendTransaction(t.Ctx(), tx)
log.Info("Proposer sent tx", "hash", tx.Hash(), "to", p.contractAddr)
require.NoError(t, err, "need to send tx") require.NoError(t, err, "need to send tx")
p.lastTx = tx.Hash() p.lastTx = tx.Hash()
......
package actions package actions
import ( import (
"math/big"
"testing" "testing"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -55,9 +55,10 @@ func TestProposer(gt *testing.T) { ...@@ -55,9 +55,10 @@ func TestProposer(gt *testing.T) {
sequencer.ActL1SafeSignal(t) sequencer.ActL1SafeSignal(t)
sequencer.ActL1FinalizedSignal(t) sequencer.ActL1FinalizedSignal(t)
require.Equal(t, sequencer.SyncStatus().UnsafeL2, sequencer.SyncStatus().FinalizedL2) require.Equal(t, sequencer.SyncStatus().UnsafeL2, sequencer.SyncStatus().FinalizedL2)
require.True(t, proposer.CanPropose(t))
// make proposals until there is nothing left to propose // make proposals until there is nothing left to propose
for proposer.CanPropose(t) { for proposer.CanPropose(t) {
// and propose it to L1
proposer.ActMakeProposalTx(t) proposer.ActMakeProposalTx(t)
// include proposal on L1 // include proposal on L1
miner.ActL1StartBlock(12)(t) miner.ActL1StartBlock(12)(t)
...@@ -72,11 +73,15 @@ func TestProposer(gt *testing.T) { ...@@ -72,11 +73,15 @@ func TestProposer(gt *testing.T) {
// check that L1 stored the expected output root // check that L1 stored the expected output root
outputOracleContract, err := bindings.NewL2OutputOracle(sd.DeploymentsL1.L2OutputOracleProxy, miner.EthClient()) outputOracleContract, err := bindings.NewL2OutputOracle(sd.DeploymentsL1.L2OutputOracleProxy, miner.EthClient())
require.NoError(t, err) require.NoError(t, err)
block := sequencer.SyncStatus().FinalizedL2 blockNumber, err := outputOracleContract.LatestBlockNumber(&bind.CallOpts{})
outputOnL1, err := outputOracleContract.GetL2OutputAfter(nil, new(big.Int).SetUint64(block.Number)) require.NoError(t, err)
require.Greater(t, int64(blockNumber.Uint64()), int64(0), "latest block number must be greater than 0")
block, err := seqEngine.EthClient().BlockByNumber(t.Ctx(), blockNumber)
require.NoError(t, err)
outputOnL1, err := outputOracleContract.GetL2OutputAfter(&bind.CallOpts{}, blockNumber)
require.NoError(t, err) require.NoError(t, err)
require.Less(t, block.Time, outputOnL1.Timestamp.Uint64(), "output is registered with L1 timestamp of proposal tx, past L2 block") require.Less(t, block.Time(), outputOnL1.Timestamp.Uint64(), "output is registered with L1 timestamp of proposal tx, past L2 block")
outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), block.Number) outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), blockNumber.Uint64())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, eth.Bytes32(outputOnL1.OutputRoot), outputComputed.OutputRoot, "output roots must match") require.Equal(t, eth.Bytes32(outputOnL1.OutputRoot), outputComputed.OutputRoot, "output roots must match")
} }
...@@ -37,6 +37,7 @@ func TestL2Sequencer_SequencerDrift(gt *testing.T) { ...@@ -37,6 +37,7 @@ func TestL2Sequencer_SequencerDrift(gt *testing.T) {
MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12)
SequencerWindowSize: 24, SequencerWindowSize: 24,
ChannelTimeout: 20, ChannelTimeout: 20,
L1BlockTime: 12,
} }
dp := e2eutils.MakeDeployParams(t, p) dp := e2eutils.MakeDeployParams(t, p)
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
......
...@@ -34,6 +34,7 @@ func TestL2Verifier_SequenceWindow(gt *testing.T) { ...@@ -34,6 +34,7 @@ func TestL2Verifier_SequenceWindow(gt *testing.T) {
MaxSequencerDrift: 10, MaxSequencerDrift: 10,
SequencerWindowSize: 24, SequencerWindowSize: 24,
ChannelTimeout: 10, ChannelTimeout: 10,
L1BlockTime: 15,
} }
dp := e2eutils.MakeDeployParams(t, p) dp := e2eutils.MakeDeployParams(t, p)
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
......
...@@ -25,6 +25,7 @@ func TestBatcherKeyRotation(gt *testing.T) { ...@@ -25,6 +25,7 @@ func TestBatcherKeyRotation(gt *testing.T) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
dp.DeployConfig.L2BlockTime = 2
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlDebug) log := testlog.Logger(t, log.LvlDebug)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
...@@ -74,6 +75,10 @@ func TestBatcherKeyRotation(gt *testing.T) { ...@@ -74,6 +75,10 @@ func TestBatcherKeyRotation(gt *testing.T) {
sysCfgOwner, err := bind.NewKeyedTransactorWithChainID(dp.Secrets.SysCfgOwner, sd.RollupCfg.L1ChainID) sysCfgOwner, err := bind.NewKeyedTransactorWithChainID(dp.Secrets.SysCfgOwner, sd.RollupCfg.L1ChainID)
require.NoError(t, err) require.NoError(t, err)
owner, err := sysCfgContract.Owner(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, dp.Addresses.SysCfgOwner, owner, "system config owner mismatch")
// Change the batch sender key to Bob! // Change the batch sender key to Bob!
tx, err := sysCfgContract.SetBatcherHash(sysCfgOwner, dp.Addresses.Bob.Hash()) tx, err := sysCfgContract.SetBatcherHash(sysCfgOwner, dp.Addresses.Bob.Hash())
require.NoError(t, err) require.NoError(t, err)
...@@ -81,7 +86,12 @@ func TestBatcherKeyRotation(gt *testing.T) { ...@@ -81,7 +86,12 @@ func TestBatcherKeyRotation(gt *testing.T) {
miner.ActL1StartBlock(12)(t) miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t) miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t)
miner.ActL1EndBlock(t) miner.ActL1EndBlock(t)
receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), tx.Hash())
require.NoError(t, err)
cfgChangeL1BlockNum := miner.l1Chain.CurrentBlock().Number.Uint64() cfgChangeL1BlockNum := miner.l1Chain.CurrentBlock().Number.Uint64()
require.Equal(t, cfgChangeL1BlockNum, receipt.BlockNumber.Uint64())
// sequence L2 blocks, and submit with new batcher // sequence L2 blocks, and submit with new batcher
sequencer.ActL1HeadSignal(t) sequencer.ActL1HeadSignal(t)
...@@ -91,17 +101,30 @@ func TestBatcherKeyRotation(gt *testing.T) { ...@@ -91,17 +101,30 @@ func TestBatcherKeyRotation(gt *testing.T) {
miner.ActL1IncludeTx(dp.Addresses.Bob)(t) miner.ActL1IncludeTx(dp.Addresses.Bob)(t)
miner.ActL1EndBlock(t) miner.ActL1EndBlock(t)
// check that the first L2 payload that adopted the L1 block with the batcher key change indeed changed the batcher key in the system config // check that the first L2 payload that adopted the L1 block with the batcher key change
// indeed changed the batcher key in the system config
engCl := seqEngine.EngineClient(t, sd.RollupCfg) engCl := seqEngine.EngineClient(t, sd.RollupCfg)
payload, err := engCl.PayloadByNumber(t.Ctx(), sequencer.L2Safe().Number+12) // 12 new L2 blocks: 5 with origin before L1 block with batch, 6 with origin of L1 block with batch, 1 with new origin that changed the batcher // 12 new L2 blocks: 5 with origin before L1 block with batch, 6 with origin of L1 block
require.NoError(t, err) // with batch, 1 with new origin that changed the batcher
ref, err := derive.PayloadToBlockRef(payload, &sd.RollupCfg.Genesis) for i := 0; i <= 12; i++ {
require.NoError(t, err) payload, err := engCl.PayloadByNumber(t.Ctx(), sequencer.L2Safe().Number+uint64(i))
require.Equal(t, ref.L1Origin.Number, cfgChangeL1BlockNum, "L2 block with L1 origin that included config change") require.NoError(t, err)
require.Equal(t, ref.SequenceNumber, uint64(0), "first L2 block with this origin") ref, err := derive.PayloadToBlockRef(payload, &sd.RollupCfg.Genesis)
sysCfg, err := derive.PayloadToSystemConfig(payload, sd.RollupCfg) require.NoError(t, err)
require.NoError(t, err) if i < 6 {
require.Equal(t, dp.Addresses.Bob, sysCfg.BatcherAddr, "bob should be batcher now") require.Equal(t, ref.L1Origin.Number, cfgChangeL1BlockNum-2)
require.Equal(t, ref.SequenceNumber, uint64(i))
} else if i < 12 {
require.Equal(t, ref.L1Origin.Number, cfgChangeL1BlockNum-1)
require.Equal(t, ref.SequenceNumber, uint64(i-6))
} else {
require.Equal(t, ref.L1Origin.Number, cfgChangeL1BlockNum)
require.Equal(t, ref.SequenceNumber, uint64(0), "first L2 block with this origin")
sysCfg, err := derive.PayloadToSystemConfig(payload, sd.RollupCfg)
require.NoError(t, err)
require.Equal(t, dp.Addresses.Bob, sysCfg.BatcherAddr, "bob should be batcher now")
}
}
// sync from L1 // sync from L1
sequencer.ActL2PipelineFull(t) sequencer.ActL2PipelineFull(t)
......
...@@ -19,7 +19,7 @@ import ( ...@@ -19,7 +19,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum-optimism/optimism/op-node/withdrawals"
) )
...@@ -31,11 +31,11 @@ type L1Bindings struct { ...@@ -31,11 +31,11 @@ type L1Bindings struct {
L2OutputOracle *bindings.L2OutputOracle L2OutputOracle *bindings.L2OutputOracle
} }
func NewL1Bindings(t Testing, l1Cl *ethclient.Client, deployments *e2eutils.DeploymentsL1) *L1Bindings { func NewL1Bindings(t Testing, l1Cl *ethclient.Client) *L1Bindings {
optimismPortal, err := bindings.NewOptimismPortal(deployments.OptimismPortalProxy, l1Cl) optimismPortal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Cl)
require.NoError(t, err) require.NoError(t, err)
l2OutputOracle, err := bindings.NewL2OutputOracle(deployments.L2OutputOracleProxy, l1Cl) l2OutputOracle, err := bindings.NewL2OutputOracle(config.L1Deployments.L2OutputOracleProxy, l1Cl)
require.NoError(t, err) require.NoError(t, err)
return &L1Bindings{ return &L1Bindings{
...@@ -319,7 +319,7 @@ func (s *CrossLayerUser) ActDeposit(t Testing) { ...@@ -319,7 +319,7 @@ func (s *CrossLayerUser) ActDeposit(t Testing) {
// estimate gas used by deposit // estimate gas used by deposit
gas, err := s.L2.env.EthCl.EstimateGas(t.Ctx(), ethereum.CallMsg{ gas, err := s.L2.env.EthCl.EstimateGas(t.Ctx(), ethereum.CallMsg{
From: s.L2.address, From: s.L2.address,
To: s.L2.txToAddr, To: &toAddr,
Value: depositTransferValue, // TODO: estimate gas does not support minting yet Value: depositTransferValue, // TODO: estimate gas does not support minting yet
Data: s.L2.txCallData, Data: s.L2.txCallData,
AccessList: nil, AccessList: nil,
......
...@@ -52,6 +52,9 @@ func runCrossLayerUserTest(gt *testing.T, test regolithScheduledTest) { ...@@ -52,6 +52,9 @@ func runCrossLayerUserTest(gt *testing.T, test regolithScheduledTest) {
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlDebug) log := testlog.Logger(t, log.LvlDebug)
require.Equal(t, dp.Secrets.Addresses().Batcher, dp.DeployConfig.BatchSenderAddress)
require.Equal(t, dp.Secrets.Addresses().Proposer, dp.DeployConfig.L2OutputOracleProposer)
miner, seqEngine, seq := setupSequencerTest(t, sd, log) miner, seqEngine, seq := setupSequencerTest(t, sd, log)
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{
MinL1TxSize: 0, MinL1TxSize: 0,
...@@ -77,7 +80,7 @@ func runCrossLayerUserTest(gt *testing.T, test regolithScheduledTest) { ...@@ -77,7 +80,7 @@ func runCrossLayerUserTest(gt *testing.T, test regolithScheduledTest) {
EthCl: l1Cl, EthCl: l1Cl,
Signer: types.LatestSigner(sd.L1Cfg.Config), Signer: types.LatestSigner(sd.L1Cfg.Config),
AddressCorpora: addresses, AddressCorpora: addresses,
Bindings: NewL1Bindings(t, l1Cl, &sd.DeploymentsL1), Bindings: NewL1Bindings(t, l1Cl),
} }
l2UserEnv := &BasicUserEnv[*L2Bindings]{ l2UserEnv := &BasicUserEnv[*L2Bindings]{
EthCl: l2Cl, EthCl: l2Cl,
......
...@@ -74,13 +74,13 @@ func TestERC20BridgeDeposits(t *testing.T) { ...@@ -74,13 +74,13 @@ func TestERC20BridgeDeposits(t *testing.T) {
require.NotNil(t, event) require.NotNil(t, event)
// Approve WETH9 with the bridge // Approve WETH9 with the bridge
tx, err = WETH9.Approve(opts, predeploys.DevL1StandardBridgeAddr, new(big.Int).SetUint64(math.MaxUint64)) tx, err = WETH9.Approve(opts, cfg.L1Deployments.L1StandardBridgeProxy, new(big.Int).SetUint64(math.MaxUint64))
require.NoError(t, err) require.NoError(t, err)
_, err = waitForTransaction(tx.Hash(), l1Client, 6*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) _, err = waitForTransaction(tx.Hash(), l1Client, 6*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.NoError(t, err) require.NoError(t, err)
// Bridge the WETH9 // Bridge the WETH9
l1StandardBridge, err := bindings.NewL1StandardBridge(predeploys.DevL1StandardBridgeAddr, l1Client) l1StandardBridge, err := bindings.NewL1StandardBridge(cfg.L1Deployments.L1StandardBridgeProxy, l1Client)
require.NoError(t, err) require.NoError(t, err)
tx, err = l1StandardBridge.BridgeERC20(opts, weth9Address, event.LocalToken, big.NewInt(100), 100000, []byte{}) tx, err = l1StandardBridge.BridgeERC20(opts, weth9Address, event.LocalToken, big.NewInt(100), 100000, []byte{})
require.NoError(t, err) require.NoError(t, err)
...@@ -90,7 +90,7 @@ func TestERC20BridgeDeposits(t *testing.T) { ...@@ -90,7 +90,7 @@ func TestERC20BridgeDeposits(t *testing.T) {
t.Log("Deposit through L1StandardBridge", "gas used", depositReceipt.GasUsed) t.Log("Deposit through L1StandardBridge", "gas used", depositReceipt.GasUsed)
// compute the deposit transaction hash + poll for it // compute the deposit transaction hash + poll for it
portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) portal, err := bindings.NewOptimismPortal(cfg.L1Deployments.OptimismPortalProxy, l1Client)
require.NoError(t, err) require.NoError(t, err)
depIt, err := portal.FilterTransactionDeposited(&bind.FilterOpts{Start: 0}, nil, nil, nil) depIt, err := portal.FilterTransactionDeposited(&bind.FilterOpts{Start: 0}, nil, nil, nil)
......
package config
import (
"flag"
"fmt"
"os"
"path/filepath"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/state"
)
var (
// All of the following variables are set in the init function
// and read from JSON files on disk that are generated by the
// foundry deploy script. The are globally exported to be used
// in end to end tests.
// L1Allocs represents the L1 genesis block state.
L1Allocs *state.Dump
// L1Deployments maps contract names to accounts in the L1
// genesis block state.
L1Deployments *genesis.L1Deployments
// DeployConfig represents the deploy config used by the system.
DeployConfig *genesis.DeployConfig
)
// Init testing to enable test flags
var _ = func() bool {
testing.Init()
return true
}()
func init() {
var l1AllocsPath, l1DeploymentsPath, deployConfigPath string
cwd, err := os.Getwd()
if err != nil {
panic(err)
}
root, err := findMonorepoRoot(cwd)
if err != nil {
panic(err)
}
defaultL1AllocsPath := filepath.Join(root, ".devnet", "allocs-l1.json")
defaultL1DeploymentsPath := filepath.Join(root, ".devnet", "addresses.json")
defaultDeployConfigPath := filepath.Join(root, "packages", "contracts-bedrock", "deploy-config", "devnetL1.json")
flag.StringVar(&l1AllocsPath, "l1-allocs", defaultL1AllocsPath, "")
flag.StringVar(&l1DeploymentsPath, "l1-deployments", defaultL1DeploymentsPath, "")
flag.StringVar(&deployConfigPath, "deploy-config", defaultDeployConfigPath, "")
flag.Parse()
if err := allExist(l1AllocsPath, l1DeploymentsPath, deployConfigPath); err != nil {
return
}
L1Allocs, err = genesis.NewStateDump(l1AllocsPath)
if err != nil {
panic(err)
}
L1Deployments, err = genesis.NewL1Deployments(l1DeploymentsPath)
if err != nil {
panic(err)
}
DeployConfig, err = genesis.NewDeployConfig(deployConfigPath)
if err != nil {
panic(err)
}
// Do not use clique in the in memory tests. Otherwise block building
// would be much more complex.
DeployConfig.L1UseClique = false
// Set the L1 genesis block timestamp to now
DeployConfig.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix())
DeployConfig.FundDevAccounts = true
// Speed up the in memory tests
DeployConfig.L1BlockTime = 2
DeployConfig.L2BlockTime = 1
if L1Deployments != nil {
DeployConfig.SetDeployments(L1Deployments)
}
}
func allExist(filenames ...string) error {
for _, filename := range filenames {
if _, err := os.Stat(filename); err != nil {
fmt.Printf("file %s does not exist, skipping genesis generation\n", filename)
return err
}
}
return nil
}
// findMonorepoRoot will recursively search upwards for a go.mod file.
// This depends on the structure of the monorepo having a go.mod file at the root.
func findMonorepoRoot(startDir string) (string, error) {
dir, err := filepath.Abs(startDir)
if err != nil {
return "", err
}
for {
modulePath := filepath.Join(dir, "go.mod")
if _, err := os.Stat(modulePath); err == nil {
return dir, nil
}
parentDir := filepath.Dir(dir)
// Check if we reached the filesystem root
if parentDir == dir {
break
}
dir = parentDir
}
return "", fmt.Errorf("monorepo root not found")
}
...@@ -11,6 +11,7 @@ func TestCollectAddresses(t *testing.T) { ...@@ -11,6 +11,7 @@ func TestCollectAddresses(t *testing.T) {
MaxSequencerDrift: 40, MaxSequencerDrift: 40,
SequencerWindowSize: 120, SequencerWindowSize: 120,
ChannelTimeout: 120, ChannelTimeout: 120,
L1BlockTime: 15,
} }
dp := MakeDeployParams(t, tp) dp := MakeDeployParams(t, tp)
alloc := &AllocParams{PrefundTestUsers: true} alloc := &AllocParams{PrefundTestUsers: true}
......
...@@ -14,14 +14,16 @@ import ( ...@@ -14,14 +14,16 @@ import (
// DefaultMnemonicConfig is the default mnemonic used in testing. // DefaultMnemonicConfig is the default mnemonic used in testing.
// We prefer a mnemonic rather than direct private keys to make it easier // We prefer a mnemonic rather than direct private keys to make it easier
// to export all testing keys in external tooling for use during debugging. // to export all testing keys in external tooling for use during debugging.
// If these values are changed, it is subject to breaking tests. They
// must be in sync with the values in the DeployConfig used to create the system.
var DefaultMnemonicConfig = &MnemonicConfig{ var DefaultMnemonicConfig = &MnemonicConfig{
Mnemonic: "test test test test test test test test test test test junk", Mnemonic: "test test test test test test test test test test test junk",
Deployer: "m/44'/60'/0'/0/1", CliqueSigner: "m/44'/60'/0'/0/0",
CliqueSigner: "m/44'/60'/0'/0/2", Proposer: "m/44'/60'/0'/0/1",
Proposer: "m/44'/60'/0'/0/3", Batcher: "m/44'/60'/0'/0/2",
Batcher: "m/44'/60'/0'/0/4", Deployer: "m/44'/60'/0'/0/3",
Alice: "m/44'/60'/0'/0/4",
SequencerP2P: "m/44'/60'/0'/0/5", SequencerP2P: "m/44'/60'/0'/0/5",
Alice: "m/44'/60'/0'/0/6",
Bob: "m/44'/60'/0'/0/7", Bob: "m/44'/60'/0'/0/7",
Mallory: "m/44'/60'/0'/0/8", Mallory: "m/44'/60'/0'/0/8",
SysCfgOwner: "m/44'/60'/0'/0/9", SysCfgOwner: "m/44'/60'/0'/0/9",
...@@ -32,8 +34,8 @@ var DefaultMnemonicConfig = &MnemonicConfig{ ...@@ -32,8 +34,8 @@ var DefaultMnemonicConfig = &MnemonicConfig{
type MnemonicConfig struct { type MnemonicConfig struct {
Mnemonic string Mnemonic string
Deployer string
CliqueSigner string CliqueSigner string
Deployer string
SysCfgOwner string SysCfgOwner string
// rollup actors // rollup actors
...@@ -97,8 +99,8 @@ func (m *MnemonicConfig) Secrets() (*Secrets, error) { ...@@ -97,8 +99,8 @@ func (m *MnemonicConfig) Secrets() (*Secrets, error) {
return &Secrets{ return &Secrets{
Deployer: deployer, Deployer: deployer,
CliqueSigner: cliqueSigner,
SysCfgOwner: sysCfgOwner, SysCfgOwner: sysCfgOwner,
CliqueSigner: cliqueSigner,
Proposer: proposer, Proposer: proposer,
Batcher: batcher, Batcher: batcher,
SequencerP2P: sequencerP2P, SequencerP2P: sequencerP2P,
......
...@@ -9,12 +9,11 @@ import ( ...@@ -9,12 +9,11 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
) )
...@@ -31,10 +30,6 @@ func WriteDefaultJWT(t TestingBase) string { ...@@ -31,10 +30,6 @@ func WriteDefaultJWT(t TestingBase) string {
return jwtPath return jwtPath
} }
func uint64ToBig(in uint64) *hexutil.Big {
return (*hexutil.Big)(new(big.Int).SetUint64(in))
}
// DeployParams bundles the deployment parameters to generate further testing inputs with. // DeployParams bundles the deployment parameters to generate further testing inputs with.
type DeployParams struct { type DeployParams struct {
DeployConfig *genesis.DeployConfig DeployConfig *genesis.DeployConfig
...@@ -56,73 +51,18 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { ...@@ -56,73 +51,18 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams {
secrets, err := mnemonicCfg.Secrets() secrets, err := mnemonicCfg.Secrets()
require.NoError(t, err) require.NoError(t, err)
addresses := secrets.Addresses() addresses := secrets.Addresses()
deployConfig := &genesis.DeployConfig{
L1ChainID: 901,
L2ChainID: 902,
L2BlockTime: 2,
MaxSequencerDrift: tp.MaxSequencerDrift,
SequencerWindowSize: tp.SequencerWindowSize,
ChannelTimeout: tp.ChannelTimeout,
P2PSequencerAddress: addresses.SequencerP2P,
BatchInboxAddress: common.Address{0: 0x42, 19: 0xff}, // tbd
BatchSenderAddress: addresses.Batcher,
L2OutputOracleSubmissionInterval: 6,
L2OutputOracleStartingTimestamp: -1,
L2OutputOracleProposer: addresses.Proposer,
L2OutputOracleChallenger: common.Address{}, // tbd
FinalSystemOwner: addresses.SysCfgOwner,
L1BlockTime: tp.L1BlockTime, deployConfig := config.DeployConfig.Copy()
L1GenesisBlockNonce: 0, deployConfig.MaxSequencerDrift = tp.MaxSequencerDrift
CliqueSignerAddress: common.Address{}, // proof of stake, no clique deployConfig.SequencerWindowSize = tp.SequencerWindowSize
L1GenesisBlockTimestamp: hexutil.Uint64(time.Now().Unix()), deployConfig.ChannelTimeout = tp.ChannelTimeout
L1GenesisBlockGasLimit: 30_000_000, deployConfig.L1BlockTime = tp.L1BlockTime
L1GenesisBlockDifficulty: uint64ToBig(1), deployConfig.L2GenesisRegolithTimeOffset = nil
L1GenesisBlockMixHash: common.Hash{},
L1GenesisBlockCoinbase: common.Address{},
L1GenesisBlockNumber: 0,
L1GenesisBlockGasUsed: 0,
L1GenesisBlockParentHash: common.Hash{},
L1GenesisBlockBaseFeePerGas: uint64ToBig(1000_000_000), // 1 gwei
FinalizationPeriodSeconds: 12,
L2GenesisBlockNonce: 0, require.NoError(t, deployConfig.Check())
L2GenesisBlockGasLimit: 30_000_000, require.Equal(t, addresses.Batcher, deployConfig.BatchSenderAddress)
L2GenesisBlockDifficulty: uint64ToBig(0), require.Equal(t, addresses.Proposer, deployConfig.L2OutputOracleProposer)
L2GenesisBlockMixHash: common.Hash{}, require.Equal(t, addresses.SequencerP2P, deployConfig.P2PSequencerAddress)
L2GenesisBlockNumber: 0,
L2GenesisBlockGasUsed: 0,
L2GenesisBlockParentHash: common.Hash{},
L2GenesisBlockBaseFeePerGas: uint64ToBig(1000_000_000),
GasPriceOracleOverhead: 2100,
GasPriceOracleScalar: 1000_000,
DeploymentWaitConfirmations: 1,
SequencerFeeVaultRecipient: common.Address{19: 1},
BaseFeeVaultRecipient: common.Address{19: 2},
L1FeeVaultRecipient: common.Address{19: 3},
BaseFeeVaultMinimumWithdrawalAmount: uint64ToBig(1000_000_000), // 1 gwei
L1FeeVaultMinimumWithdrawalAmount: uint64ToBig(1000_000_000), // 1 gwei
SequencerFeeVaultMinimumWithdrawalAmount: uint64ToBig(1000_000_000), // 1 gwei
BaseFeeVaultWithdrawalNetwork: genesis.WithdrawalNetwork("local"), // L2 withdrawal network
L1FeeVaultWithdrawalNetwork: genesis.WithdrawalNetwork("local"), // L2 withdrawal network
SequencerFeeVaultWithdrawalNetwork: genesis.WithdrawalNetwork("local"), // L2 withdrawal network
EIP1559Elasticity: 10,
EIP1559Denominator: 50,
FundDevAccounts: false,
}
// Configure the DeployConfig with the expected developer L1
// addresses.
if err := deployConfig.InitDeveloperDeployedAddresses(); err != nil {
panic(err)
}
return &DeployParams{ return &DeployParams{
DeployConfig: deployConfig, DeployConfig: deployConfig,
...@@ -132,23 +72,12 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { ...@@ -132,23 +72,12 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams {
} }
} }
// DeploymentsL1 captures the L1 addresses used in the deployment,
// commonly just the developer predeploys during testing,
// but later deployed contracts may be used in some tests too.
type DeploymentsL1 struct {
L1CrossDomainMessengerProxy common.Address
L1StandardBridgeProxy common.Address
L2OutputOracleProxy common.Address
OptimismPortalProxy common.Address
SystemConfigProxy common.Address
}
// SetupData bundles the L1, L2, rollup and deployment configuration data: everything for a full test setup. // SetupData bundles the L1, L2, rollup and deployment configuration data: everything for a full test setup.
type SetupData struct { type SetupData struct {
L1Cfg *core.Genesis L1Cfg *core.Genesis
L2Cfg *core.Genesis L2Cfg *core.Genesis
RollupCfg *rollup.Config RollupCfg *rollup.Config
DeploymentsL1 DeploymentsL1 DeploymentsL1 *genesis.L1Deployments
} }
// AllocParams defines genesis allocations to apply on top of the genesis generated by deploy parameters. // AllocParams defines genesis allocations to apply on top of the genesis generated by deploy parameters.
...@@ -169,8 +98,14 @@ func Ether(v uint64) *big.Int { ...@@ -169,8 +98,14 @@ func Ether(v uint64) *big.Int {
// Setup computes the testing setup configurations from deployment configuration and optional allocation parameters. // Setup computes the testing setup configurations from deployment configuration and optional allocation parameters.
func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *SetupData { func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *SetupData {
deployConf := deployParams.DeployConfig deployConf := deployParams.DeployConfig.Copy()
l1Genesis, err := genesis.BuildL1DeveloperGenesis(deployConf) deployConf.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix())
require.NoError(t, deployConf.Check())
l1Deployments := config.L1Deployments.Copy()
require.NoError(t, l1Deployments.Check())
l1Genesis, err := genesis.BuildL1DeveloperGenesis(deployConf, config.L1Allocs, l1Deployments, true)
require.NoError(t, err, "failed to create l1 genesis") require.NoError(t, err, "failed to create l1 genesis")
if alloc.PrefundTestUsers { if alloc.PrefundTestUsers {
for _, addr := range deployParams.Addresses.All() { for _, addr := range deployParams.Addresses.All() {
...@@ -218,18 +153,12 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) * ...@@ -218,18 +153,12 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
L1ChainID: new(big.Int).SetUint64(deployConf.L1ChainID), L1ChainID: new(big.Int).SetUint64(deployConf.L1ChainID),
L2ChainID: new(big.Int).SetUint64(deployConf.L2ChainID), L2ChainID: new(big.Int).SetUint64(deployConf.L2ChainID),
BatchInboxAddress: deployConf.BatchInboxAddress, BatchInboxAddress: deployConf.BatchInboxAddress,
DepositContractAddress: predeploys.DevOptimismPortalAddr, DepositContractAddress: deployConf.OptimismPortalProxy,
L1SystemConfigAddress: predeploys.DevSystemConfigAddr, L1SystemConfigAddress: deployConf.SystemConfigProxy,
RegolithTime: deployConf.RegolithTime(uint64(deployConf.L1GenesisBlockTimestamp)), RegolithTime: deployConf.RegolithTime(uint64(deployConf.L1GenesisBlockTimestamp)),
} }
deploymentsL1 := DeploymentsL1{ require.NoError(t, rollupCfg.Check())
L1CrossDomainMessengerProxy: predeploys.DevL1CrossDomainMessengerAddr,
L1StandardBridgeProxy: predeploys.DevL1StandardBridgeAddr,
L2OutputOracleProxy: predeploys.DevL2OutputOracleAddr,
OptimismPortalProxy: predeploys.DevOptimismPortalAddr,
SystemConfigProxy: predeploys.DevSystemConfigAddr,
}
// Sanity check that the config is correct // Sanity check that the config is correct
require.Equal(t, deployParams.Secrets.Addresses().Batcher, deployParams.DeployConfig.BatchSenderAddress) require.Equal(t, deployParams.Secrets.Addresses().Batcher, deployParams.DeployConfig.BatchSenderAddress)
...@@ -240,7 +169,7 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) * ...@@ -240,7 +169,7 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
L1Cfg: l1Genesis, L1Cfg: l1Genesis,
L2Cfg: l2Genesis, L2Cfg: l2Genesis,
RollupCfg: rollupCfg, RollupCfg: rollupCfg,
DeploymentsL1: deploymentsL1, DeploymentsL1: l1Deployments,
} }
} }
...@@ -252,46 +181,3 @@ func SystemConfigFromDeployConfig(deployConfig *genesis.DeployConfig) eth.System ...@@ -252,46 +181,3 @@ func SystemConfigFromDeployConfig(deployConfig *genesis.DeployConfig) eth.System
GasLimit: uint64(deployConfig.L2GenesisBlockGasLimit), GasLimit: uint64(deployConfig.L2GenesisBlockGasLimit),
} }
} }
// ForkedDeployConfig returns a deploy config that's suitable for use with a
// forked L1.
func ForkedDeployConfig(t require.TestingT, mnemonicCfg *MnemonicConfig, startBlock *types.Block) *genesis.DeployConfig {
startTag := rpc.BlockNumberOrHashWithHash(startBlock.Hash(), true)
secrets, err := mnemonicCfg.Secrets()
require.NoError(t, err)
addrs := secrets.Addresses()
marshalable := genesis.MarshalableRPCBlockNumberOrHash(startTag)
out := &genesis.DeployConfig{
L1StartingBlockTag: &marshalable,
L1ChainID: 1,
L2ChainID: 10,
L2BlockTime: 2,
MaxSequencerDrift: 3600,
SequencerWindowSize: 100,
ChannelTimeout: 40,
P2PSequencerAddress: addrs.SequencerP2P,
BatchInboxAddress: common.HexToAddress("0xff00000000000000000000000000000000000000"),
BatchSenderAddress: addrs.Batcher,
FinalSystemOwner: addrs.SysCfgOwner,
L1GenesisBlockDifficulty: uint64ToBig(0),
L1GenesisBlockBaseFeePerGas: uint64ToBig(0),
L2OutputOracleSubmissionInterval: 10,
L2OutputOracleStartingTimestamp: int(startBlock.Time()),
L2OutputOracleProposer: addrs.Proposer,
L2OutputOracleChallenger: addrs.Deployer,
L2GenesisBlockGasLimit: hexutil.Uint64(15_000_000),
// taken from devnet, need to check this
L2GenesisBlockBaseFeePerGas: uint64ToBig(0x3B9ACA00),
L2GenesisBlockDifficulty: uint64ToBig(0),
L1BlockTime: 12,
CliqueSignerAddress: addrs.CliqueSigner,
FinalizationPeriodSeconds: 2,
DeploymentWaitConfirmations: 1,
EIP1559Elasticity: 10,
EIP1559Denominator: 50,
GasPriceOracleOverhead: 2100,
GasPriceOracleScalar: 1_000_000,
FundDevAccounts: true,
}
return out
}
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-e2e/config"
) )
func TestWriteDefaultJWT(t *testing.T) { func TestWriteDefaultJWT(t *testing.T) {
...@@ -22,6 +23,7 @@ func TestSetup(t *testing.T) { ...@@ -22,6 +23,7 @@ func TestSetup(t *testing.T) {
MaxSequencerDrift: 40, MaxSequencerDrift: 40,
SequencerWindowSize: 120, SequencerWindowSize: 120,
ChannelTimeout: 120, ChannelTimeout: 120,
L1BlockTime: 15,
} }
dp := MakeDeployParams(t, tp) dp := MakeDeployParams(t, tp)
alloc := &AllocParams{PrefundTestUsers: true} alloc := &AllocParams{PrefundTestUsers: true}
...@@ -32,6 +34,6 @@ func TestSetup(t *testing.T) { ...@@ -32,6 +34,6 @@ func TestSetup(t *testing.T) {
require.Contains(t, sd.L2Cfg.Alloc, dp.Addresses.Alice) require.Contains(t, sd.L2Cfg.Alloc, dp.Addresses.Alice)
require.Equal(t, sd.L2Cfg.Alloc[dp.Addresses.Alice].Balance, Ether(1e12)) require.Equal(t, sd.L2Cfg.Alloc[dp.Addresses.Alice].Balance, Ether(1e12))
require.Contains(t, sd.L1Cfg.Alloc, predeploys.DevOptimismPortalAddr) require.Contains(t, sd.L1Cfg.Alloc, config.L1Deployments.OptimismPortalProxy)
require.Contains(t, sd.L2Cfg.Alloc, predeploys.L1BlockAddr) require.Contains(t, sd.L2Cfg.Alloc, predeploys.L1BlockAddr)
} }
...@@ -26,6 +26,11 @@ import ( ...@@ -26,6 +26,11 @@ import (
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
) )
var (
// errTimeout represents a timeout
errTimeout = errors.New("timeout")
)
func waitForL1OriginOnL2(l1BlockNum uint64, client *ethclient.Client, timeout time.Duration) (*types.Block, error) { func waitForL1OriginOnL2(l1BlockNum uint64, client *ethclient.Client, timeout time.Duration) (*types.Block, error) {
timeoutCh := time.After(timeout) timeoutCh := time.After(timeout)
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), timeout)
...@@ -56,7 +61,7 @@ func waitForL1OriginOnL2(l1BlockNum uint64, client *ethclient.Client, timeout ti ...@@ -56,7 +61,7 @@ func waitForL1OriginOnL2(l1BlockNum uint64, client *ethclient.Client, timeout ti
case err := <-headSub.Err(): case err := <-headSub.Err():
return nil, fmt.Errorf("error in head subscription: %w", err) return nil, fmt.Errorf("error in head subscription: %w", err)
case <-timeoutCh: case <-timeoutCh:
return nil, errors.New("timeout") return nil, errTimeout
} }
} }
} }
...@@ -77,7 +82,11 @@ func waitForTransaction(hash common.Hash, client *ethclient.Client, timeout time ...@@ -77,7 +82,11 @@ func waitForTransaction(hash common.Hash, client *ethclient.Client, timeout time
select { select {
case <-timeoutCh: case <-timeoutCh:
return nil, errors.New("timeout") tip, err := client.BlockByNumber(context.Background(), nil)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("receipt for transaction %s not found. tip block number is %d: %w", hash.Hex(), tip.NumberU64(), errTimeout)
case <-ticker.C: case <-ticker.C:
} }
} }
...@@ -104,7 +113,7 @@ func waitForBlock(number *big.Int, client *ethclient.Client, timeout time.Durati ...@@ -104,7 +113,7 @@ func waitForBlock(number *big.Int, client *ethclient.Client, timeout time.Durati
case err := <-headSub.Err(): case err := <-headSub.Err():
return nil, fmt.Errorf("error in head subscription: %w", err) return nil, fmt.Errorf("error in head subscription: %w", err)
case <-timeoutCh: case <-timeoutCh:
return nil, errors.New("timeout") return nil, errTimeout
} }
} }
} }
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
...@@ -49,7 +50,8 @@ type OpGeth struct { ...@@ -49,7 +50,8 @@ type OpGeth struct {
func NewOpGeth(t *testing.T, ctx context.Context, cfg *SystemConfig) (*OpGeth, error) { func NewOpGeth(t *testing.T, ctx context.Context, cfg *SystemConfig) (*OpGeth, error) {
logger := testlog.Logger(t, log.LvlCrit) logger := testlog.Logger(t, log.LvlCrit)
l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig)
l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments, true)
require.Nil(t, err) require.Nil(t, err)
l1Block := l1Genesis.ToBlock() l1Block := l1Genesis.ToBlock()
......
...@@ -33,6 +33,7 @@ import ( ...@@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -42,6 +43,7 @@ import ( ...@@ -42,6 +43,7 @@ import (
batchermetrics "github.com/ethereum-optimism/optimism/op-batcher/metrics" batchermetrics "github.com/ethereum-optimism/optimism/op-batcher/metrics"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
...@@ -78,81 +80,27 @@ func newTxMgrConfig(l1Addr string, privKey *ecdsa.PrivateKey) txmgr.CLIConfig { ...@@ -78,81 +80,27 @@ func newTxMgrConfig(l1Addr string, privKey *ecdsa.PrivateKey) txmgr.CLIConfig {
func DefaultSystemConfig(t *testing.T) SystemConfig { func DefaultSystemConfig(t *testing.T) SystemConfig {
secrets, err := e2eutils.DefaultMnemonicConfig.Secrets() secrets, err := e2eutils.DefaultMnemonicConfig.Secrets()
require.NoError(t, err) require.NoError(t, err)
addresses := secrets.Addresses() deployConfig := config.DeployConfig.Copy()
deployConfig.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix())
deployConfig := &genesis.DeployConfig{ require.NoError(t, deployConfig.Check())
L1ChainID: 900, l1Deployments := config.L1Deployments.Copy()
L2ChainID: 901, require.NoError(t, l1Deployments.Check())
L2BlockTime: 1,
FinalizationPeriodSeconds: 60 * 60 * 24,
MaxSequencerDrift: 10,
SequencerWindowSize: 30,
ChannelTimeout: 10,
P2PSequencerAddress: addresses.SequencerP2P,
BatchInboxAddress: common.Address{0: 0x52, 19: 0xff}, // tbd
BatchSenderAddress: addresses.Batcher,
L2OutputOracleSubmissionInterval: 4,
L2OutputOracleStartingTimestamp: -1,
L2OutputOracleProposer: addresses.Proposer,
L2OutputOracleChallenger: common.Address{}, // tbd
FinalSystemOwner: addresses.SysCfgOwner,
L1BlockTime: 2,
L1GenesisBlockNonce: 4660,
CliqueSignerAddress: common.Address{}, // op-e2e used to run Clique, but now uses fake Proof of Stake.
L1GenesisBlockTimestamp: hexutil.Uint64(time.Now().Unix()),
L1GenesisBlockGasLimit: 30_000_000,
L1GenesisBlockDifficulty: uint642big(1),
L1GenesisBlockMixHash: common.Hash{},
L1GenesisBlockCoinbase: common.Address{},
L1GenesisBlockNumber: 0,
L1GenesisBlockGasUsed: 0,
L1GenesisBlockParentHash: common.Hash{},
L1GenesisBlockBaseFeePerGas: uint642big(7),
L2GenesisBlockNonce: 0,
L2GenesisBlockGasLimit: 30_000_000,
L2GenesisBlockDifficulty: uint642big(1),
L2GenesisBlockMixHash: common.Hash{},
L2GenesisBlockNumber: 0,
L2GenesisBlockGasUsed: 0,
L2GenesisBlockParentHash: common.Hash{},
L2GenesisBlockBaseFeePerGas: uint642big(7),
GasPriceOracleOverhead: 2100,
GasPriceOracleScalar: 1_000_000,
SequencerFeeVaultRecipient: common.Address{19: 1},
BaseFeeVaultRecipient: common.Address{19: 2},
L1FeeVaultRecipient: common.Address{19: 3},
BaseFeeVaultMinimumWithdrawalAmount: uint642big(1000_000_000), // 1 gwei
L1FeeVaultMinimumWithdrawalAmount: uint642big(1000_000_000), // 1 gwei
SequencerFeeVaultMinimumWithdrawalAmount: uint642big(1000_000_000), // 1 gwei
BaseFeeVaultWithdrawalNetwork: genesis.WithdrawalNetwork("local"), // L2 withdrawal network
L1FeeVaultWithdrawalNetwork: genesis.WithdrawalNetwork("local"), // L2 withdrawal network
SequencerFeeVaultWithdrawalNetwork: genesis.WithdrawalNetwork("local"), // L2 withdrawal network
DeploymentWaitConfirmations: 1,
EIP1559Elasticity: 2,
EIP1559Denominator: 8,
FundDevAccounts: true,
}
if err := deployConfig.InitDeveloperDeployedAddresses(); err != nil {
panic(err)
}
return SystemConfig{ require.Equal(t, secrets.Addresses().Batcher, deployConfig.BatchSenderAddress)
Secrets: secrets, require.Equal(t, secrets.Addresses().SequencerP2P, deployConfig.P2PSequencerAddress)
require.Equal(t, secrets.Addresses().Proposer, deployConfig.L2OutputOracleProposer)
Premine: make(map[common.Address]*big.Int), // Tests depend on premine being filled with secrets addresses
premine := make(map[common.Address]*big.Int)
for _, addr := range secrets.Addresses().All() {
premine[addr] = new(big.Int).Mul(big.NewInt(1000), big.NewInt(params.Ether))
}
return SystemConfig{
Secrets: secrets,
Premine: premine,
DeployConfig: deployConfig, DeployConfig: deployConfig,
L1Deployments: config.L1Deployments,
L1InfoPredeployAddress: predeploys.L1BlockAddr, L1InfoPredeployAddress: predeploys.L1BlockAddr,
JWTFilePath: writeDefaultJWT(t), JWTFilePath: writeDefaultJWT(t),
JWTSecret: testingJWTSecret, JWTSecret: testingJWTSecret,
...@@ -169,7 +117,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { ...@@ -169,7 +117,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig {
ListenPort: 0, ListenPort: 0,
EnableAdmin: true, EnableAdmin: true,
}, },
L1EpochPollInterval: time.Second * 4, L1EpochPollInterval: time.Second * 2,
ConfigPersistence: &rollupNode.DisabledConfigPersistence{}, ConfigPersistence: &rollupNode.DisabledConfigPersistence{},
}, },
"verifier": { "verifier": {
...@@ -213,7 +161,8 @@ type SystemConfig struct { ...@@ -213,7 +161,8 @@ type SystemConfig struct {
Secrets *e2eutils.Secrets Secrets *e2eutils.Secrets
L1InfoPredeployAddress common.Address L1InfoPredeployAddress common.Address
DeployConfig *genesis.DeployConfig DeployConfig *genesis.DeployConfig
L1Deployments *genesis.L1Deployments
JWTFilePath string JWTFilePath string
JWTSecret [32]byte JWTSecret [32]byte
...@@ -355,7 +304,11 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { ...@@ -355,7 +304,11 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) {
c = sys.TimeTravelClock c = sys.TimeTravelClock
} }
l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig) if err := cfg.DeployConfig.Check(); err != nil {
return nil, err
}
l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -419,12 +372,15 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { ...@@ -419,12 +372,15 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) {
L1ChainID: cfg.L1ChainIDBig(), L1ChainID: cfg.L1ChainIDBig(),
L2ChainID: cfg.L2ChainIDBig(), L2ChainID: cfg.L2ChainIDBig(),
BatchInboxAddress: cfg.DeployConfig.BatchInboxAddress, BatchInboxAddress: cfg.DeployConfig.BatchInboxAddress,
DepositContractAddress: predeploys.DevOptimismPortalAddr, DepositContractAddress: cfg.DeployConfig.OptimismPortalProxy,
L1SystemConfigAddress: predeploys.DevSystemConfigAddr, L1SystemConfigAddress: cfg.DeployConfig.SystemConfigProxy,
RegolithTime: cfg.DeployConfig.RegolithTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), RegolithTime: cfg.DeployConfig.RegolithTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)),
} }
} }
defaultConfig := makeRollupConfig() defaultConfig := makeRollupConfig()
if err := defaultConfig.Check(); err != nil {
return nil, err
}
sys.RollupConfig = &defaultConfig sys.RollupConfig = &defaultConfig
// Initialize nodes // Initialize nodes
...@@ -620,11 +576,12 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { ...@@ -620,11 +576,12 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) {
if sys.RollupNodes["sequencer"] == nil { if sys.RollupNodes["sequencer"] == nil {
return sys, nil return sys, nil
} }
// L2Output Submitter // L2Output Submitter
sys.L2OutputSubmitter, err = l2os.NewL2OutputSubmitterFromCLIConfig(l2os.CLIConfig{ sys.L2OutputSubmitter, err = l2os.NewL2OutputSubmitterFromCLIConfig(l2os.CLIConfig{
L1EthRpc: sys.Nodes["l1"].WSEndpoint(), L1EthRpc: sys.Nodes["l1"].WSEndpoint(),
RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(),
L2OOAddress: predeploys.DevL2OutputOracleAddr.String(), L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(),
PollInterval: 50 * time.Millisecond, PollInterval: 50 * time.Millisecond,
TxMgrConfig: newTxMgrConfig(sys.Nodes["l1"].WSEndpoint(), cfg.Secrets.Proposer), TxMgrConfig: newTxMgrConfig(sys.Nodes["l1"].WSEndpoint(), cfg.Secrets.Proposer),
AllowNonFinalized: cfg.NonFinalizedProposals, AllowNonFinalized: cfg.NonFinalizedProposals,
...@@ -648,7 +605,7 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { ...@@ -648,7 +605,7 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) {
RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(),
MaxPendingTransactions: 0, MaxPendingTransactions: 0,
MaxChannelDuration: 1, MaxChannelDuration: 1,
MaxL1TxSize: 120_000, MaxL1TxSize: 240_000,
CompressorConfig: compressor.CLIConfig{ CompressorConfig: compressor.CLIConfig{
TargetL1TxSizeBytes: cfg.BatcherTargetL1TxSizeBytes, TargetL1TxSizeBytes: cfg.BatcherTargetL1TxSizeBytes,
TargetNumFrames: 1, TargetNumFrames: 1,
...@@ -762,12 +719,6 @@ func (cfg SystemConfig) L2ChainIDBig() *big.Int { ...@@ -762,12 +719,6 @@ func (cfg SystemConfig) L2ChainIDBig() *big.Int {
return new(big.Int).SetUint64(cfg.DeployConfig.L2ChainID) return new(big.Int).SetUint64(cfg.DeployConfig.L2ChainID)
} }
func uint642big(in uint64) *hexutil.Big {
b := new(big.Int).SetUint64(in)
hu := hexutil.Big(*b)
return &hu
}
func hexPriv(in *ecdsa.PrivateKey) string { func hexPriv(in *ecdsa.PrivateKey) string {
b := e2eutils.EncodePrivKey(in) b := e2eutils.EncodePrivKey(in)
return hexutil.Encode(b) return hexutil.Encode(b)
......
This diff is collapsed.
...@@ -52,7 +52,7 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) { ...@@ -52,7 +52,7 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) {
ethPrivKey := cfg.Secrets.SysCfgOwner ethPrivKey := cfg.Secrets.SysCfgOwner
// Bind to the SystemConfig & GasPriceOracle contracts // Bind to the SystemConfig & GasPriceOracle contracts
sysconfig, err := bindings.NewSystemConfig(predeploys.DevSystemConfigAddr, l1Client) sysconfig, err := bindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client)
require.Nil(t, err) require.Nil(t, err)
gpoContract, err := bindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, l2Seq) gpoContract, err := bindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, l2Seq)
require.Nil(t, err) require.Nil(t, err)
...@@ -247,7 +247,7 @@ func TestMixedDepositValidity(t *testing.T) { ...@@ -247,7 +247,7 @@ func TestMixedDepositValidity(t *testing.T) {
txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second
// Bind to the deposit contract // Bind to the deposit contract
depositContract, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) depositContract, err := bindings.NewOptimismPortal(cfg.L1Deployments.OptimismPortalProxy, l1Client)
require.NoError(t, err) require.NoError(t, err)
// Create a struct used to track our transactors and their transactions sent. // Create a struct used to track our transactors and their transactions sent.
...@@ -410,7 +410,9 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -410,7 +410,9 @@ func TestMixedWithdrawalValidity(t *testing.T) {
// Create our system configuration, funding all accounts we created for L1/L2, and start it // Create our system configuration, funding all accounts we created for L1/L2, and start it
cfg := DefaultSystemConfig(t) cfg := DefaultSystemConfig(t)
cfg.DeployConfig.FinalizationPeriodSeconds = 6 cfg.DeployConfig.L2BlockTime = 2
require.LessOrEqual(t, cfg.DeployConfig.FinalizationPeriodSeconds, uint64(6))
require.Equal(t, cfg.DeployConfig.FundDevAccounts, true)
sys, err := cfg.Start() sys, err := cfg.Start()
require.NoError(t, err, "error starting up system") require.NoError(t, err, "error starting up system")
defer sys.Close() defer sys.Close()
...@@ -421,14 +423,37 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -421,14 +423,37 @@ func TestMixedWithdrawalValidity(t *testing.T) {
l2Verif := sys.Clients["verifier"] l2Verif := sys.Clients["verifier"]
require.NoError(t, err) require.NoError(t, err)
systemConfig, err := bindings.NewSystemConfigCaller(cfg.L1Deployments.SystemConfig, l1Client)
require.NoError(t, err)
unsafeBlockSigner, err := systemConfig.UnsafeBlockSigner(nil)
require.NoError(t, err)
require.Equal(t, cfg.DeployConfig.P2PSequencerAddress, unsafeBlockSigner)
// The batcher has balance on L1
batcherBalance, err := l1Client.BalanceAt(context.Background(), cfg.DeployConfig.BatchSenderAddress, nil)
require.NoError(t, err)
require.NotEqual(t, batcherBalance, big.NewInt(0))
// The proposer has balance on L1
proposerBalance, err := l1Client.BalanceAt(context.Background(), cfg.DeployConfig.L2OutputOracleProposer, nil)
require.NoError(t, err)
require.NotEqual(t, proposerBalance, big.NewInt(0))
// Define our L1 transaction timeout duration. // Define our L1 transaction timeout duration.
txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second
// Bind to the deposit contract // Bind to the deposit contract
depositContract, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) depositContract, err := bindings.NewOptimismPortal(cfg.L1Deployments.OptimismPortalProxy, l1Client)
_ = depositContract _ = depositContract
require.NoError(t, err) require.NoError(t, err)
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(cfg.L1Deployments.L2OutputOracleProxy, l1Client)
require.NoError(t, err)
finalizationPeriod, err := l2OutputOracle.FINALIZATIONPERIODSECONDS(nil)
require.NoError(t, err)
require.Equal(t, cfg.DeployConfig.FinalizationPeriodSeconds, finalizationPeriod.Uint64())
// Create a struct used to track our transactors and their transactions sent. // Create a struct used to track our transactors and their transactions sent.
type TestAccountState struct { type TestAccountState struct {
Account *TestAccount Account *TestAccount
...@@ -439,11 +464,10 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -439,11 +464,10 @@ func TestMixedWithdrawalValidity(t *testing.T) {
} }
// Create a test account state for our transactor. // Create a test account state for our transactor.
transactorKey := cfg.Secrets.Alice
transactor := &TestAccountState{ transactor := &TestAccountState{
Account: &TestAccount{ Account: &TestAccount{
HDPath: e2eutils.DefaultMnemonicConfig.Alice, HDPath: e2eutils.DefaultMnemonicConfig.Alice,
Key: transactorKey, Key: cfg.Secrets.Alice,
L1Opts: nil, L1Opts: nil,
L2Opts: nil, L2Opts: nil,
}, },
...@@ -482,6 +506,9 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -482,6 +506,9 @@ func TestMixedWithdrawalValidity(t *testing.T) {
// Determine the address our request will come from // Determine the address our request will come from
fromAddr := crypto.PubkeyToAddress(transactor.Account.Key.PublicKey) fromAddr := crypto.PubkeyToAddress(transactor.Account.Key.PublicKey)
fromBalance, err := l2Verif.BalanceAt(context.Background(), fromAddr, nil)
require.NoError(t, err)
require.Greaterf(t, fromBalance.Uint64(), uint64(700_000_000_000), "insufficient balance for %s", fromAddr)
// Initiate Withdrawal // Initiate Withdrawal
withdrawAmount := big.NewInt(500_000_000_000) withdrawAmount := big.NewInt(500_000_000_000)
...@@ -489,9 +516,18 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -489,9 +516,18 @@ func TestMixedWithdrawalValidity(t *testing.T) {
tx, err := l2l1MessagePasser.InitiateWithdrawal(transactor.Account.L2Opts, fromAddr, big.NewInt(21000), nil) tx, err := l2l1MessagePasser.InitiateWithdrawal(transactor.Account.L2Opts, fromAddr, big.NewInt(21000), nil)
require.Nil(t, err, "sending initiate withdraw tx") require.Nil(t, err, "sending initiate withdraw tx")
t.Logf("Waiting for tx %s to be in sequencer", tx.Hash().Hex())
receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, txTimeoutDuration)
require.Nil(t, err, "withdrawal initiated on L2 sequencer")
require.Equal(t, receiptSeq.Status, types.ReceiptStatusSuccessful, "transaction failed")
verifierTip, err := l2Verif.BlockByNumber(context.Background(), nil)
require.Nil(t, err)
t.Logf("Waiting for tx %s to be in verifier. Verifier tip is %s:%d. Included in sequencer in block %s:%d", tx.Hash().Hex(), verifierTip.Hash().Hex(), verifierTip.NumberU64(), receiptSeq.BlockHash.Hex(), receiptSeq.BlockNumber)
// Wait for the transaction to appear in L2 verifier // Wait for the transaction to appear in L2 verifier
receipt, err := waitForTransaction(tx.Hash(), l2Verif, txTimeoutDuration) receipt, err := waitForTransaction(tx.Hash(), l2Verif, txTimeoutDuration)
require.Nil(t, err, "withdrawal initiated on L2 sequencer") require.Nilf(t, err, "withdrawal tx %s not found in verifier. included in block %s:%d", tx.Hash().Hex(), receiptSeq.BlockHash.Hex(), receiptSeq.BlockNumber)
require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed")
// Obtain the header for the block containing the transaction (used to calculate gas fees) // Obtain the header for the block containing the transaction (used to calculate gas fees)
...@@ -511,7 +547,8 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -511,7 +547,8 @@ func TestMixedWithdrawalValidity(t *testing.T) {
// Wait for the finalization period, then we can finalize this withdrawal. // Wait for the finalization period, then we can finalize this withdrawal.
ctx, cancel = context.WithTimeout(context.Background(), 40*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 40*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
blockNumber, err := withdrawals.WaitForOutputRootPublished(ctx, l1Client, predeploys.DevOptimismPortalAddr, receipt.BlockNumber) require.NotEqual(t, cfg.L1Deployments.L2OutputOracleProxy, common.Address{})
blockNumber, err := withdrawals.WaitForOutputRootPublished(ctx, l1Client, cfg.L1Deployments.L2OutputOracleProxy, receipt.BlockNumber)
cancel() cancel()
require.Nil(t, err) require.Nil(t, err)
...@@ -520,9 +557,6 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -520,9 +557,6 @@ func TestMixedWithdrawalValidity(t *testing.T) {
cancel() cancel()
require.Nil(t, err) require.Nil(t, err)
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client)
require.Nil(t, err)
rpcClient, err := rpc.Dial(sys.Nodes["verifier"].WSEndpoint()) rpcClient, err := rpc.Dial(sys.Nodes["verifier"].WSEndpoint())
require.Nil(t, err) require.Nil(t, err)
proofCl := gethclient.New(rpcClient) proofCl := gethclient.New(rpcClient)
...@@ -642,7 +676,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -642,7 +676,7 @@ func TestMixedWithdrawalValidity(t *testing.T) {
// Wait for finalization and then create the Finalized Withdrawal Transaction // Wait for finalization and then create the Finalized Withdrawal Transaction
ctx, cancel = context.WithTimeout(context.Background(), 45*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 45*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
defer cancel() defer cancel()
err = withdrawals.WaitForFinalizationPeriod(ctx, l1Client, predeploys.DevOptimismPortalAddr, header.Number) err = withdrawals.WaitForFinalizationPeriod(ctx, l1Client, cfg.L1Deployments.OptimismPortalProxy, header.Number)
require.Nil(t, err) require.Nil(t, err)
// Finalize withdrawal // Finalize withdrawal
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
"time" "time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"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"
...@@ -24,8 +24,9 @@ import ( ...@@ -24,8 +24,9 @@ import (
func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) { func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) {
l2Opts := defaultDepositTxOpts(l1Opts) l2Opts := defaultDepositTxOpts(l1Opts)
applyL2Opts(l2Opts) applyL2Opts(l2Opts)
// Find deposit contract // Find deposit contract
depositContract, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) depositContract, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client)
require.Nil(t, err) require.Nil(t, err)
// Finally send TX // Finally send TX
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -88,7 +89,7 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, ...@@ -88,7 +89,7 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client,
ctx, cancel := context.WithTimeout(context.Background(), 40*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 40*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
defer cancel() defer cancel()
blockNumber, err := withdrawals.WaitForOutputRootPublished(ctx, l1Client, predeploys.DevOptimismPortalAddr, l2WithdrawalReceipt.BlockNumber) blockNumber, err := withdrawals.WaitForOutputRootPublished(ctx, l1Client, config.L1Deployments.L2OutputOracleProxy, l2WithdrawalReceipt.BlockNumber)
require.Nil(t, err) require.Nil(t, err)
rpcClient, err := rpc.Dial(l2Node.WSEndpoint()) rpcClient, err := rpc.Dial(l2Node.WSEndpoint())
...@@ -103,13 +104,13 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, ...@@ -103,13 +104,13 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client,
require.Nil(t, err) require.Nil(t, err)
// Now create withdrawal // Now create withdrawal
oracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client) oracle, err := bindings.NewL2OutputOracleCaller(config.L1Deployments.L2OutputOracleProxy, l1Client)
require.Nil(t, err) require.Nil(t, err)
params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, l2WithdrawalReceipt.TxHash, header, oracle) params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, l2WithdrawalReceipt.TxHash, header, oracle)
require.Nil(t, err) require.Nil(t, err)
portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) portal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client)
require.Nil(t, err) require.Nil(t, err)
opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig())
...@@ -143,12 +144,13 @@ func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Clie ...@@ -143,12 +144,13 @@ func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Clie
// Wait for finalization and then create the Finalized Withdrawal Transaction // Wait for finalization and then create the Finalized Withdrawal Transaction
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
defer cancel() defer cancel()
err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, predeploys.DevOptimismPortalAddr, withdrawalProofReceipt.BlockNumber)
err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, config.L1Deployments.OptimismPortalProxy, withdrawalProofReceipt.BlockNumber)
require.Nil(t, err) require.Nil(t, err)
opts, err := bind.NewKeyedTransactorWithChainID(privKey, cfg.L1ChainIDBig()) opts, err := bind.NewKeyedTransactorWithChainID(privKey, cfg.L1ChainIDBig())
require.Nil(t, err) require.Nil(t, err)
portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) portal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client)
require.Nil(t, err) require.Nil(t, err)
// Finalize withdrawal // Finalize withdrawal
tx, err := portal.FinalizeWithdrawalTransaction( tx, err := portal.FinalizeWithdrawalTransaction(
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
...@@ -22,24 +23,25 @@ import ( ...@@ -22,24 +23,25 @@ import (
var Subcommands = cli.Commands{ var Subcommands = cli.Commands{
{ {
Name: "devnet", Name: "l1",
Usage: "Initialize new L1 and L2 genesis files and rollup config suitable for a local devnet", Usage: "Generates a L1 genesis state file",
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "deploy-config", Name: "deploy-config",
Usage: "Path to hardhat deploy config file", Usage: "Path to hardhat deploy config file",
Required: true,
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "outfile.l1", Name: "l1-allocs",
Usage: "Path to L1 genesis output file", Usage: "Path to L1 genesis state dump",
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "outfile.l2", Name: "l1-deployments",
Usage: "Path to L2 genesis output file", Usage: "Path to L1 deployments file",
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "outfile.rollup", Name: "outfile.l1",
Usage: "Path to rollup output file", Usage: "Path to L1 genesis output file",
}, },
}, },
Action: func(ctx *cli.Context) error { Action: func(ctx *cli.Context) error {
...@@ -49,39 +51,36 @@ var Subcommands = cli.Commands{ ...@@ -49,39 +51,36 @@ var Subcommands = cli.Commands{
return err return err
} }
// Add the developer L1 addresses to the config var deployments *genesis.L1Deployments
if err := config.InitDeveloperDeployedAddresses(); err != nil { if l1Deployments := ctx.String("l1-deployments"); l1Deployments != "" {
return err deployments, err = genesis.NewL1Deployments(l1Deployments)
if err != nil {
return err
}
} }
if err := config.Check(); err != nil { if deployments != nil {
return err config.SetDeployments(deployments)
} }
l1Genesis, err := genesis.BuildL1DeveloperGenesis(config) if err := config.Check(); err != nil {
if err != nil { return fmt.Errorf("deploy config at %s invalid: %w", deployConfig, err)
return err
} }
l1StartBlock := l1Genesis.ToBlock() var dump *state.Dump
l2Genesis, err := genesis.BuildL2Genesis(config, l1StartBlock) if l1Allocs := ctx.String("l1-allocs"); l1Allocs != "" {
if err != nil { dump, err = genesis.NewStateDump(l1Allocs)
return err if err != nil {
return err
}
} }
l2GenesisBlock := l2Genesis.ToBlock() l1Genesis, err := genesis.BuildL1DeveloperGenesis(config, dump, deployments, true)
rollupConfig, err := config.RollupConfig(l1StartBlock, l2GenesisBlock.Hash(), l2GenesisBlock.Number().Uint64())
if err != nil { if err != nil {
return err return err
} }
if err := writeGenesisFile(ctx.String("outfile.l1"), l1Genesis); err != nil { return writeGenesisFile(ctx.String("outfile.l1"), l1Genesis)
return err
}
if err := writeGenesisFile(ctx.String("outfile.l2"), l2Genesis); err != nil {
return err
}
return writeGenesisFile(ctx.String("outfile.rollup"), rollupConfig)
}, },
}, },
{ {
...@@ -161,10 +160,10 @@ var Subcommands = cli.Commands{ ...@@ -161,10 +160,10 @@ var Subcommands = cli.Commands{
log.Info("Using L1 Start Block", "number", l1StartBlock.Number(), "hash", l1StartBlock.Hash().Hex()) log.Info("Using L1 Start Block", "number", l1StartBlock.Number(), "hash", l1StartBlock.Hash().Hex())
// Build the developer L2 genesis block // Build the L2 genesis block
l2Genesis, err := genesis.BuildL2Genesis(config, l1StartBlock) l2Genesis, err := genesis.BuildL2Genesis(config, l1StartBlock)
if err != nil { if err != nil {
return fmt.Errorf("error creating l2 developer genesis: %w", err) return fmt.Errorf("error creating l2 genesis: %w", err)
} }
l2GenesisBlock := l2Genesis.ToBlock() l2GenesisBlock := l2Genesis.ToBlock()
......
...@@ -403,6 +403,11 @@ func (s *EthClient) GetStorageAt(ctx context.Context, address common.Address, st ...@@ -403,6 +403,11 @@ func (s *EthClient) GetStorageAt(ctx context.Context, address common.Address, st
// ReadStorageAt is a convenience method to read a single storage value at the given slot in the given account. // ReadStorageAt is a convenience method to read a single storage value at the given slot in the given account.
// The storage slot value is verified against the state-root of the given block if we do not trust the RPC provider, or directly retrieved without proof if we do trust the RPC. // The storage slot value is verified against the state-root of the given block if we do not trust the RPC provider, or directly retrieved without proof if we do trust the RPC.
func (s *EthClient) ReadStorageAt(ctx context.Context, address common.Address, storageSlot common.Hash, blockHash common.Hash) (common.Hash, error) { func (s *EthClient) ReadStorageAt(ctx context.Context, address common.Address, storageSlot common.Hash, blockHash common.Hash) (common.Hash, error) {
// TODO: temp
if true {
return s.GetStorageAt(ctx, address, storageSlot, blockHash.String())
}
if s.trustRPC { if s.trustRPC {
return s.GetStorageAt(ctx, address, storageSlot, blockHash.String()) return s.GetStorageAt(ctx, address, storageSlot, blockHash.String())
} }
......
...@@ -26,11 +26,11 @@ var MessagePassedTopic = crypto.Keccak256Hash([]byte("MessagePassed(uint256,addr ...@@ -26,11 +26,11 @@ var MessagePassedTopic = crypto.Keccak256Hash([]byte("MessagePassed(uint256,addr
// WaitForOutputRootPublished waits until there is an output published for an L2 block number larger than the supplied l2BlockNumber // WaitForOutputRootPublished waits until there is an output published for an L2 block number larger than the supplied l2BlockNumber
// This function polls and can block for a very long time if used on mainnet. // This function polls and can block for a very long time if used on mainnet.
// This returns the block number to use for proof generation. // This returns the block number to use for proof generation.
func WaitForOutputRootPublished(ctx context.Context, client *ethclient.Client, portalAddr common.Address, l2BlockNumber *big.Int) (uint64, error) { func WaitForOutputRootPublished(ctx context.Context, client *ethclient.Client, l2OutputOracleAddr common.Address, l2BlockNumber *big.Int) (uint64, error) {
l2BlockNumber = new(big.Int).Set(l2BlockNumber) // Don't clobber caller owned l2BlockNumber l2BlockNumber = new(big.Int).Set(l2BlockNumber) // Don't clobber caller owned l2BlockNumber
opts := &bind.CallOpts{Context: ctx} opts := &bind.CallOpts{Context: ctx}
l2OO, err := createL2OOCaller(ctx, client, portalAddr) l2OO, err := bindings.NewL2OutputOracleCaller(l2OutputOracleAddr, client)
if err != nil { if err != nil {
return 0, err return 0, err
} }
......
...@@ -132,6 +132,15 @@ services: ...@@ -132,6 +132,15 @@ services:
OP_BATCHER_METRICS_ENABLED: "true" OP_BATCHER_METRICS_ENABLED: "true"
OP_BATCHER_RPC_ENABLE_ADMIN: "true" OP_BATCHER_RPC_ENABLE_ADMIN: "true"
artifact-server:
depends_on:
- l1
image: nginx:1.25-alpine
ports:
- "8080:80"
volumes:
- "${PWD}/../.devnet/:/usr/share/nginx/html/"
stateviz: stateviz:
build: build:
context: ../ context: ../
......
...@@ -7,8 +7,8 @@ GETH_CHAINDATA_DIR="$GETH_DATA_DIR/geth/chaindata" ...@@ -7,8 +7,8 @@ GETH_CHAINDATA_DIR="$GETH_DATA_DIR/geth/chaindata"
GETH_KEYSTORE_DIR="$GETH_DATA_DIR/keystore" GETH_KEYSTORE_DIR="$GETH_DATA_DIR/keystore"
GENESIS_FILE_PATH="${GENESIS_FILE_PATH:-/genesis.json}" GENESIS_FILE_PATH="${GENESIS_FILE_PATH:-/genesis.json}"
CHAIN_ID=$(cat "$GENESIS_FILE_PATH" | jq -r .config.chainId) CHAIN_ID=$(cat "$GENESIS_FILE_PATH" | jq -r .config.chainId)
BLOCK_SIGNER_PRIVATE_KEY="3e4bde571b86929bf08e2aaad9a6a1882664cd5e65b96fff7d03e1c4e6dfa15c" BLOCK_SIGNER_PRIVATE_KEY="ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
BLOCK_SIGNER_ADDRESS="0xca062b0fd91172d89bcd4bb084ac4e21972cc467" BLOCK_SIGNER_ADDRESS="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
RPC_PORT="${RPC_PORT:-8545}" RPC_PORT="${RPC_PORT:-8545}"
WS_PORT="${WS_PORT:-8546}" WS_PORT="${WS_PORT:-8546}"
......
...@@ -25,3 +25,4 @@ deployments/901 ...@@ -25,3 +25,4 @@ deployments/901
deployments/hardhat deployments/hardhat
deployments/getting-started deployments/getting-started
deployments/*/.deploy deployments/*/.deploy
deployments/1337
{ {
"l1ChainID": 900, "l1ChainID": 901,
"l2ChainID": 901, "l2ChainID": 902,
"l2BlockTime": 2, "l2BlockTime": 2,
"maxSequencerDrift": 300, "maxSequencerDrift": 300,
"sequencerWindowSize": 200, "sequencerWindowSize": 200,
"channelTimeout": 120, "channelTimeout": 120,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", "p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"batchInboxAddress": "0xff00000000000000000000000000000000000000", "batchInboxAddress": "0xff00000000000000000000000000000000000901",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", "batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
"l2OutputOracleSubmissionInterval": 20, "cliqueSignerAddress": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"l2OutputOracleStartingTimestamp": -1, "l1UseClique": true,
"l1StartingBlockTag": "earliest",
"l2OutputOracleSubmissionInterval": 6,
"l2OutputOracleStartingTimestamp": 0,
"l2OutputOracleStartingBlockNumber": 0, "l2OutputOracleStartingBlockNumber": 0,
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l2OutputOracleChallenger": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", "l2OutputOracleChallenger": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65",
"l2GenesisBlockGasLimit": "0x1c9c380", "l2GenesisBlockGasLimit": "0x1c9c380",
"l1BlockTime": 3, "l1BlockTime": 3,
"cliqueSignerAddress": "0xca062b0fd91172d89bcd4bb084ac4e21972cc467", "baseFeeVaultRecipient": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955",
"baseFeeVaultRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "l1FeeVaultRecipient": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f",
"l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788", "sequencerFeeVaultRecipient": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"sequencerFeeVaultRecipient": "0xfabb0ac9d68b0b445fb7357272ff202c5651694a",
"baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"baseFeeVaultWithdrawalNetwork": 0, "baseFeeVaultWithdrawalNetwork": "remote",
"l1FeeVaultWithdrawalNetwork": 0, "l1FeeVaultWithdrawalNetwork": "remote",
"sequencerFeeVaultWithdrawalNetwork": 0, "sequencerFeeVaultWithdrawalNetwork": "remote",
"proxyAdminOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "proxyAdminOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"finalSystemOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "finalSystemOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"portalGuardian": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "portalGuardian": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"finalizationPeriodSeconds": 2, "finalizationPeriodSeconds": 2,
"deploymentWaitConfirmations": 1,
"fundDevAccounts": true, "fundDevAccounts": true,
"l2GenesisBlockBaseFeePerGas": "0x3B9ACA00", "l2GenesisBlockBaseFeePerGas": "0x1",
"gasPriceOracleOverhead": 2100, "gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000, "gasPriceOracleScalar": 1000000,
"enableGovernance": true, "enableGovernance": true,
"governanceTokenSymbol": "OP", "governanceTokenSymbol": "OP",
"governanceTokenName": "Optimism", "governanceTokenName": "Optimism",
"governanceTokenOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "governanceTokenOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"eip1559Denominator": 8, "eip1559Denominator": 50,
"eip1559Elasticity": 2, "eip1559Elasticity": 6,
"l1GenesisBlockTimestamp": "0x64935846", "l1GenesisBlockTimestamp": "0x64c811bf",
"l1StartingBlockTag": "earliest",
"l2GenesisRegolithTimeOffset": "0x0", "l2GenesisRegolithTimeOffset": "0x0",
"faultGameAbsolutePrestate": 96, "faultGameAbsolutePrestate": 96,
"faultGameMaxDepth": 4, "faultGameMaxDepth": 4,
"faultGameMaxDuration": 120 "faultGameMaxDuration": 120
} }
\ No newline at end of file
...@@ -246,7 +246,7 @@ contract Deploy is Deployer { ...@@ -246,7 +246,7 @@ contract Deploy is Deployer {
/// @notice Deploy the DisputeGameFactoryProxy /// @notice Deploy the DisputeGameFactoryProxy
function deployDisputeGameFactoryProxy() broadcast() public returns (address) { function deployDisputeGameFactoryProxy() broadcast() public returns (address) {
if (block.chainid == 900) { if (block.chainid == 901 || block.chainid == 1337) {
address proxyAdmin = mustGetAddress("ProxyAdmin"); address proxyAdmin = mustGetAddress("ProxyAdmin");
Proxy proxy = new Proxy({ Proxy proxy = new Proxy({
_admin: proxyAdmin _admin: proxyAdmin
...@@ -347,7 +347,7 @@ contract Deploy is Deployer { ...@@ -347,7 +347,7 @@ contract Deploy is Deployer {
/// @notice Deploy the DisputeGameFactory /// @notice Deploy the DisputeGameFactory
function deployDisputeGameFactory() broadcast() public returns (address) { function deployDisputeGameFactory() broadcast() public returns (address) {
if (block.chainid == 900) { if (block.chainid == 901 || block.chainid == 1337) {
DisputeGameFactory factory = new DisputeGameFactory(); DisputeGameFactory factory = new DisputeGameFactory();
save("DisputeGameFactory", address(factory)); save("DisputeGameFactory", address(factory));
console.log("DisputeGameFactory deployed at %s", address(factory)); console.log("DisputeGameFactory deployed at %s", address(factory));
...@@ -442,7 +442,7 @@ contract Deploy is Deployer { ...@@ -442,7 +442,7 @@ contract Deploy is Deployer {
/// @notice Initialize the DisputeGameFactory /// @notice Initialize the DisputeGameFactory
function initializeDisputeGameFactory() broadcast() public { function initializeDisputeGameFactory() broadcast() public {
if (block.chainid == 900) { if (block.chainid == 901 || block.chainid == 1337) {
ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin")); ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy"); address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy");
address disputeGameFactory = mustGetAddress("DisputeGameFactory"); address disputeGameFactory = mustGetAddress("DisputeGameFactory");
...@@ -676,7 +676,7 @@ contract Deploy is Deployer { ...@@ -676,7 +676,7 @@ contract Deploy is Deployer {
/// @notice Transfer ownership of the DisputeGameFactory contract to the final system owner /// @notice Transfer ownership of the DisputeGameFactory contract to the final system owner
function transferDisputeGameFactoryOwnership() broadcast() public { function transferDisputeGameFactoryOwnership() broadcast() public {
if (block.chainid == 900) { if (block.chainid == 901 || block.chainid == 1337) {
DisputeGameFactory disputeGameFactory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); DisputeGameFactory disputeGameFactory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
address owner = disputeGameFactory.owner(); address owner = disputeGameFactory.owner();
address finalSystemOwner = cfg.finalSystemOwner(); address finalSystemOwner = cfg.finalSystemOwner();
...@@ -689,7 +689,7 @@ contract Deploy is Deployer { ...@@ -689,7 +689,7 @@ contract Deploy is Deployer {
/// @notice Sets the implementation for the `FAULT` game type in the `DisputeGameFactory` /// @notice Sets the implementation for the `FAULT` game type in the `DisputeGameFactory`
function setFaultGameImplementation() broadcast() public { function setFaultGameImplementation() broadcast() public {
if (block.chainid == 900) { if (block.chainid == 901 || block.chainid == 1337) {
DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
Claim absolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())); Claim absolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate()));
IBigStepper faultVm = IBigStepper(new AlphabetVM(absolutePrestate)); IBigStepper faultVm = IBigStepper(new AlphabetVM(absolutePrestate));
......
...@@ -87,7 +87,7 @@ contract DeployConfig is Script { ...@@ -87,7 +87,7 @@ contract DeployConfig is Script {
eip1559Denominator = stdJson.readUint(_json, "$.eip1559Denominator"); eip1559Denominator = stdJson.readUint(_json, "$.eip1559Denominator");
eip1559Elasticity = stdJson.readUint(_json, "$.eip1559Elasticity"); eip1559Elasticity = stdJson.readUint(_json, "$.eip1559Elasticity");
if (block.chainid == 900) { if (block.chainid == 901 || block.chainid == 1337) {
faultGameAbsolutePrestate = stdJson.readUint(_json, "$.faultGameAbsolutePrestate"); faultGameAbsolutePrestate = stdJson.readUint(_json, "$.faultGameAbsolutePrestate");
faultGameMaxDepth = stdJson.readUint(_json, "$.faultGameMaxDepth"); faultGameMaxDepth = stdJson.readUint(_json, "$.faultGameMaxDepth");
faultGameMaxDuration = stdJson.readUint(_json, "$.faultGameMaxDuration"); faultGameMaxDuration = stdJson.readUint(_json, "$.faultGameMaxDuration");
......
...@@ -71,19 +71,21 @@ abstract contract Deployer is Script { ...@@ -71,19 +71,21 @@ abstract contract Deployer is Script {
deploymentContext = _getDeploymentContext(); deploymentContext = _getDeploymentContext();
string memory deployFile = vm.envOr("DEPLOY_FILE", string("run-latest.json")); string memory deployFile = vm.envOr("DEPLOY_FILE", string("run-latest.json"));
deployPath = string.concat(root, "/broadcast/", deployScript, ".s.sol/", vm.toString(block.chainid), "/", deployFile); uint256 chainId = vm.envOr("CHAIN_ID", block.chainid);
deployPath = string.concat(root, "/broadcast/", deployScript, ".s.sol/", vm.toString(chainId), "/", deployFile);
deploymentsDir = string.concat(root, "/deployments/", deploymentContext); deploymentsDir = string.concat(root, "/deployments/", deploymentContext);
try vm.createDir(deploymentsDir, true) {} catch (bytes memory) {} try vm.createDir(deploymentsDir, true) {} catch (bytes memory) {}
string memory chainIdPath = string.concat(deploymentsDir, "/.chainId"); string memory chainIdPath = string.concat(deploymentsDir, "/.chainId");
try vm.readFile(chainIdPath) returns (string memory chainid) { try vm.readFile(chainIdPath) returns (string memory localChainId) {
uint256 chainId = vm.parseUint(chainid); if (vm.envOr("STRICT_DEPLOYMENT", true)) {
require(chainId == block.chainid, "Misconfigured networks"); require(vm.parseUint(localChainId) == chainId, "Misconfigured networks");
}
} catch { } catch {
vm.writeFile(chainIdPath, vm.toString(block.chainid)); vm.writeFile(chainIdPath, vm.toString(chainId));
} }
console.log("Connected to network with chainid %s", block.chainid); console.log("Connected to network with chainid %s", chainId);
tempDeploymentsPath = string.concat(deploymentsDir, "/.deploy"); tempDeploymentsPath = string.concat(deploymentsDir, "/.deploy");
try vm.readFile(tempDeploymentsPath) returns (string memory) {} catch { try vm.readFile(tempDeploymentsPath) returns (string memory) {} catch {
...@@ -432,7 +434,7 @@ abstract contract Deployer is Script { ...@@ -432,7 +434,7 @@ abstract contract Deployer is Script {
return context; return context;
} }
uint256 chainid = block.chainid; uint256 chainid = vm.envOr("CHAIN_ID", block.chainid);
if (chainid == 1) { if (chainid == 1) {
return "mainnet"; return "mainnet";
} else if (chainid == 5) { } else if (chainid == 5) {
...@@ -441,7 +443,7 @@ abstract contract Deployer is Script { ...@@ -441,7 +443,7 @@ abstract contract Deployer is Script {
return "optimism-goerli"; return "optimism-goerli";
} else if (chainid == 10) { } else if (chainid == 10) {
return "optimism-mainnet"; return "optimism-mainnet";
} else if (chainid == 900) { } else if (chainid == 901 || chainid == 1337) {
return "devnetL1"; return "devnetL1";
} else if (chainid == 31337) { } else if (chainid == 31337) {
return "hardhat"; return "hardhat";
......
...@@ -16,7 +16,7 @@ export enum L1ChainID { ...@@ -16,7 +16,7 @@ export enum L1ChainID {
MAINNET = 1, MAINNET = 1,
GOERLI = 5, GOERLI = 5,
HARDHAT_LOCAL = 31337, HARDHAT_LOCAL = 31337,
BEDROCK_LOCAL_DEVNET = 900, BEDROCK_LOCAL_DEVNET = 901,
} }
/** /**
...@@ -27,7 +27,6 @@ export enum L2ChainID { ...@@ -27,7 +27,6 @@ export enum L2ChainID {
OPTIMISM_GOERLI = 420, OPTIMISM_GOERLI = 420,
OPTIMISM_HARDHAT_LOCAL = 31337, OPTIMISM_HARDHAT_LOCAL = 31337,
OPTIMISM_HARDHAT_DEVNET = 17, OPTIMISM_HARDHAT_DEVNET = 17,
OPTIMISM_BEDROCK_LOCAL_DEVNET = 901,
OPTIMISM_BEDROCK_ALPHA_TESTNET = 28528, OPTIMISM_BEDROCK_ALPHA_TESTNET = 28528,
BASE_GOERLI = 84531, BASE_GOERLI = 84531,
BASE_MAINNET = 8453, BASE_MAINNET = 8453,
......
...@@ -69,7 +69,6 @@ export const DEPOSIT_CONFIRMATION_BLOCKS: { ...@@ -69,7 +69,6 @@ export const DEPOSIT_CONFIRMATION_BLOCKS: {
[L2ChainID.OPTIMISM_GOERLI]: 12 as const, [L2ChainID.OPTIMISM_GOERLI]: 12 as const,
[L2ChainID.OPTIMISM_HARDHAT_LOCAL]: 2 as const, [L2ChainID.OPTIMISM_HARDHAT_LOCAL]: 2 as const,
[L2ChainID.OPTIMISM_HARDHAT_DEVNET]: 2 as const, [L2ChainID.OPTIMISM_HARDHAT_DEVNET]: 2 as const,
[L2ChainID.OPTIMISM_BEDROCK_LOCAL_DEVNET]: 2 as const,
[L2ChainID.OPTIMISM_BEDROCK_ALPHA_TESTNET]: 12 as const, [L2ChainID.OPTIMISM_BEDROCK_ALPHA_TESTNET]: 12 as const,
[L2ChainID.BASE_GOERLI]: 12 as const, [L2ChainID.BASE_GOERLI]: 12 as const,
[L2ChainID.BASE_MAINNET]: 50 as const, [L2ChainID.BASE_MAINNET]: 50 as const,
...@@ -171,22 +170,6 @@ export const CONTRACT_ADDRESSES: { ...@@ -171,22 +170,6 @@ export const CONTRACT_ADDRESSES: {
}, },
l2: DEFAULT_L2_CONTRACT_ADDRESSES, l2: DEFAULT_L2_CONTRACT_ADDRESSES,
}, },
[L2ChainID.OPTIMISM_BEDROCK_LOCAL_DEVNET]: {
l1: {
AddressManager: '0x6900000000000000000000000000000000000005' as const,
L1CrossDomainMessenger:
'0x6900000000000000000000000000000000000002' as const,
L1StandardBridge: '0x6900000000000000000000000000000000000003' as const,
StateCommitmentChain:
'0x0000000000000000000000000000000000000000' as const,
CanonicalTransactionChain:
'0x0000000000000000000000000000000000000000' as const,
BondManager: '0x0000000000000000000000000000000000000000' as const,
OptimismPortal: '0x6900000000000000000000000000000000000001' as const,
L2OutputOracle: '0x6900000000000000000000000000000000000000' as const,
},
l2: DEFAULT_L2_CONTRACT_ADDRESSES,
},
[L2ChainID.OPTIMISM_BEDROCK_ALPHA_TESTNET]: { [L2ChainID.OPTIMISM_BEDROCK_ALPHA_TESTNET]: {
l1: { l1: {
AddressManager: '0xb4e08DcE1F323608229265c9d4125E22a4B9dbAF' as const, AddressManager: '0xb4e08DcE1F323608229265c9d4125E22a4B9dbAF' as const,
......
...@@ -4,7 +4,7 @@ import { task, types } from 'hardhat/config' ...@@ -4,7 +4,7 @@ import { task, types } from 'hardhat/config'
import { HardhatRuntimeEnvironment } from 'hardhat/types' import { HardhatRuntimeEnvironment } from 'hardhat/types'
import '@nomiclabs/hardhat-ethers' import '@nomiclabs/hardhat-ethers'
import 'hardhat-deploy' import 'hardhat-deploy'
import { Event, Contract, Wallet, providers, utils } from 'ethers' import { Event, Contract, Wallet, providers, utils, ethers } from 'ethers'
import { predeploys, sleep } from '@eth-optimism/core-utils' import { predeploys, sleep } from '@eth-optimism/core-utils'
import Artifact__WETH9 from '@eth-optimism/contracts-bedrock/forge-artifacts/WETH9.sol/WETH9.json' import Artifact__WETH9 from '@eth-optimism/contracts-bedrock/forge-artifacts/WETH9.sol/WETH9.json'
import Artifact__OptimismMintableERC20TokenFactory from '@eth-optimism/contracts-bedrock/forge-artifacts/OptimismMintableERC20Factory.sol/OptimismMintableERC20Factory.json' import Artifact__OptimismMintableERC20TokenFactory from '@eth-optimism/contracts-bedrock/forge-artifacts/OptimismMintableERC20Factory.sol/OptimismMintableERC20Factory.json'
...@@ -15,6 +15,7 @@ import Artifact__L2StandardBridge from '@eth-optimism/contracts-bedrock/forge-ar ...@@ -15,6 +15,7 @@ import Artifact__L2StandardBridge from '@eth-optimism/contracts-bedrock/forge-ar
import Artifact__OptimismPortal from '@eth-optimism/contracts-bedrock/forge-artifacts/OptimismPortal.sol/OptimismPortal.json' import Artifact__OptimismPortal from '@eth-optimism/contracts-bedrock/forge-artifacts/OptimismPortal.sol/OptimismPortal.json'
import Artifact__L1CrossDomainMessenger from '@eth-optimism/contracts-bedrock/forge-artifacts/L1CrossDomainMessenger.sol/L1CrossDomainMessenger.json' import Artifact__L1CrossDomainMessenger from '@eth-optimism/contracts-bedrock/forge-artifacts/L1CrossDomainMessenger.sol/L1CrossDomainMessenger.json'
import Artifact__L1StandardBridge from '@eth-optimism/contracts-bedrock/forge-artifacts/L1StandardBridge.sol/L1StandardBridge.json' import Artifact__L1StandardBridge from '@eth-optimism/contracts-bedrock/forge-artifacts/L1StandardBridge.sol/L1StandardBridge.json'
import Artifact__L2OutputOracle from '@eth-optimism/contracts-bedrock/forge-artifacts/L2OutputOracle.sol/L2OutputOracle.json'
import { import {
CrossChainMessenger, CrossChainMessenger,
...@@ -144,30 +145,51 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.') ...@@ -144,30 +145,51 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.')
let contractAddrs = CONTRACT_ADDRESSES[l2ChainId] let contractAddrs = CONTRACT_ADDRESSES[l2ChainId]
if (args.l1ContractsJsonPath) { if (args.l1ContractsJsonPath) {
const data = await fs.readFile(args.l1ContractsJsonPath) const data = await fs.readFile(args.l1ContractsJsonPath)
const json = JSON.parse(data.toString())
contractAddrs = { contractAddrs = {
l1: JSON.parse(data.toString()), l1: {
AddressManager: json.AddressManager,
L1CrossDomainMessenger: json.L1CrossDomainMessengerProxy,
L1StandardBridge: json.L1StandardBridgeProxy,
StateCommitmentChain: ethers.constants.AddressZero,
CanonicalTransactionChain: ethers.constants.AddressZero,
BondManager: ethers.constants.AddressZero,
OptimismPortal: json.OptimismPortalProxy,
L2OutputOracle: json.L2OutputOracleProxy,
},
l2: DEFAULT_L2_CONTRACT_ADDRESSES, l2: DEFAULT_L2_CONTRACT_ADDRESSES,
} as OEContractsLike } as OEContractsLike
} }
console.log(`OptimismPortal: ${contractAddrs.l1.OptimismPortal}`)
const OptimismPortal = new hre.ethers.Contract( const OptimismPortal = new hre.ethers.Contract(
contractAddrs.l1.OptimismPortal, contractAddrs.l1.OptimismPortal,
Artifact__OptimismPortal.abi, Artifact__OptimismPortal.abi,
signer signer
) )
console.log(
`L1CrossDomainMessenger: ${contractAddrs.l1.L1CrossDomainMessenger}`
)
const L1CrossDomainMessenger = new hre.ethers.Contract( const L1CrossDomainMessenger = new hre.ethers.Contract(
contractAddrs.l1.L1CrossDomainMessenger, contractAddrs.l1.L1CrossDomainMessenger,
Artifact__L1CrossDomainMessenger.abi, Artifact__L1CrossDomainMessenger.abi,
signer signer
) )
console.log(`L1StandardBridge: ${contractAddrs.l1.L1StandardBridge}`)
const L1StandardBridge = new hre.ethers.Contract( const L1StandardBridge = new hre.ethers.Contract(
contractAddrs.l1.L1StandardBridge, contractAddrs.l1.L1StandardBridge,
Artifact__L1StandardBridge.abi, Artifact__L1StandardBridge.abi,
signer signer
) )
const L2OutputOracle = new hre.ethers.Contract(
contractAddrs.l1.L2OutputOracle,
Artifact__L2OutputOracle.abi,
signer
)
const L2ToL1MessagePasser = new hre.ethers.Contract( const L2ToL1MessagePasser = new hre.ethers.Contract(
predeploys.L2ToL1MessagePasser, predeploys.L2ToL1MessagePasser,
Artifact__L2ToL1MessagePasser.abi Artifact__L2ToL1MessagePasser.abi
...@@ -192,6 +214,10 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.') ...@@ -192,6 +214,10 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.')
contracts: contractAddrs, contracts: contractAddrs,
}) })
const params = await OptimismPortal.params()
console.log('Intial OptimismPortal.params:')
console.log(params)
console.log('Deploying WETH9 to L1') console.log('Deploying WETH9 to L1')
const WETH9 = await deployWETH9(hre, true) const WETH9 = await deployWETH9(hre, true)
console.log(`Deployed to ${WETH9.address}`) console.log(`Deployed to ${WETH9.address}`)
...@@ -221,33 +247,37 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.') ...@@ -221,33 +247,37 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.')
await depositTx.wait() await depositTx.wait()
console.log(`ERC20 deposited - ${depositTx.hash}`) console.log(`ERC20 deposited - ${depositTx.hash}`)
// Deposit might get reorged, wait 30s and also log for reorgs. console.log('Checking to make sure deposit was successful')
// Deposit might get reorged, wait and also log for reorgs.
let prevBlockHash: string = '' let prevBlockHash: string = ''
for (let i = 0; i < 30; i++) { for (let i = 0; i < 12; i++) {
const messageReceipt = await messenger.waitForMessageReceipt(depositTx) const messageReceipt = await signer.provider!.getTransactionReceipt(
if (messageReceipt.receiptStatus !== 1) { depositTx.hash
)
if (messageReceipt.status !== 1) {
console.log(`Deposit failed, retrying...`) console.log(`Deposit failed, retrying...`)
} }
if ( // Wait for stability, we want some amount of time after any reorg
prevBlockHash !== '' && if (prevBlockHash !== '' && messageReceipt.blockHash !== prevBlockHash) {
messageReceipt.transactionReceipt.blockHash !== prevBlockHash
) {
console.log( console.log(
`Block hash changed from ${prevBlockHash} to ${messageReceipt.transactionReceipt.blockHash}` `Block hash changed from ${prevBlockHash} to ${messageReceipt.blockHash}`
) )
// Wait for stability, we want at least 30 seconds after any reorg
i = 0 i = 0
} else if (prevBlockHash !== '') {
console.log(`No reorg detected: ${i}`)
} }
prevBlockHash = messageReceipt.transactionReceipt.blockHash prevBlockHash = messageReceipt.blockHash
await sleep(1000) await sleep(1000)
} }
console.log(`Deposit confirmed`)
const l2Balance = await OptimismMintableERC20.balanceOf(address) const l2Balance = await OptimismMintableERC20.balanceOf(address)
if (l2Balance.lt(utils.parseEther('1'))) { if (l2Balance.lt(utils.parseEther('1'))) {
throw new Error('bad deposit') throw new Error(
`bad deposit. recipient balance on L2: ${utils.formatEther(l2Balance)}`
)
} }
console.log(`Deposit success`) console.log(`Deposit success`)
...@@ -291,6 +321,8 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.') ...@@ -291,6 +321,8 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.')
setInterval(async () => { setInterval(async () => {
const currentStatus = await messenger.getMessageStatus(withdraw) const currentStatus = await messenger.getMessageStatus(withdraw)
console.log(`Message status: ${MessageStatus[currentStatus]}`) console.log(`Message status: ${MessageStatus[currentStatus]}`)
const latest = await L2OutputOracle.latestBlockNumber()
console.log(`Latest L2OutputOracle commitment number: ${latest.toString()}`)
}, 3000) }, 3000)
const now = Math.floor(Date.now() / 1000) const now = Math.floor(Date.now() / 1000)
......
...@@ -12,6 +12,7 @@ import Artifact__L2StandardBridge from '@eth-optimism/contracts-bedrock/forge-ar ...@@ -12,6 +12,7 @@ import Artifact__L2StandardBridge from '@eth-optimism/contracts-bedrock/forge-ar
import Artifact__OptimismPortal from '@eth-optimism/contracts-bedrock/forge-artifacts/OptimismPortal.sol/OptimismPortal.json' import Artifact__OptimismPortal from '@eth-optimism/contracts-bedrock/forge-artifacts/OptimismPortal.sol/OptimismPortal.json'
import Artifact__L1CrossDomainMessenger from '@eth-optimism/contracts-bedrock/forge-artifacts/L1CrossDomainMessenger.sol/L1CrossDomainMessenger.json' import Artifact__L1CrossDomainMessenger from '@eth-optimism/contracts-bedrock/forge-artifacts/L1CrossDomainMessenger.sol/L1CrossDomainMessenger.json'
import Artifact__L1StandardBridge from '@eth-optimism/contracts-bedrock/forge-artifacts/L1StandardBridge.sol/L1StandardBridge.json' import Artifact__L1StandardBridge from '@eth-optimism/contracts-bedrock/forge-artifacts/L1StandardBridge.sol/L1StandardBridge.json'
import Artifact__L2OutputOracle from '@eth-optimism/contracts-bedrock/forge-artifacts/L2OutputOracle.sol/L2OutputOracle.json'
import { import {
CrossChainMessenger, CrossChainMessenger,
...@@ -88,8 +89,18 @@ task('deposit-eth', 'Deposits ether to L2.') ...@@ -88,8 +89,18 @@ task('deposit-eth', 'Deposits ether to L2.')
let contractAddrs = CONTRACT_ADDRESSES[l2ChainId] let contractAddrs = CONTRACT_ADDRESSES[l2ChainId]
if (args.l1ContractsJsonPath) { if (args.l1ContractsJsonPath) {
const data = await fs.readFile(args.l1ContractsJsonPath) const data = await fs.readFile(args.l1ContractsJsonPath)
const json = JSON.parse(data.toString())
contractAddrs = { contractAddrs = {
l1: JSON.parse(data.toString()), l1: {
AddressManager: json.AddressManager,
L1CrossDomainMessenger: json.L1CrossDomainMessengerProxy,
L1StandardBridge: json.L1StandardBridgeProxy,
StateCommitmentChain: ethers.constants.AddressZero,
CanonicalTransactionChain: ethers.constants.AddressZero,
BondManager: ethers.constants.AddressZero,
OptimismPortal: json.OptimismPortalProxy,
L2OutputOracle: json.L2OutputOracleProxy,
},
l2: DEFAULT_L2_CONTRACT_ADDRESSES, l2: DEFAULT_L2_CONTRACT_ADDRESSES,
} as OEContractsLike } as OEContractsLike
} else if (!contractAddrs) { } else if (!contractAddrs) {
...@@ -145,24 +156,36 @@ task('deposit-eth', 'Deposits ether to L2.') ...@@ -145,24 +156,36 @@ task('deposit-eth', 'Deposits ether to L2.')
} }
} }
console.log(`OptimismPortal: ${contractAddrs.l1.OptimismPortal}`)
const OptimismPortal = new hre.ethers.Contract( const OptimismPortal = new hre.ethers.Contract(
contractAddrs.l1.OptimismPortal, contractAddrs.l1.OptimismPortal,
Artifact__OptimismPortal.abi, Artifact__OptimismPortal.abi,
signer signer
) )
console.log(
`L1CrossDomainMessenger: ${contractAddrs.l1.L1CrossDomainMessenger}`
)
const L1CrossDomainMessenger = new hre.ethers.Contract( const L1CrossDomainMessenger = new hre.ethers.Contract(
contractAddrs.l1.L1CrossDomainMessenger, contractAddrs.l1.L1CrossDomainMessenger,
Artifact__L1CrossDomainMessenger.abi, Artifact__L1CrossDomainMessenger.abi,
signer signer
) )
console.log(`L1StandardBridge: ${contractAddrs.l1.L1StandardBridge}`)
const L1StandardBridge = new hre.ethers.Contract( const L1StandardBridge = new hre.ethers.Contract(
contractAddrs.l1.L1StandardBridge, contractAddrs.l1.L1StandardBridge,
Artifact__L1StandardBridge.abi, Artifact__L1StandardBridge.abi,
signer signer
) )
console.log(`L2OutputOracle: ${contractAddrs.l1.L2OutputOracle}`)
const L2OutputOracle = new hre.ethers.Contract(
contractAddrs.l1.L2OutputOracle,
Artifact__L2OutputOracle.abi,
signer
)
const L2ToL1MessagePasser = new hre.ethers.Contract( const L2ToL1MessagePasser = new hre.ethers.Contract(
predeploys.L2ToL1MessagePasser, predeploys.L2ToL1MessagePasser,
Artifact__L2ToL1MessagePasser.abi Artifact__L2ToL1MessagePasser.abi
...@@ -187,11 +210,11 @@ task('deposit-eth', 'Deposits ether to L2.') ...@@ -187,11 +210,11 @@ task('deposit-eth', 'Deposits ether to L2.')
contracts: contractAddrs, contracts: contractAddrs,
}) })
const opBalanceBefore = await signer.provider.getBalance( const opBalanceBefore = await signer!.provider!.getBalance(
OptimismPortal.address OptimismPortal.address
) )
const l1BridgeBalanceBefore = await signer.provider.getBalance( const l1BridgeBalanceBefore = await signer!.provider!.getBalance(
L1StandardBridge.address L1StandardBridge.address
) )
...@@ -210,11 +233,11 @@ task('deposit-eth', 'Deposits ether to L2.') ...@@ -210,11 +233,11 @@ task('deposit-eth', 'Deposits ether to L2.')
`Deposit complete - included in block ${depositMessageReceipt.transactionReceipt.blockNumber}` `Deposit complete - included in block ${depositMessageReceipt.transactionReceipt.blockNumber}`
) )
const opBalanceAfter = await signer.provider.getBalance( const opBalanceAfter = await signer!.provider!.getBalance(
OptimismPortal.address OptimismPortal.address
) )
const l1BridgeBalanceAfter = await signer.provider.getBalance( const l1BridgeBalanceAfter = await signer!.provider!.getBalance(
L1StandardBridge.address L1StandardBridge.address
) )
...@@ -291,6 +314,8 @@ task('deposit-eth', 'Deposits ether to L2.') ...@@ -291,6 +314,8 @@ task('deposit-eth', 'Deposits ether to L2.')
const proveInterval = setInterval(async () => { const proveInterval = setInterval(async () => {
const currentStatus = await messenger.getMessageStatus(ethWithdrawReceipt) const currentStatus = await messenger.getMessageStatus(ethWithdrawReceipt)
console.log(`Message status: ${MessageStatus[currentStatus]}`) console.log(`Message status: ${MessageStatus[currentStatus]}`)
const latest = await L2OutputOracle.latestBlockNumber()
console.log(`Latest L2OutputOracle commitment number: ${latest.toString()}`)
}, 3000) }, 3000)
try { try {
...@@ -394,7 +419,7 @@ task('deposit-eth', 'Deposits ether to L2.') ...@@ -394,7 +419,7 @@ task('deposit-eth', 'Deposits ether to L2.')
} }
} }
const opBalanceFinally = await signer.provider.getBalance( const opBalanceFinally = await signer!.provider!.getBalance(
OptimismPortal.address OptimismPortal.address
) )
......
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