From 962f36e40da037defd9dcc26cf037aba6cfae0dd Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Fri, 25 Feb 2022 15:29:58 -0500 Subject: [PATCH] l2geth: Add support for system addresses Adds support for system addresses. To deploy to a system address, the deployer must either be in the list of hardcoded addresses described in `SystemAddressDeployers`, or be specified via the `SYSTEM_ADDRESS_0_DEPLOYER`/`SYSTEM_ADDRESS_1_DEPLOYER` environment variables. The hardcoded system addresses deployers will always override those placed in the environment, so specifying the `SYSTEM_ADDRESS_*` env vars on mainnet, Kovan, or Goerli is a no-op. The env vars are available primarily for testing purposes. The contract deployment **must** be the first transaction from the deployment address - i.e., it must have nonce zero. In order to make the tests work, I had to change the integration tests chain ID to no longer conflict with Goerli. The new integration tests chain ID is `987`. Co-Authored-By: @inphi --- .changeset/chatty-oranges-call.md | 7 + integration-tests/test/shared/utils.ts | 5 +- .../test/system-addresses.spec.ts | 105 ++++++++++ l2geth/core/state_processor.go | 14 +- l2geth/core/types/receipt.go | 17 +- l2geth/core/vm/evm.go | 10 + l2geth/rollup/rcfg/config.go | 8 +- l2geth/rollup/rcfg/system_address.go | 92 +++++++++ l2geth/rollup/rcfg/system_address_test.go | 180 ++++++++++++++++++ ops/docker-compose.yml | 23 ++- ops/envs/geth.env | 4 +- packages/contracts/src/predeploys.ts | 6 + 12 files changed, 460 insertions(+), 11 deletions(-) create mode 100644 .changeset/chatty-oranges-call.md create mode 100644 integration-tests/test/system-addresses.spec.ts create mode 100644 l2geth/rollup/rcfg/system_address.go create mode 100644 l2geth/rollup/rcfg/system_address_test.go diff --git a/.changeset/chatty-oranges-call.md b/.changeset/chatty-oranges-call.md new file mode 100644 index 00000000000..5bb6f88e707 --- /dev/null +++ b/.changeset/chatty-oranges-call.md @@ -0,0 +1,7 @@ +--- +'@eth-optimism/integration-tests': patch +'@eth-optimism/l2geth': patch +'@eth-optimism/contracts': patch +--- + +Add support for system addresses diff --git a/integration-tests/test/shared/utils.ts b/integration-tests/test/shared/utils.ts index d82a44e6e00..31e505b54fd 100644 --- a/integration-tests/test/shared/utils.ts +++ b/integration-tests/test/shared/utils.ts @@ -38,7 +38,7 @@ const procEnv = cleanEnv(process.env, { L1_URL: str({ default: 'http://localhost:9545' }), L1_POLLING_INTERVAL: num({ default: 10 }), - L2_CHAINID: num({ default: 420 }), + L2_CHAINID: num({ default: 987 }), L2_GAS_PRICE: gasPriceValidator({ default: 'onchain', }), @@ -87,6 +87,9 @@ const procEnv = cleanEnv(process.env, { RUN_VERIFIER_TESTS: bool({ default: true, }), + RUN_SYSTEM_ADDRESS_TESTS: bool({ + default: false, + }), MOCHA_TIMEOUT: num({ default: 120_000, diff --git a/integration-tests/test/system-addresses.spec.ts b/integration-tests/test/system-addresses.spec.ts new file mode 100644 index 00000000000..4cf0031282b --- /dev/null +++ b/integration-tests/test/system-addresses.spec.ts @@ -0,0 +1,105 @@ +/* Imports: External */ +import { BigNumber, Contract, ContractFactory, utils, Wallet } from 'ethers' +import { ethers } from 'hardhat' +import { futurePredeploys } from '@eth-optimism/contracts' + +/* Imports: Internal */ +import { expect } from './shared/setup' +import { OptimismEnv } from './shared/env' +import { envConfig } from './shared/utils' + +const SYSTEM_ADDRESSES = [futurePredeploys.System0, futurePredeploys.System1] + +describe('System addresses', () => { + let env: OptimismEnv + + let deployerWallets: Wallet[] = [] + + let contracts: Contract[] + + let Factory__ERC20: ContractFactory + + before(async function () { + if (!envConfig.RUN_SYSTEM_ADDRESS_TESTS) { + console.log('Skipping system address tests.') + this.skip() + return + } + + env = await OptimismEnv.new() + + deployerWallets = [ + new Wallet(process.env.SYSTEM_ADDRESS_0_DEPLOYER_KEY, env.l2Provider), + new Wallet(process.env.SYSTEM_ADDRESS_1_DEPLOYER_KEY, env.l2Provider), + ] + for (const deployer of deployerWallets) { + await env.l2Wallet.sendTransaction({ + to: deployer.address, + value: utils.parseEther('0.1'), + }) + } + contracts = [] + + Factory__ERC20 = await ethers.getContractFactory('ERC20', env.l2Wallet) + }) + + it('should have no code for the system addresses initially', async () => { + for (const addr of SYSTEM_ADDRESSES) { + const code = await env.l2Provider.getCode(addr, 'latest') + expect(code).to.eq('0x') + } + }) + + it('should deploy to the system address', async () => { + for (let i = 0; i < deployerWallets.length; i++) { + const contract = await Factory__ERC20.connect(deployerWallets[i]).deploy( + 100000000, + 'OVM Test', + 8, + 'OVM' + ) + // have to use the receipt here since ethers calculates the + // contract address on-the-fly + const receipt = await contract.deployTransaction.wait() + expect(receipt.contractAddress).to.eq(SYSTEM_ADDRESSES[i]) + + const fetchedReceipt = await env.l2Provider.getTransactionReceipt( + receipt.transactionHash + ) + expect(fetchedReceipt.contractAddress).to.eq(SYSTEM_ADDRESSES[i]) + + contracts.push(await ethers.getContractAt('ERC20', SYSTEM_ADDRESSES[i])) + } + }) + + it('contracts deployed at the system addresses should function', async () => { + expect(contracts.length).to.eq(2) + + for (let i = 0; i < contracts.length; i++) { + const wallet = deployerWallets[i] + const contract = contracts[i].connect(wallet) + const code = await env.l2Provider.getCode(contract.address, 'latest') + expect(code).not.to.eq('0x') + + const tx = await contract.transfer(env.l2Wallet.address, 1000) + await tx.wait() + const bal = await contract.balanceOf(env.l2Wallet.address) + expect(bal).to.deep.equal(BigNumber.from(1000)) + } + }) + + it('should not deploy any additional contracts from the deployer at the system address', async () => { + for (let i = 0; i < deployerWallets.length; i++) { + const contract = await Factory__ERC20.connect(deployerWallets[i]).deploy( + 100000000, + 'OVM Test', + 8, + 'OVM' + ) + await contract.deployed() + const receipt = await contract.deployTransaction.wait() + expect(receipt.contractAddress).not.to.eq(SYSTEM_ADDRESSES[i]) + expect(receipt.contractAddress).not.to.eq(null) + } + }) +}) diff --git a/l2geth/core/state_processor.go b/l2geth/core/state_processor.go index 04ad25c3ed6..a6716d88702 100644 --- a/l2geth/core/state_processor.go +++ b/l2geth/core/state_processor.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum-optimism/optimism/l2geth/crypto" "github.com/ethereum-optimism/optimism/l2geth/params" "github.com/ethereum-optimism/optimism/l2geth/rollup/fees" + "github.com/ethereum-optimism/optimism/l2geth/rollup/rcfg" ) // StateProcessor is a basic Processor, which takes care of transitioning @@ -132,7 +133,18 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo receipt.GasUsed = gas // if the transaction created a contract, store the creation address in the receipt. if msg.To() == nil { - receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce()) + if rcfg.UsingOVM { + sysAddress := rcfg.SystemAddressFor(config.ChainID, vmenv.Context.Origin) + // If nonce is zero, and the deployer is a system address deployer, + // set the provided system contract address. + if sysAddress != rcfg.ZeroSystemAddress && tx.Nonce() == 0 && tx.To() == nil { + receipt.ContractAddress = sysAddress + } else { + receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce()) + } + } else { + receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce()) + } } // Set the receipt logs and create a bloom for filtering receipt.Logs = statedb.GetLogs(tx.Hash()) diff --git a/l2geth/core/types/receipt.go b/l2geth/core/types/receipt.go index 994fc4e0d36..a7680453aa7 100644 --- a/l2geth/core/types/receipt.go +++ b/l2geth/core/types/receipt.go @@ -24,6 +24,8 @@ import ( "math/big" "unsafe" + "github.com/ethereum-optimism/optimism/l2geth/rollup/rcfg" + "github.com/ethereum-optimism/optimism/l2geth/common" "github.com/ethereum-optimism/optimism/l2geth/common/hexutil" "github.com/ethereum-optimism/optimism/l2geth/crypto" @@ -352,7 +354,20 @@ func (r Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, num if txs[i].To() == nil { // Deriving the signer is expensive, only do if it's actually needed from, _ := Sender(signer, txs[i]) - r[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce()) + nonce := txs[i].Nonce() + + if rcfg.UsingOVM { + sysAddress := rcfg.SystemAddressFor(config.ChainID, from) + // If nonce is zero, and the deployer is a system address deployer, + // set the provided system contract address. + if sysAddress != rcfg.ZeroSystemAddress && nonce == 0 && txs[i].To() == nil { + r[i].ContractAddress = sysAddress + } else { + r[i].ContractAddress = crypto.CreateAddress(from, nonce) + } + } else { + r[i].ContractAddress = crypto.CreateAddress(from, nonce) + } } // The used gas can be calculated based on previous r if i == 0 { diff --git a/l2geth/core/vm/evm.go b/l2geth/core/vm/evm.go index 177e7c4f4c5..fdcd0835ecf 100644 --- a/l2geth/core/vm/evm.go +++ b/l2geth/core/vm/evm.go @@ -416,6 +416,16 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, } return ret, common.Address{}, gas, errExecutionReverted } + + // Get the system address for this caller. + sysAddr := rcfg.SystemAddressFor(evm.ChainConfig().ChainID, caller.Address()) + + // If there is a configured system address for this caller, and the caller's nonce is zero, + // and there is no contract already deployed at this system address, then set the created + // address to the system address. + if sysAddr != rcfg.ZeroSystemAddress && evm.StateDB.GetNonce(caller.Address()) == 0 { + address = sysAddr + } } nonce := evm.StateDB.GetNonce(caller.Address()) evm.StateDB.SetNonce(caller.Address(), nonce+1) diff --git a/l2geth/rollup/rcfg/config.go b/l2geth/rollup/rcfg/config.go index 5ec1a7a9b9d..e508bb34743 100644 --- a/l2geth/rollup/rcfg/config.go +++ b/l2geth/rollup/rcfg/config.go @@ -11,16 +11,16 @@ import ( var UsingOVM bool var ( - // l2GasPriceSlot refers to the storage slot that the L2 gas price is stored + // L2GasPriceSlot refers to the storage slot that the L2 gas price is stored // in in the OVM_GasPriceOracle predeploy L2GasPriceSlot = common.BigToHash(big.NewInt(1)) - // l1GasPriceSlot refers to the storage slot that the L1 gas price is stored + // L1GasPriceSlot refers to the storage slot that the L1 gas price is stored // in in the OVM_GasPriceOracle predeploy L1GasPriceSlot = common.BigToHash(big.NewInt(2)) - // l2GasPriceOracleOwnerSlot refers to the storage slot that the owner of + // L2GasPriceOracleOwnerSlot refers to the storage slot that the owner of // the OVM_GasPriceOracle is stored in L2GasPriceOracleOwnerSlot = common.BigToHash(big.NewInt(0)) - // l2GasPriceOracleAddress is the address of the OVM_GasPriceOracle + // L2GasPriceOracleAddress is the address of the OVM_GasPriceOracle // predeploy L2GasPriceOracleAddress = common.HexToAddress("0x420000000000000000000000000000000000000F") // OverheadSlot refers to the storage slot in the OVM_GasPriceOracle that diff --git a/l2geth/rollup/rcfg/system_address.go b/l2geth/rollup/rcfg/system_address.go new file mode 100644 index 00000000000..32100ed0546 --- /dev/null +++ b/l2geth/rollup/rcfg/system_address.go @@ -0,0 +1,92 @@ +package rcfg + +import ( + "math/big" + "os" + + "github.com/ethereum-optimism/optimism/l2geth/common" +) + +// SystemAddress0 is the first deployable system address. +var SystemAddress0 = common.HexToAddress("0x4200000000000000000000000000000000000042") + +// SystemAddress1 is the second deployable system address. +var SystemAddress1 = common.HexToAddress("0x4200000000000000000000000000000000000014") + +// ZeroSystemAddress is the emprt system address. +var ZeroSystemAddress common.Address + +// SystemAddressDeployer is a tuple containing the deployment +// addresses for SystemAddress0 and SystemAddress1. +type SystemAddressDeployer [2]common.Address + +// SystemAddressFor returns the system address for a given deployment +// address. If no system address is configured for this deployer, +// ZeroSystemAddress is returned. +func (s SystemAddressDeployer) SystemAddressFor(addr common.Address) common.Address { + if s[0] == addr { + return SystemAddress0 + } + + if s[1] == addr { + return SystemAddress1 + } + + return ZeroSystemAddress +} + +// SystemAddressFor is a convenience method that returns an environment-based +// system address if the passed-in chain ID is not hardcoded. +func SystemAddressFor(chainID *big.Int, addr common.Address) common.Address { + sysDeployer, hasHardcodedSysDeployer := SystemAddressDeployers[chainID.Uint64()] + if !hasHardcodedSysDeployer { + sysDeployer = envSystemAddressDeployer + } + + return sysDeployer.SystemAddressFor(addr) +} + +// SystemAddressDeployers maintains a hardcoded map of chain IDs to +// system addresses. +var SystemAddressDeployers = map[uint64]SystemAddressDeployer{ + // Mainnet + 10: { + common.HexToAddress("0xcDE47C1a5e2d60b9ff262b0a3b6d486048575Ad9"), + common.HexToAddress("0x53A6eecC2dD4795Fcc68940ddc6B4d53Bd88Bd9E"), + }, + + // Kovan + 69: { + common.HexToAddress("0xd23eb5c2dd7035e6eb4a7e129249d9843123079f"), + common.HexToAddress("0xa81224490b9fa4930a2e920550cd1c9106bb6d9e"), + }, + + // Goerli + 420: { + common.HexToAddress("0xc30276833798867c1dbc5c468bf51ca900b44e4c"), + common.HexToAddress("0x5c679a57e018f5f146838138d3e032ef4913d551"), + }, +} + +var envSystemAddressDeployer SystemAddressDeployer + +func initEnvSystemAddressDeployer() { + deployer0Env := os.Getenv("SYSTEM_ADDRESS_0_DEPLOYER") + deployer1Env := os.Getenv("SYSTEM_ADDRESS_1_DEPLOYER") + + if deployer0Env == "" && deployer1Env == "" { + return + } + if !common.IsHexAddress(deployer0Env) { + panic("SYSTEM_ADDRESS_0_DEPLOYER specified but invalid") + } + if !common.IsHexAddress(deployer1Env) { + panic("SYSTEM_ADDRESS_1_DEPLOYER specified but invalid") + } + envSystemAddressDeployer[0] = common.HexToAddress(deployer0Env) + envSystemAddressDeployer[1] = common.HexToAddress(deployer1Env) +} + +func init() { + initEnvSystemAddressDeployer() +} diff --git a/l2geth/rollup/rcfg/system_address_test.go b/l2geth/rollup/rcfg/system_address_test.go new file mode 100644 index 00000000000..821b30faa91 --- /dev/null +++ b/l2geth/rollup/rcfg/system_address_test.go @@ -0,0 +1,180 @@ +package rcfg + +import ( + "crypto/rand" + "fmt" + "math/big" + "os" + "testing" + + "github.com/ethereum-optimism/optimism/l2geth/common" +) + +func TestSystemAddressFor(t *testing.T) { + tests := []struct { + deployer0 common.Address + deployer1 common.Address + chainId int64 + }{ + { + common.HexToAddress("0xcDE47C1a5e2d60b9ff262b0a3b6d486048575Ad9"), + common.HexToAddress("0x53A6eecC2dD4795Fcc68940ddc6B4d53Bd88Bd9E"), + 10, + }, + { + common.HexToAddress("0xd23eb5c2dd7035e6eb4a7e129249d9843123079f"), + common.HexToAddress("0xa81224490b9fa4930a2e920550cd1c9106bb6d9e"), + 69, + }, + { + common.HexToAddress("0xc30276833798867c1dbc5c468bf51ca900b44e4c"), + common.HexToAddress("0x5c679a57e018f5f146838138d3e032ef4913d551"), + 420, + }, + } + for _, tt := range tests { + chainID := big.NewInt(tt.chainId) + sad0 := SystemAddressFor(chainID, tt.deployer0) + if sad0 != SystemAddress0 { + t.Fatalf("expected %s, got %s", SystemAddress0.String(), sad0.String()) + } + sad1 := SystemAddressFor(chainID, tt.deployer1) + if sad1 != SystemAddress1 { + t.Fatalf("expected %s, got %s", SystemAddress1.String(), sad1.String()) + } + if SystemAddressFor(chainID, randAddr()) != ZeroSystemAddress { + t.Fatalf("expected zero address, but got a non-zero one instead") + } + } + + // test env fallback + addr0 := randAddr() + addr1 := randAddr() + chainID := big.NewInt(999) + if SystemAddressFor(chainID, addr0) != ZeroSystemAddress { + t.Fatalf("expected zero address, but got a non-zero one instead") + } + if SystemAddressFor(chainID, addr1) != ZeroSystemAddress { + t.Fatalf("expected zero address, but got a non-zero one instead") + } + if err := os.Setenv("SYSTEM_ADDRESS_0_DEPLOYER", addr0.String()); err != nil { + t.Fatalf("error setting env for deployer 0: %v", err) + } + if err := os.Setenv("SYSTEM_ADDRESS_1_DEPLOYER", addr1.String()); err != nil { + t.Fatalf("error setting env for deployer 1: %v", err) + } + initEnvSystemAddressDeployer() + sad0 := SystemAddressFor(chainID, addr0) + if sad0 != SystemAddress0 { + t.Fatalf("expected %s, got %s", SystemAddress0.String(), sad0.String()) + } + sad1 := SystemAddressFor(chainID, addr1) + if sad1 != SystemAddress1 { + t.Fatalf("expected %s, got %s", SystemAddress1.String(), sad1.String()) + } + + // reset + if err := os.Setenv("SYSTEM_ADDRESS_0_DEPLOYER", ""); err != nil { + t.Fatalf("error setting env for deployer 0: %v", err) + } + if err := os.Setenv("SYSTEM_ADDRESS_1_DEPLOYER", ""); err != nil { + t.Fatalf("error setting env for deployer 1: %v", err) + } + initEnvSystemAddressDeployer() +} + +func TestSystemAddressDeployer(t *testing.T) { + addr0 := randAddr() + addr1 := randAddr() + deployer := SystemAddressDeployer{addr0, addr1} + + assertAddress(t, deployer, addr0, SystemAddress0) + assertAddress(t, deployer, addr1, SystemAddress1) + assertAddress(t, deployer, randAddr(), ZeroSystemAddress) + + var zeroDeployer SystemAddressDeployer + assertAddress(t, zeroDeployer, randAddr(), ZeroSystemAddress) +} + +func TestEnvSystemAddressDeployer(t *testing.T) { + addr0 := randAddr() + addr1 := randAddr() + + assertAddress(t, envSystemAddressDeployer, addr0, ZeroSystemAddress) + assertAddress(t, envSystemAddressDeployer, addr1, ZeroSystemAddress) + assertAddress(t, envSystemAddressDeployer, randAddr(), ZeroSystemAddress) + + if err := os.Setenv("SYSTEM_ADDRESS_0_DEPLOYER", addr0.String()); err != nil { + t.Fatalf("error setting env for deployer 0: %v", err) + } + if err := os.Setenv("SYSTEM_ADDRESS_1_DEPLOYER", addr1.String()); err != nil { + t.Fatalf("error setting env for deployer 1: %v", err) + } + + initEnvSystemAddressDeployer() + assertAddress(t, envSystemAddressDeployer, addr0, SystemAddress0) + assertAddress(t, envSystemAddressDeployer, addr1, SystemAddress1) + assertAddress(t, envSystemAddressDeployer, randAddr(), ZeroSystemAddress) + + tests := []struct { + deployer0 string + deployer1 string + msg string + }{ + { + "not an address", + addr0.String(), + "SYSTEM_ADDRESS_0_DEPLOYER specified but invalid", + }, + { + "not an address", + "not an address", + "SYSTEM_ADDRESS_0_DEPLOYER specified but invalid", + }, + { + addr0.String(), + "not an address", + "SYSTEM_ADDRESS_1_DEPLOYER specified but invalid", + }, + } + for _, tt := range tests { + if err := os.Setenv("SYSTEM_ADDRESS_0_DEPLOYER", tt.deployer0); err != nil { + t.Fatalf("error setting env for deployer 0: %v", err) + } + if err := os.Setenv("SYSTEM_ADDRESS_1_DEPLOYER", tt.deployer1); err != nil { + t.Fatalf("error setting env for deployer 1: %v", err) + } + assertPanic(t, tt.msg, func() { + initEnvSystemAddressDeployer() + }) + } +} + +func randAddr() common.Address { + buf := make([]byte, 20) + _, err := rand.Read(buf) + if err != nil { + panic(err) + } + return common.BytesToAddress(buf) +} + +func assertAddress(t *testing.T, deployer SystemAddressDeployer, in common.Address, expected common.Address) { + actual := deployer.SystemAddressFor(in) + if actual != expected { + t.Fatalf("bad system address. expected %s, got %s", expected.String(), actual.String()) + } +} + +func assertPanic(t *testing.T, msg string, cb func()) { + defer func() { + if err := recover(); err != nil { + errMsg := fmt.Sprintf("%v", err) + if errMsg != msg { + t.Fatalf("expected error message %s, got %v", msg, errMsg) + } + } + }() + + cb() +} diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index 2e40b3bd8b0..61a189ea4a2 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -1,5 +1,15 @@ version: '3.4' +x-system-addr-env: &system-addr-env + # private key: a6aecc98b63bafb0de3b29ae9964b14acb4086057808be29f90150214ebd4a0f + # OK to publish this since it will only ever be used in itests + SYSTEM_ADDRESS_0_DEPLOYER: "0xa961b0d6dce82db098cf70a42a14add3ee3db2d5" + + # private key: 3b8d2345102cce2443acb240db6e87c8edd4bb3f821b17fab8ea2c9da08ea132 + # OK to publish this since it will only ever be used in itests + SYSTEM_ADDRESS_1_DEPLOYER: "0xdfc82d475833a50de90c642770f34a9db7deb725" + + services: # this is a helper service used because there's no official hardhat image l1_chain: @@ -41,7 +51,7 @@ services: # setting the whitelist owner to address(0) disables the whitelist WHITELIST_OWNER: '0x0000000000000000000000000000000000000000' L1_FEE_WALLET_ADDRESS: '0x391716d440c151c42cdf1c95c1d83a5427bca52c' - L2_CHAIN_ID: 420 + L2_CHAIN_ID: 987 L2_BLOCK_GAS_LIMIT: 15000000 BLOCK_SIGNER_ADDRESS: '0x00000398232E2064F896018496b4b44b3D62751F' GAS_PRICE_ORACLE_OVERHEAD: 2750 @@ -75,7 +85,7 @@ services: DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT: http://l1_chain:8545 DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT: http://l2geth:8545 DATA_TRANSPORT_LAYER__SYNC_FROM_L2: 'true' - DATA_TRANSPORT_LAYER__L2_CHAIN_ID: 420 + DATA_TRANSPORT_LAYER__L2_CHAIN_ID: 987 ports: - ${DTL_PORT:-7878}:7878 @@ -91,6 +101,7 @@ services: env_file: - ./envs/geth.env environment: + <<: *system-addr-env ETH1_HTTP: http://l1_chain:8545 ROLLUP_TIMESTAMP_REFRESH: 5s ROLLUP_STATE_DUMP_PATH: http://deployer:8081/state-dump.latest.json @@ -146,6 +157,7 @@ services: env_file: - ./envs/geth.env environment: + <<: *system-addr-env ETH1_HTTP: http://l1_chain:8545 SEQUENCER_CLIENT_HTTP: http://l2geth:8545 ROLLUP_STATE_DUMP_PATH: http://deployer:8081/state-dump.latest.json @@ -171,6 +183,7 @@ services: env_file: - ./envs/geth.env environment: + <<: *system-addr-env ETH1_HTTP: http://l1_chain:8545 SEQUENCER_CLIENT_HTTP: http://l2geth:8545 ROLLUP_STATE_DUMP_PATH: http://deployer:8081/state-dump.latest.json @@ -201,6 +214,12 @@ services: NO_NETWORK: 1 BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE: ${BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE:-zlib} + RUN_SYSTEM_ADDRESS_TESTS: "true" + + # must match l2geth environment, see above for why it's safe to publish these + SYSTEM_ADDRESS_0_DEPLOYER_KEY: "a6aecc98b63bafb0de3b29ae9964b14acb4086057808be29f90150214ebd4a0f" + SYSTEM_ADDRESS_1_DEPLOYER_KEY: "3b8d2345102cce2443acb240db6e87c8edd4bb3f821b17fab8ea2c9da08ea132" + gas_oracle: deploy: replicas: 0 diff --git a/ops/envs/geth.env b/ops/envs/geth.env index 36b2a00990b..75d32152cf3 100644 --- a/ops/envs/geth.env +++ b/ops/envs/geth.env @@ -20,12 +20,12 @@ WS_PORT=8546 WS_API=eth,net,rollup,web3 WS_ORIGINS=* -CHAIN_ID=420 +CHAIN_ID=987 DATADIR=/root/.ethereum GASPRICE=0 GCMODE=archive IPC_DISABLE=true -NETWORK_ID=420 +NETWORK_ID=987 NO_USB=true NO_DISCOVER=true TARGET_GAS_LIMIT=15000000 diff --git a/packages/contracts/src/predeploys.ts b/packages/contracts/src/predeploys.ts index 273ae7e052f..b67f677a31d 100644 --- a/packages/contracts/src/predeploys.ts +++ b/packages/contracts/src/predeploys.ts @@ -24,3 +24,9 @@ export const predeploys = { // We're also putting WETH9 at the old OVM_ETH address. WETH9: '0x4200000000000000000000000000000000000006', } + +export const futurePredeploys = { + // System addresses, for use later + System0: '0x4200000000000000000000000000000000000042', + System1: '0x4200000000000000000000000000000000000014', +}