Commit 4cbf194b authored by Joshua Gutow's avatar Joshua Gutow Committed by GitHub

Merge branch 'develop' into specs/fix

parents 9aa93e57 da669074
---
'@eth-optimism/contracts': patch
---
Significantly reduces contracts package bundle size
......@@ -221,7 +221,7 @@ jobs:
name: Check if we should run
command: |
shopt -s inherit_errexit
CHANGED=$(check-changed "op-(batcher|bindings|e2e|node|proposer)")
CHANGED=$(check-changed "op-(batcher|bindings|e2e|node|proposer|chain-ops)")
if [[ "$CHANGED" = "FALSE" ]]; then
circleci step halt
fi
......@@ -255,6 +255,11 @@ jobs:
command: |
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell ./...
working_directory: op-service
- run:
name: lint op-chain-ops
command: |
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell ./...
working_directory: op-chain-ops
- run:
name: prep results dir
command: mkdir -p /test-results
......@@ -283,6 +288,11 @@ jobs:
command: |
gotestsum --junitfile /test-results/op-service.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./...
working_directory: op-service
- run:
name: test op-chain-ops
command: |
gotestsum --junitfile /test-results/op-chain-ops.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./...
working_directory: op-chain-ops
- store_test_results:
path: /test-results
- run:
......@@ -497,19 +507,6 @@ jobs:
name: Bring up the stack
command: |
make devnet-up
- run:
name: Check L2 Config
command: npx hardhat check-l2-config --network devnetL1
working_directory: packages/contracts-bedrock
- run:
name: Do a deposit
command: |
timeout 5m npx hardhat deposit \
--to 0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244 \
--amount-eth 1 \
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--network devnetL1
working_directory: packages/contracts-bedrock
- run:
name: Deposit ERC20 through the bridge
command: timeout 5m npx hardhat deposit-erc20 --network devnetL1
......@@ -809,6 +806,17 @@ workflows:
- gcr
requires:
- contracts-bedrock-tests
- docker-publish:
name: contract-artifacts-bedrock-publish-dev
docker_file: ops/docker/Dockerfile.packages
docker_tags: us-central1-docker.pkg.dev/bedrock-goerli-development/images/contract-artifacts-bedrock:<<pipeline.git.revision>>
target: contract-artifacts-bedrock
docker_context: .
repo: us-central1-docker.pkg.dev
context:
- gcr
requires:
- contracts-bedrock-tests
- hive-test:
name: hive-test-rpc
version: <<pipeline.git.revision>>
......
......@@ -44,7 +44,7 @@ mod-tidy:
# Below GOPRIVATE line allows mod-tidy to be run immediately after
# releasing new versions. This bypasses the Go modules proxy, which
# can take a while to index new versions.
#
#
# See https://proxy.golang.org/ for more info.
export GOPRIVATE="github.com/ethereum-optimism" && \
cd ./op-service && go mod tidy && cd .. && \
......@@ -52,6 +52,7 @@ mod-tidy:
cd ./op-proposer && go mod tidy && cd .. && \
cd ./op-batcher && go mod tidy && cd .. && \
cd ./op-bindings && go mod tidy && cd .. && \
cd ./op-chain-ops && go mod tidy && cd .. && \
cd ./op-e2e && go mod tidy && cd ..
.PHONY: mod-tidy
......@@ -125,10 +126,12 @@ tag-bedrock-go-modules:
git tag "op-bindings/$(VERSION)"
git tag "op-batcher/$(VERSION)"
git tag "op-service/$(VERSION)"
git tag "op-chain-ops/$(VERSION)"
git push $(BEDROCK_TAGS_REMOTE) "op-proposer/$(VERSION)"
git push $(BEDROCK_TAGS_REMOTE) "op-node/$(VERSION)"
git push $(BEDROCK_TAGS_REMOTE) "op-e2e/$(VERSION)"
git push $(BEDROCK_TAGS_REMOTE) "op-bindings/$(VERSION)"
git push $(BEDROCK_TAGS_REMOTE) "op-batcher/$(VERSION)"
git push $(BEDROCK_TAGS_REMOTE) "op-service/$(VERSION)"
git push $(BEDROCK_TAGS_REMOTE) "op-chain-ops/$(VERSION)"
......@@ -28,7 +28,7 @@ func L1EthClientWithTimeout(ctx context.Context, url string, disableHTTP2 bool)
TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
}
}
//nolint:staticcheck // Geth v1.10.23 uses rpc.DialOptions and rpc.WithClient, but we need to update geth first. Lint is flagged because of global go workspace usage.
rpcClient, err := rpc.DialHTTPWithClient(url, httpClient)
if err != nil {
return nil, err
......
......@@ -19,7 +19,7 @@ use (
./teleportr
)
replace github.com/ethereum/go-ethereum v1.10.21 => github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61
replace github.com/ethereum/go-ethereum v1.10.23 => github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638
// For local debugging:
//replace github.com/ethereum/go-ethereum v1.10.21 => ../go-ethereum
//replace github.com/ethereum/go-ethereum v1.10.23 => ../go-ethereum
......@@ -25,6 +25,7 @@ github.com/docker/docker v1.6.2/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsvi
github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/ethereum-optimism/op-geth v0.0.0-20220906163738-712cb0a1c140/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8=
......
......@@ -6,7 +6,7 @@ require (
github.com/ethereum-optimism/optimism/op-node v0.5.0
github.com/ethereum-optimism/optimism/op-proposer v0.5.0
github.com/ethereum-optimism/optimism/op-service v0.5.0
github.com/ethereum/go-ethereum v1.10.21
github.com/ethereum/go-ethereum v1.10.23
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
github.com/urfave/cli v1.22.9
)
......@@ -70,4 +70,4 @@ require (
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
)
replace github.com/ethereum/go-ethereum v1.10.21 => github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61
replace github.com/ethereum/go-ethereum v1.10.23 => github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638
......@@ -147,8 +147,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61 h1:+WfrwiRELp3hoeb1bnPws3FtUUoYCDDYsCkwvKek5FY=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638 h1:LcvgHjeooGBobfEIEYikMzx1MoIAjRqa/ZDdkrhV3Hw=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo=
github.com/ethereum-optimism/optimism/op-bindings v0.5.0 h1:bJT8KmDu5YAVOqPQHxHkntGlRrtRdTIsH+X28LOIcqU=
github.com/ethereum-optimism/optimism/op-bindings v0.5.0/go.mod h1:Ft+sL57mlBysH6nuXZA11GLMMajfBa8SjpEBtitl1Vw=
github.com/ethereum-optimism/optimism/op-node v0.5.0 h1:MwNvYDBFS4quSWkEzfJBGJkzI1yveqQ/GuVK6aTJJ0A=
......
......@@ -5,7 +5,8 @@ pkg := bindings
all: mkdir bindings deployed
bindings: l1block-bindings \
l1-standard-bridge-bindings \
l1-cross-domain-messenger-bindings \
l1-standard-bridge-bindings \
l2-to-l1-message-passer-bindings \
optimism-portal-bindings \
l2-output-oracle-bindings \
......@@ -16,6 +17,8 @@ bindings: l1block-bindings \
sequencer-fee-vault-bindings \
optimism-mintable-erc20-factory-bindings \
optimism-mintable-erc20-bindings \
proxy-bindings \
proxy-admin-bindings \
erc20-bindings \
weth9-bindings
......@@ -27,6 +30,9 @@ deployed: l1-block-deployed \
l1-block-deployed: l1block-bindings
./gen_deployed_bytecode.sh L1Block $(pkg)
l1-cross-domain-messenger-bindings:
./gen_bindings.sh contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger $(pkg)
l1-standard-bridge-bindings:
./gen_bindings.sh contracts/L1/L1StandardBridge.sol:L1StandardBridge $(pkg)
......@@ -72,6 +78,12 @@ optimism-mintable-erc20-factory-bindings:
optimism-mintable-erc20-bindings:
./gen_bindings.sh contracts/universal/OptimismMintableERC20.sol:OptimismMintableERC20 $(pkg)
proxy-bindings:
./gen_bindings.sh contracts/universal/Proxy.sol:Proxy $(pkg)
proxy-admin-bindings:
./gen_bindings.sh contracts/universal/ProxyAdmin.sol:ProxyAdmin $(pkg)
erc20-bindings:
./gen_bindings.sh ERC20 $(pkg)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
......@@ -3,7 +3,7 @@ module github.com/ethereum-optimism/optimism/op-bindings
go 1.18
require (
github.com/ethereum/go-ethereum v1.10.21
github.com/ethereum/go-ethereum v1.10.23
github.com/stretchr/testify v1.7.2
)
......@@ -16,7 +16,6 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
......@@ -41,4 +40,6 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace github.com/ethereum/go-ethereum v1.10.21 => github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61
replace github.com/ethereum/go-ethereum v1.10.23 => github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638
// github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638
......@@ -28,16 +28,16 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61 h1:+WfrwiRELp3hoeb1bnPws3FtUUoYCDDYsCkwvKek5FY=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638 h1:LcvgHjeooGBobfEIEYikMzx1MoIAjRqa/ZDdkrhV3Hw=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
......@@ -45,8 +45,6 @@ github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog=
github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
......
package predeploys
import "github.com/ethereum/go-ethereum/common"
const (
DevL2OutputOracle = "0x6900000000000000000000000000000000000000"
DevOptimismPortal = "0x6900000000000000000000000000000000000001"
DevL1CrossDomainMessenger = "0x6900000000000000000000000000000000000002"
DevL1StandardBridge = "0x6900000000000000000000000000000000000003"
DevOptimismMintableERC20Factory = "0x6900000000000000000000000000000000000004"
DevAddressManager = "0x6900000000000000000000000000000000000005"
DevProxyAdmin = "0x6900000000000000000000000000000000000006"
)
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)
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
}
......@@ -49,14 +49,14 @@ func DumpAddresses(dataDir string, outFile string) error {
// Migrate performs the actual state migration. It does quite a lot:
//
// 1. It uses address lists, allowance lists, Mint events, and address preimages in
// the input state database to create a comprehensive list of storage slots in the
// OVM ETH contract.
// 2. It iterates over the slots in OVM ETH, and compares then against the list in (1).
// If the list doesn't match, or the total supply of OVM ETH doesn't match the sum of
// all balance storage slots, it panics.
// 3. It performs the actual migration by copying the input state DB into a new state DB.
// 4. It imports the provided genesis into the new state DB like Geth would during geth init.
// 1. It uses address lists, allowance lists, Mint events, and address preimages in
// the input state database to create a comprehensive list of storage slots in the
// OVM ETH contract.
// 2. It iterates over the slots in OVM ETH, and compares then against the list in (1).
// If the list doesn't match, or the total supply of OVM ETH doesn't match the sum of
// all balance storage slots, it panics.
// 3. It performs the actual migration by copying the input state DB into a new state DB.
// 4. It imports the provided genesis into the new state DB like Geth would during geth init.
//
// It takes the following arguments:
//
......@@ -64,9 +64,9 @@ func DumpAddresses(dataDir string, outFile string) error {
// - outDir: A directory to output the migrated database to.
// - genesis: The new chain's genesis configuration.
// - addrLists: A list of address list file paths. These address lists are used to populate
// balances from previous regenesis events.
// balances from previous regenesis events.
// - allowanceLists: A list of allowance list file paths. These allowance lists are used
// to calculate allowance storage slots from previous regenesis events.
// to calculate allowance storage slots from previous regenesis events.
// - chainID: The chain ID of the chain being migrated.
func Migrate(dataDir, outDir string, genesis *core.Genesis, addrLists, allowanceLists []string, chainID, levelDBCacheSize, levelDBHandles int) error {
db := MustOpenDBWithCacheOpts(dataDir, levelDBCacheSize, levelDBHandles)
......@@ -243,6 +243,9 @@ func Migrate(dataDir, outDir string, genesis *core.Genesis, addrLists, allowance
log.Info("trie dumping started", "root", root)
tr, err := backingStateDB.OpenTrie(root)
if err != nil {
return err
}
it := trie.NewIterator(tr.NodeIterator(nil))
totalMigrated := new(big.Int)
logAccountProgress := ProgressLogger(1000, "imported accounts")
......@@ -353,13 +356,11 @@ func Migrate(dataDir, outDir string, genesis *core.Genesis, addrLists, allowance
}
log.Info("committed trie DB")
// Now that the state is dumped, insert the genesis block. We pass in a nil
// database here because we don't want to update the state again with the
// pre-allocs.
// Now that the state is dumped, insert the genesis block.
//
// Unlike regular Geth (which panics if you try to import a genesis state with a nonzero
// block number), the block number can be anything.
block := genesis.ToBlock(nil)
block := genesis.ToBlock()
// Geth block headers are immutable, so swap the root and make a new block with the
// updated root.
......@@ -373,7 +374,7 @@ func Migrate(dataDir, outDir string, genesis *core.Genesis, addrLists, allowance
// Write the genesis state to the database. This is taken verbatim from Geth's
// core.Genesis struct.
rawdb.WriteGenesisState(outDB, block.Hash(), blob)
rawdb.WriteGenesisStateSpec(outDB, block.Hash(), blob)
rawdb.WriteTd(outDB, block.Hash(), block.NumberU64(), block.Difficulty())
rawdb.WriteBlock(outDB, block)
rawdb.WriteReceipts(outDB, block.Hash(), block.NumberU64(), nil)
......
package deployer
import (
"context"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)
// TestKey is the same test key that geth uses
var TestKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
// ChainID is the chain id used for simulated backends
var ChainID = big.NewInt(1337)
var TestAddress = crypto.PubkeyToAddress(TestKey.PublicKey)
var thousandETH = new(big.Int).Mul(big.NewInt(params.Ether), big.NewInt(1000))
type Constructor struct {
Name string
Args []interface{}
}
type Deployment struct {
Name string
Bytecode hexutil.Bytes
Address common.Address
}
type Deployer func(*backends.SimulatedBackend, *bind.TransactOpts, Constructor) (common.Address, error)
func NewBackend() *backends.SimulatedBackend {
return backends.NewSimulatedBackendWithCacheConfig(
&core.CacheConfig{
Preimages: true,
},
core.GenesisAlloc{
crypto.PubkeyToAddress(TestKey.PublicKey): {Balance: thousandETH},
},
15000000,
)
}
func Deploy(backend *backends.SimulatedBackend, constructors []Constructor, cb Deployer) ([]Deployment, error) {
results := make([]Deployment, len(constructors))
opts, err := bind.NewKeyedTransactorWithChainID(TestKey, ChainID)
if err != nil {
return nil, err
}
opts.GasLimit = 15_000_000
for i, deployment := range constructors {
addr, err := cb(backend, opts, deployment)
if err != nil {
return nil, err
}
backend.Commit()
if addr == (common.Address{}) {
return nil, fmt.Errorf("no address for %s", deployment.Name)
}
code, err := backend.CodeAt(context.Background(), addr, nil)
if len(code) == 0 {
return nil, fmt.Errorf("no code found for %s", deployment.Name)
}
if err != nil {
return nil, fmt.Errorf("cannot fetch code for %s", deployment.Name)
}
results[i] = Deployment{
Name: deployment.Name,
Bytecode: code,
Address: addr,
}
}
return results, nil
}
......@@ -2,66 +2,73 @@ package genesis
import (
"encoding/json"
"math/big"
"os"
"path/filepath"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/hardhat"
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/ethereum/go-ethereum/common"
)
// DeployConfig represents the deployment configuration for Optimism
type DeployConfig struct {
L1StartingBlockTag rpc.BlockNumberOrHash `json:"l1StartingBlockTag"`
L1ChainID *big.Int `json:"l1ChainID"`
L2ChainID *big.Int `json:"l2ChainID"`
L2BlockTime uint `json:"l2BlockTime"`
MaxSequencerDrift uint `json:"maxSequencerDrift"`
SequencerWindowSize uint `json:"sequencerWindowSize"`
ChannelTimeout uint `json:"channelTimeout"`
P2PSequencerAddress common.Address `json:"p2pSequencerAddress"`
OptimismL2FeeRecipient common.Address `json:"optimismL2FeeRecipient"`
BatchInboxAddress common.Address `json:"batchInboxAddress"`
BatchSenderAddress common.Address `json:"batchSenderAddress"`
L2OutputOracleSubmissionInterval uint `json:"l2OutputOracleSubmissionInterval"`
L2OutputOracleStartingTimestamp int `json:"l2OutputOracleStartingTimestamp"`
L2OutputOracleProposer common.Address `json:"l2OutputOracleProposer"`
L2OutputOracleOwner common.Address `json:"l2OutputOracleOwner"`
L1BlockTime uint64 `json:"l1BlockTime"`
CliqueSignerAddress common.Address `json:"cliqueSignerAddress"`
OptimismBaseFeeRecipient common.Address `json:"optimismBaseFeeRecipient"`
OptimismL1FeeRecipient common.Address `json:"optimismL1FeeRecipient"`
GasPriceOracleOwner common.Address `json:"gasPriceOracleOwner"`
GasPriceOracleOverhead uint `json:"gasPriceOracleOverhead"`
GasPriceOracleScalar uint `json:"gasPriceOracleScalar"`
GasPriceOracleDecimals uint `json:"gasPriceOracleDecimals"`
L2CrossDomainMessengerOwner common.Address `json:"l2CrossDomainMessengerOwner"`
L2GenesisBlockNonce uint64 `json:"l2GenesisBlockNonce"`
L2GenesisBlockExtraData hexutil.Bytes `json:"l2GenesisBlockExtraData"`
L2GenesisBlockGasLimit uint64 `json:"l2GenesisBlockGasLimit"`
L2GenesisBlockDifficulty *big.Int `json:"l2GenesisBlockDifficulty"`
L2GenesisBlockMixHash common.Hash `json:"l2GenesisBlockMixHash"`
L2GenesisBlockCoinbase common.Address `json:"l2GenesisBlockCoinbase"`
L2GenesisBlockNumber uint64 `json:"l2GenesisBlockNumber"`
L2GenesisBlockGasUsed uint64 `json:"l2GenesisBlockGasUsed"`
L2GenesisBlockParentHash common.Hash `json:"l2GenesisBlockParentHash"`
L2GenesisBlockBaseFeePerGas *big.Int `json:"l2GenesisBlockBaseFeePerGas"`
L1GenesisBlockTimestamp uint64 `json:"l1GenesisBlockTimestamp"`
L1GenesisBlockNonce uint64 `json:"l1GenesisBlockNonce"`
L1GenesisBlockGasLimit uint64 `json:"l1GenesisBlockGasLimit"`
L1GenesisBlockDifficulty *big.Int `json:"l1GenesisBlockDifficulty"`
L1GenesisBlockMixHash common.Hash `json:"l1GenesisBlockMixHash"`
L1GenesisBlockCoinbase common.Address `json:"l1GenesisBlockCoinbase"`
L1GenesisBlockNumber uint64 `json:"l1GenesisBlockNumber"`
L1GenesisBlockGasUsed uint64 `json:"l1GenesisBlockGasUsed"`
L1GenesisBlockParentHash common.Hash `json:"l1GenesisBlockParentHash"`
L1GenesisBlockBaseFeePerGas *big.Int `json:"l1GenesisBlockBaseFeePerGas"`
L1StartingBlockTag *rpc.BlockNumberOrHash `json:"l1StartingBlockTag"`
L1ChainID uint64 `json:"l1ChainID"`
L2ChainID uint64 `json:"l2ChainID"`
L2BlockTime uint64 `json:"l2BlockTime"`
FinalizationPeriodSeconds uint64 `json:"finalizationPeriodSeconds"`
MaxSequencerDrift uint64 `json:"maxSequencerDrift"`
SequencerWindowSize uint64 `json:"sequencerWindowSize"`
ChannelTimeout uint64 `json:"channelTimeout"`
P2PSequencerAddress common.Address `json:"p2pSequencerAddress"`
OptimismL2FeeRecipient common.Address `json:"optimismL2FeeRecipient"`
BatchInboxAddress common.Address `json:"batchInboxAddress"`
BatchSenderAddress common.Address `json:"batchSenderAddress"`
L2OutputOracleSubmissionInterval uint64 `json:"l2OutputOracleSubmissionInterval"`
L2OutputOracleStartingTimestamp int `json:"l2OutputOracleStartingTimestamp"`
L2OutputOracleProposer common.Address `json:"l2OutputOracleProposer"`
L2OutputOracleOwner common.Address `json:"l2OutputOracleOwner"`
L2OutputOracleGenesisL2Output common.Hash `json:"l2OutputOracleGenesisL2Output"`
L1BlockTime uint64 `json:"l1BlockTime"`
L1GenesisBlockTimestamp hexutil.Uint64 `json:"l1GenesisBlockTimestamp"`
L1GenesisBlockNonce hexutil.Uint64 `json:"l1GenesisBlockNonce"`
CliqueSignerAddress common.Address `json:"cliqueSignerAddress"`
L1GenesisBlockGasLimit hexutil.Uint64 `json:"l1GenesisBlockGasLimit"`
L1GenesisBlockDifficulty *hexutil.Big `json:"l1GenesisBlockDifficulty"`
L1GenesisBlockMixHash common.Hash `json:"l1GenesisBlockMixHash"`
L1GenesisBlockCoinbase common.Address `json:"l1GenesisBlockCoinbase"`
L1GenesisBlockNumber hexutil.Uint64 `json:"l1GenesisBlockNumber"`
L1GenesisBlockGasUsed hexutil.Uint64 `json:"l1GenesisBlockGasUsed"`
L1GenesisBlockParentHash common.Hash `json:"l1GenesisBlockParentHash"`
L1GenesisBlockBaseFeePerGas *hexutil.Big `json:"l1GenesisBlockBaseFeePerGas"`
L2GenesisBlockNonce hexutil.Uint64 `json:"l2GenesisBlockNonce"`
L2GenesisBlockExtraData hexutil.Bytes `json:"l2GenesisBlockExtraData"`
L2GenesisBlockGasLimit hexutil.Uint64 `json:"l2GenesisBlockGasLimit"`
L2GenesisBlockDifficulty *hexutil.Big `json:"l2GenesisBlockDifficulty"`
L2GenesisBlockMixHash common.Hash `json:"l2GenesisBlockMixHash"`
L2GenesisBlockCoinbase common.Address `json:"l2GenesisBlockCoinbase"`
L2GenesisBlockNumber hexutil.Uint64 `json:"l2GenesisBlockNumber"`
L2GenesisBlockGasUsed hexutil.Uint64 `json:"l2GenesisBlockGasUsed"`
L2GenesisBlockParentHash common.Hash `json:"l2GenesisBlockParentHash"`
L2GenesisBlockBaseFeePerGas *hexutil.Big `json:"l2GenesisBlockBaseFeePerGas"`
L2CrossDomainMessengerOwner common.Address `json:"l2CrossDomainMessengerOwner"`
OptimismBaseFeeRecipient common.Address `json:"optimismBaseFeeRecipient"`
OptimismL1FeeRecipient common.Address `json:"optimismL1FeeRecipient"`
GasPriceOracleOwner common.Address `json:"gasPriceOracleOwner"`
GasPriceOracleOverhead uint `json:"gasPriceOracleOverhead"`
GasPriceOracleScalar uint `json:"gasPriceOracleScalar"`
GasPriceOracleDecimals uint `json:"gasPriceOracleDecimals"`
DeploymentWaitConfirmations int `json:"deploymentWaitConfirmations"`
}
// NewDeployConfig reads a config file given a path on the filesystem.
......@@ -91,25 +98,11 @@ func NewDeployConfigWithNetwork(network, path string) (*DeployConfig, error) {
// contracts.
type StorageConfig map[string]state.StorageValues
// NewStorageConfig will create a StorageConfig given an instance of a
// NewL2StorageConfig will create a StorageConfig given an instance of a
// Hardhat and a DeployConfig.
func NewStorageConfig(hh *hardhat.Hardhat, config *DeployConfig, chain ethereum.ChainReader) (StorageConfig, error) {
func NewL2StorageConfig(config *DeployConfig, block *types.Block, proxyL1StandardBridge common.Address, proxyL1CrossDomainMessenger common.Address) (StorageConfig, error) {
storage := make(StorageConfig)
proxyL1StandardBridge, err := hh.GetDeployment("L1StandardBridgeProxy")
if err != nil {
return storage, err
}
proxyL1CrossDomainMessenger, err := hh.GetDeployment("L1CrossDomainMessengerProxy")
if err != nil {
return storage, err
}
block, err := getBlockFromTag(chain, config.L1StartingBlockTag)
if err != nil {
return storage, err
}
storage["L2ToL1MessagePasser"] = state.StorageValues{
"nonce": 0,
}
......@@ -122,7 +115,7 @@ func NewStorageConfig(hh *hardhat.Hardhat, config *DeployConfig, chain ethereum.
"_paused": false,
"xDomainMsgSender": "0x000000000000000000000000000000000000dEaD",
"msgNonce": 0,
"otherMessenger": proxyL1CrossDomainMessenger.Address,
"otherMessenger": proxyL1CrossDomainMessenger,
"blockedSystemAddresses": map[any]any{
predeploys.L2CrossDomainMessenger: true,
predeploys.L2ToL1MessagePasser: true,
......@@ -138,7 +131,7 @@ func NewStorageConfig(hh *hardhat.Hardhat, config *DeployConfig, chain ethereum.
"_initialized": true,
"_initializing": false,
"messenger": predeploys.L2CrossDomainMessenger,
"otherBridge": proxyL1StandardBridge.Address,
"otherBridge": proxyL1StandardBridge,
}
storage["SequencerFeeVault"] = state.StorageValues{
"l1FeeWallet": config.OptimismL1FeeRecipient,
......
package genesis
import (
"bytes"
"encoding/json"
"fmt"
"os"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require"
)
func TestConfigMarshalUnmarshal(t *testing.T) {
// NOTE: the l1 starting block tag is set to null
// in the test since the type is not JSON serializable.
// Rather than bloat the code by introducing a marshalable
// block tag type that's only used in test, I created a separate
// test to validate that the starting block tag unmarshals
// correctly.
b, err := os.ReadFile("testdata/test-deploy-config-full.json")
require.NoError(t, err)
dec := json.NewDecoder(bytes.NewReader(b))
decoded := new(DeployConfig)
require.NoError(t, dec.Decode(decoded))
encoded, err := json.MarshalIndent(decoded, "", " ")
require.NoError(t, err)
require.JSONEq(t, string(b), string(encoded))
}
func TestUnmarshalL1StartingBlockTag(t *testing.T) {
decoded := new(DeployConfig)
require.NoError(t, json.Unmarshal([]byte(`{"l1StartingBlockTag": "earliest"}`), decoded))
require.EqualValues(t, rpc.EarliestBlockNumber, *decoded.L1StartingBlockTag.BlockNumber)
h := "0x86c7263d87140ca7cd9bf1bc9e95a435a7a0efc0ae2afaf64920c5b59a6393d4"
require.NoError(t, json.Unmarshal([]byte(fmt.Sprintf(`{"l1StartingBlockTag": "%s"}`, h)), decoded))
require.EqualValues(t, common.HexToHash(h), *decoded.L1StartingBlockTag.BlockHash)
}
......@@ -5,7 +5,9 @@ import (
"math/big"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
......@@ -13,13 +15,13 @@ import (
)
// NewL2Genesis will create a new L2 genesis
func NewL2Genesis(config *DeployConfig, chain ethereum.ChainReader) (*core.Genesis, error) {
if config.L2ChainID == nil {
func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, error) {
if config.L2ChainID == 0 {
return nil, errors.New("must define L2 ChainID")
}
optimismChainConfig := params.ChainConfig{
ChainID: config.L2ChainID,
ChainID: new(big.Int).SetUint64(config.L2ChainID),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: false,
......@@ -53,42 +55,37 @@ func NewL2Genesis(config *DeployConfig, chain ethereum.ChainReader) (*core.Genes
}
gasLimit := config.L2GenesisBlockGasLimit
if gasLimit == 0 {
gasLimit = uint64(15_000_000)
gasLimit = 15_000_000
}
baseFee := config.L2GenesisBlockBaseFeePerGas
if baseFee == nil {
baseFee = big.NewInt(params.InitialBaseFee)
baseFee = newHexBig(params.InitialBaseFee)
}
difficulty := config.L2GenesisBlockDifficulty
if difficulty == nil {
difficulty = big.NewInt(1)
}
block, err := getBlockFromTag(chain, config.L1StartingBlockTag)
if err != nil {
return nil, err
difficulty = newHexBig(1)
}
return &core.Genesis{
Config: &optimismChainConfig,
Nonce: config.L2GenesisBlockNonce,
Nonce: uint64(config.L2GenesisBlockNonce),
Timestamp: block.Time(),
ExtraData: extraData,
GasLimit: gasLimit,
Difficulty: difficulty,
GasLimit: uint64(gasLimit),
Difficulty: difficulty.ToInt(),
Mixhash: config.L2GenesisBlockMixHash,
Coinbase: config.L2GenesisBlockCoinbase,
Number: config.L2GenesisBlockNumber,
GasUsed: config.L2GenesisBlockGasUsed,
Number: uint64(config.L2GenesisBlockNumber),
GasUsed: uint64(config.L2GenesisBlockGasUsed),
ParentHash: config.L2GenesisBlockParentHash,
BaseFee: baseFee,
BaseFee: baseFee.ToInt(),
Alloc: map[common.Address]core.GenesisAccount{},
}, nil
}
// NewL1Genesis will create a new L1 genesis config
func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) {
if config.L1ChainID == nil {
if config.L1ChainID == 0 {
return nil, errors.New("must define L1 ChainID")
}
......@@ -97,40 +94,40 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) {
Period: config.L1BlockTime,
Epoch: 30000,
}
chainConfig.ChainID = config.L1ChainID
chainConfig.ChainID = uint642Big(config.L1ChainID)
gasLimit := config.L1GenesisBlockGasLimit
if gasLimit == 0 {
gasLimit = uint64(15_000_000)
gasLimit = 15_000_000
}
baseFee := config.L1GenesisBlockBaseFeePerGas
if baseFee == nil {
baseFee = big.NewInt(params.InitialBaseFee)
baseFee = newHexBig(params.InitialBaseFee)
}
difficulty := config.L1GenesisBlockDifficulty
if difficulty == nil {
difficulty = big.NewInt(1)
difficulty = newHexBig(1)
}
timestamp := config.L1GenesisBlockTimestamp
if timestamp == 0 {
timestamp = uint64(time.Now().Unix())
timestamp = hexutil.Uint64(time.Now().Unix())
}
extraData := append(append(make([]byte, 32), config.CliqueSignerAddress[:]...), make([]byte, crypto.SignatureLength)...)
return &core.Genesis{
Config: &chainConfig,
Nonce: config.L1GenesisBlockNonce,
Timestamp: timestamp,
Nonce: uint64(config.L1GenesisBlockNonce),
Timestamp: uint64(timestamp),
ExtraData: extraData,
GasLimit: gasLimit,
Difficulty: difficulty,
GasLimit: uint64(gasLimit),
Difficulty: difficulty.ToInt(),
Mixhash: config.L1GenesisBlockMixHash,
Coinbase: config.L1GenesisBlockCoinbase,
Number: config.L1GenesisBlockNumber,
GasUsed: config.L1GenesisBlockGasUsed,
Number: uint64(config.L1GenesisBlockNumber),
GasUsed: uint64(config.L1GenesisBlockGasUsed),
ParentHash: config.L1GenesisBlockParentHash,
BaseFee: baseFee,
BaseFee: baseFee.ToInt(),
Alloc: map[common.Address]core.GenesisAccount{},
}, nil
}
......@@ -16,10 +16,14 @@ import (
var (
// codeNamespace represents the namespace of implementations of predeploys
codeNamespace = common.HexToAddress("0xc0D3C0d3C0d3C0D3c0d3C0d3c0D3C0d3c0d30000")
// predeployNamespace represents the namespace of predeploys
predeployNamespace = common.HexToAddress("0x4200000000000000000000000000000000000000")
// bigPredeployNamespace represents the predeploy namespace as a big.Int
bigPredeployNamespace = new(big.Int).SetBytes(predeployNamespace.Bytes())
// l2PredeployNamespace represents the namespace of L2 predeploys
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 = 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 = new(big.Int).SetBytes(codeNamespace.Bytes())
// implementationSlot represents the EIP 1967 implementation storage slot
......@@ -59,19 +63,26 @@ var DevAccounts = []common.Address{
var devBalance = hexutil.MustDecodeBig("0x200000000000000000000000000000000000000000000000000000000000000")
// AddressToCodeNamespace takes a predeploy address and computes
// the implmentation 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) {
bytesAddr := addr.Bytes()
if !bytes.Equal(bytesAddr[0:2], []byte{0x42, 0x00}) {
if !IsL1DevPredeploy(addr) && !IsL2DevPredeploy(addr) {
return common.Address{}, fmt.Errorf("cannot handle non predeploy: %s", addr)
}
bigAddress := new(big.Int).SetBytes(bytesAddr[18:])
bigAddress := new(big.Int).SetBytes(addr[18:])
num := new(big.Int).Or(bigCodeNameSpace, bigAddress)
return common.BigToAddress(num), nil
}
// getBlockFromTag will resolve a Block given an rpc block tag
func getBlockFromTag(chain ethereum.ChainReader, tag rpc.BlockNumberOrHash) (*types.Block, error) {
func IsL1DevPredeploy(addr common.Address) bool {
return bytes.Equal(addr[0:2], []byte{0x69, 0x00})
}
func IsL2DevPredeploy(addr common.Address) bool {
return bytes.Equal(addr[0:2], []byte{0x42, 0x00})
}
// GetBlockFromTag will resolve a Block given an rpc block tag
func GetBlockFromTag(chain ethereum.ChainReader, tag *rpc.BlockNumberOrHash) (*types.Block, error) {
if hash, ok := tag.Hash(); ok {
block, err := chain.BlockByHash(context.Background(), hash)
if err != nil {
......@@ -89,3 +100,14 @@ func getBlockFromTag(chain ethereum.ChainReader, tag rpc.BlockNumberOrHash) (*ty
return nil, fmt.Errorf("invalid block tag: %v", tag)
}
}
// uint642Big creates a new *big.Int from a uint64.
func uint642Big(in uint64) *big.Int {
return new(big.Int).SetUint64(in)
}
func newHexBig(in uint64) *hexutil.Big {
b := new(big.Int).SetUint64(in)
hb := hexutil.Big(*b)
return &hb
}
package genesis
import (
"errors"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-chain-ops/hardhat"
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/trie"
)
// TODO(tynes): need bindings for all of the L1 contracts to be able
// to create a genesis file with the L1 contracts predeployed.
// This would speed up testing as deployments take time when
// running tests.
func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) {
var proxies = []string{
"L2OutputOracleProxy",
"L1CrossDomainMessengerProxy",
"L1StandardBridgeProxy",
"OptimismPortalProxy",
"OptimismMintableERC20FactoryProxy",
}
var portalMeteringSlot = common.Hash{31: 0x01}
var zeroHash common.Hash
func BuildL1DeveloperGenesis(hh *hardhat.Hardhat, config *DeployConfig) (*core.Genesis, error) {
if config.L2OutputOracleStartingTimestamp != -1 {
return nil, errors.New("l2oo starting timestamp must be -1")
}
if config.L1GenesisBlockTimestamp == 0 {
return nil, errors.New("must specify l1 genesis block timestamp")
}
genesis, err := NewL1Genesis(config)
if err != nil {
return nil, err
}
db := state.NewMemoryStateDB(genesis)
backend := deployer.NewBackend()
deployments, err := deployL1Contracts(config, backend)
if err != nil {
return nil, err
}
depsByName := make(map[string]deployer.Deployment)
depsByAddr := make(map[common.Address]deployer.Deployment)
for _, dep := range deployments {
depsByName[dep.Name] = dep
depsByAddr[dep.Address] = dep
}
FundDevAccounts(db)
SetPrecompileBalances(db)
opts, err := bind.NewKeyedTransactorWithChainID(deployer.TestKey, deployer.ChainID)
if err != nil {
return nil, err
}
l2ooABI, err := bindings.L2OutputOracleMetaData.GetAbi()
if err != nil {
return nil, err
}
data, err := l2ooABI.Pack(
"initialize",
config.L2OutputOracleGenesisL2Output,
big.NewInt(0),
config.L2OutputOracleProposer,
config.L2OutputOracleOwner,
)
if err != nil {
return nil, err
}
if err := upgradeProxy(
backend,
opts,
depsByName["L2OutputOracleProxy"].Address,
depsByName["L2OutputOracle"].Address,
data,
); err != nil {
return nil, err
}
return db.Genesis(), nil
portalABI, err := bindings.OptimismPortalMetaData.GetAbi()
if err != nil {
return nil, err
}
data, err = portalABI.Pack("initialize")
if err != nil {
return nil, err
}
if err := upgradeProxy(
backend,
opts,
depsByName["OptimismPortalProxy"].Address,
depsByName["OptimismPortal"].Address,
data,
); err != nil {
return nil, err
}
l1XDMABI, err := bindings.L1CrossDomainMessengerMetaData.GetAbi()
if err != nil {
return nil, err
}
data, err = l1XDMABI.Pack("initialize")
if err != nil {
return nil, err
}
if err := upgradeProxy(
backend,
opts,
depsByName["L1CrossDomainMessengerProxy"].Address,
depsByName["L1CrossDomainMessenger"].Address,
data,
); err != nil {
return nil, err
}
l1SBrABI, err := bindings.L1StandardBridgeMetaData.GetAbi()
if err != nil {
return nil, err
}
data, err = l1SBrABI.Pack("initialize", predeploys.DevL1CrossDomainMessengerAddr)
if err != nil {
return nil, err
}
if err := upgradeProxy(
backend,
opts,
depsByName["L1StandardBridgeProxy"].Address,
depsByName["L1StandardBridge"].Address,
data,
); err != nil {
return nil, err
}
if err := upgradeProxy(
backend,
opts,
depsByName["OptimismMintableERC20FactoryProxy"].Address,
depsByName["OptimismMintableERC20Factory"].Address,
nil,
); err != nil {
return nil, err
}
backend.Commit()
memDB := state.NewMemoryStateDB(genesis)
if err := SetL1Proxies(hh, memDB, predeploys.DevProxyAdminAddr); err != nil {
return nil, err
}
FundDevAccounts(memDB)
SetPrecompileBalances(memDB)
for name, proxyAddr := range predeploys.DevPredeploys {
memDB.SetState(*proxyAddr, ImplementationSlot, depsByName[name].Address.Hash())
}
stateDB, err := backend.Blockchain().State()
if err != nil {
return nil, err
}
for _, dep := range deployments {
st := stateDB.StorageTrie(dep.Address)
iter := trie.NewIterator(st.NodeIterator(nil))
depAddr := dep.Address
if strings.HasSuffix(dep.Name, "Proxy") {
depAddr = *predeploys.DevPredeploys[strings.TrimSuffix(dep.Name, "Proxy")]
}
memDB.CreateAccount(depAddr)
memDB.SetCode(depAddr, dep.Bytecode)
for iter.Next() {
_, data, _, err := rlp.Split(iter.Value)
if err != nil {
return nil, err
}
key := common.BytesToHash(st.GetKey(iter.Key))
value := common.BytesToHash(data)
if depAddr == predeploys.DevOptimismPortalAddr && key == portalMeteringSlot {
// We need to manually set the block number in the resource
// metering storage slot to zero. Otherwise, deposits will
// revert.
copy(value[:24], zeroHash[:])
}
memDB.SetState(depAddr, key, value)
}
}
return memDB.Genesis(), nil
}
func deployL1Contracts(config *DeployConfig, backend *backends.SimulatedBackend) ([]deployer.Deployment, error) {
constructors := make([]deployer.Constructor, 0)
for _, proxy := range proxies {
constructors = append(constructors, deployer.Constructor{
Name: proxy,
})
}
constructors = append(constructors, []deployer.Constructor{
{
Name: "L2OutputOracle",
Args: []interface{}{
uint642Big(config.L2OutputOracleSubmissionInterval),
[32]byte(config.L2OutputOracleGenesisL2Output),
big.NewInt(0),
big.NewInt(0),
uint642Big(uint64(config.L1GenesisBlockTimestamp)),
uint642Big(config.L2BlockTime),
config.L2OutputOracleProposer,
config.L2OutputOracleOwner,
},
},
{
Name: "OptimismPortal",
Args: []interface{}{
uint642Big(config.FinalizationPeriodSeconds),
},
},
{
Name: "L1CrossDomainMessenger",
},
{
Name: "L1StandardBridge",
},
{
Name: "OptimismMintableERC20Factory",
},
{
Name: "AddressManager",
},
{
Name: "ProxyAdmin",
Args: []interface{}{
common.Address{19: 0x01},
},
},
}...)
return deployer.Deploy(backend, constructors, l1Deployer)
}
func l1Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, deployment deployer.Constructor) (common.Address, error) {
var addr common.Address
var err error
switch deployment.Name {
case "L2OutputOracle":
addr, _, _, err = bindings.DeployL2OutputOracle(
opts,
backend,
deployment.Args[0].(*big.Int),
deployment.Args[1].([32]byte),
deployment.Args[2].(*big.Int),
deployment.Args[3].(*big.Int),
deployment.Args[4].(*big.Int),
deployment.Args[5].(*big.Int),
deployment.Args[6].(common.Address),
deployment.Args[7].(common.Address),
)
case "OptimismPortal":
addr, _, _, err = bindings.DeployOptimismPortal(
opts,
backend,
predeploys.DevL2OutputOracleAddr,
deployment.Args[0].(*big.Int),
)
case "L1CrossDomainMessenger":
addr, _, _, err = bindings.DeployL1CrossDomainMessenger(
opts,
backend,
predeploys.DevOptimismPortalAddr,
)
case "L1StandardBridge":
addr, _, _, err = bindings.DeployL1StandardBridge(
opts,
backend,
predeploys.DevL1CrossDomainMessengerAddr,
)
case "OptimismMintableERC20Factory":
addr, _, _, err = bindings.DeployOptimismMintableERC20Factory(
opts,
backend,
predeploys.DevL1StandardBridgeAddr,
)
case "AddressManager":
addr, _, _, err = bindings.DeployAddressManager(
opts,
backend,
)
case "ProxyAdmin":
addr, _, _, err = bindings.DeployProxyAdmin(
opts,
backend,
common.Address{},
)
default:
if strings.HasSuffix(deployment.Name, "Proxy") {
addr, _, _, err = bindings.DeployProxy(opts, backend, deployer.TestAddress)
} else {
err = fmt.Errorf("unknown contract %s", deployment.Name)
}
}
return addr, err
}
func upgradeProxy(backend *backends.SimulatedBackend, opts *bind.TransactOpts, proxyAddr common.Address, implAddr common.Address, callData []byte) error {
proxy, err := bindings.NewProxy(proxyAddr, backend)
if err != nil {
return err
}
if callData == nil {
_, err = proxy.UpgradeTo(opts, implAddr)
} else {
_, err = proxy.UpgradeToAndCall(
opts,
implAddr,
callData,
)
}
if err == nil {
backend.Commit()
}
return err
}
package genesis
import (
"bytes"
"encoding/json"
"fmt"
"math/big"
"os"
"path/filepath"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/hardhat"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/stretchr/testify/require"
)
func TestBuildL1DeveloperGenesis(t *testing.T) {
b, err := os.ReadFile("testdata/test-deploy-config-full.json")
require.NoError(t, err)
dec := json.NewDecoder(bytes.NewReader(b))
config := new(DeployConfig)
require.NoError(t, dec.Decode(config))
config.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix())
tmpdir := filepath.Join(os.TempDir(), fmt.Sprintf("l2-test-%d", time.Now().Unix()))
require.NoError(t, Untar("testdata/artifacts.tar.gz", tmpdir))
hh, err := hardhat.New(
"goerli",
[]string{
filepath.Join(tmpdir, "contracts-bedrock"),
filepath.Join(tmpdir, "contracts-governance"),
},
[]string{"../../packages/contracts-bedrock/deployments"},
)
require.Nil(t, err)
genesis, err := BuildL1DeveloperGenesis(hh, config)
require.NoError(t, err)
sim := backends.NewSimulatedBackend(
genesis.Alloc,
15000000,
)
callOpts := &bind.CallOpts{}
oracle, err := bindings.NewL2OutputOracle(predeploys.DevL2OutputOracleAddr, sim)
require.NoError(t, err)
portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, sim)
require.NoError(t, err)
proposer, err := oracle.Proposer(callOpts)
require.NoError(t, err)
require.Equal(t, config.L2OutputOracleProposer, proposer)
owner, err := oracle.Owner(callOpts)
require.NoError(t, err)
require.Equal(t, config.L2OutputOracleOwner, owner)
// Same set of tests as exist in the deployment scripts
interval, err := oracle.SUBMISSIONINTERVAL(callOpts)
require.NoError(t, err)
require.EqualValues(t, config.L2OutputOracleSubmissionInterval, interval.Uint64())
histBlocks, err := oracle.HISTORICALTOTALBLOCKS(callOpts)
require.NoError(t, err)
require.EqualValues(t, 0, histBlocks.Uint64())
startBlock, err := oracle.STARTINGBLOCKNUMBER(callOpts)
require.NoError(t, err)
require.EqualValues(t, 0, startBlock.Uint64())
l2BlockTime, err := oracle.L2BLOCKTIME(callOpts)
require.NoError(t, err)
require.EqualValues(t, 2, l2BlockTime.Uint64())
oracleAddr, err := portal.L2ORACLE(callOpts)
require.NoError(t, err)
require.EqualValues(t, predeploys.DevL2OutputOracleAddr, oracleAddr)
msgr, err := bindings.NewL1CrossDomainMessenger(predeploys.DevL1CrossDomainMessengerAddr, sim)
require.NoError(t, err)
portalAddr, err := msgr.Portal(callOpts)
require.NoError(t, err)
require.Equal(t, predeploys.DevOptimismPortalAddr, portalAddr)
bridge, err := bindings.NewL1StandardBridge(predeploys.DevL1StandardBridgeAddr, sim)
require.NoError(t, err)
msgrAddr, err := bridge.Messenger(callOpts)
require.NoError(t, err)
require.Equal(t, predeploys.DevL1CrossDomainMessengerAddr, msgrAddr)
otherBridge, err := bridge.OtherBridge(callOpts)
require.NoError(t, err)
require.Equal(t, predeploys.L2StandardBridgeAddr, otherBridge)
factory, err := bindings.NewOptimismMintableERC20(predeploys.DevOptimismMintableERC20FactoryAddr, sim)
require.NoError(t, err)
bridgeAddr, err := factory.Bridge(callOpts)
require.NoError(t, err)
require.Equal(t, predeploys.DevL1StandardBridgeAddr, bridgeAddr)
// test that we can do deposits, etc.
priv, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")
require.NoError(t, err)
tOpts, err := bind.NewKeyedTransactorWithChainID(priv, deployer.ChainID)
require.NoError(t, err)
tOpts.Value = big.NewInt(0.001 * params.Ether)
tOpts.GasLimit = 1_000_000
_, err = bridge.DepositETH(tOpts, 200000, nil)
require.NoError(t, err)
}
......@@ -3,15 +3,22 @@ package genesis
import (
"github.com/ethereum-optimism/optimism/op-chain-ops/hardhat"
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/core"
)
// BuildOptimismDeveloperGenesis will build the developer Optimism Genesis
type L2Addresses struct {
ProxyAdmin common.Address
L1StandardBridgeProxy common.Address
L1CrossDomainMessengerProxy common.Address
}
// BuildL2DeveloperGenesis will build the developer Optimism Genesis
// Block. Suitable for devnets.
func BuildOptimismDeveloperGenesis(hh *hardhat.Hardhat, config *DeployConfig, chain ethereum.ChainReader) (*core.Genesis, error) {
genspec, err := NewL2Genesis(config, chain)
func BuildL2DeveloperGenesis(hh *hardhat.Hardhat, config *DeployConfig, l1StartBlock *types.Block, l2Addrs *L2Addresses) (*core.Genesis, error) {
genspec, err := NewL2Genesis(config, l1StartBlock)
if err != nil {
return nil, err
}
......@@ -21,20 +28,25 @@ func BuildOptimismDeveloperGenesis(hh *hardhat.Hardhat, config *DeployConfig, ch
FundDevAccounts(db)
SetPrecompileBalances(db)
return BuildOptimismGenesis(db, hh, config, chain)
return BuildL2Genesis(db, hh, config, l1StartBlock, l2Addrs)
}
// BuildOptimismGenesis will build the L2 Optimism Genesis Block
func BuildOptimismGenesis(db *state.MemoryStateDB, hh *hardhat.Hardhat, config *DeployConfig, chain ethereum.ChainReader) (*core.Genesis, error) {
// BuildL2Genesis will build the L2 Optimism Genesis Block
func BuildL2Genesis(db *state.MemoryStateDB, hh *hardhat.Hardhat, config *DeployConfig, l1Block *types.Block, l2Addrs *L2Addresses) (*core.Genesis, error) {
// TODO(tynes): need a function for clearing old, unused storage slots.
// Each deployed contract on L2 needs to have its existing storage
// inspected and then cleared if they are no longer used.
if err := SetProxies(hh, db); err != nil {
if err := SetL2Proxies(hh, db, l2Addrs.ProxyAdmin); err != nil {
return nil, err
}
storage, err := NewStorageConfig(hh, config, chain)
storage, err := NewL2StorageConfig(
config,
l1Block,
l2Addrs.L1StandardBridgeProxy,
l2Addrs.L1CrossDomainMessengerProxy,
)
if err != nil {
return nil, err
}
......
package genesis_test
import (
"context"
"encoding/json"
"flag"
"io/ioutil"
"fmt"
"math/big"
"os"
"path/filepath"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/core"
......@@ -25,18 +31,26 @@ func init() {
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
func TestBuildOptimismGenesis(t *testing.T) {
func TestBuildL2DeveloperGenesis(t *testing.T) {
tmpdir := filepath.Join(os.TempDir(), fmt.Sprintf("l2-test-%d", time.Now().Unix()))
require.NoError(t, genesis.Untar("testdata/artifacts.tar.gz", tmpdir))
hh, err := hardhat.New(
"goerli",
[]string{
"../../packages/contracts-bedrock/artifacts",
"../../packages/contracts-governance/artifacts",
filepath.Join(tmpdir, "contracts-bedrock"),
filepath.Join(tmpdir, "contracts-governance"),
},
[]string{"../../packages/contracts-bedrock/deployments"},
)
require.Nil(t, err)
config, err := genesis.NewDeployConfig("../../packages/contracts-bedrock/deploy-config/devnetL1.json")
config, err := genesis.NewDeployConfig("./testdata/test-deploy-config-devnet-l1.json")
require.Nil(t, err)
proxyAdmin, err := hh.GetDeployment("ProxyAdmin")
require.Nil(t, err)
proxy, err := hh.GetArtifact("Proxy")
require.Nil(t, err)
backend := backends.NewSimulatedBackend(
......@@ -45,16 +59,14 @@ func TestBuildOptimismGenesis(t *testing.T) {
},
15000000,
)
gen, err := genesis.BuildOptimismDeveloperGenesis(hh, config, backend)
block, err := backend.BlockByNumber(context.Background(), common.Big0)
require.NoError(t, err)
gen, err := genesis.BuildL2DeveloperGenesis(hh, config, block, &genesis.L2Addresses{
ProxyAdmin: proxyAdmin.Address,
})
require.Nil(t, err)
require.NotNil(t, gen)
proxyAdmin, err := hh.GetDeployment("ProxyAdmin")
require.Nil(t, err)
proxy, err := hh.GetArtifact("Proxy")
require.Nil(t, err)
for name, address := range predeploys.Predeploys {
addr := *address
......@@ -74,6 +86,6 @@ func TestBuildOptimismGenesis(t *testing.T) {
if writeFile {
file, _ := json.MarshalIndent(gen, "", " ")
_ = ioutil.WriteFile("genesis.json", file, 0644)
_ = os.WriteFile("genesis.json", file, 0644)
}
}
......@@ -20,22 +20,30 @@ func FundDevAccounts(db vm.StateDB) {
}
}
// SetProxies will set each of the proxies in the state. It requires
// SetL2Proxies 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 SetProxies(hh *hardhat.Hardhat, db vm.StateDB) error {
func SetL2Proxies(hh *hardhat.Hardhat, db vm.StateDB, proxyAdminAddr common.Address) error {
return setProxies(hh, db, proxyAdminAddr, bigL2PredeployNamespace, 2048)
}
// 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(hh *hardhat.Hardhat, db vm.StateDB, proxyAdminAddr common.Address) error {
return setProxies(hh, db, proxyAdminAddr, bigL1PredeployNamespace, 2048)
}
func setProxies(hh *hardhat.Hardhat, db vm.StateDB, proxyAdminAddr common.Address, namespace *big.Int, count uint64) error {
proxy, err := hh.GetArtifact("Proxy")
if err != nil {
return err
}
proxyAdmin, err := hh.GetDeployment("ProxyAdmin")
if err != nil {
return err
}
for i := uint64(0); i <= 2048; i++ {
bigAddr := new(big.Int).Or(bigPredeployNamespace, new(big.Int).SetUint64(i))
for i := uint64(0); i <= count; i++ {
bigAddr := new(big.Int).Or(namespace, new(big.Int).SetUint64(i))
addr := common.BigToAddress(bigAddr)
// There is no proxy at the governance token address
......@@ -45,7 +53,7 @@ func SetProxies(hh *hardhat.Hardhat, db vm.StateDB) error {
db.CreateAccount(addr)
db.SetCode(addr, proxy.DeployedBytecode)
db.SetState(addr, AdminSlot, proxyAdmin.Address.Hash())
db.SetState(addr, AdminSlot, proxyAdminAddr.Hash())
}
return nil
}
......@@ -78,7 +86,7 @@ func SetImplementations(hh *hardhat.Hardhat, db vm.StateDB, storage StorageConfi
if err != nil {
return err
}
// Set the implmentation slot in the predeploy proxy
// Set the implementation slot in the predeploy proxy
db.SetState(*address, ImplementationSlot, addr.Hash())
}
......@@ -138,14 +146,13 @@ func MigrateDepositHashes(hh *hardhat.Hardhat, db vm.StateDB) error {
ignore[encoded] = true
}
db.ForEachStorage(predeploys.L2ToL1MessagePasserAddr, func(key, value common.Hash) bool {
return db.ForEachStorage(predeploys.L2ToL1MessagePasserAddr, func(key, value common.Hash) bool {
if _, ok := ignore[key]; ok {
return true
}
// TODO(tynes): Do the value migration here
return true
})
return nil
}
// SetPrecompileBalances will set a single wei at each precompile address.
......
package genesis
import (
"archive/tar"
"compress/gzip"
"io"
"os"
"path/filepath"
)
func Untar(tarball, target string) error {
f, err := os.Open(tarball)
if err != nil {
return err
}
defer f.Close()
r, err := gzip.NewReader(f)
if err != nil {
return err
}
tarReader := tar.NewReader(r)
for {
header, err := tarReader.Next()
if err == io.EOF {
break
} else if err != nil {
return err
}
path := filepath.Join(target, header.Name)
info := header.FileInfo()
if info.IsDir() {
if err = os.MkdirAll(path, info.Mode()); err != nil {
return err
}
continue
}
file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(file, tarReader)
if err != nil {
return err
}
}
return nil
}
{
"l1StartingBlockTag": "earliest",
"l1ChainID": 900,
"l2ChainID": 901,
"l2BlockTime": 2,
"maxSequencerDrift": 100,
"sequencerWindowSize": 4,
"channelTimeout": 40,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0xd9c09e21b57c98e58a80552c170989b426766aa7",
"batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
"l2OutputOracleSubmissionInterval": 20,
"l2OutputOracleStartingTimestamp": -1,
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l2OutputOracleOwner": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l1BlockTime": 15,
"cliqueSignerAddress": "0xca062b0fd91172d89bcd4bb084ac4e21972cc467",
"optimismBaseFeeRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"optimismL1FeeRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
"deploymentWaitConfirmations": 1
}
{
"l1StartingBlockTag": null,
"l1ChainID": 901,
"l2ChainID": 902,
"l2BlockTime": 2,
"maxSequencerDrift": 20,
"sequencerWindowSize": 100,
"channelTimeout": 30,
"p2pSequencerAddress": "0x0000000000000000000000000000000000000000",
"optimismL2FeeRecipient": "0x42000000000000000000000000000000000000f0",
"batchInboxAddress": "0x42000000000000000000000000000000000000ff",
"batchSenderAddress": "0x0000000000000000000000000000000000000000",
"l2OutputOracleSubmissionInterval": 6,
"l2OutputOracleStartingTimestamp": -1,
"l2OutputOracleProposer": "0x7770000000000000000000000000000000000001",
"l2OutputOracleOwner": "0x7770000000000000000000000000000000000002",
"l1BlockTime": 15,
"l1GenesisBlockNonce": "0x0",
"cliqueSignerAddress": "0x0000000000000000000000000000000000000000",
"l1GenesisBlockGasLimit": "0xe4e1c0",
"l1GenesisBlockDifficulty": "0x1",
"finalizationPeriodSeconds": 2,
"l1GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"l1GenesisBlockCoinbase": "0x0000000000000000000000000000000000000000",
"l1GenesisBlockNumber": "0x0",
"l1GenesisBlockGasUsed": "0x0",
"l1GenesisBlockParentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"l1GenesisBlockTimestamp": "0x0",
"l1GenesisBlockBaseFeePerGas": "0x3b9aca00",
"l2GenesisBlockNonce": "0x0",
"l2GenesisBlockExtraData": "0x",
"l2GenesisBlockGasLimit": "0xe4e1c0",
"l2GenesisBlockDifficulty": "0x1",
"l2GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"l2GenesisBlockCoinbase": "0x42000000000000000000000000000000000000f0",
"l2OutputOracleGenesisL2Output": "0x0000000000000000000000000000000000000000000000000000000000000000",
"l2GenesisBlockNumber": "0x0",
"l2GenesisBlockGasUsed": "0x0",
"l2GenesisBlockParentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"l2GenesisBlockBaseFeePerGas": "0x3b9aca00",
"optimismBaseFeeRecipient": "0x42000000000000000000000000000000000000f1",
"optimismL1FeeRecipient": "0x0000000000000000000000000000000000000000",
"l2CrossDomainMessengerOwner": "0x42000000000000000000000000000000000000f2",
"gasPriceOracleOwner": "0x42000000000000000000000000000000000000f3",
"gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000,
"gasPriceOracleDecimals": 6,
"deploymentWaitConfirmations": 1
}
\ No newline at end of file
......@@ -4,8 +4,8 @@ go 1.18
require (
github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220820030939-de38b6f6f77e
github.com/ethereum-optimism/optimism/op-bindings v0.4.0
github.com/ethereum/go-ethereum v1.10.21
github.com/ethereum-optimism/optimism/op-bindings v0.5.0
github.com/ethereum/go-ethereum v1.10.23
github.com/mattn/go-isatty v0.0.14
github.com/stretchr/testify v1.7.2
github.com/urfave/cli/v2 v2.10.2
......@@ -52,3 +52,5 @@ require (
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace github.com/ethereum/go-ethereum v1.10.21 => github.com/ethereum-optimism/op-geth v0.0.0-20220904174542-4311f9d2cead
......@@ -174,12 +174,12 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220820030939-de38b6f6f77e h1:LUfy9ofKcen9Cm1T9JyGNnrPLR2AmyelFbohS6bs4X8=
github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220820030939-de38b6f6f77e/go.mod h1:Oj5A6Qs/Ao1SP17i3uKroyhz49q/ehagSXRAlvwaI5Y=
github.com/ethereum-optimism/optimism/op-bindings v0.4.0 h1:4Yop9PGMBUhRtg12aR/ydTTut72s/1J+ztl0lv8UvSI=
github.com/ethereum-optimism/optimism/op-bindings v0.4.0/go.mod h1:LHuyDHLNLalBJouGRnryAivhRBz+r4T0+stIKaE1+/g=
github.com/ethereum-optimism/optimism/op-bindings v0.5.0 h1:bJT8KmDu5YAVOqPQHxHkntGlRrtRdTIsH+X28LOIcqU=
github.com/ethereum-optimism/optimism/op-bindings v0.5.0/go.mod h1:Ft+sL57mlBysH6nuXZA11GLMMajfBa8SjpEBtitl1Vw=
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y=
github.com/ethereum/go-ethereum v1.10.21 h1:5lqsEx92ZaZzRyOqBEXux4/UR06m296RGzN3ol3teJY=
github.com/ethereum/go-ethereum v1.10.21/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/ethereum/go-ethereum v1.10.23 h1:Xk8XAT4/UuqcjMLIMF+7imjkg32kfVFKoeyQDaO2yWM=
github.com/ethereum/go-ethereum v1.10.23/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
......
......@@ -26,7 +26,7 @@ type Hardhat struct {
artifacts []*Artifact
deployments []*Deployment
buildInfos []*BuildInfo
buildInfos []*BuildInfo //nolint:unused
}
// New creates a new `Hardhat` struct and reads all of the files from
......@@ -202,7 +202,7 @@ func (h *Hardhat) GetBuildInfo(name string) (*BuildInfo, error) {
for _, artifactPath := range h.ArtifactPaths {
fileSystem := os.DirFS(artifactPath)
fs.WalkDir(fileSystem, ".", func(path string, d fs.DirEntry, err error) error {
err := fs.WalkDir(fileSystem, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
......@@ -249,6 +249,9 @@ func (h *Hardhat) GetBuildInfo(name string) (*BuildInfo, error) {
return nil
})
if err != nil {
return nil, err
}
}
// TODO(tynes): handle multiple contracts with same name when required
......
......@@ -57,7 +57,7 @@ type Log struct {
}
// Artifact represents a hardhat compilation artifact
// The Bytecode and DeployedBytecode are not guranteed
// The Bytecode and DeployedBytecode are not guaranteed
// to be hexutil.Bytes when there are link references.
// In the future, custom json marshalling can be used
// to place the link reference values in the correct location.
......
package immutables
import (
"context"
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"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/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
)
// testKey is the same test key that geth uses
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
// chainID is the chain id used for simulated backends
var chainID = big.NewInt(1337)
// TODO(tynes): we are planning on making some constructor arguments
// into immutables before the final deployment of the system. This
// means that this struct will need to be updated with an additional
// parameter: Args []interface{}{} and each step will need to typecast
// each argument before doing the simulated deployment
type Deployment struct {
Name string
}
// DeploymentResults represents the output of deploying each of the
// contracts so that the immutables can be set properly in the bytecode.
type DeploymentResults map[string]hexutil.Bytes
......@@ -40,7 +21,7 @@ type DeploymentResults map[string]hexutil.Bytes
// a JSON file/cli flags and then populate the Deployment
// Args.
func BuildOptimism() (DeploymentResults, error) {
deployments := []Deployment{
deployments := []deployer.Constructor{
{
Name: "GasPriceOracle",
},
......@@ -63,81 +44,56 @@ func BuildOptimism() (DeploymentResults, error) {
Name: "OptimismMintableERC20Factory",
},
}
return Build(deployments)
return BuildL2(deployments)
}
// Build will deploy contracts to a simulated backend so that their immutables
// BuildL2 will deploy contracts to a simulated backend so that their immutables
// can be properly set. The bytecode returned in the results is suitable to be
// inserted into the state via state surgery.
func Build(deployments []Deployment) (DeploymentResults, error) {
backend := backends.NewSimulatedBackend(
core.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
},
15000000,
)
results := make(DeploymentResults)
opts, err := bind.NewKeyedTransactorWithChainID(testKey, chainID)
func BuildL2(constructors []deployer.Constructor) (DeploymentResults, error) {
deployments, err := deployer.Deploy(deployer.NewBackend(), constructors, l2Deployer)
if err != nil {
return nil, err
}
results := make(DeploymentResults)
for _, dep := range deployments {
results[dep.Name] = dep.Bytecode
}
return results, nil
}
for _, deployment := range deployments {
var addr common.Address
switch deployment.Name {
case "GasPriceOracle":
// The owner of the gas price oracle is not immutable, not required
// to be set here. It cannot be `address(0)`
owner := common.Address{1}
addr, _, _, err = bindings.DeployGasPriceOracle(opts, backend, owner)
if err != nil {
return nil, err
}
case "L1Block":
// No arguments required for the L1Block contract
addr, _, _, err = bindings.DeployL1Block(opts, backend)
if err != nil {
return nil, err
}
case "L2CrossDomainMessenger":
// The L1CrossDomainMessenger value is not immutable, no need to set
// it here correctly
l1CrossDomainMessenger := common.Address{}
addr, _, _, err = bindings.DeployL2CrossDomainMessenger(opts, backend, l1CrossDomainMessenger)
if err != nil {
return nil, err
}
case "L2StandardBridge":
// The OtherBridge value is not immutable, no need to set
otherBridge := common.Address{}
addr, _, _, err = bindings.DeployL2StandardBridge(opts, backend, otherBridge)
case "L2ToL1MessagePasser":
// No arguments required for L2ToL1MessagePasser
addr, _, _, err = bindings.DeployL2ToL1MessagePasser(opts, backend)
case "SequencerFeeVault":
// No arguments to SequencerFeeVault
addr, _, _, err = bindings.DeploySequencerFeeVault(opts, backend)
case "OptimismMintableERC20Factory":
addr, _, _, err = bindings.DeployOptimismMintableERC20Factory(opts, backend, predeploys.L2StandardBridgeAddr)
default:
return nil, fmt.Errorf("unknown contract: %s", deployment.Name)
}
backend.Commit()
if addr == (common.Address{}) {
return nil, fmt.Errorf("no address for %s", deployment.Name)
}
code, err := backend.CodeAt(context.Background(), addr, nil)
if len(code) == 0 {
return nil, fmt.Errorf("no code found for %s", deployment.Name)
}
if err != nil {
return nil, fmt.Errorf("cannot fetch code for %s", deployment.Name)
}
results[deployment.Name] = code
func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, deployment deployer.Constructor) (common.Address, error) {
var addr common.Address
var err error
switch deployment.Name {
case "GasPriceOracle":
// The owner of the gas price oracle is not immutable, not required
// to be set here. It cannot be `address(0)`
owner := common.Address{1}
addr, _, _, err = bindings.DeployGasPriceOracle(opts, backend, owner)
case "L1Block":
// No arguments required for the L1Block contract
addr, _, _, err = bindings.DeployL1Block(opts, backend)
case "L2CrossDomainMessenger":
// The L1CrossDomainMessenger value is not immutable, no need to set
// it here correctly
l1CrossDomainMessenger := common.Address{}
addr, _, _, err = bindings.DeployL2CrossDomainMessenger(opts, backend, l1CrossDomainMessenger)
case "L2StandardBridge":
// The OtherBridge value is not immutable, no need to set
otherBridge := common.Address{}
addr, _, _, err = bindings.DeployL2StandardBridge(opts, backend, otherBridge)
case "L2ToL1MessagePasser":
// No arguments required for L2ToL1MessagePasser
addr, _, _, err = bindings.DeployL2ToL1MessagePasser(opts, backend)
case "SequencerFeeVault":
// No arguments to SequencerFeeVault
addr, _, _, err = bindings.DeploySequencerFeeVault(opts, backend)
case "OptimismMintableERC20Factory":
addr, _, _, err = bindings.DeployOptimismMintableERC20Factory(opts, backend, predeploys.L2StandardBridgeAddr)
default:
return addr, fmt.Errorf("unknown contract: %s", deployment.Name)
}
return results, nil
return addr, err
}
......@@ -55,7 +55,7 @@ type StorageLayoutEntry struct {
Label string `json:"label"`
Offset uint `json:"offset"`
Slot uint `json:"slot,string"`
Type string `json"type"`
Type string `json:"type"`
}
type StorageLayoutType struct {
......@@ -73,7 +73,7 @@ type CompilerOutputEvm struct {
MethodIdentifiers map[string]string `json:"methodIdentifiers"`
}
// Object must be a string because its not guranteed to be
// Object must be a string because its not guaranteed to be
// a hex string
type CompilerOutputBytecode struct {
Object string `json:"object"`
......
......@@ -21,7 +21,7 @@ type EncodedStorage struct {
Value common.Hash
}
// EncodedStorage will encode a storage layout
// EncodeStorage will encode a storage layout
func EncodeStorage(entry solc.StorageLayoutEntry, value any, storageType solc.StorageLayoutType) ([]*EncodedStorage, error) {
if storageType.NumberOfBytes > 32 {
return nil, fmt.Errorf("%s is larger than 32 bytes", storageType.Encoding)
......
......@@ -276,7 +276,11 @@ func TestMergeStorage(t *testing.T) {
for _, test := range cases {
got := state.MergeStorage(test.input)
require.Equal(t, got, test.expect)
// deep equal check
require.Equal(t, len(got), len(test.expect))
for i := range got {
require.Equal(t, *got[i], *test.expect[i])
}
}
}
......
......@@ -624,4 +624,3 @@ func (_Testdata *TestdataSession) SetStorage(key [32]byte, value [32]byte) (*typ
func (_Testdata *TestdataTransactorSession) SetStorage(key [32]byte, value [32]byte) (*types.Transaction, error) {
return _Testdata.Contract.SetStorage(&_Testdata.TransactOpts, key, value)
}
......@@ -8,6 +8,8 @@ import (
"math/big"
"time"
"github.com/ethereum/go-ethereum/cmd/utils"
rollupEth "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/keystore"
......@@ -216,6 +218,10 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, pri
}
// PR 25459 changed this to only default in CLI, but not in default programmatic RPC selection.
// PR 25642 fixed it for the mobile version only...
utils.RegisterFilterAPI(n, backend.APIBackend, ethCfg)
n.RegisterAPIs(tracers.APIs(backend.APIBackend))
// Enable catalyst if l2
......
......@@ -8,7 +8,7 @@ require (
github.com/ethereum-optimism/optimism/op-node v0.5.0
github.com/ethereum-optimism/optimism/op-proposer v0.5.0
github.com/ethereum-optimism/optimism/op-service v0.5.0
github.com/ethereum/go-ethereum v1.10.21
github.com/ethereum/go-ethereum v1.10.23
github.com/libp2p/go-libp2p v0.21.0
github.com/libp2p/go-libp2p-core v0.19.1
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
......@@ -31,6 +31,7 @@ require (
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
......@@ -47,6 +48,7 @@ require (
github.com/google/gopacket v1.1.19 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/graph-gophers/graphql-go v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-bexpr v0.1.11 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
......@@ -54,6 +56,9 @@ require (
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.0 // indirect
github.com/huin/goupnp v1.0.3 // indirect
github.com/influxdata/influxdb v1.8.3 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/ipfs/go-cid v0.2.0 // indirect
github.com/ipfs/go-datastore v0.5.1 // indirect
github.com/ipfs/go-ds-leveldb v0.5.0 // indirect
......@@ -105,6 +110,7 @@ require (
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
......@@ -144,8 +150,9 @@ require (
golang.org/x/tools v0.1.12 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
)
replace github.com/ethereum/go-ethereum v1.10.21 => github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61
replace github.com/ethereum/go-ethereum v1.10.23 => github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638
This diff is collapsed.
......@@ -45,7 +45,7 @@ var _ = func() bool {
var verboseGethNodes bool
func init() {
flag.BoolVar(&verboseGethNodes, "gethlogs", false, "Enable logs on geth nodes")
flag.BoolVar(&verboseGethNodes, "gethlogs", true, "Enable logs on geth nodes")
flag.Parse()
}
......
......@@ -2,147 +2,120 @@ package genesis
import (
"encoding/json"
"fmt"
"math/big"
"os"
"strings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/urfave/cli"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-chain-ops/hardhat"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/ethclient"
)
var Subcommands = cli.Commands{
{
Name: "devnet-l2",
Usage: "Initialized a new L2 devnet genesis file",
Name: "devnet",
Usage: "Initialize new L1 and L2 genesis files and rollup config suitable for a local devnet",
Flags: []cli.Flag{
cli.StringFlag{
Name: "artifacts",
Usage: "Comma delimeted list of hardhat artifact directories",
Usage: "Comma delimited list of hardhat artifact directories",
},
cli.StringFlag{
Name: "network",
Usage: "Name of hardhat deploy network",
Name: "deploy-config",
Usage: "Path to hardhat deploy config file",
},
cli.StringFlag{
Name: "deployments",
Usage: "Comma delimated list of hardhat deploy artifact directories",
Name: "outfile.l1",
Usage: "Path to L1 genesis output file",
},
cli.StringFlag{
Name: "deploy-config",
Usage: "Path to hardhat deploy config directory",
Name: "outfile.l2",
Usage: "Path to L2 genesis output file",
},
cli.StringFlag{
Name: "rpc-url",
Usage: "L1 RPC URL",
},
cli.StringFlag{
Name: "outfile",
Usage: "Path to file to write output to",
Name: "outfile.rollup",
Usage: "Path to rollup output file",
},
},
Action: func(ctx *cli.Context) error {
// Turn off logging for this command unless it is a critical
// error so that the output can be piped to jq
log.Root().SetHandler(
log.LvlFilterHandler(
log.LvlCrit,
log.StreamHandler(os.Stdout, log.TerminalFormat(true)),
),
)
artifact := ctx.String("artifacts")
artifacts := strings.Split(artifact, ",")
deployment := ctx.String("deployments")
deployments := strings.Split(deployment, ",")
network := ctx.String("network")
hh, err := hardhat.New(network, artifacts, deployments)
hh, err := hardhat.New("", artifacts, nil)
if err != nil {
return err
}
deployConfig := ctx.String("deploy-config")
config, err := genesis.NewDeployConfigWithNetwork(network, deployConfig)
config, err := genesis.NewDeployConfig(deployConfig)
if err != nil {
return err
}
rpcUrl := ctx.String("rpc-url")
client, err := ethclient.Dial(rpcUrl)
l1Genesis, err := genesis.BuildL1DeveloperGenesis(hh, config)
if err != nil {
return err
}
gen, err := genesis.BuildOptimismDeveloperGenesis(hh, config, client)
if err != nil {
return err
l1StartBlock := l1Genesis.ToBlock()
l2Addrs := &genesis.L2Addresses{
ProxyAdmin: predeploys.DevProxyAdminAddr,
L1StandardBridgeProxy: predeploys.DevL1StandardBridgeAddr,
L1CrossDomainMessengerProxy: predeploys.DevL1CrossDomainMessengerAddr,
}
file, err := json.MarshalIndent(gen, "", " ")
l2Genesis, err := genesis.BuildL2DeveloperGenesis(hh, config, l1StartBlock, l2Addrs)
if err != nil {
return err
}
outfile := ctx.String("outfile")
if outfile == "" {
fmt.Println(string(file))
} else {
if err := os.WriteFile(outfile, file, 0644); err != nil {
return err
}
}
return nil
},
},
{
Name: "devnet-l1",
Usage: "Initialized a new L1 devnet genesis file",
Flags: []cli.Flag{
cli.StringFlag{
Name: "network",
Usage: "Name of hardhat deploy network",
},
cli.StringFlag{
Name: "deploy-config",
Usage: "Path to hardhat deploy config directory",
},
cli.StringFlag{
Name: "outfile",
Usage: "Path to file to write output to",
},
},
Action: func(ctx *cli.Context) error {
network := ctx.String("network")
deployConfig := ctx.String("deploy-config")
config, err := genesis.NewDeployConfigWithNetwork(network, deployConfig)
if err != nil {
return err
rollupConfig := &rollup.Config{
Genesis: rollup.Genesis{
L1: eth.BlockID{
Hash: l1StartBlock.Hash(),
Number: 0,
},
L2: eth.BlockID{
Hash: l2Genesis.ToBlock().Hash(),
Number: 0,
},
L2Time: uint64(config.L1GenesisBlockTimestamp),
},
BlockTime: config.L2BlockTime,
MaxSequencerDrift: config.MaxSequencerDrift,
SeqWindowSize: config.SequencerWindowSize,
ChannelTimeout: config.ChannelTimeout,
L1ChainID: new(big.Int).SetUint64(config.L1ChainID),
L2ChainID: new(big.Int).SetUint64(config.L2ChainID),
P2PSequencerAddress: config.P2PSequencerAddress,
FeeRecipientAddress: config.OptimismL2FeeRecipient,
BatchInboxAddress: config.BatchInboxAddress,
BatchSenderAddress: config.BatchSenderAddress,
DepositContractAddress: predeploys.DevOptimismPortalAddr,
}
gen, err := genesis.BuildL1DeveloperGenesis(config)
if err != nil {
if err := writeGenesisFile(ctx.String("outfile.l1"), l1Genesis); err != nil {
return err
}
file, err := json.MarshalIndent(gen, "", " ")
if err != nil {
if err := writeGenesisFile(ctx.String("outfile.l2"), l2Genesis); err != nil {
return err
}
outfile := ctx.String("outfile")
if outfile == "" {
fmt.Println(string(file))
} else {
if err := os.WriteFile(outfile, file, 0644); err != nil {
return err
}
}
return nil
return writeGenesisFile(ctx.String("outfile.rollup"), rollupConfig)
},
},
}
func writeGenesisFile(outfile string, input interface{}) error {
f, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755)
if err != nil {
return err
}
defer f.Close()
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
return enc.Encode(input)
}
......@@ -7,7 +7,7 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
github.com/ethereum-optimism/optimism/op-bindings v0.5.0
github.com/ethereum-optimism/optimism/op-chain-ops v0.0.0-20220822214343-2106bdb7fc11
github.com/ethereum/go-ethereum v1.10.21
github.com/ethereum/go-ethereum v1.10.23
github.com/golang/snappy v0.0.4
github.com/google/go-cmp v0.5.8
github.com/hashicorp/go-multierror v1.1.1
......@@ -160,4 +160,4 @@ require (
lukechampine.com/blake3 v1.1.7 // indirect
)
replace github.com/ethereum/go-ethereum v1.10.21 => github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61
replace github.com/ethereum/go-ethereum v1.10.23 => github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638
......@@ -188,8 +188,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61 h1:+WfrwiRELp3hoeb1bnPws3FtUUoYCDDYsCkwvKek5FY=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638 h1:LcvgHjeooGBobfEIEYikMzx1MoIAjRqa/ZDdkrhV3Hw=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo=
github.com/ethereum-optimism/optimism/op-bindings v0.5.0 h1:bJT8KmDu5YAVOqPQHxHkntGlRrtRdTIsH+X28LOIcqU=
github.com/ethereum-optimism/optimism/op-bindings v0.5.0/go.mod h1:Ft+sL57mlBysH6nuXZA11GLMMajfBa8SjpEBtitl1Vw=
github.com/ethereum-optimism/optimism/op-chain-ops v0.0.0-20220822214343-2106bdb7fc11 h1:be6PccBLLuTZZKC9FuwArNjMVX8R83TCnwknncWJqQw=
......
......@@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/backoff"
"github.com/ethereum/go-ethereum/log"
gn "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
)
......@@ -43,7 +44,7 @@ func (cfg *L2EndpointConfig) Setup(ctx context.Context, log log.Logger) (*rpc.Cl
if err := cfg.Check(); err != nil {
return nil, err
}
auth := rpc.NewJWTAuthProvider(cfg.L2EngineJWTSecret)
auth := rpc.WithHTTPAuth(gn.NewJWTAuth(cfg.L2EngineJWTSecret))
l2Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L2EngineAddr, auth)
if err != nil {
return nil, err
......@@ -82,7 +83,7 @@ type L1EndpointConfig struct {
var _ L1EndpointSetup = (*L1EndpointConfig)(nil)
func (cfg *L1EndpointConfig) Setup(ctx context.Context, log log.Logger) (cl *rpc.Client, trust bool, err error) {
l1Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L1NodeAddr, nil)
l1Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L1NodeAddr)
if err != nil {
return nil, false, fmt.Errorf("failed to dial L1 address (%s): %w", cfg.L1NodeAddr, err)
}
......@@ -102,17 +103,11 @@ func (p *PreparedL1Endpoint) Setup(ctx context.Context, log log.Logger) (cl *rpc
}
// Dials a JSON-RPC endpoint repeatedly, with a backoff, until a client connection is established. Auth is optional.
func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string, auth rpc.HeaderAuthProvider) (*rpc.Client, error) {
func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string, opts ...rpc.ClientOption) (*rpc.Client, error) {
bOff := backoff.Exponential()
var ret *rpc.Client
err := backoff.Do(10, bOff, func() error {
var client *rpc.Client
var err error
if auth == nil {
client, err = rpc.DialContext(ctx, addr)
} else {
client, err = rpc.DialWithAuth(ctx, addr, auth)
}
client, err := rpc.DialOptions(ctx, addr, opts...)
if err != nil {
if client == nil {
return fmt.Errorf("failed to dial address (%s): %w", addr, err)
......
......@@ -109,7 +109,7 @@ func TestOutputAtBlock(t *testing.T) {
assert.NoError(t, server.Start())
defer server.Stop()
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String(), nil)
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String())
assert.NoError(t, err)
var out []eth.Bytes32
......@@ -135,7 +135,7 @@ func TestVersion(t *testing.T) {
assert.NoError(t, server.Start())
defer server.Stop()
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String(), nil)
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String())
assert.NoError(t, err)
var out string
......@@ -170,7 +170,7 @@ func TestSyncStatus(t *testing.T) {
assert.NoError(t, server.Start())
defer server.Stop()
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String(), nil)
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String())
assert.NoError(t, err)
var out *driver.SyncStatus
......
......@@ -6,7 +6,7 @@ require (
github.com/ethereum-optimism/optimism/op-bindings v0.5.0
github.com/ethereum-optimism/optimism/op-node v0.5.0
github.com/ethereum-optimism/optimism/op-service v0.5.0
github.com/ethereum/go-ethereum v1.10.21
github.com/ethereum/go-ethereum v1.10.23
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
github.com/stretchr/testify v1.8.0
github.com/urfave/cli v1.22.9
......@@ -78,4 +78,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace github.com/ethereum/go-ethereum v1.10.21 => github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61
replace github.com/ethereum/go-ethereum v1.10.23 => github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638
......@@ -150,8 +150,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61 h1:+WfrwiRELp3hoeb1bnPws3FtUUoYCDDYsCkwvKek5FY=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638 h1:LcvgHjeooGBobfEIEYikMzx1MoIAjRqa/ZDdkrhV3Hw=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo=
github.com/ethereum-optimism/optimism/op-bindings v0.5.0 h1:bJT8KmDu5YAVOqPQHxHkntGlRrtRdTIsH+X28LOIcqU=
github.com/ethereum-optimism/optimism/op-bindings v0.5.0/go.mod h1:Ft+sL57mlBysH6nuXZA11GLMMajfBa8SjpEBtitl1Vw=
github.com/ethereum-optimism/optimism/op-node v0.5.0 h1:MwNvYDBFS4quSWkEzfJBGJkzI1yveqQ/GuVK6aTJJ0A=
......
......@@ -3,7 +3,7 @@ module github.com/ethereum-optimism/optimism/op-service
go 1.18
require (
github.com/ethereum/go-ethereum v1.10.21
github.com/ethereum/go-ethereum v1.10.23
github.com/prometheus/client_golang v1.13.0
github.com/stretchr/testify v1.8.0
github.com/urfave/cli v1.22.9
......@@ -65,4 +65,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace github.com/ethereum/go-ethereum v1.10.21 => github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61
replace github.com/ethereum/go-ethereum v1.10.23 => github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638
......@@ -108,8 +108,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61 h1:+WfrwiRELp3hoeb1bnPws3FtUUoYCDDYsCkwvKek5FY=
github.com/ethereum-optimism/op-geth v0.0.0-20220819161933-acfde114de61/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638 h1:LcvgHjeooGBobfEIEYikMzx1MoIAjRqa/ZDdkrhV3Hw=
github.com/ethereum-optimism/op-geth v0.0.0-20220907143004-2aacc679d638/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
......
......@@ -62,14 +62,21 @@ mkdir -p ./.devnet
# Regenerate the L1 genesis file if necessary. The existence of the genesis
# file is used to determine if we need to recreate the devnet's state folder.
if [ ! -f $DEVNET/genesis-l1.json ]; then
echo "Regenerating L1 genesis."
if [ ! -f "$DEVNET/done" ]; then
echo "Regenerating genesis files"
TIMESTAMP=$(date +%s | xargs printf '0x%x')
cat "$CONTRACTS_BEDROCK/deploy-config/devnetL1.json" | jq -r ".l1GenesisBlockTimestamp = \"$TIMESTAMP\"" > /tmp/bedrock-devnet-deploy-config.json
(
cd "$OP_NODE"
go run cmd/main.go genesis devnet-l1 \
--network $NETWORK \
--deploy-config $CONTRACTS_BEDROCK/deploy-config \
--outfile $DEVNET/genesis-l1.json
go run cmd/main.go genesis devnet \
--artifacts "$CONTRACTS_BEDROCK/artifacts,$CONTRACTS_GOVERNANCE/artifacts" \
--deploy-config /tmp/bedrock-devnet-deploy-config.json \
--outfile.l1 $DEVNET/genesis-l1.json \
--outfile.l2 $DEVNET/genesis-l2.json \
--outfile.rollup $DEVNET/rollup.json
touch "$DEVNET/done"
)
fi
......@@ -82,34 +89,6 @@ fi
wait_up $L1_URL
)
# Deploy contracts using Hardhat.
if [ ! -d "$CONTRACTS_BEDROCK/deployments/$NETWORK" ]; then
(
echo "Deploying contracts."
cd "$CONTRACTS_BEDROCK"
yarn hardhat --network $NETWORK deploy
)
else
echo "Contracts already deployed, skipping."
fi
if [ ! -f "$DEVNET/genesis-l2.json" ]; then
(
echo "Creating L2 genesis file."
cd "$OP_NODE"
go run cmd/main.go genesis devnet-l2 \
--artifacts "$CONTRACTS_BEDROCK/artifacts,$CONTRACTS_GOVERNANCE/artifacts" \
--network $NETWORK \
--deployments "$CONTRACTS_BEDROCK/deployments" \
--deploy-config "$CONTRACTS_BEDROCK/deploy-config" \
--rpc-url http://localhost:8545 \
--outfile "$DEVNET/genesis-l2.json"
echo "Created L2 genesis."
)
else
echo "L2 genesis already exists."
fi
# Bring up L2.
(
cd ops-bedrock
......@@ -118,19 +97,7 @@ fi
wait_up $L2_URL
)
# Start putting together the rollup config.
if [ ! -f "$DEVNET/rollup.json" ]; then
(
echo "Building rollup config..."
cd "$CONTRACTS_BEDROCK"
npx hardhat --network $NETWORK rollup-config
mv rollup.json "$DEVNET/rollup.json"
)
else
echo "Rollup config already exists"
fi
L2OO_ADDRESS=$(jq -r .address < "$CONTRACTS_BEDROCK/deployments/$NETWORK/L2OutputOracleProxy.json")
L2OO_ADDRESS="0x6900000000000000000000000000000000000000"
SEQUENCER_GENESIS_HASH="$(jq -r '.l2.hash' < $DEVNET/rollup.json)"
SEQUENCER_BATCH_INBOX_ADDRESS="$(cat $DEVNET/rollup.json | jq -r '.batch_inbox_address')"
......
......@@ -67,6 +67,13 @@ WORKDIR /opt/optimism/packages/contracts
COPY ./ops/scripts/deployer.sh .
CMD ["yarn", "run", "deploy"]
FROM alpine:3.16.2 as contract-artifacts-bedrock
RUN mkdir -p /artifacts
WORKDIR /artifacts
COPY --from=base /opt/optimism/packages/contracts-bedrock/artifacts /artifacts/contracts-bedrock
COPY --from=base /opt/optimism/packages/contracts-governance/artifacts /artifacts/contracts-governance
CMD ["echo", "0"]
FROM base as deployer-bedrock
WORKDIR /opt/optimism/packages/contracts-bedrock
CMD ["yarn", "run", "deploy"]
......
{
"l1StartingBlockTag": "earliest",
"l1ChainID": 900,
"l2ChainID": 901,
"l2BlockTime": 2,
......@@ -16,6 +15,7 @@
"l2OutputOracleStartingTimestamp": -1,
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l2OutputOracleOwner": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l2GenesisBlockCoinbase": "0x42000000000000000000000000000000000000f0",
"l1BlockTime": 15,
"cliqueSignerAddress": "0xca062b0fd91172d89bcd4bb084ac4e21972cc467",
......
......@@ -8,8 +8,11 @@
"dist/**/*.js",
"dist/**/*.d.ts",
"dist/types",
"artifacts/contracts/**/*.json",
"deployments/**/*.json",
"artifacts/contracts/chugsplash/**/*.json",
"artifacts/contracts/L1/**/*.json",
"artifacts/contracts/L2/**/*.json",
"artifacts/contracts/libraries/**/*.json",
"artifacts/contracts/standards/**/*.json",
"chugsplash",
"L1",
"L2",
......@@ -104,6 +107,7 @@
"prettier": "^2.3.1",
"prettier-plugin-solidity": "^1.0.0-beta.18",
"random-bytes-seed": "^1.0.3",
"rimraf": "^3.0.2",
"rlp": "^2.2.6",
"solhint": "^3.3.6",
"solhint-plugin-prettier": "^0.0.5",
......
......@@ -50,7 +50,11 @@ const main = async () => {
)
artifactNames.push(artifactName)
content += `const ${artifactName} = require('${relPath}')\n`
// eslint-disable-next-line @typescript-eslint/no-var-requires
const artifact = require(relPath)
content += `const ${artifactName} = { abi: ${JSON.stringify(
artifact.abi
)}, address: '${artifact.address}' }\n`
}
}
......
......@@ -31,7 +31,10 @@ export const getContractDefinition = (name: string): any => {
export const getDeployedContractDefinition = (
name: string,
network: string
): any => {
): {
address: string
abi: any
} => {
const {
getDeployedContractArtifact,
// eslint-disable-next-line @typescript-eslint/no-var-requires
......
......@@ -130,17 +130,17 @@ export const CONTRACT_ADDRESSES: {
},
[L2ChainID.OPTIMISM_BEDROCK_LOCAL_DEVNET]: {
l1: {
AddressManager: '0x610178dA211FEF7D417bC0e6FeD39F05609AD788' as const,
AddressManager: '0x6900000000000000000000000000000000000005' as const,
L1CrossDomainMessenger:
'0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512' as const,
L1StandardBridge: '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0' as const,
'0x6900000000000000000000000000000000000002' as const,
L1StandardBridge: '0x6900000000000000000000000000000000000003' as const,
StateCommitmentChain:
'0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9' as const,
'0x0000000000000000000000000000000000000000' as const,
CanonicalTransactionChain:
'0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9' as const,
BondManager: '0x5FC8d32690cc91D4c39d9d3abcBD16989F875707' as const,
OptimismPortal: '0x0165878A594ca255338adfa4d48449f69242Eb8F' as const,
L2OutputOracle: '0x5FbDB2315678afecb367f032d93F642f64180aa3' as const,
'0x0000000000000000000000000000000000000000' as const,
BondManager: '0x0000000000000000000000000000000000000000' as const,
OptimismPortal: '0x6900000000000000000000000000000000000001' as const,
L2OutputOracle: '0x6900000000000000000000000000000000000000' as const,
},
l2: DEFAULT_L2_CONTRACT_ADDRESSES,
},
......
......@@ -2,14 +2,13 @@ import { task, types } from 'hardhat/config'
import { HardhatRuntimeEnvironment } from 'hardhat/types'
import '@nomiclabs/hardhat-ethers'
import 'hardhat-deploy'
import { predeploys } from '@eth-optimism/contracts-bedrock'
import {
predeploys,
getContractDefinition,
} from '@eth-optimism/contracts-bedrock'
import { Event, Contract, Wallet, providers, utils } from 'ethers'
import {
CrossChainMessenger,
StandardBridgeAdapter,
MessageStatus,
} from '../src'
import { CrossChainMessenger, MessageStatus, CONTRACT_ADDRESSES } from '../src'
const deployWETH9 = async (
hre: HardhatRuntimeEnvironment,
......@@ -18,7 +17,7 @@ const deployWETH9 = async (
const signers = await hre.ethers.getSigners()
const signer = signers[0]
const Artifact__WETH9 = await hre.deployments.getArtifact('WETH9')
const Artifact__WETH9 = await getContractDefinition('WETH9')
const Factory__WETH9 = new hre.ethers.ContractFactory(
Artifact__WETH9.abi,
Artifact__WETH9.bytecode,
......@@ -44,15 +43,16 @@ const createOptimismMintableERC20 = async (
L1ERC20: Contract,
l2Signer: Wallet
): Promise<Contract> => {
const Deployment__OptimismMintableERC20TokenFactory =
await hre.deployments.get('OptimismMintableERC20Factory')
const Artifact__OptimismMintableERC20Token = await getContractDefinition(
'OptimismMintableERC20'
)
const Artifact__OptimismMintableERC20Token =
await hre.deployments.getArtifact('OptimismMintableERC20')
const Artifact__OptimismMintableERC20TokenFactory =
await getContractDefinition('OptimismMintableERC20Factory')
const OptimismMintableERC20TokenFactory = await hre.ethers.getContractAt(
Deployment__OptimismMintableERC20TokenFactory.abi,
const OptimismMintableERC20TokenFactory = new Contract(
predeploys.OptimismMintableERC20Factory,
Artifact__OptimismMintableERC20TokenFactory.abi,
l2Signer
)
......@@ -80,13 +80,11 @@ const createOptimismMintableERC20 = async (
const l2WethAddress = event.args.remoteToken
console.log(`Deployed to ${l2WethAddress}`)
const contract = new Contract(
return new Contract(
l2WethAddress,
Artifact__OptimismMintableERC20Token.abi,
l2Signer
)
return contract
}
// TODO(tynes): this task could be modularized in the future
......@@ -130,61 +128,48 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.')
l2Provider
)
const Deployment__L2OutputOracleProxy = await hre.deployments.get(
'L2OutputOracleProxy'
)
const l2ChainId = await l2Signer.getChainId()
const contractAddrs = CONTRACT_ADDRESSES[l2ChainId]
const Artifact__L2ToL1MessagePasser = await hre.deployments.getArtifact(
const Artifact__L2ToL1MessagePasser = await getContractDefinition(
'L2ToL1MessagePasser'
)
const Artifact__L2CrossDomainMessenger = await hre.deployments.getArtifact(
const Artifact__L2CrossDomainMessenger = await getContractDefinition(
'L2CrossDomainMessenger'
)
const Artifact__L2StandardBridge = await hre.deployments.getArtifact(
const Artifact__L2StandardBridge = await getContractDefinition(
'L2StandardBridge'
)
const Deployment__OptimismPortal = await hre.deployments.get(
const Artifact__OptimismPortal = await getContractDefinition(
'OptimismPortal'
)
const Deployment__OptimismPortalProxy = await hre.deployments.get(
'OptimismPortalProxy'
)
const Deployment__L1StandardBridgeProxy = await hre.deployments.get(
'L1StandardBridgeProxy'
)
const Deployment__L1CrossDomainMessenger = await hre.deployments.get(
const Artifact__L1CrossDomainMessenger = await getContractDefinition(
'L1CrossDomainMessenger'
)
const Deployment__L1CrossDomainMessengerProxy = await hre.deployments.get(
'L1CrossDomainMessengerProxy'
)
const Deployment__L1StandardBridge = await hre.deployments.get(
const Artifact__L1StandardBridge = await getContractDefinition(
'L1StandardBridge'
)
const OptimismPortal = new hre.ethers.Contract(
Deployment__OptimismPortalProxy.address,
Deployment__OptimismPortal.abi,
contractAddrs.l1.OptimismPortal,
Artifact__OptimismPortal.abi,
signer
)
const L1CrossDomainMessenger = new hre.ethers.Contract(
Deployment__L1CrossDomainMessengerProxy.address,
Deployment__L1CrossDomainMessenger.abi,
contractAddrs.l1.L1CrossDomainMessenger,
Artifact__L1CrossDomainMessenger.abi,
signer
)
const L1StandardBridge = new hre.ethers.Contract(
Deployment__L1StandardBridgeProxy.address,
Deployment__L1StandardBridge.abi,
contractAddrs.l1.L1StandardBridge,
Artifact__L1StandardBridge.abi,
signer
)
......@@ -207,23 +192,7 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.')
l1SignerOrProvider: signer,
l2SignerOrProvider: l2Signer,
l1ChainId: await signer.getChainId(),
l2ChainId: await l2Signer.getChainId(),
bridges: {
Standard: {
Adapter: StandardBridgeAdapter,
l1Bridge: Deployment__L1StandardBridgeProxy.address,
l2Bridge: predeploys.L2StandardBridge,
},
},
contracts: {
l1: {
L1StandardBridge: Deployment__L1StandardBridgeProxy.address,
L1CrossDomainMessenger:
Deployment__L1CrossDomainMessengerProxy.address,
L2OutputOracle: Deployment__L2OutputOracleProxy.address,
OptimismPortal: Deployment__OptimismPortalProxy.address,
},
},
l2ChainId,
bedrock: true,
})
......
import { task, types } from 'hardhat/config'
import '@nomiclabs/hardhat-ethers'
import 'hardhat-deploy'
import { predeploys } from '@eth-optimism/contracts-bedrock'
import {
predeploys,
getContractDefinition,
} from '@eth-optimism/contracts-bedrock'
import { providers, utils } from 'ethers'
import {
CrossChainMessenger,
StandardBridgeAdapter,
MessageStatus,
} from '../src'
import { CrossChainMessenger, MessageStatus, CONTRACT_ADDRESSES } from '../src'
task('deposit-eth', 'Deposits WETH9 onto L2.')
.addParam(
......@@ -56,10 +55,6 @@ task('deposit-eth', 'Deposits WETH9 onto L2.')
const l2Provider = new providers.StaticJsonRpcProvider(args.l2ProviderUrl)
const Deployment__L2OutputOracleProxy = await hre.deployments.get(
'L2OutputOracleProxy'
)
// send to self if not specified
const to = args.to ? args.to : address
const amount = args.amount
......@@ -74,57 +69,48 @@ task('deposit-eth', 'Deposits WETH9 onto L2.')
l2Provider
)
const Artifact__L2ToL1MessagePasser = await hre.deployments.getArtifact(
const l2ChainId = await l2Signer.getChainId()
const contractAddrs = CONTRACT_ADDRESSES[l2ChainId]
const Artifact__L2ToL1MessagePasser = await getContractDefinition(
'L2ToL1MessagePasser'
)
const Artifact__L2CrossDomainMessenger = await hre.deployments.getArtifact(
const Artifact__L2CrossDomainMessenger = await getContractDefinition(
'L2CrossDomainMessenger'
)
const Artifact__L2StandardBridge = await hre.deployments.getArtifact(
const Artifact__L2StandardBridge = await getContractDefinition(
'L2StandardBridge'
)
const Deployment__OptimismPortal = await hre.deployments.get(
const Artifact__OptimismPortal = await getContractDefinition(
'OptimismPortal'
)
const Deployment__OptimismPortalProxy = await hre.deployments.get(
'OptimismPortalProxy'
)
const Deployment__L1StandardBridgeProxy = await hre.deployments.get(
'L1StandardBridgeProxy'
)
const Deployment__L1CrossDomainMessenger = await hre.deployments.get(
const Artifact__L1CrossDomainMessenger = await getContractDefinition(
'L1CrossDomainMessenger'
)
const Deployment__L1CrossDomainMessengerProxy = await hre.deployments.get(
'L1CrossDomainMessengerProxy'
)
const Deployment__L1StandardBridge = await hre.deployments.get(
const Artifact__L1StandardBridge = await getContractDefinition(
'L1StandardBridge'
)
const OptimismPortal = new hre.ethers.Contract(
Deployment__OptimismPortalProxy.address,
Deployment__OptimismPortal.abi,
contractAddrs.l1.OptimismPortal,
Artifact__OptimismPortal.abi,
signer
)
const L1CrossDomainMessenger = new hre.ethers.Contract(
Deployment__L1CrossDomainMessengerProxy.address,
Deployment__L1CrossDomainMessenger.abi,
contractAddrs.l1.L1CrossDomainMessenger,
Artifact__L1CrossDomainMessenger.abi,
signer
)
const L1StandardBridge = new hre.ethers.Contract(
Deployment__L1StandardBridgeProxy.address,
Deployment__L1StandardBridge.abi,
contractAddrs.l1.L1StandardBridge,
Artifact__L1StandardBridge.abi,
signer
)
......@@ -147,23 +133,7 @@ task('deposit-eth', 'Deposits WETH9 onto L2.')
l1SignerOrProvider: signer,
l2SignerOrProvider: l2Signer,
l1ChainId: await signer.getChainId(),
l2ChainId: await l2Signer.getChainId(),
bridges: {
Standard: {
Adapter: StandardBridgeAdapter,
l1Bridge: Deployment__L1StandardBridgeProxy.address,
l2Bridge: predeploys.L2StandardBridge,
},
},
contracts: {
l1: {
L1StandardBridge: Deployment__L1StandardBridgeProxy.address,
L1CrossDomainMessenger:
Deployment__L1CrossDomainMessengerProxy.address,
L2OutputOracle: Deployment__L2OutputOracleProxy.address,
OptimismPortal: Deployment__OptimismPortalProxy.address,
},
},
l2ChainId,
bedrock: true,
})
......@@ -238,15 +208,19 @@ task('deposit-eth', 'Deposits WETH9 onto L2.')
)
console.log('Waiting to be able to withdraw')
setInterval(async () => {
const interval = setInterval(async () => {
const currentStatus = await messenger.getMessageStatus(ethWithdrawReceipt)
console.log(`Message status: ${MessageStatus[currentStatus]}`)
}, 3000)
await messenger.waitForMessageStatus(
ethWithdrawReceipt,
MessageStatus.READY_FOR_RELAY
)
try {
await messenger.waitForMessageStatus(
ethWithdrawReceipt,
MessageStatus.READY_FOR_RELAY
)
} finally {
clearInterval(interval)
}
const ethFinalize = await messenger.finalizeMessage(ethWithdrawReceipt)
const ethFinalizeReceipt = await ethFinalize.wait()
......
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